output: stop using wlr_output.back_buffer in output_ensure_buffer()

This allows us to use the new render pass API, and drops some
implicit state usage.
This commit is contained in:
Simon Ser 2023-06-20 11:32:17 +02:00 committed by Alexander Orzechowski
parent b625a13156
commit c4d4409deb
2 changed files with 52 additions and 46 deletions

View file

@ -688,7 +688,6 @@ bool wlr_output_test_state(struct wlr_output *output,
bool success = output->impl->test(output, &copy); bool success = output->impl->test(output, &copy);
if (new_back_buffer) { if (new_back_buffer) {
wlr_buffer_unlock(copy.buffer); wlr_buffer_unlock(copy.buffer);
output_clear_back_buffer(output);
} }
return success; return success;
} }
@ -723,9 +722,6 @@ bool wlr_output_commit_state(struct wlr_output *output,
if (!output_ensure_buffer(output, &pending, &new_back_buffer)) { if (!output_ensure_buffer(output, &pending, &new_back_buffer)) {
return false; return false;
} }
if (new_back_buffer) {
output_clear_back_buffer(output);
}
if ((pending.committed & WLR_OUTPUT_STATE_BUFFER) && if ((pending.committed & WLR_OUTPUT_STATE_BUFFER) &&
output->idle_frame != NULL) { output->idle_frame != NULL) {

View file

@ -43,15 +43,24 @@ bool wlr_output_init_render(struct wlr_output *output,
return true; return true;
} }
static bool output_attach_back_buffer(struct wlr_output *output, void output_clear_back_buffer(struct wlr_output *output) {
const struct wlr_output_state *state, int *buffer_age) { if (output->back_buffer == NULL) {
return;
}
struct wlr_renderer *renderer = output->renderer;
assert(renderer != NULL);
renderer_bind_buffer(renderer, NULL);
wlr_buffer_unlock(output->back_buffer);
output->back_buffer = NULL;
}
bool wlr_output_attach_render(struct wlr_output *output, int *buffer_age) {
assert(output->back_buffer == NULL); assert(output->back_buffer == NULL);
// wlr_output_configure_primary_swapchain() function will call if (!wlr_output_configure_primary_swapchain(output, &output->pending,
// 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)) { &output->swapchain)) {
return false; return false;
} }
@ -74,50 +83,49 @@ static bool output_attach_back_buffer(struct wlr_output *output,
return true; return true;
} }
void output_clear_back_buffer(struct wlr_output *output) { static struct wlr_buffer *output_acquire_empty_buffer(struct wlr_output *output,
if (output->back_buffer == NULL) {
return;
}
struct wlr_renderer *renderer = output->renderer;
assert(renderer != NULL);
renderer_bind_buffer(renderer, NULL);
wlr_buffer_unlock(output->back_buffer);
output->back_buffer = NULL;
}
bool wlr_output_attach_render(struct wlr_output *output, int *buffer_age) {
return output_attach_back_buffer(output, &output->pending, buffer_age);
}
static bool output_attach_empty_back_buffer(struct wlr_output *output,
const struct wlr_output_state *state) { const struct wlr_output_state *state) {
assert(!(state->committed & WLR_OUTPUT_STATE_BUFFER)); assert(!(state->committed & WLR_OUTPUT_STATE_BUFFER));
if (!output_attach_back_buffer(output, state, NULL)) { // 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 false; return false;
} }
int width, height; struct wlr_buffer *buffer = wlr_swapchain_acquire(output->swapchain, NULL);
output_pending_resolution(output, state, &width, &height); if (buffer == NULL) {
struct wlr_renderer *renderer = output->renderer;
if (!wlr_renderer_begin(renderer, width, height)) {
return false; return false;
} }
wlr_renderer_clear(renderer, (float[]){0, 0, 0, 0});
wlr_renderer_end(renderer);
return true; struct wlr_render_pass *pass =
wlr_renderer_begin_buffer_pass(output->renderer, buffer, NULL);
if (pass == NULL) {
wlr_buffer_unlock(buffer);
return NULL;
} }
// This function may attach a new, empty back buffer if necessary. 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. // If so, the new_back_buffer out parameter will be set to true.
bool output_ensure_buffer(struct wlr_output *output, bool output_ensure_buffer(struct wlr_output *output,
struct wlr_output_state *state, bool *new_back_buffer) { struct wlr_output_state *state, bool *new_buffer) {
assert(*new_back_buffer == false); assert(*new_buffer == false);
// If we already have a buffer, we don't need to allocate a new one // If we already have a buffer, we don't need to allocate a new one
if (state->committed & WLR_OUTPUT_STATE_BUFFER) { if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
@ -158,12 +166,14 @@ bool output_ensure_buffer(struct wlr_output *output,
} }
wlr_log(WLR_DEBUG, "Attaching empty buffer to output for modeset"); wlr_log(WLR_DEBUG, "Attaching empty buffer to output for modeset");
if (!output_attach_empty_back_buffer(output, state)) { struct wlr_buffer *buffer = output_acquire_empty_buffer(output, state);
if (buffer == NULL) {
return false; return false;
} }
*new_back_buffer = true; *new_buffer = true;
wlr_output_state_set_buffer(state, output->back_buffer); wlr_output_state_set_buffer(state, buffer);
wlr_buffer_unlock(buffer);
return true; return true;
} }
@ -237,7 +247,7 @@ uint32_t wlr_output_preferred_read_format(struct wlr_output *output) {
return DRM_FORMAT_INVALID; return DRM_FORMAT_INVALID;
} }
if (!output_attach_back_buffer(output, &output->pending, NULL)) { if (!wlr_output_attach_render(output, NULL)) {
return false; return false;
} }