Skip to content

Commit 0a4cc19

Browse files
committed
reimplement kms window cursor
1 parent 2286019 commit 0a4cc19

File tree

1 file changed

+94
-23
lines changed

1 file changed

+94
-23
lines changed

src/window.c

Lines changed: 94 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,7 @@ struct window {
156156
drmModeModeInfo *mode;
157157

158158
bool should_apply_mode;
159+
struct cursor_buffer *cursor;
159160
} kms;
160161

161162
/**
@@ -209,9 +210,9 @@ struct window {
209210
int (*push_composition)(struct window *window, struct fl_layer_composition *composition);
210211
struct render_surface *(*get_render_surface)(struct window *window, struct vec2i size);
211212
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);
215216
void (*deinit)(struct window *window);
216217
};
217218

@@ -389,9 +390,9 @@ static int window_init(
389390
window->push_composition = NULL;
390391
window->get_render_surface = NULL;
391392
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;
395396
window->deinit = window_deinit;
396397
return 0;
397398
}
@@ -493,20 +494,20 @@ int window_set_cursor(
493494
if (has_enabled) {
494495
if (enabled && !window->cursor_enabled) {
495496
// 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);
498499
} else if (!enabled && window->cursor_enabled) {
499500
// 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);
502503
}
503504
}
504505

505506
if (has_pos) {
506507
if (window->cursor_enabled) {
507508
// 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);
510511
} else {
511512
// !enabled && !window->cursor_enabled
512513
// move cursor while cursor is disabled
@@ -540,7 +541,7 @@ struct cursor_buffer {
540541
enum pixfmt format;
541542
int width, height;
542543
enum cursor_size size;
543-
int rotation;
544+
drm_plane_transform_t rotation;
544545

545546
int hot_x, hot_y;
546547
};
@@ -572,7 +573,7 @@ MAYBE_UNUSED static enum cursor_size cursor_size_from_pixel_ratio(double device_
572573
return size;
573574
}
574575

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) {
576577
const struct cursor_icon *icon;
577578
struct cursor_buffer *b;
578579
uint32_t gem_handle, pitch;
@@ -583,7 +584,7 @@ MAYBE_UNUSED static struct cursor_buffer *cursor_buffer_new(struct drmdev *drmde
583584
int ok;
584585

585586
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));
587588

588589
if (!drmdev_supports_dumb_buffers(drmdev)) {
589590
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
621622
DEBUG_ASSERT_EQUALS(pixel_size, icon->width);
622623
DEBUG_ASSERT_EQUALS(pixel_size, icon->height);
623624

624-
if (rotation == 0) {
625+
if (rotation.rotate_0 == 0) {
625626
DEBUG_ASSERT_EQUALS(pixel_size * 4, pitch);
626627
memcpy(map_void, icon->data, buffer_size);
627628
hot_x = icon->hot_x;
628629
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) {
630631
uint32_t *map_uint32 = (uint32_t*) map_void;
631632

632633
for (int y = 0; y < pixel_size; y++) {
633634
for (int x = 0; x < pixel_size; x++) {
634635
int buffer_x, buffer_y;
635-
if (rotation == 1) {
636+
if (rotation.rotate_90) {
636637
buffer_x = pixel_size - y - 1;
637638
buffer_y = x;
638-
} else if (rotation == 2) {
639+
} else if (rotation.rotate_180) {
639640
buffer_x = pixel_size - y - 1;
640641
buffer_y = pixel_size - x - 1;
641642
} else {
643+
DEBUG_ASSERT(rotation.rotate_270);
642644
buffer_x = y;
643645
buffer_y = pixel_size - x - 1;
644646
}
@@ -650,14 +652,14 @@ MAYBE_UNUSED static struct cursor_buffer *cursor_buffer_new(struct drmdev *drmde
650652
}
651653
}
652654

653-
if (rotation == 1) {
655+
if (rotation.rotate_90) {
654656
hot_x = pixel_size - icon->hot_y - 1;
655657
hot_y = icon->hot_x;
656-
} else if (rotation == 2) {
658+
} else if (rotation.rotate_180) {
657659
hot_x = pixel_size - icon->hot_x - 1;
658660
hot_y = pixel_size - icon->hot_y - 1;
659661
} else {
660-
DEBUG_ASSERT(rotation == 3);
662+
DEBUG_ASSERT(rotation.rotate_270);
661663
hot_x = icon->hot_y;
662664
hot_y = pixel_size - icon->hot_x - 1;
663665
}
@@ -863,6 +865,9 @@ static int kms_window_push_composition(struct window *window, struct fl_layer_co
863865
static struct render_surface *kms_window_get_render_surface(struct window *window, struct vec2i size);
864866
static EGLSurface kms_window_get_egl_surface(struct window *window);
865867
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);
866871

867872
ATTR_MALLOC struct window *kms_window_new(
868873
// clang-format off
@@ -970,6 +975,7 @@ ATTR_MALLOC struct window *kms_window_new(
970975
window->kms.crtc = selected_crtc;
971976
window->kms.mode = selected_mode;
972977
window->kms.should_apply_mode = true;
978+
window->kms.cursor = NULL;
973979
window->renderer_type = renderer_type;
974980
window->gl_renderer = gl_renderer != NULL ? gl_renderer_ref(gl_renderer) : NULL;
975981
if (vk_renderer != NULL) {
@@ -985,6 +991,9 @@ ATTR_MALLOC struct window *kms_window_new(
985991
window->get_render_surface = kms_window_get_render_surface;
986992
window->get_egl_surface = kms_window_get_egl_surface;
987993
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;
988997
return window;
989998

990999

@@ -1108,7 +1117,6 @@ static int kms_window_push_composition(struct window *window, struct fl_layer_co
11081117
window_lock(window);
11091118

11101119
/// TODO: If we don't have new revisions, we don't need to scanout anything.
1111-
11121120
fl_layer_composition_swap_ptrs(&window->composition, composition);
11131121

11141122
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
11421150
}
11431151
}
11441152

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+
11451187
req = kms_req_builder_build(builder);
11461188
if (req == NULL) {
11471189
goto fail_unref_builder;
@@ -1353,3 +1395,32 @@ static EGLSurface kms_window_get_egl_surface(struct window *window) {
13531395
return EGL_NO_SURFACE;
13541396
}
13551397
}
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

Comments
 (0)