mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-11-02 09:01:38 -05:00
output: refactor frame submission API
This is necessary for direct scan-out and other upcoming features. This patch changes the output API to look like the wl_surface API. Outputs now have some double-buffered state: the frame to be submitted (currently only wlr_renderer frames are supported) and the damaged region. To attach a pending frame, use wlr_output_attach_render. To set the pending damaged region, use wlr_output_set_damage. To submit the pending state, call wlr_output_commit. This will submit the pending frame to the backend. To migrate from the old API to the new one: - Replace wlr_output_make_current calls by wlr_output_attach_render - Replace wlr_output_swap_buffers calls by wlr_output_set_damage and wlr_output_commit
This commit is contained in:
parent
56ceed38bf
commit
23e37e7b1d
12 changed files with 115 additions and 74 deletions
|
|
@ -282,6 +282,7 @@ void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend,
|
|||
wl_signal_init(&output->events.transform);
|
||||
wl_signal_init(&output->events.destroy);
|
||||
pixman_region32_init(&output->damage);
|
||||
pixman_region32_init(&output->pending.damage);
|
||||
|
||||
const char *no_hardware_cursors = getenv("WLR_NO_HARDWARE_CURSORS");
|
||||
if (no_hardware_cursors != NULL && strcmp(no_hardware_cursors, "1") == 0) {
|
||||
|
|
@ -317,6 +318,7 @@ void wlr_output_destroy(struct wlr_output *output) {
|
|||
wl_event_source_remove(output->idle_frame);
|
||||
}
|
||||
|
||||
pixman_region32_fini(&output->pending.damage);
|
||||
pixman_region32_fini(&output->damage);
|
||||
|
||||
if (output->impl && output->impl->destroy) {
|
||||
|
|
@ -360,13 +362,18 @@ struct wlr_output_mode *wlr_output_preferred_mode(struct wlr_output *output) {
|
|||
return mode;
|
||||
}
|
||||
|
||||
bool wlr_output_make_current(struct wlr_output *output, int *buffer_age) {
|
||||
return output->impl->make_current(output, buffer_age);
|
||||
bool wlr_output_attach_render(struct wlr_output *output, int *buffer_age) {
|
||||
if (!output->impl->make_current(output, buffer_age)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
output->pending.committed |= WLR_OUTPUT_STATE_BUFFER;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool wlr_output_preferred_read_format(struct wlr_output *output,
|
||||
enum wl_shm_format *fmt) {
|
||||
if (!wlr_output_make_current(output, NULL)) {
|
||||
if (!output->impl->make_current(output, NULL)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -378,10 +385,21 @@ bool wlr_output_preferred_read_format(struct wlr_output *output,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when,
|
||||
void wlr_output_set_damage(struct wlr_output *output,
|
||||
pixman_region32_t *damage) {
|
||||
pixman_region32_intersect_rect(&output->pending.damage, damage,
|
||||
0, 0, output->width, output->height);
|
||||
output->pending.committed |= WLR_OUTPUT_STATE_DAMAGE;
|
||||
}
|
||||
|
||||
static void output_state_clear(struct wlr_output_state *state) {
|
||||
state->committed = 0;
|
||||
pixman_region32_clear(&state->damage);
|
||||
}
|
||||
|
||||
bool wlr_output_commit(struct wlr_output *output) {
|
||||
if (output->frame_pending) {
|
||||
wlr_log(WLR_ERROR, "Tried to swap buffers when a frame is pending");
|
||||
wlr_log(WLR_ERROR, "Tried to commit when a frame is pending");
|
||||
return false;
|
||||
}
|
||||
if (output->idle_frame != NULL) {
|
||||
|
|
@ -389,46 +407,43 @@ bool wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when,
|
|||
output->idle_frame = NULL;
|
||||
}
|
||||
|
||||
struct timespec now;
|
||||
if (when == NULL) {
|
||||
if (output->pending.committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
when = &now;
|
||||
}
|
||||
|
||||
struct wlr_output_event_swap_buffers event = {
|
||||
.output = output,
|
||||
.when = when,
|
||||
.damage = damage,
|
||||
};
|
||||
wlr_signal_emit_safe(&output->events.swap_buffers, &event);
|
||||
pixman_region32_t *damage = NULL;
|
||||
if (output->pending.committed & WLR_OUTPUT_STATE_DAMAGE) {
|
||||
damage = &output->pending.damage;
|
||||
}
|
||||
|
||||
pixman_region32_t render_damage;
|
||||
pixman_region32_init(&render_damage);
|
||||
pixman_region32_union_rect(&render_damage, &render_damage, 0, 0,
|
||||
output->width, output->height);
|
||||
if (damage != NULL) {
|
||||
// Damage tracking supported
|
||||
pixman_region32_intersect(&render_damage, &render_damage, damage);
|
||||
}
|
||||
struct wlr_output_event_swap_buffers event = {
|
||||
.output = output,
|
||||
.when = &now,
|
||||
.damage = damage,
|
||||
};
|
||||
wlr_signal_emit_safe(&output->events.swap_buffers, &event);
|
||||
|
||||
if (!output->impl->swap_buffers(output, damage ? &render_damage : NULL)) {
|
||||
pixman_region32_fini(&render_damage);
|
||||
if (!output->impl->swap_buffers(output, damage)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct wlr_output_cursor *cursor;
|
||||
wl_list_for_each(cursor, &output->cursors, link) {
|
||||
if (!cursor->enabled || !cursor->visible || cursor->surface == NULL) {
|
||||
continue;
|
||||
}
|
||||
wlr_surface_send_frame_done(cursor->surface, &now);
|
||||
}
|
||||
|
||||
output->frame_pending = true;
|
||||
output->needs_swap = false;
|
||||
output_state_clear(&output->pending);
|
||||
return true;
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Tried to commit without attaching a buffer");
|
||||
return false;
|
||||
}
|
||||
|
||||
pixman_region32_fini(&render_damage);
|
||||
|
||||
struct wlr_output_cursor *cursor;
|
||||
wl_list_for_each(cursor, &output->cursors, link) {
|
||||
if (!cursor->enabled || !cursor->visible || cursor->surface == NULL) {
|
||||
continue;
|
||||
}
|
||||
wlr_surface_send_frame_done(cursor->surface, when);
|
||||
}
|
||||
|
||||
output->frame_pending = true;
|
||||
output->needs_swap = false;
|
||||
pixman_region32_clear(&output->damage);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ bool wlr_output_damage_make_current(struct wlr_output_damage *output_damage,
|
|||
struct wlr_output *output = output_damage->output;
|
||||
|
||||
int buffer_age = -1;
|
||||
if (!wlr_output_make_current(output, &buffer_age)) {
|
||||
if (!wlr_output_attach_render(output, &buffer_age)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -142,7 +142,10 @@ bool wlr_output_damage_make_current(struct wlr_output_damage *output_damage,
|
|||
|
||||
bool wlr_output_damage_swap_buffers(struct wlr_output_damage *output_damage,
|
||||
struct timespec *when, pixman_region32_t *damage) {
|
||||
if (!wlr_output_swap_buffers(output_damage->output, when, damage)) {
|
||||
if (damage != NULL) {
|
||||
wlr_output_set_damage(output_damage->output, damage);
|
||||
}
|
||||
if (!wlr_output_commit(output_damage->output)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue