From ea0b2eb5914a2b059adb91e1224bb47e6341d719 Mon Sep 17 00:00:00 2001 From: Rakarake Date: Mon, 19 Jan 2026 01:35:40 +0100 Subject: [PATCH] WIP callbacks or something --- glonkers.c | 15 ++++++++++----- wayland.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++------ wayland.h | 8 +++++++- 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/glonkers.c b/glonkers.c index f45ebba..9516771 100644 --- a/glonkers.c +++ b/glonkers.c @@ -26,6 +26,10 @@ double time_since_start() { (now.tv_nsec - program_start.tv_nsec) / 1e9; } +void invoke_render(void *data, int width, int height, double time) { + render(Renderer *renderer, int w, int h, double time, char *shader_path, int reload_shader) +} + int main(int argc, char *argv[]) { char *shader_path = NULL; int output_type = OUTPUT_WINDOW; @@ -52,6 +56,7 @@ int main(int argc, char *argv[]) { } struct client_state state; + state.render_func = invoke_render; wayland_init(&state, output_type); Renderer renderer = new_renderer(); @@ -62,11 +67,11 @@ int main(int argc, char *argv[]) { struct event event; wait_for_event(&state, &event); - if (event.type == EVENT_DRAW) { - int width = event.data.draw.width; - int height = event.data.draw.height; - render(&renderer, width, height, time, shader_path, 0); - } + //if (event.type == EVENT_DRAW) { + // int width = event.data.draw.width; + // int height = event.data.draw.height; + // render(&renderer, width, height, time, shader_path, 0); + //} } //while (state.running) { // double time = time_since_start(); diff --git a/wayland.c b/wayland.c index 0bb46aa..6f5939d 100644 --- a/wayland.c +++ b/wayland.c @@ -88,6 +88,40 @@ static const struct zwlr_layer_surface_v1_listener zwlr_layer_surface_v1_listene .closed = zwlr_layer_surface_v1_closed, }; +static const struct wl_callback_listener wl_surface_frame_listener; + +static void +wl_surface_frame_done(void *data, struct wl_callback *cb, uint32_t time) { + /* Destroy this callback */ + wl_callback_destroy(cb); + + struct surface *surface = data; + struct client_state *state = surface->state; + + /* Request another frame */ + // TODO, maybe skip this to avoid unecessary frames + cb = wl_surface_frame(surface->wl_surface); + wl_callback_add_listener(cb, &wl_surface_frame_listener, surface); + + ///* Update scroll amount at 24 pixels per second */ + //if (state->last_frame != 0) { + // int elapsed = time - state->last_frame; + // state->offset += elapsed / 1000.0 * 24; + //} + + ///* Submit a frame for this event */ + //struct wl_buffer *buffer = draw_frame(state); + //wl_surface_attach(state->wl_surface, buffer, 0, 0); + //wl_surface_damage_buffer(state->wl_surface, 0, 0, INT32_MAX, INT32_MAX); + //wl_surface_commit(state->wl_surface); + + //state->last_frame = time; +} + +static const struct wl_callback_listener wl_surface_frame_listener = { + .done = wl_surface_frame_done, +}; + static void registry_handle_global( void *data, struct wl_registry *registry, @@ -122,14 +156,19 @@ static void registry_handle_global( xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, state); // save all the pointers - struct surface surface = { + struct surface stack_surface = { .wl_surface = wl_surface, .xdg_surface = xdg_surface, .xdg_toplevel = xdg_toplevel, }; state->surface_list = malloc(sizeof(struct surface_list)); - state->surface_list->data = surface; + state->surface_list->data = stack_surface; state->surface_list->next = NULL; + + // frame callback + struct wl_callback *cb = wl_surface_frame(wl_surface); + state->surface_list->data.state = state; + wl_callback_add_listener(cb, &wl_surface_frame_listener, &state->surface_list->data); } if ((strcmp(interface, zwlr_layer_shell_v1_interface.name) == 0) && (state->output_type == OUTPUT_LAYER)) { state->zwlr_layer_shell_v1 = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 4); @@ -160,17 +199,24 @@ static void registry_handle_global( .wl_surface = wl_surface, .zwlr_layer_surface_v1 = zwlr_layer_surface_v1, }; + struct surface *surface_location; if (state->surface_list == NULL) { state->surface_list = malloc(sizeof(struct surface_list)); state->surface_list->data = surface; state->surface_list->next = NULL; + surface_location = &state->surface_list->data; } else { struct surface_list *next = state->surface_list; while (next->next != NULL) { next = next->next; } next->next = malloc(sizeof(struct surface_list)); next->next->data = surface; next->next->next = NULL; + surface_location = &next->next->data; } + + struct wl_callback *cb = wl_surface_frame(wl_surface); + state->surface_list->data.state = state; + wl_callback_add_listener(cb, &wl_surface_frame_listener, surface_location); } } @@ -295,9 +341,6 @@ void wayland_init(struct client_state *state, int output_type) { } egl_init(state); - - // TODO fix frame callbacks for all surfaces - } /// Swaps front/backbuffers and dispatches pending wayland commands. @@ -320,7 +363,7 @@ void commit(struct client_state *state) { } } -void wait_for_event(struct client_state *state, struct event event) { +void wait_for_event(struct client_state *state, struct event *event) { wl_display_dispatch(state->wl_display); } diff --git a/wayland.h b/wayland.h index d423984..05cb93d 100644 --- a/wayland.h +++ b/wayland.h @@ -19,6 +19,9 @@ struct surface { struct wl_output *wl_output; EGLSurface egl_surface; + + // notice, surface does not own `state`, this is a backlink. + struct client_state *state; }; struct surface_list { @@ -41,6 +44,9 @@ struct client_state { EGLDisplay egl_display; EGLConfig egl_config; EGLContext egl_context; + + /// Provide this from caller. + void(*render_func)(void *data, int width, int height, double time); }; #define EVENT_DRAW 0 @@ -58,5 +64,5 @@ struct event { void wayland_init(struct client_state *state, int output_type); void commit(struct client_state *state); /// Provide pointer to be filled. -void wait_for_event(struct client_state *state, struct event event); +void wait_for_event(struct client_state *state, struct event *event);