27
27
**************************************************************************/
28
28
29
29
#include "vmwgfx_drv.h"
30
+
31
+ #include "vmwgfx_bo.h"
30
32
#include <linux/highmem.h>
31
33
32
34
/*
@@ -420,13 +422,105 @@ static int vmw_bo_cpu_blit_line(struct vmw_bo_blit_line_data *d,
420
422
return 0 ;
421
423
}
422
424
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
+
423
517
/**
424
518
* vmw_bo_cpu_blit - in-kernel cpu blit.
425
519
*
426
- * @dst : Destination buffer object.
520
+ * @vmw_dst : Destination buffer object.
427
521
* @dst_offset: Destination offset of blit start in bytes.
428
522
* @dst_stride: Destination stride in bytes.
429
- * @src : Source buffer object.
523
+ * @vmw_src : Source buffer object.
430
524
* @src_offset: Source offset of blit start in bytes.
431
525
* @src_stride: Source stride in bytes.
432
526
* @w: Width of blit.
@@ -444,13 +538,15 @@ static int vmw_bo_cpu_blit_line(struct vmw_bo_blit_line_data *d,
444
538
* Neither of the buffer objects may be placed in PCI memory
445
539
* (Fixed memory in TTM terminology) when using this function.
446
540
*/
447
- int vmw_bo_cpu_blit (struct ttm_buffer_object * dst ,
541
+ int vmw_bo_cpu_blit (struct vmw_bo * vmw_dst ,
448
542
u32 dst_offset , u32 dst_stride ,
449
- struct ttm_buffer_object * src ,
543
+ struct vmw_bo * vmw_src ,
450
544
u32 src_offset , u32 src_stride ,
451
545
u32 w , u32 h ,
452
546
struct vmw_diff_cpy * diff )
453
547
{
548
+ struct ttm_buffer_object * src = & vmw_src -> tbo ;
549
+ struct ttm_buffer_object * dst = & vmw_dst -> tbo ;
454
550
struct ttm_operation_ctx ctx = {
455
551
.interruptible = false,
456
552
.no_wait_gpu = false
@@ -460,6 +556,11 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
460
556
int ret = 0 ;
461
557
struct page * * dst_pages = NULL ;
462
558
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 ;
463
564
464
565
/* Buffer objects need to be either pinned or reserved: */
465
566
if (!(dst -> pin_count ))
@@ -479,6 +580,11 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst,
479
580
return ret ;
480
581
}
481
582
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
+
482
588
if (!src -> ttm -> pages && src -> ttm -> sg ) {
483
589
src_pages = kvmalloc_array (src -> ttm -> num_pages ,
484
590
sizeof (struct page * ), GFP_KERNEL );
0 commit comments