WIP callbacks or something

This commit is contained in:
Rakarake 2026-01-19 01:35:40 +01:00
parent 33ceed2d22
commit ea0b2eb591
3 changed files with 66 additions and 12 deletions

View file

@ -26,6 +26,10 @@ double time_since_start() {
(now.tv_nsec - program_start.tv_nsec) / 1e9; (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[]) { int main(int argc, char *argv[]) {
char *shader_path = NULL; char *shader_path = NULL;
int output_type = OUTPUT_WINDOW; int output_type = OUTPUT_WINDOW;
@ -52,6 +56,7 @@ int main(int argc, char *argv[]) {
} }
struct client_state state; struct client_state state;
state.render_func = invoke_render;
wayland_init(&state, output_type); wayland_init(&state, output_type);
Renderer renderer = new_renderer(); Renderer renderer = new_renderer();
@ -62,11 +67,11 @@ int main(int argc, char *argv[]) {
struct event event; struct event event;
wait_for_event(&state, &event); wait_for_event(&state, &event);
if (event.type == EVENT_DRAW) { //if (event.type == EVENT_DRAW) {
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);
} //}
} }
//while (state.running) { //while (state.running) {
// double time = time_since_start(); // double time = time_since_start();

View file

@ -88,6 +88,40 @@ 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) {
/* 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( static void registry_handle_global(
void *data, void *data,
struct wl_registry *registry, struct wl_registry *registry,
@ -122,14 +156,19 @@ static void registry_handle_global(
xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, state); xdg_toplevel_add_listener(xdg_toplevel, &xdg_toplevel_listener, state);
// save all the pointers // save all the pointers
struct surface surface = { struct surface stack_surface = {
.wl_surface = wl_surface, .wl_surface = wl_surface,
.xdg_surface = xdg_surface, .xdg_surface = xdg_surface,
.xdg_toplevel = xdg_toplevel, .xdg_toplevel = xdg_toplevel,
}; };
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 = stack_surface;
state->surface_list->next = NULL; 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)) { 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);
@ -160,17 +199,24 @@ static void registry_handle_global(
.wl_surface = wl_surface, .wl_surface = wl_surface,
.zwlr_layer_surface_v1 = zwlr_layer_surface_v1, .zwlr_layer_surface_v1 = zwlr_layer_surface_v1,
}; };
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;
} }
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); 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 +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); wl_display_dispatch(state->wl_display);
} }

View file

@ -19,6 +19,9 @@ struct surface {
struct wl_output *wl_output; struct wl_output *wl_output;
EGLSurface egl_surface; EGLSurface egl_surface;
// notice, surface does not own `state`, this is a backlink.
struct client_state *state;
}; };
struct surface_list { struct surface_list {
@ -41,6 +44,9 @@ struct client_state {
EGLDisplay egl_display; EGLDisplay egl_display;
EGLConfig egl_config; EGLConfig egl_config;
EGLContext egl_context; EGLContext egl_context;
/// Provide this from caller.
void(*render_func)(void *data, int width, int height, double time);
}; };
#define EVENT_DRAW 0 #define EVENT_DRAW 0
@ -58,5 +64,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); void wait_for_event(struct client_state *state, struct event *event);