rpi: Add support for EGL buffers
The EGL implementation on the RPi allocates a front and a back DispmanX resources for each EGLSurface, which we composite along the others.
This commit is contained in:
committed by
Kristian Høgsberg
parent
8d7bef2673
commit
b4659eb159
@@ -296,6 +296,13 @@ vc_dispmanx_snapshot(DISPMANX_DISPLAY_HANDLE_T display,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct wl_resource;
|
||||||
|
static inline DISPMANX_RESOURCE_HANDLE_T
|
||||||
|
vc_dispmanx_get_handle_from_wl_buffer(struct wl_resource *_buffer)
|
||||||
|
{
|
||||||
|
return DISPMANX_NO_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
/* from /opt/vc/include/EGL/eglplatform.h */
|
/* from /opt/vc/include/EGL/eglplatform.h */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
+248
-33
@@ -35,6 +35,12 @@
|
|||||||
#include "compositor.h"
|
#include "compositor.h"
|
||||||
#include "rpi-renderer.h"
|
#include "rpi-renderer.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_EGL
|
||||||
|
#include <EGL/egl.h>
|
||||||
|
#include <EGL/eglext.h>
|
||||||
|
#include "weston-egl-ext.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Dispmanx API offers alpha-blended overlays for hardware compositing.
|
* Dispmanx API offers alpha-blended overlays for hardware compositing.
|
||||||
* The final composite consists of dispmanx elements, and their contents:
|
* The final composite consists of dispmanx elements, and their contents:
|
||||||
@@ -84,6 +90,17 @@ struct rpi_resource {
|
|||||||
|
|
||||||
struct rpir_output;
|
struct rpir_output;
|
||||||
|
|
||||||
|
struct rpir_egl_buffer {
|
||||||
|
struct weston_buffer_reference buffer_ref;
|
||||||
|
DISPMANX_RESOURCE_HANDLE_T resource_handle;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum buffer_type {
|
||||||
|
BUFFER_TYPE_NULL,
|
||||||
|
BUFFER_TYPE_SHM,
|
||||||
|
BUFFER_TYPE_EGL
|
||||||
|
};
|
||||||
|
|
||||||
struct rpir_surface {
|
struct rpir_surface {
|
||||||
struct weston_surface *surface;
|
struct weston_surface *surface;
|
||||||
|
|
||||||
@@ -102,7 +119,12 @@ struct rpir_surface {
|
|||||||
struct rpi_resource *back;
|
struct rpi_resource *back;
|
||||||
pixman_region32_t prev_damage;
|
pixman_region32_t prev_damage;
|
||||||
|
|
||||||
|
struct rpir_egl_buffer *egl_front;
|
||||||
|
struct rpir_egl_buffer *egl_back;
|
||||||
|
struct rpir_egl_buffer *egl_old_front;
|
||||||
|
|
||||||
struct weston_buffer_reference buffer_ref;
|
struct weston_buffer_reference buffer_ref;
|
||||||
|
enum buffer_type buffer_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rpir_output {
|
struct rpir_output {
|
||||||
@@ -125,6 +147,15 @@ struct rpi_renderer {
|
|||||||
struct weston_renderer base;
|
struct weston_renderer base;
|
||||||
|
|
||||||
int single_buffer;
|
int single_buffer;
|
||||||
|
|
||||||
|
#ifdef ENABLE_EGL
|
||||||
|
EGLDisplay egl_display;
|
||||||
|
|
||||||
|
PFNEGLBINDWAYLANDDISPLAYWL bind_display;
|
||||||
|
PFNEGLUNBINDWAYLANDDISPLAYWL unbind_display;
|
||||||
|
PFNEGLQUERYWAYLANDBUFFERWL query_buffer;
|
||||||
|
#endif
|
||||||
|
int has_bind_display;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline struct rpir_surface *
|
static inline struct rpir_surface *
|
||||||
@@ -335,6 +366,7 @@ rpir_surface_create(struct rpi_renderer *renderer)
|
|||||||
surface->back = &surface->resources[0];
|
surface->back = &surface->resources[0];
|
||||||
else
|
else
|
||||||
surface->back = &surface->resources[1];
|
surface->back = &surface->resources[1];
|
||||||
|
surface->buffer_type = BUFFER_TYPE_NULL;
|
||||||
|
|
||||||
pixman_region32_init(&surface->prev_damage);
|
pixman_region32_init(&surface->prev_damage);
|
||||||
|
|
||||||
@@ -354,6 +386,24 @@ rpir_surface_destroy(struct rpir_surface *surface)
|
|||||||
rpi_resource_release(&surface->resources[1]);
|
rpi_resource_release(&surface->resources[1]);
|
||||||
DBG("rpir_surface %p destroyed (%u)\n", surface, surface->handle);
|
DBG("rpir_surface %p destroyed (%u)\n", surface, surface->handle);
|
||||||
|
|
||||||
|
if (surface->egl_back != NULL) {
|
||||||
|
weston_buffer_reference(&surface->egl_back->buffer_ref, NULL);
|
||||||
|
free(surface->egl_back);
|
||||||
|
surface->egl_back = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (surface->egl_front != NULL) {
|
||||||
|
weston_buffer_reference(&surface->egl_front->buffer_ref, NULL);
|
||||||
|
free(surface->egl_front);
|
||||||
|
surface->egl_front = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (surface->egl_old_front != NULL) {
|
||||||
|
weston_buffer_reference(&surface->egl_old_front->buffer_ref, NULL);
|
||||||
|
free(surface->egl_old_front);
|
||||||
|
surface->egl_old_front = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
free(surface);
|
free(surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,8 +522,16 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
|
|||||||
|
|
||||||
src_x = 0 << 16;
|
src_x = 0 << 16;
|
||||||
src_y = 0 << 16;
|
src_y = 0 << 16;
|
||||||
src_width = surface->front->width << 16;
|
|
||||||
src_height = surface->front->height << 16;
|
if (surface->buffer_type == BUFFER_TYPE_EGL) {
|
||||||
|
struct weston_buffer *buffer = surface->egl_front->buffer_ref.buffer;
|
||||||
|
|
||||||
|
src_width = buffer->width << 16;
|
||||||
|
src_height = buffer->height << 16;
|
||||||
|
} else {
|
||||||
|
src_width = surface->front->width << 16;
|
||||||
|
src_height = surface->front->height << 16;
|
||||||
|
}
|
||||||
|
|
||||||
weston_matrix_multiply(&matrix, &output->matrix);
|
weston_matrix_multiply(&matrix, &output->matrix);
|
||||||
|
|
||||||
@@ -647,6 +705,10 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* EGL buffers will be upside-down related to what DispmanX expects */
|
||||||
|
if (surface->buffer_type == BUFFER_TYPE_EGL)
|
||||||
|
flipt ^= TRANSFORM_VFLIP;
|
||||||
|
|
||||||
vc_dispmanx_rect_set(src_rect, src_x, src_y, src_width, src_height);
|
vc_dispmanx_rect_set(src_rect, src_x, src_y, src_width, src_height);
|
||||||
vc_dispmanx_rect_set(dst_rect, dst_x, dst_y, dst_width, dst_height);
|
vc_dispmanx_rect_set(dst_rect, dst_x, dst_y, dst_width, dst_height);
|
||||||
*flipmask = flipt;
|
*flipmask = flipt;
|
||||||
@@ -681,6 +743,22 @@ vc_image2dispmanx_transform(VC_IMAGE_TRANSFORM_T t)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static DISPMANX_RESOURCE_HANDLE_T
|
||||||
|
rpir_surface_get_resource(struct rpir_surface *surface)
|
||||||
|
{
|
||||||
|
switch (surface->buffer_type) {
|
||||||
|
case BUFFER_TYPE_SHM:
|
||||||
|
case BUFFER_TYPE_NULL:
|
||||||
|
return surface->front->handle;
|
||||||
|
case BUFFER_TYPE_EGL:
|
||||||
|
if (surface->egl_front != NULL)
|
||||||
|
return surface->egl_front->resource_handle;
|
||||||
|
default:
|
||||||
|
return DISPMANX_NO_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
|
rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
|
||||||
DISPMANX_UPDATE_HANDLE_T update, int layer)
|
DISPMANX_UPDATE_HANDLE_T update, int layer)
|
||||||
@@ -700,6 +778,13 @@ rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
|
|||||||
VC_RECT_T src_rect;
|
VC_RECT_T src_rect;
|
||||||
VC_IMAGE_TRANSFORM_T flipmask;
|
VC_IMAGE_TRANSFORM_T flipmask;
|
||||||
int ret;
|
int ret;
|
||||||
|
DISPMANX_RESOURCE_HANDLE_T resource_handle;
|
||||||
|
|
||||||
|
resource_handle = rpir_surface_get_resource(surface);
|
||||||
|
if (resource_handle == DISPMANX_NO_HANDLE) {
|
||||||
|
weston_log("%s: no buffer yet, aborting\n", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
ret = rpir_surface_compute_rects(surface, &src_rect, &dst_rect,
|
ret = rpir_surface_compute_rects(surface, &src_rect, &dst_rect,
|
||||||
&flipmask);
|
&flipmask);
|
||||||
@@ -711,17 +796,14 @@ rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
|
|||||||
output->display,
|
output->display,
|
||||||
layer,
|
layer,
|
||||||
&dst_rect,
|
&dst_rect,
|
||||||
surface->front->handle,
|
resource_handle,
|
||||||
&src_rect,
|
&src_rect,
|
||||||
DISPMANX_PROTECTION_NONE,
|
DISPMANX_PROTECTION_NONE,
|
||||||
&alphasetup,
|
&alphasetup,
|
||||||
NULL /* clamp */,
|
NULL /* clamp */,
|
||||||
vc_image2dispmanx_transform(flipmask));
|
vc_image2dispmanx_transform(flipmask));
|
||||||
DBG("rpir_surface %p add %u, alpha %f\n", surface, surface->handle,
|
DBG("rpir_surface %p add %u, alpha %f resource %d\n", surface,
|
||||||
surface->surface->alpha);
|
surface->handle, surface->surface->alpha, resource_handle);
|
||||||
|
|
||||||
if (surface->handle == DISPMANX_NO_HANDLE)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -758,6 +840,20 @@ rpir_surface_dmx_move(struct rpir_surface *surface,
|
|||||||
|
|
||||||
/* XXX: return early, if all attributes stay the same */
|
/* XXX: return early, if all attributes stay the same */
|
||||||
|
|
||||||
|
if (surface->buffer_type == BUFFER_TYPE_EGL) {
|
||||||
|
DISPMANX_RESOURCE_HANDLE_T resource_handle;
|
||||||
|
|
||||||
|
resource_handle = rpir_surface_get_resource(surface);
|
||||||
|
if (resource_handle == DISPMANX_NO_HANDLE) {
|
||||||
|
weston_log("%s: no buffer yet, aborting\n", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vc_dispmanx_element_change_source(update,
|
||||||
|
surface->handle,
|
||||||
|
resource_handle);
|
||||||
|
}
|
||||||
|
|
||||||
ret = rpir_surface_compute_rects(surface, &src_rect, &dst_rect,
|
ret = rpir_surface_compute_rects(surface, &src_rect, &dst_rect,
|
||||||
&flipmask);
|
&flipmask);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
@@ -835,8 +931,31 @@ rpir_surface_update(struct rpir_surface *surface, struct rpir_output *output,
|
|||||||
int ret;
|
int ret;
|
||||||
int obscured;
|
int obscured;
|
||||||
|
|
||||||
if (need_swap)
|
if (surface->buffer_type == BUFFER_TYPE_EGL) {
|
||||||
rpir_surface_swap_pointers(surface);
|
if (surface->egl_back != NULL) {
|
||||||
|
assert(surface->egl_old_front == NULL);
|
||||||
|
surface->egl_old_front = surface->egl_front;
|
||||||
|
surface->egl_front = surface->egl_back;
|
||||||
|
surface->egl_back = NULL;
|
||||||
|
}
|
||||||
|
if (surface->egl_front->buffer_ref.buffer == NULL) {
|
||||||
|
weston_log("warning: client unreffed current front buffer\n");
|
||||||
|
|
||||||
|
wl_list_remove(&surface->link);
|
||||||
|
if (surface->handle == DISPMANX_NO_HANDLE) {
|
||||||
|
wl_list_init(&surface->link);
|
||||||
|
} else {
|
||||||
|
rpir_surface_dmx_remove(surface, update);
|
||||||
|
wl_list_insert(&output->surface_cleanup_list,
|
||||||
|
&surface->link);
|
||||||
|
}
|
||||||
|
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (need_swap)
|
||||||
|
rpir_surface_swap_pointers(surface);
|
||||||
|
}
|
||||||
|
|
||||||
obscured = is_surface_not_visible(surface->surface);
|
obscured = is_surface_not_visible(surface->surface);
|
||||||
if (obscured) {
|
if (obscured) {
|
||||||
@@ -1133,40 +1252,72 @@ static void
|
|||||||
rpi_renderer_attach(struct weston_surface *base, struct weston_buffer *buffer)
|
rpi_renderer_attach(struct weston_surface *base, struct weston_buffer *buffer)
|
||||||
{
|
{
|
||||||
/* Called every time a client commits an attach. */
|
/* Called every time a client commits an attach. */
|
||||||
static int warned;
|
|
||||||
struct rpir_surface *surface = to_rpir_surface(base);
|
struct rpir_surface *surface = to_rpir_surface(base);
|
||||||
|
|
||||||
assert(surface);
|
assert(surface);
|
||||||
if (!surface)
|
if (!surface)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (buffer && !wl_shm_buffer_get(buffer->resource) && !warned) {
|
if (surface->buffer_type == BUFFER_TYPE_SHM) {
|
||||||
weston_log("Error: non-wl_shm buffers not supported.\n");
|
if (!surface->single_buffer)
|
||||||
warned = 1;
|
/* XXX: need to check if in middle of update */
|
||||||
return;
|
rpi_resource_release(surface->back);
|
||||||
|
|
||||||
|
if (surface->handle == DISPMANX_NO_HANDLE)
|
||||||
|
/* XXX: cannot do this, if middle of an update */
|
||||||
|
rpi_resource_release(surface->front);
|
||||||
|
|
||||||
|
weston_buffer_reference(&surface->buffer_ref, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wl_shm_buffer_get(buffer->resource)) {
|
|
||||||
buffer->shm_buffer = wl_shm_buffer_get(buffer->resource);
|
|
||||||
buffer->width = wl_shm_buffer_get_width(buffer->shm_buffer);
|
|
||||||
buffer->height = wl_shm_buffer_get_height(buffer->shm_buffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
weston_buffer_reference(&surface->buffer_ref, buffer);
|
|
||||||
|
|
||||||
/* XXX: need to check if in middle of update
|
|
||||||
if (!buffer && !surface->single_buffer)
|
|
||||||
rpi_resource_release(surface->back); */
|
|
||||||
|
|
||||||
/* XXX: cannot do this, if middle of an update
|
|
||||||
if (surface->handle == DISPMANX_NO_HANDLE)
|
|
||||||
rpi_resource_release(surface->front); */
|
|
||||||
|
|
||||||
/* If buffer is NULL, Weston core unmaps the surface, the surface
|
/* If buffer is NULL, Weston core unmaps the surface, the surface
|
||||||
* will not appear in repaint list, and so rpi_renderer_repaint_output
|
* will not appear in repaint list, and so rpi_renderer_repaint_output
|
||||||
* will remove the DispmanX element. Later, also the front buffer
|
* will remove the DispmanX element. Later, for SHM, also the front
|
||||||
* will be released in the cleanup_list processing.
|
* buffer will be released in the cleanup_list processing.
|
||||||
*/
|
*/
|
||||||
|
if (!buffer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (wl_shm_buffer_get(buffer->resource)) {
|
||||||
|
surface->buffer_type = BUFFER_TYPE_SHM;
|
||||||
|
buffer->shm_buffer = wl_shm_buffer_get(buffer->resource);
|
||||||
|
buffer->width = wl_shm_buffer_get_width(buffer->shm_buffer);
|
||||||
|
buffer->height = wl_shm_buffer_get_height(buffer->shm_buffer);
|
||||||
|
|
||||||
|
weston_buffer_reference(&surface->buffer_ref, buffer);
|
||||||
|
} else {
|
||||||
|
#if ENABLE_EGL
|
||||||
|
struct rpi_renderer *renderer = to_rpi_renderer(base->compositor);
|
||||||
|
struct wl_resource *wl_resource =
|
||||||
|
(struct wl_resource *)buffer->resource;
|
||||||
|
|
||||||
|
if (!renderer->has_bind_display ||
|
||||||
|
!renderer->query_buffer(renderer->egl_display,
|
||||||
|
wl_resource,
|
||||||
|
EGL_WIDTH, &buffer->width)) {
|
||||||
|
weston_log("unhandled buffer type!\n");
|
||||||
|
weston_buffer_reference(&surface->buffer_ref, NULL);
|
||||||
|
surface->buffer_type = BUFFER_TYPE_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->query_buffer(renderer->egl_display,
|
||||||
|
wl_resource,
|
||||||
|
EGL_HEIGHT, &buffer->height);
|
||||||
|
|
||||||
|
surface->buffer_type = BUFFER_TYPE_EGL;
|
||||||
|
|
||||||
|
if(surface->egl_back == NULL)
|
||||||
|
surface->egl_back = calloc(1, sizeof *surface->egl_back);
|
||||||
|
|
||||||
|
weston_buffer_reference(&surface->egl_back->buffer_ref, buffer);
|
||||||
|
surface->egl_back->resource_handle =
|
||||||
|
vc_dispmanx_get_handle_from_wl_buffer(wl_resource);
|
||||||
|
#else
|
||||||
|
weston_log("unhandled buffer type!\n");
|
||||||
|
weston_buffer_reference(&surface->buffer_ref, NULL);
|
||||||
|
surface->buffer_type = BUFFER_TYPE_NULL;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -1256,6 +1407,12 @@ rpi_renderer_destroy(struct weston_compositor *compositor)
|
|||||||
{
|
{
|
||||||
struct rpi_renderer *renderer = to_rpi_renderer(compositor);
|
struct rpi_renderer *renderer = to_rpi_renderer(compositor);
|
||||||
|
|
||||||
|
#if ENABLE_EGL
|
||||||
|
if (renderer->has_bind_display)
|
||||||
|
renderer->unbind_display(renderer->egl_display,
|
||||||
|
compositor->wl_display);
|
||||||
|
#endif
|
||||||
|
|
||||||
free(renderer);
|
free(renderer);
|
||||||
compositor->renderer = NULL;
|
compositor->renderer = NULL;
|
||||||
}
|
}
|
||||||
@@ -1265,6 +1422,11 @@ rpi_renderer_create(struct weston_compositor *compositor,
|
|||||||
const struct rpi_renderer_parameters *params)
|
const struct rpi_renderer_parameters *params)
|
||||||
{
|
{
|
||||||
struct rpi_renderer *renderer;
|
struct rpi_renderer *renderer;
|
||||||
|
#if ENABLE_EGL
|
||||||
|
const char *extensions;
|
||||||
|
EGLBoolean ret;
|
||||||
|
EGLint major, minor;
|
||||||
|
#endif
|
||||||
|
|
||||||
weston_log("Initializing the DispmanX compositing renderer\n");
|
weston_log("Initializing the DispmanX compositing renderer\n");
|
||||||
|
|
||||||
@@ -1283,6 +1445,43 @@ rpi_renderer_create(struct weston_compositor *compositor,
|
|||||||
renderer->base.destroy_surface = rpi_renderer_destroy_surface;
|
renderer->base.destroy_surface = rpi_renderer_destroy_surface;
|
||||||
renderer->base.destroy = rpi_renderer_destroy;
|
renderer->base.destroy = rpi_renderer_destroy;
|
||||||
|
|
||||||
|
#ifdef ENABLE_EGL
|
||||||
|
renderer->egl_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||||
|
if (renderer->egl_display == EGL_NO_DISPLAY) {
|
||||||
|
weston_log("failed to create EGL display\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eglInitialize(renderer->egl_display, &major, &minor)) {
|
||||||
|
weston_log("failed to initialize EGL display\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderer->bind_display =
|
||||||
|
(void *) eglGetProcAddress("eglBindWaylandDisplayWL");
|
||||||
|
renderer->unbind_display =
|
||||||
|
(void *) eglGetProcAddress("eglUnbindWaylandDisplayWL");
|
||||||
|
renderer->query_buffer =
|
||||||
|
(void *) eglGetProcAddress("eglQueryWaylandBufferWL");
|
||||||
|
|
||||||
|
extensions = (const char *) eglQueryString(renderer->egl_display,
|
||||||
|
EGL_EXTENSIONS);
|
||||||
|
if (!extensions) {
|
||||||
|
weston_log("Retrieving EGL extension string failed.\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strstr(extensions, "EGL_WL_bind_wayland_display"))
|
||||||
|
renderer->has_bind_display = 1;
|
||||||
|
|
||||||
|
if (renderer->has_bind_display) {
|
||||||
|
ret = renderer->bind_display(renderer->egl_display,
|
||||||
|
compositor->wl_display);
|
||||||
|
if (!ret)
|
||||||
|
renderer->has_bind_display = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
compositor->renderer = &renderer->base;
|
compositor->renderer = &renderer->base;
|
||||||
compositor->read_format = PIXMAN_a8r8g8b8;
|
compositor->read_format = PIXMAN_a8r8g8b8;
|
||||||
/* WESTON_CAP_ROTATION_ANY not supported */
|
/* WESTON_CAP_ROTATION_ANY not supported */
|
||||||
@@ -1354,6 +1553,8 @@ WL_EXPORT void
|
|||||||
rpi_renderer_finish_frame(struct weston_output *base)
|
rpi_renderer_finish_frame(struct weston_output *base)
|
||||||
{
|
{
|
||||||
struct rpir_output *output = to_rpir_output(base);
|
struct rpir_output *output = to_rpir_output(base);
|
||||||
|
struct weston_compositor *compositor = base->compositor;
|
||||||
|
struct weston_surface *ws;
|
||||||
struct rpir_surface *surface;
|
struct rpir_surface *surface;
|
||||||
|
|
||||||
while (!wl_list_empty(&output->surface_cleanup_list)) {
|
while (!wl_list_empty(&output->surface_cleanup_list)) {
|
||||||
@@ -1376,5 +1577,19 @@ rpi_renderer_finish_frame(struct weston_output *base)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wl_list_for_each(ws, &compositor->surface_list, link) {
|
||||||
|
surface = to_rpir_surface(ws);
|
||||||
|
|
||||||
|
if (surface->buffer_type != BUFFER_TYPE_EGL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(surface->egl_old_front == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
weston_buffer_reference(&surface->egl_old_front->buffer_ref, NULL);
|
||||||
|
free(surface->egl_old_front);
|
||||||
|
surface->egl_old_front = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
wl_signal_emit(&base->frame_signal, base);
|
wl_signal_emit(&base->frame_signal, base);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user