swapchain: Introduce new helper for damage rings

This is advantageous over rolling your own logic because this will choose
the ideal buffer (the youngest buffer - the one with the least damage)
This commit is contained in:
Alexander Orzechowski 2024-10-14 19:06:38 -04:00
parent 3b3ed21e61
commit 551340a39e
2 changed files with 56 additions and 0 deletions

View file

@ -1,12 +1,15 @@
#ifndef WLR_RENDER_SWAPCHAIN_H
#define WLR_RENDER_SWAPCHAIN_H
#include <pixman.h>
#include <stdbool.h>
#include <wayland-server-core.h>
#include <wlr/render/drm_format_set.h>
#define WLR_SWAPCHAIN_CAP 4
struct wlr_damage_ring;
struct wlr_swapchain_slot {
struct wlr_buffer *buffer;
bool acquired; // waiting for release
@ -29,13 +32,31 @@ struct wlr_swapchain *wlr_swapchain_create(
struct wlr_allocator *alloc, int width, int height,
const struct wlr_drm_format *format);
void wlr_swapchain_destroy(struct wlr_swapchain *swapchain);
/**
* Acquire a buffer from the swap chain.
*
* Can return NULL if the swapchain failed to acquire a buffer either because
* the swapchain is full, or the buffer couldn't be allocated.
*
* The returned buffer is locked. When the caller is done with it, they must
* unlock it by calling wlr_buffer_unlock.
*/
struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain);
/**
* Acquire a buffer from the swap chain that is optimal for the damage ring.
* Will automatically rotate the swapchain.
*
* Can return NULL if the swapchain failed to acquire a buffer either because
* the swapchain is full, or the buffer couldn't be allocated.
*
* The returned buffer is locked. When the caller is done with it, they must
* unlock it by calling wlr_buffer_unlock.
*/
struct wlr_buffer *wlr_swapchain_acquire_from_damage_ring(struct wlr_swapchain *swapchain,
struct wlr_damage_ring *ring, pixman_region32_t *damage);
/**
* Returns true if this buffer has been created by this swapchain, and false
* otherwise.

View file

@ -3,6 +3,7 @@
#include <wlr/util/log.h>
#include <wlr/render/swapchain.h>
#include <wlr/types/wlr_buffer.h>
#include <wlr/types/wlr_damage_ring.h>
#include "render/allocator/allocator.h"
#include "render/drm_format_set.h"
@ -108,6 +109,40 @@ struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain) {
return slot_acquire(swapchain, free_slot);
}
struct wlr_buffer *wlr_swapchain_acquire_from_damage_ring(struct wlr_swapchain *swapchain,
struct wlr_damage_ring *ring, pixman_region32_t *damage) {
struct wlr_buffer *buffer = NULL;
struct wlr_damage_ring_buffer *entry;
wl_list_for_each(entry, &ring->buffers, link) {
for (size_t i = 0; i < WLR_SWAPCHAIN_CAP; i++) {
struct wlr_swapchain_slot *slot = &swapchain->slots[i];
if (slot->acquired) {
continue;
}
if (slot->buffer == entry->buffer) {
buffer = slot_acquire(swapchain, slot);
break;
}
}
if (buffer) {
break;
}
}
if (!buffer) {
buffer = wlr_swapchain_acquire(swapchain);
if (!buffer) {
return NULL;
}
}
wlr_damage_ring_rotate_buffer(ring, buffer, damage);
return buffer;
}
bool wlr_swapchain_has_buffer(struct wlr_swapchain *swapchain,
struct wlr_buffer *buffer) {
for (size_t i = 0; i < WLR_SWAPCHAIN_CAP; i++) {