using dirty bits for poll-based frame events

This commit is contained in:
Rakarake 2026-01-22 23:40:06 +01:00
parent 33ceed2d22
commit 3311810666
3 changed files with 94 additions and 9 deletions

View file

@ -60,9 +60,9 @@ int main(int argc, char *argv[]) {
while (running) { while (running) {
double time = time_since_start(); double time = time_since_start();
struct event event; struct event event = wait_for_event(&state);
wait_for_event(&state, &event);
if (event.type == EVENT_DRAW) { if (event.type == EVENT_DRAW) {
printf("drawing!!!!\n");
int width = event.data.draw.width; int width = event.data.draw.width;
int height = event.data.draw.height; int height = event.data.draw.height;
render(&renderer, width, height, time, shader_path, 0); render(&renderer, width, height, time, shader_path, 0);

View file

@ -1,6 +1,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include "wayland.h" #include "wayland.h"
/// Starting values. /// Starting values.
@ -47,6 +48,7 @@ static void xdg_toplevel_configure (
while (next->data.xdg_toplevel != xdg_toplevel) { next = next->next; } while (next->data.xdg_toplevel != xdg_toplevel) { next = next->next; }
next->data.width = width; next->data.width = width;
next->data.height = height; next->data.height = height;
printf("🧟🧟🧟\n");
wl_egl_window_resize(next->data.egl_window, width, height, 0, 0); wl_egl_window_resize(next->data.egl_window, width, height, 0, 0);
} }
@ -76,6 +78,7 @@ static void zwlr_layer_surface_v1_configure(void *data, struct zwlr_layer_surfac
next->data.height = height; next->data.height = height;
wl_egl_window_resize(next->data.egl_window, width, height, 0, 0); wl_egl_window_resize(next->data.egl_window, width, height, 0, 0);
zwlr_layer_surface_v1_ack_configure(zwlr_layer_surface_v1, serial); zwlr_layer_surface_v1_ack_configure(zwlr_layer_surface_v1, serial);
printf("🐍🐍🐍🐍\n");
} }
static void zwlr_layer_surface_v1_closed(void *data, struct zwlr_layer_surface_v1 * zwlr_layer_surface_v1) { static void zwlr_layer_surface_v1_closed(void *data, struct zwlr_layer_surface_v1 * zwlr_layer_surface_v1) {
@ -88,6 +91,43 @@ static const struct zwlr_layer_surface_v1_listener zwlr_layer_surface_v1_listene
.closed = zwlr_layer_surface_v1_closed, .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) {
printf("FRAME CALLBACK 🐷🐷\n");
/* Destroy this callback */
wl_callback_destroy(cb);
struct surface *surface = data;
surface->dirty = true;
//struct client_state *state = surface->state;
/* Request another frame */
// TODO make sure this is done after the frame has been handled.
//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( static void registry_handle_global(
void *data, void *data,
struct wl_registry *registry, struct wl_registry *registry,
@ -126,10 +166,17 @@ static void registry_handle_global(
.wl_surface = wl_surface, .wl_surface = wl_surface,
.xdg_surface = xdg_surface, .xdg_surface = xdg_surface,
.xdg_toplevel = xdg_toplevel, .xdg_toplevel = xdg_toplevel,
.dirty = false,
.width = DEFAULT_WIDTH,
.height = DEFAULT_HEIGHT,
}; };
state->surface_list = malloc(sizeof(struct surface_list)); state->surface_list = malloc(sizeof(struct surface_list));
state->surface_list->data = surface; state->surface_list->data = surface;
state->surface_list->next = NULL; state->surface_list->next = NULL;
// frame callback
struct wl_callback *cb = wl_surface_frame(wl_surface);
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)) { 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); state->zwlr_layer_shell_v1 = wl_registry_bind(registry, name, &zwlr_layer_shell_v1_interface, 4);
@ -159,18 +206,29 @@ static void registry_handle_global(
struct surface surface = { struct surface surface = {
.wl_surface = wl_surface, .wl_surface = wl_surface,
.zwlr_layer_surface_v1 = zwlr_layer_surface_v1, .zwlr_layer_surface_v1 = zwlr_layer_surface_v1,
.dirty = false,
.width = DEFAULT_WIDTH,
.height = DEFAULT_HEIGHT,
}; };
// persistent pointer for the callback
struct surface *surface_location;
if (state->surface_list == NULL) { if (state->surface_list == NULL) {
state->surface_list = malloc(sizeof(struct surface_list)); state->surface_list = malloc(sizeof(struct surface_list));
state->surface_list->data = surface; state->surface_list->data = surface;
state->surface_list->next = NULL; state->surface_list->next = NULL;
surface_location = &state->surface_list->data;
} else { } else {
struct surface_list *next = state->surface_list; struct surface_list *next = state->surface_list;
while (next->next != NULL) { next = next->next; } while (next->next != NULL) { next = next->next; }
next->next = malloc(sizeof(struct surface_list)); next->next = malloc(sizeof(struct surface_list));
next->next->data = surface; next->next->data = surface;
next->next->next = NULL; next->next->next = NULL;
surface_location = &next->next->data;
} }
// frame callback
struct wl_callback *cb = wl_surface_frame(wl_surface);
wl_callback_add_listener(cb, &wl_surface_frame_listener, surface_location);
} }
} }
@ -253,6 +311,7 @@ static void egl_init(struct client_state *state) {
// EGL window // EGL window
struct surface_list *next = state->surface_list; struct surface_list *next = state->surface_list;
while (next != NULL) { while (next != NULL) {
printf("Creating egl window of size: %dx%d\n", next->data.width, next->data.height);
next->data.egl_window = wl_egl_window_create(next->data.wl_surface, next->data.egl_window = wl_egl_window_create(next->data.wl_surface,
next->data.width, next->data.height); next->data.width, next->data.height);
if (next->data.egl_window == EGL_NO_SURFACE) { if (next->data.egl_window == EGL_NO_SURFACE) {
@ -295,9 +354,6 @@ void wayland_init(struct client_state *state, int output_type) {
} }
egl_init(state); egl_init(state);
// TODO fix frame callbacks for all surfaces
} }
/// Swaps front/backbuffers and dispatches pending wayland commands. /// Swaps front/backbuffers and dispatches pending wayland commands.
@ -320,7 +376,29 @@ void commit(struct client_state *state) {
} }
} }
void wait_for_event(struct client_state *state, struct event event) { struct event wait_for_event(struct client_state *state) {
for (;;) {
// before dispatch: check that there is nothing elese to do
// check for dirty surface
struct surface_list *next = state->surface_list;
printf("listtttt\n");
while (next != NULL) {
if (next->data.dirty) {
printf("dirty\n");
struct event event = {
.type = EVENT_DRAW,
.data = {
.draw = {
.width = next->data.width,
.height = next->data.height,
}
}
};
return event;
}
next = next->next;
}
wl_display_dispatch(state->wl_display); wl_display_dispatch(state->wl_display);
}
} }

View file

@ -8,9 +8,15 @@
/// A desktop layer (wallpaper) /// A desktop layer (wallpaper)
#define OUTPUT_LAYER 1 #define OUTPUT_LAYER 1
#define DEFAULT_WIDTH 400
#define DEFAULT_HEIGHT 400
struct surface { struct surface {
int width, height; int width, height;
/// Wating to be redrawn.
bool dirty;
struct wl_surface *wl_surface; struct wl_surface *wl_surface;
struct xdg_surface *xdg_surface; struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel; struct xdg_toplevel *xdg_toplevel;
@ -43,7 +49,8 @@ struct client_state {
EGLContext egl_context; EGLContext egl_context;
}; };
#define EVENT_DRAW 0 #define EVENT_NONE 0
#define EVENT_DRAW 1
struct event { struct event {
int type; int type;
@ -58,5 +65,5 @@ struct event {
void wayland_init(struct client_state *state, int output_type); void wayland_init(struct client_state *state, int output_type);
void commit(struct client_state *state); void commit(struct client_state *state);
/// Provide pointer to be filled. /// Provide pointer to be filled.
void wait_for_event(struct client_state *state, struct event event); struct event wait_for_event(struct client_state *state);