@@ -556,7 +556,7 @@ struct cursor_buffer {
556
556
557
557
struct gbm_bo * bo ;
558
558
559
- int hot_x , hot_y ;
559
+ struct vec2i hotspot ;
560
560
};
561
561
562
562
static const int pixel_size_for_cursor_size [] = {
@@ -581,82 +581,43 @@ UNUSED static enum cursor_size cursor_size_from_pixel_ratio(double device_pixel_
581
581
return size ;
582
582
}
583
583
584
- static void write_cursor_icon (
585
- void * map_void ,
584
+ static struct vec2i get_cursor_hotspot (
586
585
enum cursor_size size ,
587
- uint32_t pitch ,
588
- size_t buffer_size ,
589
- drm_plane_transform_t rotation ,
590
- int * hot_x_out ,
591
- int * hot_y_out
586
+ drm_plane_transform_t rotation
592
587
) {
593
588
const struct cursor_icon * icon ;
594
589
int pixel_size ;
595
590
int hot_x , hot_y ;
596
-
597
- ASSERT_NOT_NULL (map_void );
591
+
598
592
assert (PLANE_TRANSFORM_IS_ONLY_ROTATION (rotation ));
599
593
icon = cursors + size ;
600
594
pixel_size = pixel_size_for_cursor_size [size ];
601
- ASSERT_EQUALS (pixel_size , icon -> width );
602
- ASSERT_EQUALS (pixel_size , icon -> height );
603
595
604
- if (rotation .rotate_0 == 0 ) {
605
- ASSERT_EQUALS (pixel_size * 4 , pitch );
606
- memcpy (map_void , icon -> data , buffer_size );
596
+ if (rotation .rotate_0 ) {
607
597
hot_x = icon -> hot_x ;
608
598
hot_y = icon -> hot_y ;
599
+ } else if (rotation .rotate_90 ) {
600
+ hot_x = pixel_size - icon -> hot_y - 1 ;
601
+ hot_y = icon -> hot_x ;
602
+ } else if (rotation .rotate_180 ) {
603
+ hot_x = pixel_size - icon -> hot_x - 1 ;
604
+ hot_y = pixel_size - icon -> hot_y - 1 ;
609
605
} else {
610
- ASSUME (rotation .rotate_90 || rotation .rotate_180 || rotation .rotate_270 );
611
-
612
- uint32_t * map_uint32 = (uint32_t * ) map_void ;
613
-
614
- for (int y = 0 ; y < pixel_size ; y ++ ) {
615
- for (int x = 0 ; x < pixel_size ; x ++ ) {
616
- int buffer_x , buffer_y ;
617
- if (rotation .rotate_90 ) {
618
- buffer_x = pixel_size - y - 1 ;
619
- buffer_y = x ;
620
- } else if (rotation .rotate_180 ) {
621
- buffer_x = pixel_size - y - 1 ;
622
- buffer_y = pixel_size - x - 1 ;
623
- } else {
624
- assert (rotation .rotate_270 );
625
- buffer_x = y ;
626
- buffer_y = pixel_size - x - 1 ;
627
- }
628
-
629
- int buffer_offset = pitch * buffer_y + 4 * buffer_x ;
630
- int cursor_offset = pixel_size * y + x ;
631
-
632
- map_uint32 [buffer_offset / 4 ] = icon -> data [cursor_offset ];
633
- }
634
- }
635
-
636
- if (rotation .rotate_90 ) {
637
- hot_x = pixel_size - icon -> hot_y - 1 ;
638
- hot_y = icon -> hot_x ;
639
- } else if (rotation .rotate_180 ) {
640
- hot_x = pixel_size - icon -> hot_x - 1 ;
641
- hot_y = pixel_size - icon -> hot_y - 1 ;
642
- } else {
643
- assert (rotation .rotate_270 );
644
- hot_x = icon -> hot_y ;
645
- hot_y = pixel_size - icon -> hot_x - 1 ;
646
- }
606
+ ASSUME (rotation .rotate_270 );
607
+ hot_x = icon -> hot_y ;
608
+ hot_y = pixel_size - icon -> hot_x - 1 ;
647
609
}
648
610
649
- * hot_x_out = hot_x ;
650
- * hot_y_out = hot_y ;
611
+ return VEC2I (hot_x , hot_y );
651
612
}
652
613
653
- static struct cursor_buffer * cursor_buffer_new_using_gbm_bo (struct drmdev * drmdev , enum cursor_size size , drm_plane_transform_t rotation ) {
614
+ static struct cursor_buffer * cursor_buffer_new (struct drmdev * drmdev , enum cursor_size size , drm_plane_transform_t rotation ) {
615
+ const struct cursor_icon * icon ;
654
616
struct cursor_buffer * b ;
655
617
struct gbm_bo * bo ;
656
- uint32_t stride ;
657
618
uint32_t fb_id ;
658
- void * mapdata , * map ;
659
- int pixel_size , hot_x , hot_y ;
619
+ int pixel_size ;
620
+ int ok ;
660
621
661
622
ASSERT_NOT_NULL (drmdev );
662
623
assert (PLANE_TRANSFORM_IS_ONLY_ROTATION (rotation ));
@@ -680,15 +641,60 @@ static struct cursor_buffer *cursor_buffer_new_using_gbm_bo(struct drmdev *drmde
680
641
goto fail_free_b ;
681
642
}
682
643
683
- map = gbm_bo_map (bo , 0 , 0 , pixel_size , pixel_size , GBM_BO_TRANSFER_READ | GBM_BO_TRANSFER_WRITE , & stride , & mapdata );
684
- if (map == NULL ) {
685
- LOG_ERROR ("Couldn't map GBM bo for uploading mouse cursor icon. gbm_bo_map: %s\n" , strerror (errno ));
644
+ if (gbm_bo_get_stride (bo ) != pixel_size * 4 ) {
645
+ LOG_ERROR ("GBM BO has unsupported framebuffer stride %u, expected was: %d\n" , gbm_bo_get_stride (bo ), pixel_size * 4 );
686
646
goto fail_destroy_bo ;
687
647
}
688
648
689
- write_cursor_icon (map , size , stride , stride * pixel_size , rotation , & hot_x , & hot_y );
649
+ icon = cursors + size ;
650
+ ASSERT_EQUALS (pixel_size , icon -> width );
651
+ ASSERT_EQUALS (pixel_size , icon -> height );
652
+
653
+ if (rotation .rotate_0 ) {
654
+ ok = gbm_bo_write (bo , icon -> data , gbm_bo_get_stride (bo ) * pixel_size );
655
+ if (ok != 0 ) {
656
+ LOG_ERROR ("Couldn't write cursor icon to GBM BO. gbm_bo_write: %s\n" , strerror (errno ));
657
+ goto fail_destroy_bo ;
658
+ }
659
+ } else {
660
+ ASSUME (rotation .rotate_90 || rotation .rotate_180 || rotation .rotate_270 );
661
+
662
+ uint32_t * rotated = malloc (pixel_size * pixel_size * 4 );
663
+ if (rotated == NULL ) {
664
+ goto fail_destroy_bo ;
665
+ }
666
+
667
+ for (int y = 0 ; y < pixel_size ; y ++ ) {
668
+ for (int x = 0 ; x < pixel_size ; x ++ ) {
669
+ int buffer_x , buffer_y ;
670
+ if (rotation .rotate_90 ) {
671
+ buffer_x = pixel_size - y - 1 ;
672
+ buffer_y = x ;
673
+ } else if (rotation .rotate_180 ) {
674
+ buffer_x = pixel_size - y - 1 ;
675
+ buffer_y = pixel_size - x - 1 ;
676
+ } else {
677
+ ASSUME (rotation .rotate_270 );
678
+ buffer_x = y ;
679
+ buffer_y = pixel_size - x - 1 ;
680
+ }
681
+
682
+ int buffer_offset = pixel_size * buffer_y + buffer_x ;
683
+ int cursor_offset = pixel_size * y + x ;
690
684
691
- gbm_bo_unmap (bo , mapdata );
685
+ rotated [buffer_offset ] = icon -> data [cursor_offset ];
686
+ }
687
+ }
688
+
689
+ ok = gbm_bo_write (bo , rotated , pixel_size * pixel_size * 4 );
690
+
691
+ free (rotated );
692
+
693
+ if (ok != 0 ) {
694
+ LOG_ERROR ("Couldn't write rotated cursor icon to GBM BO. gbm_bo_write: %s\n" , strerror (errno ));
695
+ goto fail_destroy_bo ;
696
+ }
697
+ }
692
698
693
699
fb_id = drmdev_add_fb (
694
700
drmdev ,
@@ -715,8 +721,7 @@ static struct cursor_buffer *cursor_buffer_new_using_gbm_bo(struct drmdev *drmde
715
721
b -> gem_handle = gbm_bo_get_handle (bo ).u32 ;
716
722
b -> drm_fb_id = fb_id ;
717
723
b -> bo = bo ;
718
- b -> hot_x = hot_x ;
719
- b -> hot_y = hot_y ;
724
+ b -> hotspot = get_cursor_hotspot (size , rotation );
720
725
return b ;
721
726
722
727
fail_destroy_bo :
@@ -727,98 +732,6 @@ static struct cursor_buffer *cursor_buffer_new_using_gbm_bo(struct drmdev *drmde
727
732
return NULL ;
728
733
}
729
734
730
- static struct cursor_buffer *
731
- cursor_buffer_new_using_kms_dumb_buffers (struct drmdev * drmdev , enum cursor_size size , drm_plane_transform_t rotation ) {
732
- const struct cursor_icon * icon ;
733
- struct cursor_buffer * b ;
734
- uint32_t gem_handle , pitch ;
735
- uint32_t fb_id ;
736
- size_t buffer_size ;
737
- void * map_void ;
738
- int pixel_size , hot_x , hot_y ;
739
- int ok ;
740
-
741
- ASSERT_NOT_NULL (drmdev );
742
- assert (PLANE_TRANSFORM_IS_ONLY_ROTATION (rotation ));
743
-
744
- if (!drmdev_supports_dumb_buffers (drmdev )) {
745
- LOG_ERROR ("KMS doesn't support dumb buffers. Can't upload mouse cursor icon.\n" );
746
- return NULL ;
747
- }
748
-
749
- b = malloc (sizeof * b );
750
- if (b == NULL ) {
751
- return NULL ;
752
- }
753
-
754
- pixel_size = pixel_size_for_cursor_size [size ];
755
-
756
- ok = drmdev_create_dumb_buffer (drmdev , pixel_size , pixel_size , 32 , & gem_handle , & pitch , & buffer_size );
757
- if (ok != 0 ) {
758
- goto fail_free_b ;
759
- }
760
-
761
- fb_id = drmdev_add_fb (drmdev , pixel_size , pixel_size , kARGB8888_FpiPixelFormat , gem_handle , pitch , 0 , true, DRM_FORMAT_MOD_LINEAR );
762
- if (fb_id == 0 ) {
763
- LOG_ERROR ("Couldn't add mouse cursor buffer as KMS framebuffer.\n" );
764
- goto fail_destroy_dumb_buffer ;
765
- }
766
-
767
- map_void = drmdev_map_dumb_buffer (drmdev , gem_handle , buffer_size );
768
- if (map_void == NULL ) {
769
- goto fail_rm_fb ;
770
- }
771
-
772
- icon = cursors + size ;
773
- ASSERT_EQUALS (pixel_size , icon -> width );
774
- ASSERT_EQUALS (pixel_size , icon -> height );
775
-
776
- write_cursor_icon (map_void , size , pitch , buffer_size , rotation , & hot_x , & hot_y );
777
-
778
- drmdev_unmap_dumb_buffer (drmdev , map_void , buffer_size );
779
-
780
- b -> n_refs = REFCOUNT_INIT_1 ;
781
- b -> format = kARGB8888_FpiPixelFormat ;
782
- b -> width = pixel_size ;
783
- b -> height = pixel_size ;
784
- b -> size = size ;
785
- b -> rotation = rotation ;
786
- b -> drmdev = drmdev_ref (drmdev );
787
- b -> gem_handle = gem_handle ;
788
- b -> drm_fb_id = fb_id ;
789
- b -> bo = NULL ;
790
- b -> hot_x = hot_x ;
791
- b -> hot_y = hot_y ;
792
- return b ;
793
-
794
- fail_rm_fb :
795
- drmdev_rm_fb (drmdev , fb_id );
796
-
797
- fail_destroy_dumb_buffer :
798
- drmdev_destroy_dumb_buffer (drmdev , gem_handle );
799
-
800
- fail_free_b :
801
- free (b );
802
- return NULL ;
803
- }
804
-
805
- static struct cursor_buffer * cursor_buffer_new (struct drmdev * drmdev , enum cursor_size size , drm_plane_transform_t rotation ) {
806
- struct cursor_buffer * b ;
807
-
808
- b = cursor_buffer_new_using_kms_dumb_buffers (drmdev , size , rotation );
809
-
810
- if (b == NULL ) {
811
- b = cursor_buffer_new_using_gbm_bo (drmdev , size , rotation );
812
- }
813
-
814
- if (b == NULL ) {
815
- LOG_ERROR ("Couldn't upload mouse cursor icon using any method.\n" );
816
- return NULL ;
817
- }
818
-
819
- return b ;
820
- }
821
-
822
735
static void cursor_buffer_destroy (struct cursor_buffer * buffer ) {
823
736
drmdev_rm_fb (buffer -> drmdev , buffer -> drm_fb_id );
824
737
drmdev_destroy_dumb_buffer (buffer -> drmdev , buffer -> gem_handle );
@@ -1295,8 +1208,8 @@ static int kms_window_push_composition(struct window *window, struct fl_layer_co
1295
1208
.src_y = 0 ,
1296
1209
.src_w = ((uint16_t ) window -> kms .cursor -> width ) << 16 ,
1297
1210
.src_h = ((uint16_t ) window -> kms .cursor -> height ) << 16 ,
1298
- .dst_x = window -> cursor_pos .x - window -> kms .cursor -> hot_x ,
1299
- .dst_y = window -> cursor_pos .y - window -> kms .cursor -> hot_y ,
1211
+ .dst_x = window -> cursor_pos .x - window -> kms .cursor -> hotspot . x ,
1212
+ .dst_y = window -> cursor_pos .y - window -> kms .cursor -> hotspot . y ,
1300
1213
.dst_w = window -> kms .cursor -> width ,
1301
1214
.dst_h = window -> kms .cursor -> height ,
1302
1215
.has_rotation = false,
@@ -1626,6 +1539,6 @@ static int kms_window_move_cursor_locked(struct window *window, struct vec2i pos
1626
1539
window -> cursor_pos = pos ;
1627
1540
1628
1541
/// TODO: Draw a new frame or redraw the last frame with new cursor pos here.
1629
- drmdev_move_cursor (window -> kms .drmdev , window -> kms .crtc -> id , pos );
1542
+ drmdev_move_cursor (window -> kms .drmdev , window -> kms .crtc -> id , vec2i_sub ( pos , window -> kms . cursor -> hotspot ) );
1630
1543
return 0 ;
1631
1544
}
0 commit comments