From df43752fa74754c7550d5a3b02d1e0c825955f35 Mon Sep 17 00:00:00 2001 From: IoIxD Date: Mon, 8 Dec 2025 15:28:20 -0700 Subject: [PATCH] wayland: properly pump the events system, only drawing when necessary --- include/Mw/LowLevel/Wayland.h | 14 +++- src/backend/wayland.c | 131 +++++++++++++++++++++++----------- 2 files changed, 100 insertions(+), 45 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index ed40bfe..de63469 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -76,18 +76,25 @@ struct _MwLLWayland { struct wl_surface* surface; struct wl_shm* shm; struct wl_registry_listener registry_listener; + struct wl_event_queue* event_queue; struct wl_pointer* pointer; MwLL* subwidgets; - MwBool configured; - MwBool force_redraw; + MwBool configured; + MwBool force_redraw; + MwBool egl_setup; - MwBool egl_do_resetup; + MwBool has_set_xy; MwU32 x, y, ww, wh; MwPoint cur_mouse_pos; + struct timeval timer; + + MwU64 cooldown_timer; + MwU64 cooldown_timer_epoch; + MwLL parent; GLuint fbo; @@ -107,6 +114,7 @@ struct _MwLLWaylandColor { struct _MwLLWaylandPixmap { struct _MwLLCommonPixmap common; GLuint texture; + MwBool texture_deleted; }; #endif diff --git a/src/backend/wayland.c b/src/backend/wayland.c index 6f34ab8..d461c5c 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -26,6 +26,8 @@ void (*focus_out)(MwLL handle, void* data); */ +static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer); + #define WAYLAND_GET_INTERFACE(r, inter) shget(r.wl_protocol_map, inter##_interface.name) static void new_protocol(void* data, struct wl_registry* registry, @@ -48,12 +50,12 @@ static void protocol_removed(void* data, }; -static void pointer_enter(void* data, struct wl_pointer* wl_pointer, uint32_t serial, +static void pointer_enter(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {}; -static void pointer_leave(void* data, struct wl_pointer* wl_pointer, uint32_t serial, +static void pointer_leave(void* data, struct wl_pointer* wl_pointer, MwU32 serial, struct wl_surface* surface) {}; -static void pointer_motion(void* data, struct wl_pointer* wl_pointer, uint32_t time, +static void pointer_motion(void* data, struct wl_pointer* wl_pointer, MwU32 time, wl_fixed_t surface_x, wl_fixed_t surface_y) { MwLL self = data; MwLLMouse p; @@ -62,8 +64,10 @@ static void pointer_motion(void* data, struct wl_pointer* wl_pointer, uint32_t t self->wayland.cur_mouse_pos.y = wl_fixed_to_double(surface_y); p.point = self->wayland.cur_mouse_pos; MwLLDispatch(self, move, &p); + + timed_redraw(self, time, 50, &self->wayland.cooldown_timer); }; -static void pointer_button(void* data, struct wl_pointer* wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { +static void pointer_button(void* data, struct wl_pointer* wl_pointer, MwU32 serial, MwU32 time, MwU32 button, MwU32 state) { MwLL self = data; MwLLMouse p; p.point = self->wayland.cur_mouse_pos; @@ -88,9 +92,11 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, uint32_t s break; } } + + timed_redraw(self, time, 50, &self->wayland.cooldown_timer); }; -static void pointer_axis(void* data, struct wl_pointer* wl_pointer, uint32_t time, - uint32_t axis, wl_fixed_t value) {}; +static void pointer_axis(void* data, struct wl_pointer* wl_pointer, MwU32 time, + MwU32 axis, wl_fixed_t value) {}; struct wl_pointer_listener pointer_listener = { .enter = pointer_enter, @@ -112,7 +118,6 @@ static void wl_seat_capabilities(void* data, struct wl_seat* wl_seat, if(capabilities & WL_SEAT_CAPABILITY_POINTER && !self->wayland.pointer) { self->wayland.pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(self->wayland.pointer, &pointer_listener, data); - return; } }; @@ -258,9 +263,14 @@ static MwBool egl_setup(MwLL self, int width, int height) { return MwFALSE; } - if(!eglMakeCurrent(display, surface, surface, context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - return MwFALSE; + self->wayland.egl_display = display; + self->wayland.egl_surface = surface; + self->wayland.egl_context = context; + + if(self->wayland.parent == NULL) { + if(!eglMakeCurrent(self->wayland.egl_display, self->wayland.egl_surface, self->wayland.egl_surface, self->wayland.egl_context)) { + printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + } } glMatrixMode(GL_PROJECTION); @@ -270,26 +280,21 @@ static MwBool egl_setup(MwLL self, int width, int height) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_BLEND); - self->wayland.egl_display = display; - self->wayland.egl_surface = surface; - self->wayland.egl_context = context; return MwTRUE; } static void egl_resetup(MwLL handle) { int err; - if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { - printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); - return; - } + // if(!eglMakeCurrent(handle->wayland.egl_display, handle->wayland.egl_surface, handle->wayland.egl_surface, handle->wayland.egl_context)) { + // printf("ERROR: eglMakeCurrent, %0X\n", eglGetError()); + // return; + // } glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, handle->wayland.ww, handle->wayland.wh, 0, -1, 1); glViewport(0, 0, handle->wayland.ww, handle->wayland.wh); - - handle->wayland.egl_do_resetup = MwFALSE; } static void recursive_draw(MwLL handle) { @@ -302,16 +307,25 @@ static void recursive_draw(MwLL handle) { } } -static void recursive_resize(MwLL handle) { - int i; - if(handle->wayland.subwidgets != NULL) { - for(i = 0; i < arrlen(handle->wayland.subwidgets); i++) { - MwLLDispatch(handle->wayland.subwidgets[i], resize, NULL); - recursive_resize(handle->wayland.subwidgets[i]); +static void timed_redraw(MwLL handle, MwU32 time, int cooldown, MwU64* cooldown_timer) { + if(handle->wayland.parent == NULL) { + if(time >= (*cooldown_timer + cooldown)) { + egl_resetup(handle); + MwLLDispatch(handle, draw, NULL); + // recursive_draw(handle); + *cooldown_timer = time; } } } +static void timed_redraw_by_epoch(MwLL handle, int cooldown) { + gettimeofday(&handle->wayland.timer, NULL); + unsigned long long time = + (unsigned long long)(handle->wayland.timer.tv_sec) * 1000 + + (unsigned long long)(handle->wayland.timer.tv_usec) / 1000; + timed_redraw(handle, time, cooldown, &handle->wayland.cooldown_timer_epoch); +} + static void xdg_toplevel_configure(void* data, struct xdg_toplevel* xdg_toplevel, MwI32 width, MwI32 height, @@ -326,20 +340,17 @@ static void xdg_toplevel_configure(void* data, return; } } + self->wayland.ww = width; self->wayland.wh = height; xdg_surface_set_window_geometry(self->wayland.toplevel->xdg_surface, 0, 0, self->wayland.ww, self->wayland.wh); - MwLLSetWH(self, width, height); MwLLDispatch(self, resize, NULL); - recursive_resize(self); if(!self->wayland.egl_setup) { self->wayland.egl_setup = egl_setup(self, width, height); - MwLLForceRender(self); } else { wl_egl_window_resize(self->wayland.egl_window_native, width, height, 0, 0); - self->wayland.egl_do_resetup = MwTRUE; egl_resetup(self); } @@ -413,9 +424,13 @@ static int event_loop(MwLL handle) { if(wl_display_dispatch_pending(wayland->display) > 0) { } } else { + /* Condition for no events being sent */ if(wl_display_dispatch_pending(wayland->display) == 0) { - MwLLDispatch(handle, draw, NULL); - recursive_draw(handle); + if(wayland->event_queue != NULL) { + if(wl_display_roundtrip_queue(wayland->display, wayland->event_queue) < 0) { + printf("error\n"); + }; + } } } @@ -444,8 +459,7 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { #undef WL_INTERFACE static void setup_toplevel(MwLL r, int x, int y) { - int i; - struct wl_region* region; + int i; r->wayland.type = MWLL_WAYLAND_TOPLEVEL; r->wayland.toplevel = malloc(sizeof(struct _MwLLWaylandTopLevel)); @@ -517,6 +531,10 @@ static void setup_toplevel(MwLL r, int x, int y) { printf("zxdg null\n"); } + r->wayland.event_queue = wl_display_create_queue(r->wayland.display); + + MwLLForceRender(r); + // buffer_setup(&r->wayland); // glGenBuffers(1, &vertex_buffer); @@ -526,8 +544,8 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { struct wl_compositor* compositor = parent->wayland.compositor; struct wl_subcompositor* subcompositor = parent->wayland.subcompositor; struct wl_surface* parent_surface = parent->wayland.surface; - MwLL topmost_parent = parent; struct wl_region* region; + MwLL topmost_parent = parent; while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { topmost_parent = topmost_parent->wayland.parent; @@ -572,7 +590,15 @@ static void setup_sublevel(MwLL parent, MwLL r, int x, int y) { MwLLForceRender(r); }; + r->wayland.event_queue = parent->wayland.event_queue; + arrpush(parent->wayland.subwidgets, r); + + wl_surface_damage(parent->wayland.surface, 0, 0, parent->wayland.ww, parent->wayland.wh); + + egl_resetup(topmost_parent); + MwLLDispatch(topmost_parent, draw, NULL); + recursive_draw(topmost_parent); } static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { @@ -599,6 +625,9 @@ static MwLL MwLLCreateImpl(MwLL parent, int x, int y, int width, int height) { r->wayland.parent = parent; + r->wayland.cooldown_timer = 0; + r->wayland.has_set_xy = MwFALSE; + r->wayland.force_redraw = MwFALSE; r->wayland.subwidgets = NULL; r->wayland.pointer = NULL; @@ -626,10 +655,20 @@ static void MwLLGetXYWHImpl(MwLL handle, int* x, int* y, unsigned int* w, unsign static void MwLLSetXYImpl(MwLL handle, int x, int y) { if(handle->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + MwLL topmost_parent = handle->wayland.parent; + + while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + topmost_parent = topmost_parent->wayland.parent; + } + handle->wayland.x = x; handle->wayland.y = y; - // wl_sublevel_set_position(handle->wayland.sublevel, x, y); - MwLLForceRender(handle); + if(handle->wayland.has_set_xy) { + timed_redraw_by_epoch(topmost_parent, 25); + recursive_draw(topmost_parent); + } else if(x != 0 && y != 0) { + handle->wayland.has_set_xy = MwTRUE; + } } } @@ -646,6 +685,13 @@ static void MwLLSetWHImpl(MwLL handle, int w, int h) { if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { xdg_surface_set_window_geometry(handle->wayland.toplevel->xdg_surface, 0, 0, handle->wayland.ww, handle->wayland.wh); } else { + MwLL topmost_parent = handle->wayland.parent; + + while(topmost_parent->wayland.type != MWLL_WAYLAND_TOPLEVEL) { + topmost_parent = topmost_parent->wayland.parent; + } + timed_redraw_by_epoch(topmost_parent, 25); + recursive_draw(topmost_parent); } } @@ -692,6 +738,8 @@ static void MwLLBeginDrawImpl(MwLL handle) { return; } } + // glClear(GL_COLOR_BUFFER_BIT); + // glClearColor(1.0, 0, 0, 1); } static void MwLLEndDrawImpl(MwLL handle) { @@ -711,8 +759,6 @@ static void MwLLEndDrawImpl(MwLL handle) { // glClear(GL_COLOR_BUFFER_BIT); // glClearColor(1.0, 0, 0, 1); - wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); - if(handle->wayland.parent == NULL) { if(!eglSwapBuffers(handle->wayland.egl_display, handle->wayland.egl_surface)) { printf("error swapping buffers! %0X\n", eglGetError()); @@ -745,7 +791,7 @@ static void MwLLFreeColorImpl(MwLLColor color) { static int MwLLPendingImpl(MwLL handle) { if(wl_display_dispatch_pending(handle->wayland.display) == 0) { } - return event_loop(handle) || handle->wayland.force_redraw; + return event_loop(handle); } static void MwLLNextEventImpl(MwLL handle) { @@ -815,16 +861,17 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { glTexCoord2f(0.0f, 1); glVertex2f(x, y + rect->height); glEnd(); + glFinish(); } - static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { } static void MwLLForceRenderImpl(MwLL handle) { wl_surface_damage(handle->wayland.surface, 0, 0, handle->wayland.ww, handle->wayland.wh); - wl_surface_commit(handle->wayland.surface); - + if(handle->wayland.egl_setup) { + timed_redraw_by_epoch(handle, 25); + } handle->wayland.force_redraw = MwTRUE; }