mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2024-11-22 07:02:28 +00:00
swapchain, damage_ring: Drop buffer age
This commit is contained in:
parent
eebaca8dbf
commit
bfcaa4bc44
@ -89,7 +89,7 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_buffer *dst = wlr_swapchain_acquire(surf->swapchain, NULL);
|
struct wlr_buffer *dst = wlr_swapchain_acquire(surf->swapchain);
|
||||||
if (!dst) {
|
if (!dst) {
|
||||||
wlr_log(WLR_ERROR, "Failed to acquire multi-GPU swapchain buffer");
|
wlr_log(WLR_ERROR, "Failed to acquire multi-GPU swapchain buffer");
|
||||||
goto error_tex;
|
goto error_tex;
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
struct wlr_swapchain_slot {
|
struct wlr_swapchain_slot {
|
||||||
struct wlr_buffer *buffer;
|
struct wlr_buffer *buffer;
|
||||||
bool acquired; // waiting for release
|
bool acquired; // waiting for release
|
||||||
int age;
|
|
||||||
|
|
||||||
struct wl_listener release;
|
struct wl_listener release;
|
||||||
};
|
};
|
||||||
@ -36,21 +35,12 @@ void wlr_swapchain_destroy(struct wlr_swapchain *swapchain);
|
|||||||
* The returned buffer is locked. When the caller is done with it, they must
|
* The returned buffer is locked. When the caller is done with it, they must
|
||||||
* unlock it by calling wlr_buffer_unlock.
|
* unlock it by calling wlr_buffer_unlock.
|
||||||
*/
|
*/
|
||||||
struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain,
|
struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain);
|
||||||
int *age);
|
|
||||||
/**
|
/**
|
||||||
* Returns true if this buffer has been created by this swapchain, and false
|
* Returns true if this buffer has been created by this swapchain, and false
|
||||||
* otherwise.
|
* otherwise.
|
||||||
*/
|
*/
|
||||||
bool wlr_swapchain_has_buffer(struct wlr_swapchain *swapchain,
|
bool wlr_swapchain_has_buffer(struct wlr_swapchain *swapchain,
|
||||||
struct wlr_buffer *buffer);
|
struct wlr_buffer *buffer);
|
||||||
/**
|
|
||||||
* Mark the buffer as submitted for presentation. This needs to be called by
|
|
||||||
* swap chain users on frame boundaries.
|
|
||||||
*
|
|
||||||
* If the buffer hasn't been created via the swap chain, the call is ignored.
|
|
||||||
*/
|
|
||||||
void wlr_swapchain_set_buffer_submitted(struct wlr_swapchain *swapchain,
|
|
||||||
struct wlr_buffer *buffer);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,9 +15,6 @@
|
|||||||
#include <pixman.h>
|
#include <pixman.h>
|
||||||
#include <wayland-server-core.h>
|
#include <wayland-server-core.h>
|
||||||
|
|
||||||
/* For triple buffering, a history of two frames is required. */
|
|
||||||
#define WLR_DAMAGE_RING_PREVIOUS_LEN 2
|
|
||||||
|
|
||||||
struct wlr_box;
|
struct wlr_box;
|
||||||
|
|
||||||
struct wlr_damage_ring_buffer {
|
struct wlr_damage_ring_buffer {
|
||||||
@ -37,9 +34,6 @@ struct wlr_damage_ring {
|
|||||||
|
|
||||||
// private state
|
// private state
|
||||||
|
|
||||||
pixman_region32_t previous[WLR_DAMAGE_RING_PREVIOUS_LEN];
|
|
||||||
size_t previous_idx;
|
|
||||||
|
|
||||||
struct wl_list buffers; // wlr_damage_ring_buffer.link
|
struct wl_list buffers; // wlr_damage_ring_buffer.link
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,20 +73,6 @@ bool wlr_damage_ring_add_box(struct wlr_damage_ring *ring,
|
|||||||
*/
|
*/
|
||||||
void wlr_damage_ring_add_whole(struct wlr_damage_ring *ring);
|
void wlr_damage_ring_add_whole(struct wlr_damage_ring *ring);
|
||||||
|
|
||||||
/**
|
|
||||||
* Rotate the damage ring. This needs to be called after using the accumulated
|
|
||||||
* damage, e.g. after rendering to an output's back buffer.
|
|
||||||
*/
|
|
||||||
void wlr_damage_ring_rotate(struct wlr_damage_ring *ring);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get accumulated damage, which is the difference between the current buffer
|
|
||||||
* and the buffer with age of buffer_age; in context of rendering, this is
|
|
||||||
* the region that needs to be redrawn.
|
|
||||||
*/
|
|
||||||
void wlr_damage_ring_get_buffer_damage(struct wlr_damage_ring *ring,
|
|
||||||
int buffer_age, pixman_region32_t *damage);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get accumulated buffer damage and rotate the damage ring.
|
* Get accumulated buffer damage and rotate the damage ring.
|
||||||
*
|
*
|
||||||
|
@ -65,7 +65,7 @@ static void slot_handle_release(struct wl_listener *listener, void *data) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct wlr_buffer *slot_acquire(struct wlr_swapchain *swapchain,
|
static struct wlr_buffer *slot_acquire(struct wlr_swapchain *swapchain,
|
||||||
struct wlr_swapchain_slot *slot, int *age) {
|
struct wlr_swapchain_slot *slot) {
|
||||||
assert(!slot->acquired);
|
assert(!slot->acquired);
|
||||||
assert(slot->buffer != NULL);
|
assert(slot->buffer != NULL);
|
||||||
|
|
||||||
@ -74,15 +74,10 @@ static struct wlr_buffer *slot_acquire(struct wlr_swapchain *swapchain,
|
|||||||
slot->release.notify = slot_handle_release;
|
slot->release.notify = slot_handle_release;
|
||||||
wl_signal_add(&slot->buffer->events.release, &slot->release);
|
wl_signal_add(&slot->buffer->events.release, &slot->release);
|
||||||
|
|
||||||
if (age != NULL) {
|
|
||||||
*age = slot->age;
|
|
||||||
}
|
|
||||||
|
|
||||||
return wlr_buffer_lock(slot->buffer);
|
return wlr_buffer_lock(slot->buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain,
|
struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain) {
|
||||||
int *age) {
|
|
||||||
struct wlr_swapchain_slot *free_slot = NULL;
|
struct wlr_swapchain_slot *free_slot = NULL;
|
||||||
for (size_t i = 0; i < WLR_SWAPCHAIN_CAP; i++) {
|
for (size_t i = 0; i < WLR_SWAPCHAIN_CAP; i++) {
|
||||||
struct wlr_swapchain_slot *slot = &swapchain->slots[i];
|
struct wlr_swapchain_slot *slot = &swapchain->slots[i];
|
||||||
@ -90,7 +85,7 @@ struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (slot->buffer != NULL) {
|
if (slot->buffer != NULL) {
|
||||||
return slot_acquire(swapchain, slot, age);
|
return slot_acquire(swapchain, slot);
|
||||||
}
|
}
|
||||||
free_slot = slot;
|
free_slot = slot;
|
||||||
}
|
}
|
||||||
@ -110,7 +105,7 @@ struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain,
|
|||||||
wlr_log(WLR_ERROR, "Failed to allocate buffer");
|
wlr_log(WLR_ERROR, "Failed to allocate buffer");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
return slot_acquire(swapchain, free_slot, age);
|
return slot_acquire(swapchain, free_slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wlr_swapchain_has_buffer(struct wlr_swapchain *swapchain,
|
bool wlr_swapchain_has_buffer(struct wlr_swapchain *swapchain,
|
||||||
@ -123,23 +118,3 @@ bool wlr_swapchain_has_buffer(struct wlr_swapchain *swapchain,
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_swapchain_set_buffer_submitted(struct wlr_swapchain *swapchain,
|
|
||||||
struct wlr_buffer *buffer) {
|
|
||||||
assert(buffer != NULL);
|
|
||||||
|
|
||||||
if (!wlr_swapchain_has_buffer(swapchain, buffer)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// See the algorithm described in:
|
|
||||||
// https://www.khronos.org/registry/EGL/extensions/EXT/EGL_EXT_buffer_age.txt
|
|
||||||
for (size_t i = 0; i < WLR_SWAPCHAIN_CAP; i++) {
|
|
||||||
struct wlr_swapchain_slot *slot = &swapchain->slots[i];
|
|
||||||
if (slot->buffer == buffer) {
|
|
||||||
slot->age = 1;
|
|
||||||
} else if (slot->age > 0) {
|
|
||||||
slot->age++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -241,8 +241,7 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_buffer *buffer =
|
struct wlr_buffer *buffer = wlr_swapchain_acquire(output->cursor_swapchain);
|
||||||
wlr_swapchain_acquire(output->cursor_swapchain, NULL);
|
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -271,11 +271,6 @@ static void output_apply_state(struct wlr_output *output,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((state->committed & WLR_OUTPUT_STATE_BUFFER) &&
|
|
||||||
output->swapchain != NULL) {
|
|
||||||
wlr_swapchain_set_buffer_submitted(output->swapchain, state->buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mode_updated = false;
|
bool mode_updated = false;
|
||||||
if (state->committed & WLR_OUTPUT_STATE_MODE) {
|
if (state->committed & WLR_OUTPUT_STATE_MODE) {
|
||||||
int width = 0, height = 0, refresh = 0;
|
int width = 0, height = 0, refresh = 0;
|
||||||
|
@ -55,7 +55,7 @@ static struct wlr_buffer *output_acquire_empty_buffer(struct wlr_output *output,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_buffer *buffer = wlr_swapchain_acquire(output->swapchain, NULL);
|
struct wlr_buffer *buffer = wlr_swapchain_acquire(output->swapchain);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -204,7 +204,7 @@ struct wlr_render_pass *wlr_output_begin_render_pass(struct wlr_output *output,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_buffer *buffer = wlr_swapchain_acquire(output->swapchain, NULL);
|
struct wlr_buffer *buffer = wlr_swapchain_acquire(output->swapchain);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ static struct wlr_swapchain *create_swapchain(struct wlr_output *output,
|
|||||||
|
|
||||||
static bool test_swapchain(struct wlr_output *output,
|
static bool test_swapchain(struct wlr_output *output,
|
||||||
struct wlr_swapchain *swapchain, const struct wlr_output_state *state) {
|
struct wlr_swapchain *swapchain, const struct wlr_output_state *state) {
|
||||||
struct wlr_buffer *buffer = wlr_swapchain_acquire(swapchain, NULL);
|
struct wlr_buffer *buffer = wlr_swapchain_acquire(swapchain);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -2089,7 +2089,7 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
|||||||
swapchain = output->swapchain;
|
swapchain = output->swapchain;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_buffer *buffer = wlr_swapchain_acquire(swapchain, NULL);
|
struct wlr_buffer *buffer = wlr_swapchain_acquire(swapchain);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,6 @@ void wlr_damage_ring_init(struct wlr_damage_ring *ring) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pixman_region32_init(&ring->current);
|
pixman_region32_init(&ring->current);
|
||||||
for (size_t i = 0; i < WLR_DAMAGE_RING_PREVIOUS_LEN; ++i) {
|
|
||||||
pixman_region32_init(&ring->previous[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
wl_list_init(&ring->buffers);
|
wl_list_init(&ring->buffers);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,9 +27,6 @@ static void buffer_destroy(struct wlr_damage_ring_buffer *entry) {
|
|||||||
|
|
||||||
void wlr_damage_ring_finish(struct wlr_damage_ring *ring) {
|
void wlr_damage_ring_finish(struct wlr_damage_ring *ring) {
|
||||||
pixman_region32_fini(&ring->current);
|
pixman_region32_fini(&ring->current);
|
||||||
for (size_t i = 0; i < WLR_DAMAGE_RING_PREVIOUS_LEN; ++i) {
|
|
||||||
pixman_region32_fini(&ring->previous[i]);
|
|
||||||
}
|
|
||||||
struct wlr_damage_ring_buffer *entry, *tmp_entry;
|
struct wlr_damage_ring_buffer *entry, *tmp_entry;
|
||||||
wl_list_for_each_safe(entry, tmp_entry, &ring->buffers, link) {
|
wl_list_for_each_safe(entry, tmp_entry, &ring->buffers, link) {
|
||||||
buffer_destroy(entry);
|
buffer_destroy(entry);
|
||||||
@ -92,43 +85,6 @@ void wlr_damage_ring_add_whole(struct wlr_damage_ring *ring) {
|
|||||||
&ring->current, 0, 0, ring->width, ring->height);
|
&ring->current, 0, 0, ring->width, ring->height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void wlr_damage_ring_rotate(struct wlr_damage_ring *ring) {
|
|
||||||
// modular decrement
|
|
||||||
ring->previous_idx = ring->previous_idx +
|
|
||||||
WLR_DAMAGE_RING_PREVIOUS_LEN - 1;
|
|
||||||
ring->previous_idx %= WLR_DAMAGE_RING_PREVIOUS_LEN;
|
|
||||||
|
|
||||||
pixman_region32_copy(&ring->previous[ring->previous_idx], &ring->current);
|
|
||||||
pixman_region32_clear(&ring->current);
|
|
||||||
}
|
|
||||||
|
|
||||||
void wlr_damage_ring_get_buffer_damage(struct wlr_damage_ring *ring,
|
|
||||||
int buffer_age, pixman_region32_t *damage) {
|
|
||||||
if (buffer_age <= 0 || buffer_age - 1 > WLR_DAMAGE_RING_PREVIOUS_LEN) {
|
|
||||||
pixman_region32_clear(damage);
|
|
||||||
pixman_region32_union_rect(damage, damage,
|
|
||||||
0, 0, ring->width, ring->height);
|
|
||||||
} else {
|
|
||||||
pixman_region32_copy(damage, &ring->current);
|
|
||||||
|
|
||||||
// Accumulate damage from old buffers
|
|
||||||
for (int i = 0; i < buffer_age - 1; ++i) {
|
|
||||||
int j = (ring->previous_idx + i) % WLR_DAMAGE_RING_PREVIOUS_LEN;
|
|
||||||
pixman_region32_union(damage, damage, &ring->previous[j]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check the number of rectangles
|
|
||||||
int n_rects = pixman_region32_n_rects(damage);
|
|
||||||
if (n_rects > WLR_DAMAGE_RING_MAX_RECTS) {
|
|
||||||
pixman_box32_t *extents = pixman_region32_extents(damage);
|
|
||||||
pixman_region32_union_rect(damage, damage,
|
|
||||||
extents->x1, extents->y1,
|
|
||||||
extents->x2 - extents->x1,
|
|
||||||
extents->y2 - extents->y1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void entry_squash_damage(struct wlr_damage_ring_buffer *entry) {
|
static void entry_squash_damage(struct wlr_damage_ring_buffer *entry) {
|
||||||
pixman_region32_t *prev;
|
pixman_region32_t *prev;
|
||||||
if (entry->link.prev == &entry->ring->buffers) {
|
if (entry->link.prev == &entry->ring->buffers) {
|
||||||
|
@ -143,7 +143,7 @@ static bool manager_output_prepare(struct wlr_output_swapchain_manager_output *m
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct wlr_buffer *buffer = wlr_swapchain_acquire(swapchain, NULL);
|
struct wlr_buffer *buffer = wlr_swapchain_acquire(swapchain);
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -542,8 +542,7 @@ static void capture_output(struct wl_client *wl_client,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
int buffer_age;
|
struct wlr_buffer *buffer = wlr_swapchain_acquire(output->swapchain);
|
||||||
struct wlr_buffer *buffer = wlr_swapchain_acquire(output->swapchain, &buffer_age);
|
|
||||||
if (buffer == NULL) {
|
if (buffer == NULL) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user