2727 **************************************************************************/
2828
2929#include "vmwgfx_drv.h"
30+
31+ #include "vmwgfx_bo.h"
3032#include <linux/highmem.h>
3133
3234/*
@@ -420,13 +422,105 @@ static int vmw_bo_cpu_blit_line(struct vmw_bo_blit_line_data *d,
420422 return 0 ;
421423}
422424
425+ static void * map_external (struct vmw_bo * bo , struct iosys_map * map )
426+ {
427+ struct vmw_private * vmw =
428+ container_of (bo -> tbo .bdev , struct vmw_private , bdev );
429+ void * ptr = NULL ;
430+ int ret ;
431+
432+ if (bo -> tbo .base .import_attach ) {
433+ ret = dma_buf_vmap (bo -> tbo .base .dma_buf , map );
434+ if (ret ) {
435+ drm_dbg_driver (& vmw -> drm ,
436+ "Wasn't able to map external bo!\n" );
437+ goto out ;
438+ }
439+ ptr = map -> vaddr ;
440+ } else {
441+ ptr = vmw_bo_map_and_cache (bo );
442+ }
443+
444+ out :
445+ return ptr ;
446+ }
447+
448+ static void unmap_external (struct vmw_bo * bo , struct iosys_map * map )
449+ {
450+ if (bo -> tbo .base .import_attach )
451+ dma_buf_vunmap (bo -> tbo .base .dma_buf , map );
452+ else
453+ vmw_bo_unmap (bo );
454+ }
455+
456+ static int vmw_external_bo_copy (struct vmw_bo * dst , u32 dst_offset ,
457+ u32 dst_stride , struct vmw_bo * src ,
458+ u32 src_offset , u32 src_stride ,
459+ u32 width_in_bytes , u32 height ,
460+ struct vmw_diff_cpy * diff )
461+ {
462+ struct vmw_private * vmw =
463+ container_of (dst -> tbo .bdev , struct vmw_private , bdev );
464+ size_t dst_size = dst -> tbo .resource -> size ;
465+ size_t src_size = src -> tbo .resource -> size ;
466+ struct iosys_map dst_map = {0 };
467+ struct iosys_map src_map = {0 };
468+ int ret , i ;
469+ int x_in_bytes ;
470+ u8 * vsrc ;
471+ u8 * vdst ;
472+
473+ vsrc = map_external (src , & src_map );
474+ if (!vsrc ) {
475+ drm_dbg_driver (& vmw -> drm , "Wasn't able to map src\n" );
476+ ret = - ENOMEM ;
477+ goto out ;
478+ }
479+
480+ vdst = map_external (dst , & dst_map );
481+ if (!vdst ) {
482+ drm_dbg_driver (& vmw -> drm , "Wasn't able to map dst\n" );
483+ ret = - ENOMEM ;
484+ goto out ;
485+ }
486+
487+ vsrc += src_offset ;
488+ vdst += dst_offset ;
489+ if (src_stride == dst_stride ) {
490+ dst_size -= dst_offset ;
491+ src_size -= src_offset ;
492+ memcpy (vdst , vsrc ,
493+ min (dst_stride * height , min (dst_size , src_size )));
494+ } else {
495+ WARN_ON (dst_stride < width_in_bytes );
496+ for (i = 0 ; i < height ; ++ i ) {
497+ memcpy (vdst , vsrc , width_in_bytes );
498+ vsrc += src_stride ;
499+ vdst += dst_stride ;
500+ }
501+ }
502+
503+ x_in_bytes = (dst_offset % dst_stride );
504+ diff -> rect .x1 = x_in_bytes / diff -> cpp ;
505+ diff -> rect .y1 = ((dst_offset - x_in_bytes ) / dst_stride );
506+ diff -> rect .x2 = diff -> rect .x1 + width_in_bytes / diff -> cpp ;
507+ diff -> rect .y2 = diff -> rect .y1 + height ;
508+
509+ ret = 0 ;
510+ out :
511+ unmap_external (src , & src_map );
512+ unmap_external (dst , & dst_map );
513+
514+ return ret ;
515+ }
516+
423517/**
424518 * vmw_bo_cpu_blit - in-kernel cpu blit.
425519 *
426- * @dst : Destination buffer object.
520+ * @vmw_dst : Destination buffer object.
427521 * @dst_offset: Destination offset of blit start in bytes.
428522 * @dst_stride: Destination stride in bytes.
429- * @src : Source buffer object.
523+ * @vmw_src : Source buffer object.
430524 * @src_offset: Source offset of blit start in bytes.
431525 * @src_stride: Source stride in bytes.
432526 * @w: Width of blit.
@@ -444,13 +538,15 @@ static int vmw_bo_cpu_blit_line(struct vmw_bo_blit_line_data *d,
444538 * Neither of the buffer objects may be placed in PCI memory
445539 * (Fixed memory in TTM terminology) when using this function.
446540 */
447- int vmw_bo_cpu_blit (struct ttm_buffer_object * dst ,
541+ int vmw_bo_cpu_blit (struct vmw_bo * vmw_dst ,
448542 u32 dst_offset , u32 dst_stride ,
449- struct ttm_buffer_object * src ,
543+ struct vmw_bo * vmw_src ,
450544 u32 src_offset , u32 src_stride ,
451545 u32 w , u32 h ,
452546 struct vmw_diff_cpy * diff )
453547{
548+ struct ttm_buffer_object * src = & vmw_src -> tbo ;
549+ struct ttm_buffer_object * dst = & vmw_dst -> tbo ;
454550 struct ttm_operation_ctx ctx = {
455551 .interruptible = false,
456552 .no_wait_gpu = false
@@ -460,6 +556,11 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
460556 int ret = 0 ;
461557 struct page * * dst_pages = NULL ;
462558 struct page * * src_pages = NULL ;
559+ bool src_external = (src -> ttm -> page_flags & TTM_TT_FLAG_EXTERNAL ) != 0 ;
560+ bool dst_external = (dst -> ttm -> page_flags & TTM_TT_FLAG_EXTERNAL ) != 0 ;
561+
562+ if (WARN_ON (dst == src ))
563+ return - EINVAL ;
463564
464565 /* Buffer objects need to be either pinned or reserved: */
465566 if (!(dst -> pin_count ))
@@ -479,6 +580,11 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
479580 return ret ;
480581 }
481582
583+ if (src_external || dst_external )
584+ return vmw_external_bo_copy (vmw_dst , dst_offset , dst_stride ,
585+ vmw_src , src_offset , src_stride ,
586+ w , h , diff );
587+
482588 if (!src -> ttm -> pages && src -> ttm -> sg ) {
483589 src_pages = kvmalloc_array (src -> ttm -> num_pages ,
484590 sizeof (struct page * ), GFP_KERNEL );
0 commit comments