libweston: Use explicit renderbuffer destruction

Renderbuffers currently have a libweston-internal base data structure
with a ref-counting system to handle their lifetime. The problem is
that renderers keep a ref to all renderbuffers in a list per output
(to deal with damages) and that it prevents backends from releasing
renderbuffer resources when not needed anymore. Renderbuffers are then
only released (last ref removed) when the output is destroyed or
resized. dma-buf renderbuffers even expose a dedicated function
remove_renderbuffer_dmabuf() to explictly request the release of their
resources.

This commit proposes to get rid of the ref-counting system by exposing
a single entry point to explicitly destroy all types of renderbuffers
from the renderer.

Instead of removing a renderbuffer from its output list and dropping
its ref when the output is resized, this commit also introduces the
concept of stale renderbuffers which consists in releasing the
resources of a renderbuffer when it's discarded by the renderer while
keeping it in the output list, with a stale state, until it's
explicitly destroyed.

Signed-off-by: Loïc Molinari <loic.molinari@collabora.com>
This commit is contained in:
Loïc Molinari 2024-08-01 10:02:11 +02:00
parent 1619a4a1e5
commit b9e199b47d
16 changed files with 196 additions and 222 deletions

View file

@ -580,7 +580,7 @@ struct drm_output {
struct drm_writeback_state *wb_state;
struct drm_fb *dumb[2];
struct weston_renderbuffer *renderbuffer[2];
weston_renderbuffer_t renderbuffer[2];
int current_image;
struct vaapi_recorder *recorder;

View file

@ -1642,7 +1642,7 @@ err:
if (output->dumb[i])
drm_fb_unref(output->dumb[i]);
if (output->renderbuffer[i])
weston_renderbuffer_unref(output->renderbuffer[i]);
renderer->destroy_renderbuffer(output->renderbuffer[i]);
output->dumb[i] = NULL;
output->renderbuffer[i] = NULL;
@ -1668,7 +1668,7 @@ drm_output_fini_pixman(struct drm_output *output)
}
for (i = 0; i < ARRAY_LENGTH(output->dumb); i++) {
weston_renderbuffer_unref(output->renderbuffer[i]);
renderer->destroy_renderbuffer(output->renderbuffer[i]);
drm_fb_unref(output->dumb[i]);
output->dumb[i] = NULL;
output->renderbuffer[i] = NULL;

View file

@ -81,7 +81,7 @@ struct headless_output {
struct weston_mode mode;
struct wl_event_source *finish_frame_timer;
struct weston_renderbuffer *renderbuffer;
weston_renderbuffer_t renderbuffer;
struct frame *frame;
struct {
@ -192,7 +192,7 @@ headless_output_disable_gl(struct headless_output *output)
weston_gl_borders_fini(&output->gl.borders, &output->base);
weston_renderbuffer_unref(output->renderbuffer);
renderer->destroy_renderbuffer(output->renderbuffer);
output->renderbuffer = NULL;
renderer->gl->output_destroy(&output->base);
@ -207,7 +207,7 @@ headless_output_disable_pixman(struct headless_output *output)
{
struct weston_renderer *renderer = output->base.compositor->renderer;
weston_renderbuffer_unref(output->renderbuffer);
renderer->destroy_renderbuffer(output->renderbuffer);
output->renderbuffer = NULL;
renderer->pixman->output_destroy(&output->base);
}

View file

@ -101,7 +101,7 @@ struct pipewire_head {
};
struct pipewire_frame_data {
struct weston_renderbuffer *renderbuffer;
weston_renderbuffer_t renderbuffer;
struct pipewire_memfd *memfd;
struct pipewire_dmabuf *dmabuf;
};
@ -593,7 +593,7 @@ pipewire_output_stream_param_changed(void *data, uint32_t id,
pw_stream_update_params(output->stream, params, 2);
}
static struct weston_renderbuffer *
static weston_renderbuffer_t
pipewire_output_stream_add_buffer_pixman(struct pipewire_output *output,
struct pw_buffer *buffer)
{
@ -618,7 +618,7 @@ pipewire_output_stream_add_buffer_pixman(struct pipewire_output *output,
ptr, stride);
}
static struct weston_renderbuffer *
static weston_renderbuffer_t
pipewire_output_stream_add_buffer_gl(struct pipewire_output *output,
struct pw_buffer *buffer)
{
@ -800,21 +800,20 @@ pipewire_output_stream_remove_buffer(void *data, struct pw_buffer *buffer)
pipewire_output_debug(output, "remove buffer: %p", buffer);
if (frame_data->dmabuf) {
struct weston_compositor *ec = output->base.compositor;
const struct weston_renderer *renderer = ec->renderer;
renderer->remove_renderbuffer_dmabuf(&output->base,
frame_data->renderbuffer);
if (frame_data->dmabuf)
pipewire_destroy_dmabuf(output, frame_data->dmabuf);
}
if (frame_data->memfd) {
munmap(d[0].data, d[0].maxsize);
pipewire_destroy_memfd(output, frame_data->memfd);
}
if (frame_data->renderbuffer)
weston_renderbuffer_unref(frame_data->renderbuffer);
if (frame_data->renderbuffer) {
struct weston_compositor *ec = output->base.compositor;
const struct weston_renderer *renderer = ec->renderer;
renderer->destroy_renderbuffer(frame_data->renderbuffer);
}
wl_list_for_each(fence_data, &output->fence_list, link) {
if (fence_data->buffer == buffer)
fence_data->buffer = NULL;

View file

@ -346,7 +346,7 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
struct weston_output *output = base;
struct rdp_peers_item *rdpPeer;
rdpSettings *settings;
struct weston_renderbuffer *new_renderbuffer;
weston_renderbuffer_t new_renderbuffer;
mode->refresh = b->rdp_monitor_refresh_rate;
weston_output_set_single_mode(base, mode);
@ -384,7 +384,7 @@ rdp_output_set_mode(struct weston_output *base, struct weston_mode *mode)
default:
unreachable("cannot have auto renderer at runtime");
}
weston_renderbuffer_unref(rdpOutput->renderbuffer);
renderer->destroy_renderbuffer(rdpOutput->renderbuffer);
rdpOutput->renderbuffer = new_renderbuffer;
pixman_image_unref(rdpOutput->shadow_surface);
rdpOutput->shadow_surface = new_image;
@ -531,7 +531,7 @@ rdp_output_disable(struct weston_output *base)
if (!output->base.enabled)
return 0;
weston_renderbuffer_unref(output->renderbuffer);
renderer->destroy_renderbuffer(output->renderbuffer);
output->renderbuffer = NULL;
switch (renderer->type) {
case WESTON_RENDERER_PIXMAN:

View file

@ -55,6 +55,7 @@
#include <winpr/string.h>
#include "backend.h"
#include "libweston-internal.h"
#include "shared/helpers.h"
#include "shared/string-helpers.h"
@ -149,7 +150,7 @@ struct rdp_output {
struct weston_output base;
struct rdp_backend *backend;
struct wl_event_source *finish_frame_timer;
struct weston_renderbuffer *renderbuffer;
weston_renderbuffer_t renderbuffer;
pixman_image_t *shadow_surface;
};

View file

@ -674,7 +674,7 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
struct vnc_backend *backend = nvnc_get_userdata(server);
struct vnc_output *output = backend->output;
struct weston_compositor *ec = output->base.compositor;
struct weston_renderbuffer *renderbuffer;
weston_renderbuffer_t renderbuffer;
pixman_region32_t local_damage;
pixman_region16_t nvnc_damage;
struct nvnc_fb *fb;
@ -715,7 +715,7 @@ vnc_update_buffer(struct nvnc_display *display, struct pixman_region32 *damage)
}
nvnc_set_userdata(fb, renderbuffer,
(nvnc_cleanup_fn)weston_renderbuffer_unref);
(nvnc_cleanup_fn)ec->renderer->destroy_renderbuffer);
}
vnc_log_damage(backend, damage);

View file

@ -192,7 +192,7 @@ struct wayland_shm_buffer {
int height;
int frame_damaged;
struct weston_renderbuffer *renderbuffer;
weston_renderbuffer_t renderbuffer;
cairo_surface_t *c_surface;
};
@ -266,9 +266,14 @@ to_wayland_backend(struct weston_backend *base)
static void
wayland_shm_buffer_destroy(struct wayland_shm_buffer *buffer)
{
struct wayland_output *output = buffer->output;
const struct weston_renderer *renderer;
cairo_surface_destroy(buffer->c_surface);
if (buffer->output)
weston_renderbuffer_unref(buffer->renderbuffer);
if (output) {
renderer = output->base.compositor->renderer;
renderer->destroy_renderbuffer(buffer->renderbuffer);
}
wl_buffer_destroy(buffer->buffer);
munmap(buffer->data, buffer->size);
@ -657,15 +662,16 @@ wayland_backend_destroy_output_surface(struct wayland_output *output)
static void
wayland_output_destroy_shm_buffers(struct wayland_output *output)
{
const struct weston_renderer *renderer =
output->base.compositor->renderer;
struct wayland_shm_buffer *buffer, *next;
/* Throw away any remaining SHM buffers */
wl_list_for_each_safe(buffer, next, &output->shm.free_buffers, free_link)
wayland_shm_buffer_destroy(buffer);
/* These will get thrown away when they get released */
wl_list_for_each(buffer, &output->shm.buffers, link) {
if (buffer->renderbuffer) {
weston_renderbuffer_unref(buffer->renderbuffer);
renderer->destroy_renderbuffer(buffer->renderbuffer);
buffer->renderbuffer = NULL;
}
buffer->output = NULL;

View file

@ -140,7 +140,7 @@ struct x11_output {
xcb_gc_t gc;
xcb_shm_seg_t segment;
struct weston_renderbuffer *renderbuffer;
weston_renderbuffer_t renderbuffer;
int shm_id;
void *buf;
uint8_t depth;
@ -568,7 +568,7 @@ x11_output_deinit_shm(struct x11_backend *b, struct x11_output *output)
xcb_generic_error_t *err;
xcb_free_gc(b->conn, output->gc);
weston_renderbuffer_unref(output->renderbuffer);
b->compositor->renderer->destroy_renderbuffer(output->renderbuffer);
output->renderbuffer = NULL;
cookie = xcb_shm_detach_checked(b->conn, output->segment);
err = xcb_request_check(b->conn, cookie);

View file

@ -10414,25 +10414,6 @@ weston_output_disable_planes_decr(struct weston_output *output)
}
WL_EXPORT struct weston_renderbuffer *
weston_renderbuffer_ref(struct weston_renderbuffer *renderbuffer)
{
renderbuffer->refcount++;
return renderbuffer;
}
WL_EXPORT void
weston_renderbuffer_unref(struct weston_renderbuffer *renderbuffer)
{
assert(renderbuffer->refcount > 0);
if (--renderbuffer->refcount > 0)
return;
renderbuffer->destroy(renderbuffer);
}
/** Tell the renderer that the target framebuffer size has changed
*
* \param output The output that was resized.

View file

@ -46,17 +46,9 @@
/* compositor <-> renderer interface */
struct weston_renderbuffer {
int refcount;
void (*destroy)(struct weston_renderbuffer *renderbuffer);
};
struct weston_renderbuffer *
weston_renderbuffer_ref(struct weston_renderbuffer *renderbuffer);
void
weston_renderbuffer_unref(struct weston_renderbuffer *renderbuffer);
/** Opaque pointer to renderbuffer data.
*/
typedef void *weston_renderbuffer_t;
struct weston_renderer_options {
};
@ -74,7 +66,7 @@ struct weston_renderer {
uint32_t width, uint32_t height);
void (*repaint_output)(struct weston_output *output,
pixman_region32_t *output_damage,
struct weston_renderbuffer *renderbuffer);
weston_renderbuffer_t renderbuffer);
/** See weston_renderer_resize_output()
*
@ -112,34 +104,27 @@ struct weston_renderer {
*
* \param output The output to add the DMABUF renderbuffer for.
* \param dmabuf The description object of the DMABUF to import.
* \return A weston_renderbuffer on success, NULL on failure.
* \return A renderbuffer on success, NULL on failure.
*
* This function imports the DMABUF memory as renderbuffer and adds
* it to the output. The returned weston_renderbuffer can be passed to
* This function imports the DMABUF memory as renderbuffer and adds it
* to the output. The returned renderbuffer can be passed to
* repaint_output() to render into the DMABUF.
*
* The ownership of the linux_dmabuf_memory is transferred to the
* returned weston_renderbuffer. The linux_dmabuf_memory will be
* destroyed automatically when the weston_renderbuffer is destroyed.
* returned renderbuffer. The linux_dmabuf_memory will be destroyed
* automatically when the renderbuffer is destroyed.
*/
struct weston_renderbuffer *
weston_renderbuffer_t
(*create_renderbuffer_dmabuf)(struct weston_output *output,
struct linux_dmabuf_memory *dmabuf);
/**
* Remove the DAMBUF renderbuffer from the output
/** Destroy a renderbuffer
*
* \param output The output to remove a DMABUF renderbuffer from.
* \param renderbuffer The weston_renderbuffer that shall be removed
* \param renderbuffer The renderbuffer to destroy.
*
* This function removes the DMABUF renderbuffer from the output.
*
* This allows the backend to signal the renderer that it will no longer
* use the renderbuffer for rendering and the renderer may free the
* resources of the renderbuffer.
* This function destroys a \c renderbuffer.
*/
void (*remove_renderbuffer_dmabuf)(struct weston_output *output,
struct weston_renderbuffer *renderbuffer);
void (*destroy_renderbuffer)(weston_renderbuffer_t renderbuffer);
/* Allocate a DMABUF that can be imported as renderbuffer
*

View file

@ -48,7 +48,7 @@ noop_renderer_read_pixels(struct weston_output *output,
static void
noop_renderer_repaint_output(struct weston_output *output,
pixman_region32_t *output_damage,
struct weston_renderbuffer *renderbuffer)
weston_renderbuffer_t renderbuffer)
{
}

View file

@ -64,10 +64,9 @@ struct pixman_surface_state {
};
struct pixman_renderbuffer {
struct weston_renderbuffer base;
pixman_region32_t damage;
pixman_image_t *image;
bool stale;
struct wl_list link;
};
@ -81,16 +80,11 @@ struct pixman_renderer {
struct wl_signal destroy_signal;
};
static inline struct pixman_renderbuffer *
to_pixman_renderbuffer(struct weston_renderbuffer *renderbuffer)
{
return container_of(renderbuffer, struct pixman_renderbuffer, base);
}
static pixman_image_t *
pixman_renderer_renderbuffer_get_image(struct weston_renderbuffer *renderbuffer)
pixman_renderer_renderbuffer_get_image(weston_renderbuffer_t renderbuffer)
{
struct pixman_renderbuffer *rb = to_pixman_renderbuffer(renderbuffer);
struct pixman_renderbuffer *rb =
(struct pixman_renderbuffer *) renderbuffer;
return rb->image;
}
@ -645,7 +639,7 @@ pixman_renderer_output_set_buffer(struct weston_output *output,
static void
pixman_renderer_repaint_output(struct weston_output *output,
pixman_region32_t *output_damage,
struct weston_renderbuffer *renderbuffer)
weston_renderbuffer_t renderbuffer)
{
struct pixman_output_state *po = get_output_state(output);
struct pixman_renderbuffer *rb;
@ -657,7 +651,7 @@ pixman_renderer_repaint_output(struct weston_output *output,
pixman_region32_union(&rb->damage, &rb->damage, output_damage);
}
rb = to_pixman_renderbuffer(renderbuffer);
rb = (struct pixman_renderbuffer *) renderbuffer;
pixman_renderer_output_set_buffer(output, rb->image);
@ -921,13 +915,54 @@ pixman_renderer_surface_copy_content(struct weston_surface *surface,
return 0;
}
static void
pixman_renderbuffer_fini(struct pixman_renderbuffer *renderbuffer)
{
assert(!renderbuffer->stale);
pixman_region32_fini(&renderbuffer->damage);
pixman_image_unref(renderbuffer->image);
renderbuffer->stale = true;
}
static void
pixman_renderer_destroy_renderbuffer(weston_renderbuffer_t renderbuffer)
{
struct pixman_renderbuffer *rb =
(struct pixman_renderbuffer *) renderbuffer;
wl_list_remove(&rb->link);
if (!rb->stale)
pixman_renderbuffer_fini(rb);
free(rb);
}
static void
pixman_renderer_discard_renderbuffers(struct pixman_output_state *po,
bool destroy)
{
struct pixman_renderbuffer *rb, *tmp;
/* A renderbuffer goes stale after being discarded. Most resources are
* released. It's kept in the output state's renderbuffer list while
* waiting for the backend to destroy it. */
wl_list_for_each_safe(rb, tmp, &po->renderbuffer_list, link) {
if (destroy)
pixman_renderer_destroy_renderbuffer((weston_renderbuffer_t) rb);
else if (!rb->stale)
pixman_renderbuffer_fini(rb);
}
}
static bool
pixman_renderer_resize_output(struct weston_output *output,
const struct weston_size *fb_size,
const struct weston_geometry *area)
{
struct pixman_output_state *po = get_output_state(output);
struct pixman_renderbuffer *renderbuffer, *tmp;
check_compositing_area(fb_size, area);
@ -942,10 +977,7 @@ pixman_renderer_resize_output(struct weston_output *output,
pixman_renderer_output_set_buffer(output, NULL);
wl_list_for_each_safe(renderbuffer, tmp, &po->renderbuffer_list, link) {
wl_list_remove(&renderbuffer->link);
weston_renderbuffer_unref(&renderbuffer->base);
}
pixman_renderer_discard_renderbuffers(po, false);
po->fb_size = *fb_size;
@ -1025,6 +1057,8 @@ pixman_renderer_init(struct weston_compositor *ec)
renderer->base.destroy = pixman_renderer_destroy;
renderer->base.surface_copy_content =
pixman_renderer_surface_copy_content;
renderer->base.destroy_renderbuffer =
pixman_renderer_destroy_renderbuffer;
renderer->base.type = WESTON_RENDERER_PIXMAN;
renderer->base.pixman = &pixman_renderer_interface;
ec->renderer = &renderer->base;
@ -1133,7 +1167,6 @@ static void
pixman_renderer_output_destroy(struct weston_output *output)
{
struct pixman_output_state *po = get_output_state(output);
struct pixman_renderbuffer *renderbuffer, *tmp;
if (po->shadow_image)
pixman_image_unref(po->shadow_image);
@ -1144,18 +1177,12 @@ pixman_renderer_output_destroy(struct weston_output *output)
po->shadow_image = NULL;
po->hw_buffer = NULL;
wl_list_for_each_safe(renderbuffer, tmp, &po->renderbuffer_list, link) {
wl_list_remove(&renderbuffer->link);
weston_renderbuffer_unref(&renderbuffer->base);
}
pixman_renderer_discard_renderbuffers(po, true);
free(po);
}
static void
pixman_renderer_renderbuffer_destroy(struct weston_renderbuffer *renderbuffer);
static struct weston_renderbuffer *
static weston_renderbuffer_t
pixman_renderer_create_image_from_ptr(struct weston_output *output,
const struct pixel_format_info *format,
int width, int height, uint32_t *ptr,
@ -1178,14 +1205,12 @@ pixman_renderer_create_image_from_ptr(struct weston_output *output,
pixman_region32_init(&renderbuffer->damage);
pixman_region32_copy(&renderbuffer->damage, &output->region);
renderbuffer->base.refcount = 2;
renderbuffer->base.destroy = pixman_renderer_renderbuffer_destroy;
wl_list_insert(&po->renderbuffer_list, &renderbuffer->link);
return &renderbuffer->base;
return (weston_renderbuffer_t) renderbuffer;
}
static struct weston_renderbuffer *
static weston_renderbuffer_t
pixman_renderer_create_image(struct weston_output *output,
const struct pixel_format_info *format, int width,
int height)
@ -1207,21 +1232,9 @@ pixman_renderer_create_image(struct weston_output *output,
pixman_region32_init(&renderbuffer->damage);
pixman_region32_copy(&renderbuffer->damage, &output->region);
renderbuffer->base.refcount = 2;
renderbuffer->base.destroy = pixman_renderer_renderbuffer_destroy;
wl_list_insert(&po->renderbuffer_list, &renderbuffer->link);
return &renderbuffer->base;
}
static void
pixman_renderer_renderbuffer_destroy(struct weston_renderbuffer *renderbuffer)
{
struct pixman_renderbuffer *rb = to_pixman_renderbuffer(renderbuffer);
pixman_image_unref(rb->image);
pixman_region32_fini(&rb->damage);
free(rb);
return (weston_renderbuffer_t) renderbuffer;
}
static struct pixman_renderer_interface pixman_renderer_interface = {

View file

@ -47,14 +47,14 @@ struct pixman_renderer_interface {
const struct pixman_renderer_output_options *options);
void (*output_destroy)(struct weston_output *output);
struct weston_renderbuffer *(*create_image_from_ptr)(struct weston_output *output,
const struct pixel_format_info *format,
int width,
int height,
uint32_t *ptr,
int stride);
struct weston_renderbuffer *(*create_image)(struct weston_output *output,
const struct pixel_format_info *format,
int width, int height);
pixman_image_t *(*renderbuffer_get_image)(struct weston_renderbuffer *renderbuffer);
weston_renderbuffer_t (*create_image_from_ptr)(struct weston_output *output,
const struct pixel_format_info *format,
int width,
int height,
uint32_t *ptr,
int stride);
weston_renderbuffer_t (*create_image)(struct weston_output *output,
const struct pixel_format_info *format,
int width, int height);
pixman_image_t *(*renderbuffer_get_image)(weston_renderbuffer_t renderbuffer);
};

View file

@ -90,6 +90,12 @@ enum gl_border_status {
BORDER_SIZE_CHANGED = 0x10
};
enum gl_renderbuffer_type {
RENDERBUFFER_DUMMY = 0,
RENDERBUFFER_FBO,
RENDERBUFFER_DMABUF,
};
struct gl_border_image {
GLuint tex;
int32_t width, height;
@ -103,9 +109,10 @@ struct gl_fbo_texture {
};
struct gl_renderbuffer {
struct weston_renderbuffer base;
enum gl_renderbuffer_type type;
pixman_region32_t damage;
enum gl_border_status border_damage;
bool stale;
/* The fbo value zero represents the default surface framebuffer. */
GLuint fbo;
GLuint rb;
@ -677,12 +684,6 @@ gl_fbo_texture_fini(struct gl_fbo_texture *fbotex)
fbotex->tex = 0;
}
static inline struct gl_renderbuffer *
to_gl_renderbuffer(struct weston_renderbuffer *renderbuffer)
{
return container_of(renderbuffer, struct gl_renderbuffer, base);
}
static inline struct dmabuf_renderbuffer *
to_dmabuf_renderbuffer(struct gl_renderbuffer *renderbuffer)
{
@ -690,14 +691,61 @@ to_dmabuf_renderbuffer(struct gl_renderbuffer *renderbuffer)
}
static void
gl_renderer_renderbuffer_destroy(struct weston_renderbuffer *renderbuffer)
gl_renderbuffer_fini(struct gl_renderbuffer *renderbuffer)
{
struct gl_renderbuffer *rb = to_gl_renderbuffer(renderbuffer);
struct dmabuf_renderbuffer *dmabuf_rb;
glDeleteFramebuffers(1, &rb->fbo);
glDeleteRenderbuffers(1, &rb->rb);
pixman_region32_fini(&rb->damage);
free(rb);
assert(!renderbuffer->stale);
pixman_region32_fini(&renderbuffer->damage);
glDeleteFramebuffers(1, &renderbuffer->fbo);
glDeleteRenderbuffers(1, &renderbuffer->rb);
if (renderbuffer->type == RENDERBUFFER_DMABUF) {
dmabuf_rb = to_dmabuf_renderbuffer(renderbuffer);
dmabuf_rb->gr->destroy_image(dmabuf_rb->gr->egl_display,
dmabuf_rb->image);
}
renderbuffer->stale = true;
}
static void
gl_renderer_destroy_renderbuffer(weston_renderbuffer_t weston_renderbuffer)
{
struct gl_renderbuffer *rb =
(struct gl_renderbuffer *) weston_renderbuffer;
struct dmabuf_renderbuffer *dmabuf_rb;
wl_list_remove(&rb->link);
if (!rb->stale)
gl_renderbuffer_fini(rb);
if (rb->type == RENDERBUFFER_DMABUF) {
dmabuf_rb = to_dmabuf_renderbuffer(rb);
dmabuf_rb->dmabuf->destroy(dmabuf_rb->dmabuf);
free(dmabuf_rb);
} else {
free(rb);
}
}
static void
gl_renderer_discard_renderbuffers(struct gl_output_state *go,
bool destroy)
{
struct gl_renderbuffer *rb, *tmp;
/* A renderbuffer goes stale after being discarded. Most resources are
* released. It's kept in the output states' renderbuffer list waiting
* for the backend to destroy it. */
wl_list_for_each_safe(rb, tmp, &go->renderbuffer_list, link) {
if ((rb->type == RENDERBUFFER_DUMMY) || destroy)
gl_renderer_destroy_renderbuffer((weston_renderbuffer_t) rb);
else if (!rb->stale)
gl_renderbuffer_fini(rb);
}
}
static struct gl_renderbuffer *
@ -708,23 +756,18 @@ gl_renderer_create_dummy_renderbuffer(struct weston_output *output)
renderbuffer = xzalloc(sizeof(*renderbuffer));
renderbuffer->type = RENDERBUFFER_DUMMY;
renderbuffer->fbo = 0;
pixman_region32_init(&renderbuffer->damage);
pixman_region32_copy(&renderbuffer->damage, &output->region);
renderbuffer->border_damage = BORDER_ALL_DIRTY;
/*
* A single reference is kept on the renderbuffer_list,
* the caller just borrows it.
*/
renderbuffer->base.refcount = 1;
renderbuffer->base.destroy = gl_renderer_renderbuffer_destroy;
wl_list_insert(&go->renderbuffer_list, &renderbuffer->link);
return renderbuffer;
}
static struct weston_renderbuffer *
static weston_renderbuffer_t
gl_renderer_create_fbo(struct weston_output *output,
const struct pixel_format_info *format,
int width, int height, uint32_t *pixels)
@ -775,18 +818,13 @@ gl_renderer_create_fbo(struct weston_output *output,
}
renderbuffer->pixels = pixels;
renderbuffer->type = RENDERBUFFER_FBO;
pixman_region32_init(&renderbuffer->damage);
pixman_region32_copy(&renderbuffer->damage, &output->region);
/*
* One reference is kept on the renderbuffer_list,
* the other is returned to the calling backend.
*/
renderbuffer->base.refcount = 2;
renderbuffer->base.destroy = gl_renderer_renderbuffer_destroy;
wl_list_insert(&go->renderbuffer_list, &renderbuffer->link);
return &renderbuffer->base;
return (weston_renderbuffer_t) renderbuffer;
}
static bool
@ -2337,7 +2375,7 @@ blit_shadow_to_output(struct weston_output *output,
static void
gl_renderer_repaint_output(struct weston_output *output,
pixman_region32_t *output_damage,
struct weston_renderbuffer *renderbuffer)
weston_renderbuffer_t renderbuffer)
{
struct gl_output_state *go = get_output_state(output);
struct weston_compositor *compositor = output->compositor;
@ -2362,7 +2400,7 @@ gl_renderer_repaint_output(struct weston_output *output,
}
if (renderbuffer)
rb = to_gl_renderbuffer(renderbuffer);
rb = (struct gl_renderbuffer *) renderbuffer;
else
rb = output_get_dummy_renderbuffer(output);
@ -4020,22 +4058,6 @@ gl_renderer_output_set_border(struct weston_output *output,
go->border_status |= 1 << side;
}
static void
gl_renderer_remove_renderbuffer(struct gl_renderbuffer *renderbuffer)
{
wl_list_remove(&renderbuffer->link);
weston_renderbuffer_unref(&renderbuffer->base);
}
static void
gl_renderer_remove_renderbuffers(struct gl_output_state *go)
{
struct gl_renderbuffer *renderbuffer, *tmp;
wl_list_for_each_safe(renderbuffer, tmp, &go->renderbuffer_list, link)
gl_renderer_remove_renderbuffer(renderbuffer);
}
static bool
gl_renderer_resize_output(struct weston_output *output,
const struct weston_size *fb_size,
@ -4048,7 +4070,7 @@ gl_renderer_resize_output(struct weston_output *output,
check_compositing_area(fb_size, area);
gl_renderer_remove_renderbuffers(go);
gl_renderer_discard_renderbuffers(go, false);
go->fb_size = *fb_size;
go->area = *area;
@ -4199,26 +4221,7 @@ gl_renderer_output_fbo_create(struct weston_output *output,
&options->fb_size, &options->area);
}
static void
gl_renderer_dmabuf_renderbuffer_destroy(struct weston_renderbuffer *renderbuffer)
{
struct gl_renderbuffer *gl_renderbuffer = to_gl_renderbuffer(renderbuffer);
struct dmabuf_renderbuffer *dmabuf_renderbuffer = to_dmabuf_renderbuffer(gl_renderbuffer);
struct gl_renderer *gr = dmabuf_renderbuffer->gr;
glDeleteFramebuffers(1, &gl_renderbuffer->fbo);
glDeleteRenderbuffers(1, &gl_renderbuffer->rb);
pixman_region32_fini(&gl_renderbuffer->damage);
gr->destroy_image(gr->egl_display, dmabuf_renderbuffer->image);
/* Destroy the owned dmabuf */
dmabuf_renderbuffer->dmabuf->destroy(dmabuf_renderbuffer->dmabuf);
free(dmabuf_renderbuffer);
}
static struct weston_renderbuffer *
static weston_renderbuffer_t
gl_renderer_create_renderbuffer_dmabuf(struct weston_output *output,
struct linux_dmabuf_memory *dmabuf)
{
@ -4272,26 +4275,12 @@ gl_renderer_create_renderbuffer_dmabuf(struct weston_output *output,
rb->gr = gr;
rb->dmabuf = dmabuf;
renderbuffer->type = RENDERBUFFER_DMABUF;
pixman_region32_init(&renderbuffer->damage);
pixman_region32_copy(&renderbuffer->damage, &output->region);
/*
* One reference is kept on the renderbuffer_list,
* the other is returned to the calling backend.
*/
rb->base.base.refcount = 2;
rb->base.base.destroy = gl_renderer_dmabuf_renderbuffer_destroy;
wl_list_insert(&go->renderbuffer_list, &rb->base.link);
wl_list_insert(&go->renderbuffer_list, &renderbuffer->link);
return &rb->base.base;
}
static void
gl_renderer_remove_renderbuffer_dmabuf(struct weston_output *output,
struct weston_renderbuffer *renderbuffer)
{
struct gl_renderbuffer *gl_renderbuffer = to_gl_renderbuffer(renderbuffer);
gl_renderer_remove_renderbuffer(gl_renderbuffer);
return (weston_renderbuffer_t) rb;
}
#ifdef HAVE_GBM
@ -4403,7 +4392,7 @@ gl_renderer_output_destroy(struct weston_output *output)
if (go->render_sync != EGL_NO_SYNC_KHR)
gr->destroy_sync(gr->egl_display, go->render_sync);
gl_renderer_remove_renderbuffers(go);
gl_renderer_discard_renderbuffers(go, true);
free(go);
}
@ -4581,6 +4570,7 @@ gl_renderer_display_create(struct weston_compositor *ec,
gr->base.read_pixels = gl_renderer_read_pixels;
gr->base.repaint_output = gl_renderer_repaint_output;
gr->base.resize_output = gl_renderer_resize_output;
gr->base.destroy_renderbuffer = gl_renderer_destroy_renderbuffer;
gr->base.flush_damage = gl_renderer_flush_damage;
gr->base.attach = gl_renderer_attach;
gr->base.destroy = gl_renderer_destroy;
@ -4649,7 +4639,6 @@ gl_renderer_display_create(struct weston_compositor *ec,
gr->base.import_dmabuf = gl_renderer_import_dmabuf;
gr->base.get_supported_formats = gl_renderer_get_supported_formats;
gr->base.create_renderbuffer_dmabuf = gl_renderer_create_renderbuffer_dmabuf;
gr->base.remove_renderbuffer_dmabuf = gl_renderer_remove_renderbuffer_dmabuf;
ret = populate_supported_formats(ec, &gr->supported_formats);
if (ret < 0)
goto fail_terminate;

View file

@ -230,8 +230,8 @@ struct gl_renderer_interface {
* glReadPixels to download pixel data into the provided buffer after
* repaint.
*/
struct weston_renderbuffer *(*create_fbo)(struct weston_output *output,
const struct pixel_format_info *format,
int width, int height,
uint32_t *pixels);
weston_renderbuffer_t (*create_fbo)(struct weston_output *output,
const struct pixel_format_info *format,
int width, int height,
uint32_t *pixels);
};