@@ -476,12 +476,11 @@ static int qxl_primary_atomic_check(struct drm_plane *plane,
476
476
return qxl_check_framebuffer (qdev , bo );
477
477
}
478
478
479
- static int qxl_primary_apply_cursor (struct drm_plane * plane )
479
+ static int qxl_primary_apply_cursor (struct qxl_device * qdev ,
480
+ struct drm_plane_state * plane_state )
480
481
{
481
- struct drm_device * dev = plane -> dev ;
482
- struct qxl_device * qdev = to_qxl (dev );
483
- struct drm_framebuffer * fb = plane -> state -> fb ;
484
- struct qxl_crtc * qcrtc = to_qxl_crtc (plane -> state -> crtc );
482
+ struct drm_framebuffer * fb = plane_state -> fb ;
483
+ struct qxl_crtc * qcrtc = to_qxl_crtc (plane_state -> crtc );
485
484
struct qxl_cursor_cmd * cmd ;
486
485
struct qxl_release * release ;
487
486
int ret = 0 ;
@@ -505,8 +504,8 @@ static int qxl_primary_apply_cursor(struct drm_plane *plane)
505
504
506
505
cmd = (struct qxl_cursor_cmd * )qxl_release_map (qdev , release );
507
506
cmd -> type = QXL_CURSOR_SET ;
508
- cmd -> u .set .position .x = plane -> state -> crtc_x + fb -> hot_x ;
509
- cmd -> u .set .position .y = plane -> state -> crtc_y + fb -> hot_y ;
507
+ cmd -> u .set .position .x = plane_state -> crtc_x + fb -> hot_x ;
508
+ cmd -> u .set .position .y = plane_state -> crtc_y + fb -> hot_y ;
510
509
511
510
cmd -> u .set .shape = qxl_bo_physical_address (qdev , qcrtc -> cursor_bo , 0 );
512
511
@@ -523,6 +522,113 @@ static int qxl_primary_apply_cursor(struct drm_plane *plane)
523
522
return ret ;
524
523
}
525
524
525
+ static int qxl_primary_move_cursor (struct qxl_device * qdev ,
526
+ struct drm_plane_state * plane_state )
527
+ {
528
+ struct drm_framebuffer * fb = plane_state -> fb ;
529
+ struct qxl_crtc * qcrtc = to_qxl_crtc (plane_state -> crtc );
530
+ struct qxl_cursor_cmd * cmd ;
531
+ struct qxl_release * release ;
532
+ int ret = 0 ;
533
+
534
+ if (!qcrtc -> cursor_bo )
535
+ return 0 ;
536
+
537
+ ret = qxl_alloc_release_reserved (qdev , sizeof (* cmd ),
538
+ QXL_RELEASE_CURSOR_CMD ,
539
+ & release , NULL );
540
+ if (ret )
541
+ return ret ;
542
+
543
+ ret = qxl_release_reserve_list (release , true);
544
+ if (ret ) {
545
+ qxl_release_free (qdev , release );
546
+ return ret ;
547
+ }
548
+
549
+ cmd = (struct qxl_cursor_cmd * )qxl_release_map (qdev , release );
550
+ cmd -> type = QXL_CURSOR_MOVE ;
551
+ cmd -> u .position .x = plane_state -> crtc_x + fb -> hot_x ;
552
+ cmd -> u .position .y = plane_state -> crtc_y + fb -> hot_y ;
553
+ qxl_release_unmap (qdev , release , & cmd -> release_info );
554
+
555
+ qxl_release_fence_buffer_objects (release );
556
+ qxl_push_cursor_ring_release (qdev , release , QXL_CMD_CURSOR , false);
557
+ return ret ;
558
+ }
559
+
560
+ static struct qxl_bo * qxl_create_cursor (struct qxl_device * qdev ,
561
+ struct qxl_bo * user_bo ,
562
+ int hot_x , int hot_y )
563
+ {
564
+ static const u32 size = 64 * 64 * 4 ;
565
+ struct qxl_bo * cursor_bo ;
566
+ struct dma_buf_map cursor_map ;
567
+ struct dma_buf_map user_map ;
568
+ struct qxl_cursor cursor ;
569
+ int ret ;
570
+
571
+ if (!user_bo )
572
+ return NULL ;
573
+
574
+ ret = qxl_bo_create (qdev , sizeof (struct qxl_cursor ) + size ,
575
+ false, true, QXL_GEM_DOMAIN_VRAM , 1 ,
576
+ NULL , & cursor_bo );
577
+ if (ret )
578
+ goto err ;
579
+
580
+ ret = qxl_bo_vmap (cursor_bo , & cursor_map );
581
+ if (ret )
582
+ goto err_unref ;
583
+
584
+ ret = qxl_bo_vmap (user_bo , & user_map );
585
+ if (ret )
586
+ goto err_unmap ;
587
+
588
+ cursor .header .unique = 0 ;
589
+ cursor .header .type = SPICE_CURSOR_TYPE_ALPHA ;
590
+ cursor .header .width = 64 ;
591
+ cursor .header .height = 64 ;
592
+ cursor .header .hot_spot_x = hot_x ;
593
+ cursor .header .hot_spot_y = hot_y ;
594
+ cursor .data_size = size ;
595
+ cursor .chunk .next_chunk = 0 ;
596
+ cursor .chunk .prev_chunk = 0 ;
597
+ cursor .chunk .data_size = size ;
598
+ if (cursor_map .is_iomem ) {
599
+ memcpy_toio (cursor_map .vaddr_iomem ,
600
+ & cursor , sizeof (cursor ));
601
+ memcpy_toio (cursor_map .vaddr_iomem + sizeof (cursor ),
602
+ user_map .vaddr , size );
603
+ } else {
604
+ memcpy (cursor_map .vaddr ,
605
+ & cursor , sizeof (cursor ));
606
+ memcpy (cursor_map .vaddr + sizeof (cursor ),
607
+ user_map .vaddr , size );
608
+ }
609
+
610
+ qxl_bo_vunmap (user_bo );
611
+ qxl_bo_vunmap (cursor_bo );
612
+ return cursor_bo ;
613
+
614
+ err_unmap :
615
+ qxl_bo_vunmap (cursor_bo );
616
+ err_unref :
617
+ qxl_bo_unpin (cursor_bo );
618
+ qxl_bo_unref (& cursor_bo );
619
+ err :
620
+ return NULL ;
621
+ }
622
+
623
+ static void qxl_free_cursor (struct qxl_bo * cursor_bo )
624
+ {
625
+ if (!cursor_bo )
626
+ return ;
627
+
628
+ qxl_bo_unpin (cursor_bo );
629
+ qxl_bo_unref (& cursor_bo );
630
+ }
631
+
526
632
static void qxl_primary_atomic_update (struct drm_plane * plane ,
527
633
struct drm_plane_state * old_state )
528
634
{
@@ -543,7 +649,7 @@ static void qxl_primary_atomic_update(struct drm_plane *plane,
543
649
if (qdev -> primary_bo )
544
650
qxl_io_destroy_primary (qdev );
545
651
qxl_io_create_primary (qdev , primary );
546
- qxl_primary_apply_cursor (plane );
652
+ qxl_primary_apply_cursor (qdev , plane -> state );
547
653
}
548
654
549
655
if (bo -> is_dumb )
@@ -574,124 +680,21 @@ static void qxl_primary_atomic_disable(struct drm_plane *plane,
574
680
static void qxl_cursor_atomic_update (struct drm_plane * plane ,
575
681
struct drm_plane_state * old_state )
576
682
{
577
- struct drm_device * dev = plane -> dev ;
578
- struct qxl_device * qdev = to_qxl (dev );
683
+ struct qxl_device * qdev = to_qxl (plane -> dev );
579
684
struct drm_framebuffer * fb = plane -> state -> fb ;
580
- struct qxl_crtc * qcrtc = to_qxl_crtc (plane -> state -> crtc );
581
- struct qxl_release * release ;
582
- struct qxl_cursor_cmd * cmd ;
583
- struct qxl_cursor * cursor ;
584
- struct drm_gem_object * obj ;
585
- struct qxl_bo * cursor_bo = NULL , * user_bo = NULL , * old_cursor_bo = NULL ;
586
- int ret ;
587
- struct dma_buf_map user_map ;
588
- struct dma_buf_map cursor_map ;
589
- void * user_ptr ;
590
- int size = 64 * 64 * 4 ;
591
-
592
- ret = qxl_alloc_release_reserved (qdev , sizeof (* cmd ),
593
- QXL_RELEASE_CURSOR_CMD ,
594
- & release , NULL );
595
- if (ret )
596
- return ;
597
685
598
686
if (fb != old_state -> fb ) {
599
- obj = fb -> obj [0 ];
600
- user_bo = gem_to_qxl_bo (obj );
601
-
602
- /* pinning is done in the prepare/cleanup framevbuffer */
603
- ret = qxl_bo_vmap_locked (user_bo , & user_map );
604
- if (ret )
605
- goto out_free_release ;
606
- user_ptr = user_map .vaddr ; /* TODO: Use mapping abstraction properly */
607
-
608
- ret = qxl_alloc_bo_reserved (qdev , release ,
609
- sizeof (struct qxl_cursor ) + size ,
610
- & cursor_bo );
611
- if (ret )
612
- goto out_kunmap ;
613
-
614
- ret = qxl_bo_pin (cursor_bo );
615
- if (ret )
616
- goto out_free_bo ;
617
-
618
- ret = qxl_release_reserve_list (release , true);
619
- if (ret )
620
- goto out_unpin ;
621
-
622
- ret = qxl_bo_vmap_locked (cursor_bo , & cursor_map );
623
- if (ret )
624
- goto out_backoff ;
625
- if (cursor_map .is_iomem ) /* TODO: Use mapping abstraction properly */
626
- cursor = (struct qxl_cursor __force * )cursor_map .vaddr_iomem ;
627
- else
628
- cursor = (struct qxl_cursor * )cursor_map .vaddr ;
629
-
630
- cursor -> header .unique = 0 ;
631
- cursor -> header .type = SPICE_CURSOR_TYPE_ALPHA ;
632
- cursor -> header .width = 64 ;
633
- cursor -> header .height = 64 ;
634
- cursor -> header .hot_spot_x = fb -> hot_x ;
635
- cursor -> header .hot_spot_y = fb -> hot_y ;
636
- cursor -> data_size = size ;
637
- cursor -> chunk .next_chunk = 0 ;
638
- cursor -> chunk .prev_chunk = 0 ;
639
- cursor -> chunk .data_size = size ;
640
- memcpy (cursor -> chunk .data , user_ptr , size );
641
- qxl_bo_vunmap_locked (cursor_bo );
642
- qxl_bo_vunmap_locked (user_bo );
643
-
644
- cmd = (struct qxl_cursor_cmd * ) qxl_release_map (qdev , release );
645
- cmd -> u .set .visible = 1 ;
646
- cmd -> u .set .shape = qxl_bo_physical_address (qdev ,
647
- cursor_bo , 0 );
648
- cmd -> type = QXL_CURSOR_SET ;
649
-
650
- old_cursor_bo = qcrtc -> cursor_bo ;
651
- qcrtc -> cursor_bo = cursor_bo ;
652
- cursor_bo = NULL ;
687
+ qxl_primary_apply_cursor (qdev , plane -> state );
653
688
} else {
654
-
655
- ret = qxl_release_reserve_list (release , true);
656
- if (ret )
657
- goto out_free_release ;
658
-
659
- cmd = (struct qxl_cursor_cmd * ) qxl_release_map (qdev , release );
660
- cmd -> type = QXL_CURSOR_MOVE ;
689
+ qxl_primary_move_cursor (qdev , plane -> state );
661
690
}
662
-
663
- cmd -> u .position .x = plane -> state -> crtc_x + fb -> hot_x ;
664
- cmd -> u .position .y = plane -> state -> crtc_y + fb -> hot_y ;
665
-
666
- qxl_release_unmap (qdev , release , & cmd -> release_info );
667
- qxl_release_fence_buffer_objects (release );
668
- qxl_push_cursor_ring_release (qdev , release , QXL_CMD_CURSOR , false);
669
-
670
- if (old_cursor_bo != NULL )
671
- qxl_bo_unpin (old_cursor_bo );
672
- qxl_bo_unref (& old_cursor_bo );
673
- qxl_bo_unref (& cursor_bo );
674
-
675
- return ;
676
-
677
- out_backoff :
678
- qxl_release_backoff_reserve_list (release );
679
- out_unpin :
680
- qxl_bo_unpin (cursor_bo );
681
- out_free_bo :
682
- qxl_bo_unref (& cursor_bo );
683
- out_kunmap :
684
- qxl_bo_vunmap_locked (user_bo );
685
- out_free_release :
686
- qxl_release_free (qdev , release );
687
- return ;
688
-
689
691
}
690
692
691
693
static void qxl_cursor_atomic_disable (struct drm_plane * plane ,
692
694
struct drm_plane_state * old_state )
693
695
{
694
696
struct qxl_device * qdev = to_qxl (plane -> dev );
697
+ struct qxl_crtc * qcrtc ;
695
698
struct qxl_release * release ;
696
699
struct qxl_cursor_cmd * cmd ;
697
700
int ret ;
@@ -714,6 +717,10 @@ static void qxl_cursor_atomic_disable(struct drm_plane *plane,
714
717
715
718
qxl_release_fence_buffer_objects (release );
716
719
qxl_push_cursor_ring_release (qdev , release , QXL_CMD_CURSOR , false);
720
+
721
+ qcrtc = to_qxl_crtc (old_state -> crtc );
722
+ qxl_free_cursor (qcrtc -> cursor_bo );
723
+ qcrtc -> cursor_bo = NULL ;
717
724
}
718
725
719
726
static void qxl_update_dumb_head (struct qxl_device * qdev ,
@@ -822,6 +829,17 @@ static int qxl_plane_prepare_fb(struct drm_plane *plane,
822
829
qxl_prepare_shadow (qdev , user_bo , new_state -> crtc -> index );
823
830
}
824
831
832
+ if (plane -> type == DRM_PLANE_TYPE_CURSOR &&
833
+ plane -> state -> fb != new_state -> fb ) {
834
+ struct qxl_crtc * qcrtc = to_qxl_crtc (new_state -> crtc );
835
+ struct qxl_bo * old_cursor_bo = qcrtc -> cursor_bo ;
836
+
837
+ qcrtc -> cursor_bo = qxl_create_cursor (qdev , user_bo ,
838
+ new_state -> fb -> hot_x ,
839
+ new_state -> fb -> hot_y );
840
+ qxl_free_cursor (old_cursor_bo );
841
+ }
842
+
825
843
return qxl_bo_pin (user_bo );
826
844
}
827
845
0 commit comments