diff --git a/backend/drm/drm.c b/backend/drm/drm.c index d07d98afc..d4c110f10 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -1178,7 +1178,7 @@ static bool drm_connector_move_cursor(struct wlr_output *output, struct wlr_box box = { .x = x, .y = y }; int width, height; - wlr_output_transformed_resolution(output, &width, &height); + wlr_output_transformed_resolution(output, NULL, &width, &height); enum wl_output_transform transform = wlr_output_transform_invert(output->transform); 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 956d851af..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, &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 0535ff0b1..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, &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 18bfbd38d..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, &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 78666fff7..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, &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 b891837a4..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, &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); } diff --git a/include/types/wlr_output.h b/include/types/wlr_output.h index 2dc979c66..5784efdec 100644 --- a/include/types/wlr_output.h +++ b/include/types/wlr_output.h @@ -12,8 +12,6 @@ bool output_pending_enabled(struct wlr_output *output, bool output_pick_format(struct wlr_output *output, const struct wlr_drm_format_set *display_formats, struct wlr_drm_format *format, uint32_t fmt); -bool output_ensure_buffer(struct wlr_output *output, - struct wlr_output_state *state, bool *new_back_buffer); bool output_cursor_set_texture(struct wlr_output_cursor *cursor, struct wlr_texture *texture, bool own_texture, const struct wlr_fbox *src_box, diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 9c08a2c34..0e45f4697 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -339,12 +339,12 @@ void wlr_output_destroy(struct wlr_output *output); * Computes the transformed output resolution. */ void wlr_output_transformed_resolution(struct wlr_output *output, - int *width, int *height); + const struct wlr_output_state *state, int *width, int *height); /** * Computes the transformed and scaled output resolution. */ void wlr_output_effective_resolution(struct wlr_output *output, - int *width, int *height); + const struct wlr_output_state *state, int *width, int *height); /** * Test whether this output state would be accepted by the backend. If this * function returns true, wlr_output_commit_state() will only fail due to a diff --git a/tinywl/tinywl.c b/tinywl/tinywl.c index 89837b4fb..404aedc98 100644 --- a/tinywl/tinywl.c +++ b/tinywl/tinywl.c @@ -604,6 +604,20 @@ static void server_new_output(struct wl_listener *listener, void *data) { * and our renderer. Must be done once, before commiting the output */ wlr_output_init_render(wlr_output, server->allocator, server->renderer); + /* Adds this to the output layout. The add_auto function arranges outputs + * from left-to-right in the order they appear. A more sophisticated + * compositor would let the user configure the arrangement of outputs in the + * layout. + * + * The output layout utility automatically adds a wl_output global to the + * display, which Wayland clients can see to find out information about the + * output (such as DPI, scale factor, manufacturer, etc). + */ + struct wlr_output_layout_output *l_output = wlr_output_layout_add_auto(server->output_layout, + wlr_output); + struct wlr_scene_output *scene_output = wlr_scene_output_create(server->scene, wlr_output); + wlr_scene_output_layout_add_output(server->scene_layout, l_output, scene_output); + /* The output may be disabled, switch it on. */ struct wlr_output_state state; wlr_output_state_init(&state); @@ -619,6 +633,11 @@ static void server_new_output(struct wl_listener *listener, void *data) { wlr_output_state_set_mode(&state, mode); } + /* When enabling an output, wlroots requires that a buffer is also included + * in that commit to enable the output. + */ + wlr_scene_output_build_state(scene_output, &state, NULL); + /* Atomically applies the new output state. */ wlr_output_commit_state(wlr_output, &state); wlr_output_state_finish(&state); @@ -641,20 +660,6 @@ static void server_new_output(struct wl_listener *listener, void *data) { wl_signal_add(&wlr_output->events.destroy, &output->destroy); wl_list_insert(&server->outputs, &output->link); - - /* Adds this to the output layout. The add_auto function arranges outputs - * from left-to-right in the order they appear. A more sophisticated - * compositor would let the user configure the arrangement of outputs in the - * layout. - * - * The output layout utility automatically adds a wl_output global to the - * display, which Wayland clients can see to find out information about the - * output (such as DPI, scale factor, manufacturer, etc). - */ - struct wlr_output_layout_output *l_output = wlr_output_layout_add_auto(server->output_layout, - wlr_output); - struct wlr_scene_output *scene_output = wlr_scene_output_create(server->scene, wlr_output); - wlr_scene_output_layout_add_output(server->scene_layout, l_output, scene_output); } static void xdg_toplevel_map(struct wl_listener *listener, void *data) { diff --git a/types/output/cursor.c b/types/output/cursor.c index 154b91120..89f1cb2a9 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -89,8 +89,9 @@ static void output_cursor_get_box(struct wlr_output_cursor *cursor, void wlr_output_add_software_cursors_to_render_pass(struct wlr_output *output, struct wlr_render_pass *render_pass, const pixman_region32_t *damage) { + // TODO: pass output state from caller int width, height; - wlr_output_transformed_resolution(output, &width, &height); + wlr_output_transformed_resolution(output, NULL, &width, &height); struct wlr_output_cursor *cursor; wl_list_for_each(cursor, &output->cursors, link) { @@ -152,7 +153,7 @@ static void output_cursor_damage_whole(struct wlr_output_cursor *cursor) { static void output_cursor_update_visible(struct wlr_output_cursor *cursor) { struct wlr_box output_box; output_box.x = output_box.y = 0; - wlr_output_transformed_resolution(cursor->output, &output_box.width, + wlr_output_transformed_resolution(cursor->output, NULL, &output_box.width, &output_box.height); struct wlr_box cursor_box; diff --git a/types/output/output.c b/types/output/output.c index a352a5e59..9407895bb 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -441,21 +441,32 @@ void wlr_output_destroy(struct wlr_output *output) { } void wlr_output_transformed_resolution(struct wlr_output *output, - int *width, int *height) { - if (output->transform % 2 == 0) { - *width = output->width; - *height = output->height; - } else { - *width = output->height; - *height = output->width; + const struct wlr_output_state *state, int *width, int *height) { + output_pending_resolution(output, state, width, height); + + enum wl_output_transform transform = output->transform; + if (state && state->committed & WLR_OUTPUT_STATE_TRANSFORM) { + transform = state->transform; + } + + if (transform % 2 != 0) { + int tmp = *width; + *width = *height; + *height = tmp; } } void wlr_output_effective_resolution(struct wlr_output *output, - int *width, int *height) { - wlr_output_transformed_resolution(output, width, height); - *width /= output->scale; - *height /= output->scale; + const struct wlr_output_state *state, int *width, int *height) { + wlr_output_transformed_resolution(output, state, width, height); + + float scale = output->scale; + if (state && state->committed & WLR_OUTPUT_STATE_SCALE) { + scale = state->scale; + } + + *width /= scale; + *height /= scale; } struct wlr_output_mode *wlr_output_preferred_mode(struct wlr_output *output) { @@ -476,7 +487,7 @@ struct wlr_output_mode *wlr_output_preferred_mode(struct wlr_output *output) { void output_pending_resolution(struct wlr_output *output, const struct wlr_output_state *state, int *width, int *height) { - if (state->committed & WLR_OUTPUT_STATE_MODE) { + if (state && state->committed & WLR_OUTPUT_STATE_MODE) { switch (state->mode_type) { case WLR_OUTPUT_STATE_MODE_FIXED: *width = state->mode->width; @@ -610,6 +621,12 @@ static bool output_basic_test(struct wlr_output *output, } } + if ((state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) && + (state->committed & WLR_OUTPUT_STATE_BUFFER) == 0) { + wlr_log(WLR_DEBUG, "Tried to change the render format without a buffer."); + return false; + } + if (state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { struct wlr_allocator *allocator = output->allocator; assert(allocator != NULL); @@ -625,8 +642,13 @@ static bool output_basic_test(struct wlr_output *output, wlr_drm_format_finish(&format); } - bool enabled = output_pending_enabled(output, state); + if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled && + (state->committed & WLR_OUTPUT_STATE_BUFFER) == 0) { + wlr_log(WLR_DEBUG, "Tried to enable an output without a buffer"); + return false; + } + bool enabled = output_pending_enabled(output, state); if (enabled && (state->committed & (WLR_OUTPUT_STATE_ENABLED | WLR_OUTPUT_STATE_MODE))) { int pending_width, pending_height; @@ -699,16 +721,7 @@ bool wlr_output_test_state(struct wlr_output *output, return true; } - bool new_back_buffer = false; - if (!output_ensure_buffer(output, ©, &new_back_buffer)) { - return false; - } - - bool success = output->impl->test(output, ©); - if (new_back_buffer) { - wlr_buffer_unlock(copy.buffer); - } - return success; + return output->impl->test(output, ©); } bool output_prepare_commit(struct wlr_output *output, const struct wlr_output_state *state) { @@ -770,28 +783,16 @@ bool wlr_output_commit_state(struct wlr_output *output, return false; } - bool new_back_buffer = false; - if (!output_ensure_buffer(output, &pending, &new_back_buffer)) { - return false; - } - if (!output_prepare_commit(output, &pending)) { return false; } if (!output->impl->commit(output, &pending)) { - if (new_back_buffer) { - wlr_buffer_unlock(pending.buffer); - } return false; } output_apply_commit(output, &pending); - if (new_back_buffer) { - wlr_buffer_unlock(pending.buffer); - } - return true; } diff --git a/types/output/render.c b/types/output/render.c index 155da5cf8..f841fe87c 100644 --- a/types/output/render.c +++ b/types/output/render.c @@ -38,100 +38,6 @@ bool wlr_output_init_render(struct wlr_output *output, return true; } -static struct wlr_buffer *output_acquire_empty_buffer(struct wlr_output *output, - const struct wlr_output_state *state) { - assert(!(state->committed & WLR_OUTPUT_STATE_BUFFER)); - - // wlr_output_configure_primary_swapchain() function will call - // wlr_output_test_state(), which can call us again. This is dangerous: we - // risk infinite recursion. However, a buffer will always be supplied in - // wlr_output_test_state(), which will prevent us from being called. - if (!wlr_output_configure_primary_swapchain(output, state, - &output->swapchain)) { - return NULL; - } - - struct wlr_buffer *buffer = wlr_swapchain_acquire(output->swapchain); - if (buffer == NULL) { - return NULL; - } - - struct wlr_render_pass *pass = - wlr_renderer_begin_buffer_pass(output->renderer, buffer, NULL); - if (pass == NULL) { - wlr_buffer_unlock(buffer); - return NULL; - } - - wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){ - .color = { 0, 0, 0, 0 }, - .blend_mode = WLR_RENDER_BLEND_MODE_NONE, - }); - - if (!wlr_render_pass_submit(pass)) { - wlr_buffer_unlock(buffer); - return NULL; - } - - return buffer; -} - -// This function may attach a new, empty buffer if necessary. -// If so, the new_back_buffer out parameter will be set to true. -bool output_ensure_buffer(struct wlr_output *output, - struct wlr_output_state *state, bool *new_buffer) { - assert(*new_buffer == false); - - // If we already have a buffer, we don't need to allocate a new one - if (state->committed & WLR_OUTPUT_STATE_BUFFER) { - return true; - } - - // If the compositor hasn't called wlr_output_init_render(), they will use - // their own logic to attach buffers - if (output->renderer == NULL) { - return true; - } - - bool enabled = output->enabled; - if (state->committed & WLR_OUTPUT_STATE_ENABLED) { - enabled = state->enabled; - } - - // If we're lighting up an output or changing its mode, make sure to - // provide a new buffer - bool needs_new_buffer = false; - if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled) { - needs_new_buffer = true; - } - if (state->committed & WLR_OUTPUT_STATE_MODE) { - needs_new_buffer = true; - } - if (state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { - needs_new_buffer = true; - } - if (state->allow_reconfiguration && output->commit_seq == 0 && enabled) { - // On first commit, require a new buffer if the compositor called a - // mode-setting function, even if the mode won't change. This makes it - // so the swapchain is created now. - needs_new_buffer = true; - } - if (!needs_new_buffer) { - return true; - } - - wlr_log(WLR_DEBUG, "Attaching empty buffer to output for modeset"); - struct wlr_buffer *buffer = output_acquire_empty_buffer(output, state); - if (buffer == NULL) { - return false; - } - - *new_buffer = true; - wlr_output_state_set_buffer(state, buffer); - wlr_buffer_unlock(buffer); - return true; -} - void wlr_output_lock_attach_render(struct wlr_output *output, bool lock) { if (lock) { ++output->attach_render_locks; diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index d64ee4ada..ad134e21d 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -339,7 +339,7 @@ static void logical_to_buffer_coords(pixman_region32_t *region, const struct ren static void output_to_buffer_coords(pixman_region32_t *damage, struct wlr_output *output) { int width, height; - wlr_output_transformed_resolution(output, &width, &height); + wlr_output_transformed_resolution(output, NULL, &width, &height); wlr_region_transform(damage, damage, wlr_output_transform_invert(output->transform), width, height); @@ -445,7 +445,7 @@ static void update_node_update_outputs(struct wlr_scene_node *node, .x = scene_output->x, .y = scene_output->y, }; - wlr_output_effective_resolution(scene_output->output, + wlr_output_effective_resolution(scene_output->output, NULL, &output_box.width, &output_box.height); pixman_region32_t intersection; @@ -1579,7 +1579,7 @@ static void scene_output_handle_damage(struct wl_listener *listener, void *data) struct wlr_output_event_damage *event = data; int width, height; - wlr_output_transformed_resolution(output, &width, &height); + wlr_output_transformed_resolution(output, NULL, &width, &height); pixman_region32_t damage; pixman_region32_init(&damage); @@ -2337,7 +2337,7 @@ static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box, void wlr_scene_output_for_each_buffer(struct wlr_scene_output *scene_output, wlr_scene_buffer_iterator_func_t iterator, void *user_data) { struct wlr_box box = { .x = scene_output->x, .y = scene_output->y }; - wlr_output_effective_resolution(scene_output->output, + wlr_output_effective_resolution(scene_output->output, NULL, &box.width, &box.height); scene_output_for_each_scene_buffer(&box, &scene_output->scene->tree.node, 0, 0, iterator, user_data); diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index ef2751179..fe4a297fd 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -71,7 +71,7 @@ static void output_layout_output_get_box( struct wlr_box *box) { box->x = l_output->x; box->y = l_output->y; - wlr_output_effective_resolution(l_output->output, + wlr_output_effective_resolution(l_output->output, NULL, &box->width, &box->height); } diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c index c49ed6bdf..9bdf0dcb8 100644 --- a/types/wlr_screencopy_v1.c +++ b/types/wlr_screencopy_v1.c @@ -573,7 +573,7 @@ static void capture_output(struct wl_client *wl_client, buffer_box.height = output->height; } else { int ow, oh; - wlr_output_effective_resolution(output, &ow, &oh); + wlr_output_effective_resolution(output, NULL, &ow, &oh); buffer_box = *box; diff --git a/types/wlr_xdg_output_v1.c b/types/wlr_xdg_output_v1.c index 262123987..6b86d2d68 100644 --- a/types/wlr_xdg_output_v1.c +++ b/types/wlr_xdg_output_v1.c @@ -46,7 +46,7 @@ static void output_update(struct wlr_xdg_output_v1 *xdg_output) { } int width, height; - wlr_output_effective_resolution(layout_output->output, &width, &height); + wlr_output_effective_resolution(layout_output->output, NULL, &width, &height); if (xdg_output->width != width || xdg_output->height != height) { xdg_output->width = width; xdg_output->height = height;