From 9b1bdf74750fc52bb702d51d76fc6531818d4f93 Mon Sep 17 00:00:00 2001 From: Alexander Orzechowski Date: Wed, 21 Aug 2024 11:12:22 -0400 Subject: [PATCH] examples: Modeset with a buffer This means that for most examples, rendering code had to be extracted so that it could be called during modeset and during a regular refresh. --- examples/cairo-buffer.c | 1 + examples/fullscreen-shell.c | 21 +++++++++------ examples/output-layers.c | 41 ++++++++++++++++------------- examples/output-layout.c | 21 ++++++++------- examples/pointer.c | 34 +++++++++++++------------ examples/rotation.c | 51 +++++++++++++++++++++---------------- examples/scene-graph.c | 1 + examples/simple.c | 32 +++++++++++++---------- examples/tablet.c | 29 ++++++++++++--------- examples/touch.c | 27 +++++++++++--------- 10 files changed, 147 insertions(+), 111 deletions(-) diff --git a/examples/cairo-buffer.c b/examples/cairo-buffer.c index 6392b2ac5..0000744ae 100644 --- a/examples/cairo-buffer.c +++ b/examples/cairo-buffer.c @@ -116,6 +116,7 @@ static void server_handle_new_output(struct wl_listener *listener, void *data) { if (mode != NULL) { wlr_output_state_set_mode(&state, mode); } + wlr_scene_output_build_state(output->scene_output, &state, NULL); wlr_output_commit_state(wlr_output, &state); wlr_output_state_finish(&state); } diff --git a/examples/fullscreen-shell.c b/examples/fullscreen-shell.c index 6a758f22f..084f25138 100644 --- a/examples/fullscreen-shell.c +++ b/examples/fullscreen-shell.c @@ -79,18 +79,13 @@ static void render_surface(struct wlr_surface *surface, wlr_surface_send_frame_done(surface, rdata->when); } -static void output_handle_frame(struct wl_listener *listener, void *data) { - struct fullscreen_output *output = - wl_container_of(listener, output, frame); - +static void render(struct fullscreen_output *output, struct wlr_output_state *state) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); int width, height; - wlr_output_effective_resolution(output->wlr_output, NULL, &width, &height); + wlr_output_effective_resolution(output->wlr_output, state, &width, &height); - struct wlr_output_state state; - wlr_output_state_init(&state); - struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, &state, NULL); + struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, state, NULL); if (pass == NULL) { return; } @@ -110,6 +105,15 @@ static void output_handle_frame(struct wl_listener *listener, void *data) { } wlr_render_pass_submit(pass); +} + +static void output_handle_frame(struct wl_listener *listener, void *data) { + struct fullscreen_output *output = + wl_container_of(listener, output, frame); + + struct wlr_output_state state; + wlr_output_state_init(&state); + render(output, &state); wlr_output_commit_state(output->wlr_output, &state); wlr_output_state_finish(&state); } @@ -169,6 +173,7 @@ static void server_handle_new_output(struct wl_listener *listener, void *data) { if (mode != NULL) { wlr_output_state_set_mode(&state, mode); } + render(output, &state); wlr_output_commit_state(wlr_output, &state); wlr_output_state_finish(&state); } diff --git a/examples/output-layers.c b/examples/output-layers.c index dc1a83f6a..ec2b16bf5 100644 --- a/examples/output-layers.c +++ b/examples/output-layers.c @@ -61,8 +61,9 @@ struct output { struct wl_listener frame; }; -static void output_handle_frame(struct wl_listener *listener, void *data) { - struct output *output = wl_container_of(listener, output, frame); +static void render_and_commit(struct output *output, struct wlr_output_state *state) { + int width, height; + wlr_output_effective_resolution(output->wlr_output, state, &width, &height); struct wl_array layers_arr = {0}; struct output_surface *output_surface; @@ -81,22 +82,19 @@ static void output_handle_frame(struct wl_listener *listener, void *data) { }; } - struct wlr_output_state output_state; - wlr_output_state_init(&output_state); - wlr_output_state_set_layers(&output_state, layers_arr.data, - layers_arr.size / sizeof(struct wlr_output_layer_state)); + // don't submit output layers for modeset or enable. + if ((state->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_ENABLED)) == 0) { + wlr_output_state_set_layers(state, layers_arr.data, + layers_arr.size / sizeof(struct wlr_output_layer_state)); - if (!wlr_output_test_state(output->wlr_output, &output_state)) { - wlr_log(WLR_ERROR, "wlr_output_test_state() failed"); - return; + if (!wlr_output_test_state(output->wlr_output, state)) { + wlr_log(WLR_ERROR, "wlr_output_test_state() failed"); + return; + } } - int width, height; - wlr_output_effective_resolution(output->wlr_output, NULL, &width, &height); - - struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, &output_state, NULL); + struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, state, NULL); wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ - .box = { .width = width, .height = height }, .color = { 0.3, 0.3, 0.3, 1 }, }); @@ -125,9 +123,6 @@ static void output_handle_frame(struct wl_listener *listener, void *data) { wlr_render_pass_submit(pass); - wlr_output_commit_state(output->wlr_output, &output_state); - wlr_output_state_finish(&output_state); - struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -154,9 +149,19 @@ static void output_handle_frame(struct wl_listener *listener, void *data) { output_surface->first_commit = false; } + wlr_output_commit_state(output->wlr_output, state); wl_array_release(&layers_arr); } +static void output_handle_frame(struct wl_listener *listener, void *data) { + struct output *output = wl_container_of(listener, output, frame); + + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); + render_and_commit(output, &output_state); + wlr_output_state_finish(&output_state); +} + static void server_handle_new_output(struct wl_listener *listener, void *data) { struct server *server = wl_container_of(listener, server, new_output); struct wlr_output *wlr_output = data; @@ -178,7 +183,7 @@ static void server_handle_new_output(struct wl_listener *listener, void *data) { if (mode != NULL) { wlr_output_state_set_mode(&state, mode); } - wlr_output_commit_state(wlr_output, &state); + render_and_commit(output, &state); wlr_output_state_finish(&state); wlr_output_create_global(wlr_output, server->wl_display); diff --git a/examples/output-layout.c b/examples/output-layout.c index c481ddf80..dca532584 100644 --- a/examples/output-layout.c +++ b/examples/output-layout.c @@ -107,17 +107,11 @@ static void animate_cat(struct sample_state *sample, sample->ts_last = ts; } -static void output_frame_notify(struct wl_listener *listener, void *data) { - struct sample_output *output = wl_container_of(listener, output, frame); +static void render(struct sample_output *output, struct wlr_output_state *state) { + struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->output, state, NULL); struct sample_state *sample = output->sample; - struct wlr_output *wlr_output = output->output; - - struct wlr_output_state output_state; - wlr_output_state_init(&output_state); - struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL); wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ - .box = { .width = wlr_output->width, .height = wlr_output->height }, .color = { 0.25, 0.25, 0.25, 1 }, }); @@ -141,7 +135,15 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { } wlr_render_pass_submit(pass); - wlr_output_commit_state(wlr_output, &output_state); +} + +static void output_frame_notify(struct wl_listener *listener, void *data) { + struct sample_output *output = wl_container_of(listener, output, frame); + + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); + render(output, &output_state); + wlr_output_commit_state(output->output, &output_state); wlr_output_state_finish(&output_state); } @@ -182,6 +184,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { if (mode != NULL) { wlr_output_state_set_mode(&state, mode); } + render(sample_output, &state); wlr_output_commit_state(output, &state); wlr_output_state_finish(&state); } diff --git a/examples/pointer.c b/examples/pointer.c index f3ef5435e..64853f1e6 100644 --- a/examples/pointer.c +++ b/examples/pointer.c @@ -92,28 +92,29 @@ static void warp_to_touch(struct sample_state *state, wlr_cursor_warp_absolute(state->cursor, dev, x, y); } -static void output_frame_notify(struct wl_listener *listener, void *data) { - struct sample_output *sample_output = wl_container_of(listener, sample_output, frame); - struct sample_state *state = sample_output->state; - struct wlr_output *wlr_output = sample_output->output; - struct wlr_renderer *renderer = state->renderer; - assert(renderer); - - struct wlr_output_state output_state; - wlr_output_state_init(&output_state); - struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL); +static void render(struct sample_output *output, struct wlr_output_state *state) { + struct wlr_output *wlr_output = output->output; + struct sample_state *sample_state = output->state; + struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, state, NULL); wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ - .box = { .width = wlr_output->width, .height = wlr_output->height }, .color = { - state->clear_color[0], - state->clear_color[1], - state->clear_color[2], - state->clear_color[3], + sample_state->clear_color[0], + sample_state->clear_color[1], + sample_state->clear_color[2], + sample_state->clear_color[3], }, }); wlr_output_add_software_cursors_to_render_pass(wlr_output, pass, NULL); wlr_render_pass_submit(pass); - wlr_output_commit_state(wlr_output, &output_state); +} + +static void output_frame_notify(struct wl_listener *listener, void *data) { + struct sample_output *sample_output = wl_container_of(listener, sample_output, frame); + + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); + render(sample_output, &output_state); + wlr_output_commit_state(sample_output->output, &output_state); wlr_output_state_finish(&output_state); } @@ -280,6 +281,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { if (mode != NULL) { wlr_output_state_set_mode(&state, mode); } + render(sample_output, &state); wlr_output_commit_state(output, &state); wlr_output_state_finish(&state); } diff --git a/examples/rotation.c b/examples/rotation.c index a50297f70..82f517ea0 100644 --- a/examples/rotation.c +++ b/examples/rotation.c @@ -47,27 +47,25 @@ struct sample_keyboard { struct wl_listener destroy; }; -static void output_frame_notify(struct wl_listener *listener, void *data) { - struct sample_output *sample_output = wl_container_of(listener, sample_output, frame); - struct sample_state *sample = sample_output->sample; - struct wlr_output *wlr_output = sample_output->output; +static void render (struct sample_output *output, struct wlr_output_state *state) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - int32_t width, height; - wlr_output_effective_resolution(wlr_output, NULL, &width, &height); - struct wlr_output_state output_state; - wlr_output_state_init(&output_state); - struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL); + struct sample_state *sample = output->sample; + struct wlr_output *wlr_output = output->output; + struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, state, NULL); + + int32_t width, height; + wlr_output_effective_resolution(wlr_output, state, &width, &height); + wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ - .box = { .width = wlr_output->width, .height = wlr_output->height }, .color = { 0.25, 0.25, 0.25, 1 }, }); - for (int y = -128 + (int)sample_output->y_offs; y < height; y += 128) { - for (int x = -128 + (int)sample_output->x_offs; x < width; x += 128) { + for (int y = -128 + (int)output->y_offs; y < height; y += 128) { + for (int x = -128 + (int)output->x_offs; x < width; x += 128) { wlr_render_pass_add_texture(pass, &(struct wlr_render_texture_options){ .texture = sample->cat_texture, .dst_box = { .x = x, .y = y }, @@ -77,24 +75,32 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { } wlr_render_pass_submit(pass); - wlr_output_commit_state(wlr_output, &output_state); - wlr_output_state_finish(&output_state); long ms = (now.tv_sec - sample->last_frame.tv_sec) * 1000 + (now.tv_nsec - sample->last_frame.tv_nsec) / 1000000; float seconds = ms / 1000.0f; + output->x_offs += output->x_vel * seconds; + output->y_offs += output->y_vel * seconds; + if (output->x_offs > 128) { + output->x_offs = 0; + } + if (output->y_offs > 128) { + output->y_offs = 0; + } - sample_output->x_offs += sample_output->x_vel * seconds; - sample_output->y_offs += sample_output->y_vel * seconds; - if (sample_output->x_offs > 128) { - sample_output->x_offs = 0; - } - if (sample_output->y_offs > 128) { - sample_output->y_offs = 0; - } sample->last_frame = now; } +static void output_frame_notify(struct wl_listener *listener, void *data) { + struct sample_output *sample_output = wl_container_of(listener, sample_output, frame); + + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); + render(sample_output, &output_state); + wlr_output_commit_state(sample_output->output, &output_state); + wlr_output_state_finish(&output_state); +} + static void update_velocities(struct sample_state *sample, float x_diff, float y_diff) { struct sample_output *sample_output; @@ -137,6 +143,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { if (mode != NULL) { wlr_output_state_set_mode(&state, mode); } + render(sample_output, &state); wlr_output_commit_state(output, &state); wlr_output_state_finish(&state); } diff --git a/examples/scene-graph.c b/examples/scene-graph.c index 421986534..e57ce9c90 100644 --- a/examples/scene-graph.c +++ b/examples/scene-graph.c @@ -86,6 +86,7 @@ static void server_handle_new_output(struct wl_listener *listener, void *data) { if (mode != NULL) { wlr_output_state_set_mode(&state, mode); } + wlr_scene_output_build_state(output->scene_output, &state, NULL); wlr_output_commit_state(wlr_output, &state); wlr_output_state_finish(&state); diff --git a/examples/simple.c b/examples/simple.c index d16708654..dd0690ce7 100644 --- a/examples/simple.c +++ b/examples/simple.c @@ -39,11 +39,25 @@ struct sample_keyboard { struct wl_listener destroy; }; +static void render(struct sample_output *output, struct wlr_output_state *state) { + struct wlr_output *wlr_output = output->output; + struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, state, NULL); + wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ + .box = { .width = wlr_output->width, .height = wlr_output->height }, + .color = { + .r = output->sample->color[0], + .g = output->sample->color[1], + .b = output->sample->color[2], + .a = output->sample->color[3], + }, + }); + wlr_render_pass_submit(pass); +} + static void output_frame_notify(struct wl_listener *listener, void *data) { struct sample_output *sample_output = wl_container_of(listener, sample_output, frame); struct sample_state *sample = sample_output->sample; - struct wlr_output *wlr_output = sample_output->output; struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); @@ -63,19 +77,8 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { struct wlr_output_state state; wlr_output_state_init(&state); - struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &state, NULL); - wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ - .box = { .width = wlr_output->width, .height = wlr_output->height }, - .color = { - .r = sample->color[0], - .g = sample->color[1], - .b = sample->color[2], - .a = sample->color[3], - }, - }); - wlr_render_pass_submit(pass); - - wlr_output_commit_state(wlr_output, &state); + render(sample_output, &state); + wlr_output_commit_state(sample_output->output, &state); wlr_output_state_finish(&state); sample->last_frame = now; } @@ -111,6 +114,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { if (mode != NULL) { wlr_output_state_set_mode(&state, mode); } + render(sample_output, &state); wlr_output_commit_state(output, &state); wlr_output_state_finish(&state); } diff --git a/examples/tablet.c b/examples/tablet.c index 658895a1d..32adf5f44 100644 --- a/examples/tablet.c +++ b/examples/tablet.c @@ -77,22 +77,18 @@ struct sample_keyboard { struct wl_listener destroy; }; -static void output_frame_notify(struct wl_listener *listener, void *data) { - struct sample_output *sample_output = wl_container_of(listener, sample_output, frame); - struct sample_state *sample = sample_output->sample; - struct wlr_output *wlr_output = sample_output->output; +static void render(struct sample_output *output, struct wlr_output_state *state) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); + struct wlr_output *wlr_output = output->output; + struct sample_state *sample = output->sample; + int32_t width, height; - wlr_output_effective_resolution(wlr_output, NULL, &width, &height); - - struct wlr_output_state output_state; - wlr_output_state_init(&output_state); - struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL); + wlr_output_effective_resolution(wlr_output, state, &width, &height); + struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, state, NULL); wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ - .box = { .width = wlr_output->width, .height = wlr_output->height }, .color = { 0.25, 0.25, 0.25, 1 }, }); @@ -157,11 +153,19 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { } wlr_render_pass_submit(pass); - wlr_output_commit_state(wlr_output, &output_state); - wlr_output_state_finish(&output_state); sample->last_frame = now; } +static void output_frame_notify(struct wl_listener *listener, void *data) { + struct sample_output *sample_output = wl_container_of(listener, sample_output, frame); + + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); + render(sample_output, &output_state); + wlr_output_commit_state(sample_output->output, &output_state); + wlr_output_state_finish(&output_state); +} + static void tablet_tool_axis_notify(struct wl_listener *listener, void *data) { struct tablet_tool_state *tstate = wl_container_of(listener, tstate, axis); struct wlr_tablet_tool_axis_event *event = data; @@ -285,6 +289,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { if (mode != NULL) { wlr_output_state_set_mode(&state, mode); } + render(sample_output, &state); wlr_output_commit_state(output, &state); wlr_output_state_finish(&state); } diff --git a/examples/touch.c b/examples/touch.c index 03ce2dee0..23bba2c28 100644 --- a/examples/touch.c +++ b/examples/touch.c @@ -63,22 +63,16 @@ struct sample_keyboard { struct wl_listener destroy; }; -static void output_frame_notify(struct wl_listener *listener, void *data) { - struct sample_output *sample_output = wl_container_of(listener, sample_output, frame); - struct sample_state *sample = sample_output->sample; +static void render(struct sample_output *output, struct wlr_output_state *state) { struct timespec now; clock_gettime(CLOCK_MONOTONIC, &now); - struct wlr_output *wlr_output = sample_output->output; - int32_t width, height; - wlr_output_effective_resolution(wlr_output, NULL, &width, &height); + wlr_output_effective_resolution(output->output, state, &width, &height); + struct sample_state *sample = output->sample; - struct wlr_output_state output_state; - wlr_output_state_init(&output_state); - struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL); + struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->output, state, NULL); wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ - .box = { .width = width, .height = height }, .color = { 0.25, 0.25, 0.25, 1 }, }); @@ -93,11 +87,19 @@ static void output_frame_notify(struct wl_listener *listener, void *data) { } wlr_render_pass_submit(pass); - wlr_output_commit_state(wlr_output, &output_state); - wlr_output_state_finish(&output_state); sample->last_frame = now; } +static void output_frame_notify(struct wl_listener *listener, void *data) { + struct sample_output *sample_output = wl_container_of(listener, sample_output, frame); + + struct wlr_output_state output_state; + wlr_output_state_init(&output_state); + render(sample_output, &output_state); + wlr_output_commit_state(sample_output->output, &output_state); + wlr_output_state_finish(&output_state); +} + static void touch_down_notify(struct wl_listener *listener, void *data) { struct wlr_touch_down_event *event = data; struct touch_state *tstate = wl_container_of(listener, tstate, down); @@ -188,6 +190,7 @@ static void new_output_notify(struct wl_listener *listener, void *data) { if (mode != NULL) { wlr_output_state_set_mode(&state, mode); } + render(sample_output, &state); wlr_output_commit_state(output, &state); wlr_output_state_finish(&state); }