mirror of
https://gitlab.freedesktop.org/wayland/weston.git
synced 2025-12-20 02:20:13 +01:00
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:
parent
1619a4a1e5
commit
b9e199b47d
16 changed files with 196 additions and 222 deletions
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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 = {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue