@@ -156,6 +156,7 @@ struct window {
156
156
drmModeModeInfo * mode ;
157
157
158
158
bool should_apply_mode ;
159
+ struct cursor_buffer * cursor ;
159
160
} kms ;
160
161
161
162
/**
@@ -209,9 +210,9 @@ struct window {
209
210
int (* push_composition )(struct window * window , struct fl_layer_composition * composition );
210
211
struct render_surface * (* get_render_surface )(struct window * window , struct vec2i size );
211
212
EGLSurface (* get_egl_surface )(struct window * window );
212
- int (* enable_cursor )(struct window * window , struct vec2i pos );
213
- int (* disable_cursor )(struct window * window );
214
- int (* move_cursor )(struct window * window , struct vec2i pos );
213
+ int (* enable_cursor_locked )(struct window * window , struct vec2i pos );
214
+ int (* disable_cursor_locked )(struct window * window );
215
+ int (* move_cursor_locked )(struct window * window , struct vec2i pos );
215
216
void (* deinit )(struct window * window );
216
217
};
217
218
@@ -389,9 +390,9 @@ static int window_init(
389
390
window -> push_composition = NULL ;
390
391
window -> get_render_surface = NULL ;
391
392
window -> get_egl_surface = NULL ;
392
- window -> enable_cursor = NULL ;
393
- window -> disable_cursor = NULL ;
394
- window -> move_cursor = NULL ;
393
+ window -> enable_cursor_locked = NULL ;
394
+ window -> disable_cursor_locked = NULL ;
395
+ window -> move_cursor_locked = NULL ;
395
396
window -> deinit = window_deinit ;
396
397
return 0 ;
397
398
}
@@ -493,20 +494,20 @@ int window_set_cursor(
493
494
if (has_enabled ) {
494
495
if (enabled && !window -> cursor_enabled ) {
495
496
// enable cursor
496
- DEBUG_ASSERT_NOT_NULL (window -> enable_cursor );
497
- ok = window -> enable_cursor (window , pos );
497
+ DEBUG_ASSERT_NOT_NULL (window -> enable_cursor_locked );
498
+ ok = window -> enable_cursor_locked (window , pos );
498
499
} else if (!enabled && window -> cursor_enabled ) {
499
500
// disable cursor
500
- DEBUG_ASSERT_NOT_NULL (window -> disable_cursor );
501
- ok = window -> disable_cursor (window );
501
+ DEBUG_ASSERT_NOT_NULL (window -> disable_cursor_locked );
502
+ ok = window -> disable_cursor_locked (window );
502
503
}
503
504
}
504
505
505
506
if (has_pos ) {
506
507
if (window -> cursor_enabled ) {
507
508
// move cursor
508
- DEBUG_ASSERT_NOT_NULL (window -> move_cursor );
509
- ok = window -> move_cursor (window , pos );
509
+ DEBUG_ASSERT_NOT_NULL (window -> move_cursor_locked );
510
+ ok = window -> move_cursor_locked (window , pos );
510
511
} else {
511
512
// !enabled && !window->cursor_enabled
512
513
// move cursor while cursor is disabled
@@ -540,7 +541,7 @@ struct cursor_buffer {
540
541
enum pixfmt format ;
541
542
int width , height ;
542
543
enum cursor_size size ;
543
- int rotation ;
544
+ drm_plane_transform_t rotation ;
544
545
545
546
int hot_x , hot_y ;
546
547
};
@@ -572,7 +573,7 @@ MAYBE_UNUSED static enum cursor_size cursor_size_from_pixel_ratio(double device_
572
573
return size ;
573
574
}
574
575
575
- MAYBE_UNUSED static struct cursor_buffer * cursor_buffer_new (struct drmdev * drmdev , enum cursor_size size , int rotation ) {
576
+ MAYBE_UNUSED static struct cursor_buffer * cursor_buffer_new (struct drmdev * drmdev , enum cursor_size size , drm_plane_transform_t rotation ) {
576
577
const struct cursor_icon * icon ;
577
578
struct cursor_buffer * b ;
578
579
uint32_t gem_handle , pitch ;
@@ -583,7 +584,7 @@ MAYBE_UNUSED static struct cursor_buffer *cursor_buffer_new(struct drmdev *drmde
583
584
int ok ;
584
585
585
586
DEBUG_ASSERT_NOT_NULL (drmdev );
586
- DEBUG_ASSERT (rotation == 0 || rotation == 1 || rotation == 2 || rotation == 3 );
587
+ DEBUG_ASSERT (PLANE_TRANSFORM_IS_ONLY_ROTATION ( rotation ) );
587
588
588
589
if (!drmdev_supports_dumb_buffers (drmdev )) {
589
590
LOG_ERROR ("KMS doesn't support dumb buffers. Can't upload mouse cursor icon.\n" );
@@ -621,24 +622,25 @@ MAYBE_UNUSED static struct cursor_buffer *cursor_buffer_new(struct drmdev *drmde
621
622
DEBUG_ASSERT_EQUALS (pixel_size , icon -> width );
622
623
DEBUG_ASSERT_EQUALS (pixel_size , icon -> height );
623
624
624
- if (rotation == 0 ) {
625
+ if (rotation . rotate_0 == 0 ) {
625
626
DEBUG_ASSERT_EQUALS (pixel_size * 4 , pitch );
626
627
memcpy (map_void , icon -> data , buffer_size );
627
628
hot_x = icon -> hot_x ;
628
629
hot_y = icon -> hot_y ;
629
- } else if (( rotation == 1 ) || ( rotation == 2 ) || ( rotation == 3 ) ) {
630
+ } else if (rotation . rotate_90 || rotation . rotate_180 || rotation . rotate_270 ) {
630
631
uint32_t * map_uint32 = (uint32_t * ) map_void ;
631
632
632
633
for (int y = 0 ; y < pixel_size ; y ++ ) {
633
634
for (int x = 0 ; x < pixel_size ; x ++ ) {
634
635
int buffer_x , buffer_y ;
635
- if (rotation == 1 ) {
636
+ if (rotation . rotate_90 ) {
636
637
buffer_x = pixel_size - y - 1 ;
637
638
buffer_y = x ;
638
- } else if (rotation == 2 ) {
639
+ } else if (rotation . rotate_180 ) {
639
640
buffer_x = pixel_size - y - 1 ;
640
641
buffer_y = pixel_size - x - 1 ;
641
642
} else {
643
+ DEBUG_ASSERT (rotation .rotate_270 );
642
644
buffer_x = y ;
643
645
buffer_y = pixel_size - x - 1 ;
644
646
}
@@ -650,14 +652,14 @@ MAYBE_UNUSED static struct cursor_buffer *cursor_buffer_new(struct drmdev *drmde
650
652
}
651
653
}
652
654
653
- if (rotation == 1 ) {
655
+ if (rotation . rotate_90 ) {
654
656
hot_x = pixel_size - icon -> hot_y - 1 ;
655
657
hot_y = icon -> hot_x ;
656
- } else if (rotation == 2 ) {
658
+ } else if (rotation . rotate_180 ) {
657
659
hot_x = pixel_size - icon -> hot_x - 1 ;
658
660
hot_y = pixel_size - icon -> hot_y - 1 ;
659
661
} else {
660
- DEBUG_ASSERT (rotation == 3 );
662
+ DEBUG_ASSERT (rotation . rotate_270 );
661
663
hot_x = icon -> hot_y ;
662
664
hot_y = pixel_size - icon -> hot_x - 1 ;
663
665
}
@@ -863,6 +865,9 @@ static int kms_window_push_composition(struct window *window, struct fl_layer_co
863
865
static struct render_surface * kms_window_get_render_surface (struct window * window , struct vec2i size );
864
866
static EGLSurface kms_window_get_egl_surface (struct window * window );
865
867
static void kms_window_deinit (struct window * window );
868
+ static int kms_window_enable_cursor_locked (struct window * window , struct vec2i pos );
869
+ static int kms_window_disable_cursor_locked (struct window * window );
870
+ static int kms_window_move_cursor_locked (struct window * window , struct vec2i pos );
866
871
867
872
ATTR_MALLOC struct window * kms_window_new (
868
873
// clang-format off
@@ -970,6 +975,7 @@ ATTR_MALLOC struct window *kms_window_new(
970
975
window -> kms .crtc = selected_crtc ;
971
976
window -> kms .mode = selected_mode ;
972
977
window -> kms .should_apply_mode = true;
978
+ window -> kms .cursor = NULL ;
973
979
window -> renderer_type = renderer_type ;
974
980
window -> gl_renderer = gl_renderer != NULL ? gl_renderer_ref (gl_renderer ) : NULL ;
975
981
if (vk_renderer != NULL ) {
@@ -985,6 +991,9 @@ ATTR_MALLOC struct window *kms_window_new(
985
991
window -> get_render_surface = kms_window_get_render_surface ;
986
992
window -> get_egl_surface = kms_window_get_egl_surface ;
987
993
window -> deinit = kms_window_deinit ;
994
+ window -> enable_cursor_locked = kms_window_enable_cursor_locked ;
995
+ window -> disable_cursor_locked = kms_window_disable_cursor_locked ;
996
+ window -> move_cursor_locked = kms_window_move_cursor_locked ;
988
997
return window ;
989
998
990
999
@@ -1108,7 +1117,6 @@ static int kms_window_push_composition(struct window *window, struct fl_layer_co
1108
1117
window_lock (window );
1109
1118
1110
1119
/// TODO: If we don't have new revisions, we don't need to scanout anything.
1111
-
1112
1120
fl_layer_composition_swap_ptrs (& window -> composition , composition );
1113
1121
1114
1122
builder = drmdev_create_request_builder (window -> kms .drmdev , window -> kms .crtc -> id );
@@ -1142,6 +1150,40 @@ static int kms_window_push_composition(struct window *window, struct fl_layer_co
1142
1150
}
1143
1151
}
1144
1152
1153
+ // add cursor infos
1154
+ if (window -> kms .cursor != NULL ) {
1155
+ ok = kms_req_builder_push_fb_layer (
1156
+ builder ,
1157
+ & (const struct kms_fb_layer ) {
1158
+ .drm_fb_id = window -> kms .cursor -> drm_fb_id ,
1159
+ .format = window -> kms .cursor -> format ,
1160
+ .has_modifier = true,
1161
+ .modifier = DRM_FORMAT_MOD_LINEAR ,
1162
+ .src_x = 0 ,
1163
+ .src_y = 0 ,
1164
+ .src_w = ((uint16_t ) window -> kms .cursor -> width ) << 16 ,
1165
+ .src_h = ((uint16_t ) window -> kms .cursor -> height ) << 16 ,
1166
+ .dst_x = window -> cursor_pos .x - window -> kms .cursor -> hot_x ,
1167
+ .dst_y = window -> cursor_pos .y - window -> kms .cursor -> hot_y ,
1168
+ .dst_w = window -> kms .cursor -> width ,
1169
+ .dst_h = window -> kms .cursor -> height ,
1170
+ .has_rotation = false,
1171
+ .rotation = PLANE_TRANSFORM_NONE ,
1172
+ .has_in_fence_fd = false,
1173
+ .in_fence_fd = 0 ,
1174
+ .prefer_cursor = true,
1175
+ },
1176
+ cursor_buffer_unref_void ,
1177
+ NULL ,
1178
+ window -> kms .cursor
1179
+ );
1180
+ if (ok != 0 ) {
1181
+ LOG_ERROR ("Couldn't present cursor.\n" );
1182
+ } else {
1183
+ cursor_buffer_ref (window -> kms .cursor );
1184
+ }
1185
+ }
1186
+
1145
1187
req = kms_req_builder_build (builder );
1146
1188
if (req == NULL ) {
1147
1189
goto fail_unref_builder ;
@@ -1353,3 +1395,32 @@ static EGLSurface kms_window_get_egl_surface(struct window *window) {
1353
1395
return EGL_NO_SURFACE ;
1354
1396
}
1355
1397
}
1398
+
1399
+ static int kms_window_enable_cursor_locked (struct window * window , struct vec2i pos ) {
1400
+ struct cursor_buffer * cursor ;
1401
+
1402
+ DEBUG_ASSERT_EQUALS (window -> kms .cursor , NULL );
1403
+
1404
+ cursor = cursor_buffer_new (window -> kms .drmdev , cursor_size_from_pixel_ratio (window -> pixel_ratio ), window -> rotation );
1405
+ if (cursor == NULL ) {
1406
+ return EIO ;
1407
+ }
1408
+
1409
+ window -> cursor_pos = pos ;
1410
+
1411
+ window -> kms .cursor = cursor ;
1412
+ return 0 ;
1413
+ }
1414
+
1415
+ static int kms_window_disable_cursor_locked (struct window * window ) {
1416
+ cursor_buffer_unrefp (& window -> kms .cursor );
1417
+ return 0 ;
1418
+ }
1419
+
1420
+ static int kms_window_move_cursor_locked (struct window * window , struct vec2i pos ) {
1421
+ window -> cursor_pos = pos ;
1422
+
1423
+ /// TODO: Draw a new frame or redraw the last frame with new cursor pos here.
1424
+
1425
+ return 0 ;
1426
+ }
0 commit comments