[PATCH weston 13/13] Update the RPI renderer to handle views
Jason Ekstrand
jason at jlekstrand.net
Sun Oct 13 05:38:23 CEST 2013
Note that I have not been able to test that this patch works properly on
the Pi. Before the RPI EGL patches landed it worked, but I have not been
able to test the rebased version.
Signed-off-by: Jason Ekstrand <jason at jlekstrand.net>
---
src/compositor.c | 18 ++-
src/compositor.h | 4 +
src/rpi-renderer.c | 453 +++++++++++++++++++++++++++++++++--------------------
3 files changed, 298 insertions(+), 177 deletions(-)
diff --git a/src/compositor.c b/src/compositor.c
index e397403..b68b3d3 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -356,6 +356,17 @@ weston_view_create(struct weston_surface *surface)
if (view == NULL)
return NULL;
+ view->surface = surface;
+
+ if (surface->compositor->renderer->create_view &&
+ surface->compositor->renderer->create_view(view) < 0) {
+ free(view);
+ return NULL;
+ }
+
+ /* Assign to surface */
+ wl_list_insert(&surface->views, &view->surface_link);
+
wl_signal_init(&view->destroy_signal);
wl_list_init(&view->link);
wl_list_init(&view->layer_link);
@@ -377,10 +388,6 @@ weston_view_create(struct weston_surface *surface)
view->output = NULL;
- /* Assign to surface */
- view->surface = surface;
- wl_list_insert(&surface->views, &view->surface_link);
-
return view;
}
@@ -1200,6 +1207,9 @@ weston_view_destroy(struct weston_view *view)
weston_view_set_transform_parent(view, NULL);
+ if (view->surface->compositor->renderer->destroy_view)
+ view->surface->compositor->renderer->destroy_view(view);
+
wl_list_remove(&view->surface_link);
free(view);
diff --git a/src/compositor.h b/src/compositor.h
index 5f82e15..0c37037 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -516,10 +516,12 @@ struct weston_renderer {
void (*flush_damage)(struct weston_surface *surface);
void (*attach)(struct weston_surface *es, struct weston_buffer *buffer);
int (*create_surface)(struct weston_surface *surface);
+ int (*create_view)(struct weston_view *view);
void (*surface_set_color)(struct weston_surface *surface,
float red, float green,
float blue, float alpha);
void (*destroy_surface)(struct weston_surface *surface);
+ void (*destroy_view)(struct weston_view *view);
void (*destroy)(struct weston_compositor *ec);
};
@@ -724,6 +726,8 @@ struct weston_view {
pixman_region32_t clip;
float alpha; /* part of geometry, see below */
+ void *renderer_state;
+
/* Surface geometry state, mutable.
* If you change anything, call weston_surface_geometry_dirty().
* That includes the transformations referenced from the list.
diff --git a/src/rpi-renderer.c b/src/rpi-renderer.c
index a95cc60..235223d 100644
--- a/src/rpi-renderer.c
+++ b/src/rpi-renderer.c
@@ -104,13 +104,8 @@ enum buffer_type {
struct rpir_surface {
struct weston_surface *surface;
- /* If link is empty, the surface is guaranteed to not be on screen,
- * i.e. updates removing Elements have completed.
- */
- struct wl_list link;
-
- DISPMANX_ELEMENT_HANDLE_T handle;
- int layer;
+ struct wl_list views;
+ int visible_views;
int need_swap;
int single_buffer;
@@ -127,6 +122,20 @@ struct rpir_surface {
enum buffer_type buffer_type;
};
+struct rpir_view {
+ struct rpir_surface *surface;
+ struct wl_list surface_link;
+ struct weston_view *view;
+
+ /* If link is empty, the view is guaranteed to not be on screen,
+ * i.e. updates removing Elements have completed.
+ */
+ struct wl_list link;
+
+ DISPMANX_ELEMENT_HANDLE_T handle;
+ int layer;
+};
+
struct rpir_output {
DISPMANX_DISPLAY_HANDLE_T display;
@@ -134,10 +143,10 @@ struct rpir_output {
struct weston_matrix matrix;
/* all Elements currently on screen */
- struct wl_list surface_list; /* struct rpir_surface::link */
+ struct wl_list view_list; /* struct rpir_surface::link */
/* Elements just removed, waiting for update completion */
- struct wl_list surface_cleanup_list; /* struct rpir_surface::link */
+ struct wl_list view_cleanup_list; /* struct rpir_surface::link */
struct rpi_resource capture_buffer;
uint8_t *capture_data;
@@ -164,6 +173,12 @@ to_rpir_surface(struct weston_surface *surface)
return surface->renderer_state;
}
+static inline struct rpir_view *
+to_rpir_view(struct weston_view *view)
+{
+ return view->renderer_state;
+}
+
static inline struct rpir_output *
to_rpir_output(struct weston_output *output)
{
@@ -356,9 +371,8 @@ rpir_surface_create(struct rpi_renderer *renderer)
if (!surface)
return NULL;
- wl_list_init(&surface->link);
+ surface->visible_views = 0;
surface->single_buffer = renderer->single_buffer;
- surface->handle = DISPMANX_NO_HANDLE;
rpi_resource_init(&surface->resources[0]);
rpi_resource_init(&surface->resources[1]);
surface->front = &surface->resources[0];
@@ -376,15 +390,18 @@ rpir_surface_create(struct rpi_renderer *renderer)
static void
rpir_surface_destroy(struct rpir_surface *surface)
{
- wl_list_remove(&surface->link);
-
- if (surface->handle != DISPMANX_NO_HANDLE)
+ if (surface->visible_views)
weston_log("ERROR rpi: destroying on-screen element\n");
+ assert(wl_list_empty(&surface->views));
+
+ if (surface->surface)
+ surface->surface->renderer_state = NULL;
+
pixman_region32_fini(&surface->prev_damage);
rpi_resource_release(&surface->resources[0]);
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->visible_views);
if (surface->egl_back != NULL) {
weston_buffer_reference(&surface->egl_back->buffer_ref, NULL);
@@ -436,6 +453,46 @@ rpir_surface_damage(struct rpir_surface *surface, struct weston_buffer *buffer,
return ret;
}
+static struct rpir_view *
+rpir_view_create(struct rpir_surface *surface)
+{
+ struct rpir_view *view;
+
+ view = calloc(1, sizeof *view);
+ if (!view)
+ return NULL;
+
+ view->surface = surface;
+ wl_list_insert(&surface->views, &view->surface_link);
+
+ wl_list_init(&view->link);
+ view->handle = DISPMANX_NO_HANDLE;
+
+ return view;
+}
+
+static void
+rpir_view_destroy(struct rpir_view *view)
+{
+ wl_list_remove(&view->link);
+
+ if (view->handle != DISPMANX_NO_HANDLE) {
+ view->surface->visible_views--;
+ weston_log("ERROR rpi: destroying on-screen element\n");
+ }
+
+ if (view->view)
+ view->view->renderer_state = NULL;
+
+ wl_list_remove(&view->surface_link);
+ if (wl_list_empty(&view->surface->views) && view->surface->surface == NULL)
+ rpir_surface_destroy(view->surface);
+
+ DBG("rpir_view %p destroyed (%d)\n", view, view->handle);
+
+ free(view);
+}
+
static void
matrix_type_str(struct weston_matrix *matrix, char *buf, int len)
{
@@ -495,13 +552,13 @@ warn_bad_matrix(struct weston_matrix *total, struct weston_matrix *output,
/*#define SURFACE_TRANSFORM */
static int
-rpir_surface_compute_rects(struct rpir_surface *surface,
- VC_RECT_T *src_rect, VC_RECT_T *dst_rect,
- VC_IMAGE_TRANSFORM_T *flipmask)
+rpir_view_compute_rects(struct rpir_view *view,
+ VC_RECT_T *src_rect, VC_RECT_T *dst_rect,
+ VC_IMAGE_TRANSFORM_T *flipmask)
{
- struct weston_output *output_base = surface->surface->output;
+ struct weston_output *output_base = view->view->surface->output;
struct rpir_output *output = to_rpir_output(output_base);
- struct weston_matrix matrix = surface->surface->transform.matrix;
+ struct weston_matrix matrix = view->view->transform.matrix;
VC_IMAGE_TRANSFORM_T flipt = 0;
int src_x, src_y;
int dst_x, dst_y;
@@ -523,14 +580,15 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
src_x = 0 << 16;
src_y = 0 << 16;
- if (surface->buffer_type == BUFFER_TYPE_EGL) {
- struct weston_buffer *buffer = surface->egl_front->buffer_ref.buffer;
+ if (view->surface->buffer_type == BUFFER_TYPE_EGL) {
+ struct weston_buffer *buffer =
+ view->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;
+ src_width = view->surface->front->width << 16;
+ src_height = view->surface->front->height << 16;
}
weston_matrix_multiply(&matrix, &output->matrix);
@@ -541,7 +599,7 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
if (matrix.type >= WESTON_MATRIX_TRANSFORM_ROTATE) {
#endif
warn_bad_matrix(&matrix, &output->matrix,
- &surface->surface->transform.matrix);
+ &view->view->transform.matrix);
} else {
if (matrix.type & WESTON_MATRIX_TRANSFORM_ROTATE) {
if (fabsf(matrix.d[0]) < 1e-4f &&
@@ -552,13 +610,13 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
/* no transpose */
} else {
warn_bad_matrix(&matrix, &output->matrix,
- &surface->surface->transform.matrix);
+ &view->view->transform.matrix);
}
}
}
- p2.f[0] = surface->surface->geometry.width;
- p2.f[1] = surface->surface->geometry.height;
+ p2.f[0] = view->view->geometry.width;
+ p2.f[1] = view->view->geometry.height;
/* transform top-left and bot-right corner into screen coordinates */
weston_matrix_transform(&matrix, &p1);
@@ -680,9 +738,9 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
src_width = int_max(src_width, 0);
src_height = int_max(src_height, 0);
- DBG("rpir_surface %p %dx%d: p1 %f, %f; p2 %f, %f\n", surface,
- surface->surface->geometry.width,
- surface->surface->geometry.height,
+ DBG("rpir_view %p %dx%d: p1 %f, %f; p2 %f, %f\n", view,
+ view->view->geometry.width,
+ view->view->geometry.height,
p1.f[0], p1.f[1], p2.f[0], p2.f[1]);
DBG("src rect %d;%d, %d;%d, %d;%dx%d;%d\n",
src_x >> 16, src_x & 0xffff,
@@ -706,7 +764,7 @@ rpir_surface_compute_rects(struct rpir_surface *surface,
}
/* EGL buffers will be upside-down related to what DispmanX expects */
- if (surface->buffer_type == BUFFER_TYPE_EGL)
+ if (view->surface->buffer_type == BUFFER_TYPE_EGL)
flipt ^= TRANSFORM_VFLIP;
vc_dispmanx_rect_set(src_rect, src_x, src_y, src_width, src_height);
@@ -760,8 +818,8 @@ rpir_surface_get_resource(struct rpir_surface *surface)
}
static int
-rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
- DISPMANX_UPDATE_HANDLE_T update, int layer)
+rpir_view_dmx_add(struct rpir_view *view, struct rpir_output *output,
+ DISPMANX_UPDATE_HANDLE_T update, int layer)
{
/* Do not use DISPMANX_FLAGS_ALPHA_PREMULT here.
* If you define PREMULT and ALPHA_MIX, the hardware will not
@@ -771,7 +829,7 @@ rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
VC_DISPMANX_ALPHA_T alphasetup = {
DISPMANX_FLAGS_ALPHA_FROM_SOURCE |
DISPMANX_FLAGS_ALPHA_MIX,
- float2uint8(surface->surface->alpha), /* opacity 0-255 */
+ float2uint8(view->view->alpha), /* opacity 0-255 */
0 /* mask resource handle */
};
VC_RECT_T dst_rect;
@@ -780,18 +838,17 @@ rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
int ret;
DISPMANX_RESOURCE_HANDLE_T resource_handle;
- resource_handle = rpir_surface_get_resource(surface);
+ resource_handle = rpir_surface_get_resource(view->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,
- &flipmask);
+ ret = rpir_view_compute_rects(view, &src_rect, &dst_rect, &flipmask);
if (ret < 0)
return 0;
- surface->handle = vc_dispmanx_element_add(
+ view->handle = vc_dispmanx_element_add(
update,
output->display,
layer,
@@ -802,37 +859,42 @@ rpir_surface_dmx_add(struct rpir_surface *surface, struct rpir_output *output,
&alphasetup,
NULL /* clamp */,
vc_image2dispmanx_transform(flipmask));
- DBG("rpir_surface %p add %u, alpha %f resource %d\n", surface,
- surface->handle, surface->surface->alpha, resource_handle);
+ DBG("rpir_surface %p add %u, alpha %f resource %d\n", view,
+ view->handle, view->view->alpha, resource_handle);
+
+ if (view->handle == DISPMANX_NO_HANDLE)
+ return -1;
+
+ view->surface->visible_views++;
return 1;
}
static void
-rpir_surface_dmx_swap(struct rpir_surface *surface,
- DISPMANX_UPDATE_HANDLE_T update)
+rpir_view_dmx_swap(struct rpir_view *view,
+ DISPMANX_UPDATE_HANDLE_T update)
{
VC_RECT_T rect;
pixman_box32_t *r;
/* XXX: skip, iff resource was not reallocated, and single-buffering */
- vc_dispmanx_element_change_source(update, surface->handle,
- surface->front->handle);
+ vc_dispmanx_element_change_source(update, view->handle,
+ view->surface->front->handle);
/* This is current damage now, after rpir_surface_damage() */
- r = pixman_region32_extents(&surface->prev_damage);
+ r = pixman_region32_extents(&view->surface->prev_damage);
vc_dispmanx_rect_set(&rect, r->x1, r->y1,
r->x2 - r->x1, r->y2 - r->y1);
- vc_dispmanx_element_modified(update, surface->handle, &rect);
- DBG("rpir_surface %p swap\n", surface);
+ vc_dispmanx_element_modified(update, view->handle, &rect);
+ DBG("rpir_view %p swap\n", view);
}
static int
-rpir_surface_dmx_move(struct rpir_surface *surface,
- DISPMANX_UPDATE_HANDLE_T update, int layer)
+rpir_view_dmx_move(struct rpir_view *view,
+ DISPMANX_UPDATE_HANDLE_T update, int layer)
{
- uint8_t alpha = float2uint8(surface->surface->alpha);
+ uint8_t alpha = float2uint8(view->view->alpha);
VC_RECT_T dst_rect;
VC_RECT_T src_rect;
VC_IMAGE_TRANSFORM_T flipmask;
@@ -840,28 +902,27 @@ rpir_surface_dmx_move(struct rpir_surface *surface,
/* XXX: return early, if all attributes stay the same */
- if (surface->buffer_type == BUFFER_TYPE_EGL) {
+ if (view->surface->buffer_type == BUFFER_TYPE_EGL) {
DISPMANX_RESOURCE_HANDLE_T resource_handle;
- resource_handle = rpir_surface_get_resource(surface);
+ resource_handle = rpir_surface_get_resource(view->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,
+ view->handle,
resource_handle);
}
- ret = rpir_surface_compute_rects(surface, &src_rect, &dst_rect,
- &flipmask);
+ ret = rpir_view_compute_rects(view, &src_rect, &dst_rect, &flipmask);
if (ret < 0)
return 0;
ret = vc_dispmanx_element_change_attributes(
update,
- surface->handle,
+ view->handle,
ELEMENT_CHANGE_LAYER |
ELEMENT_CHANGE_OPACITY |
ELEMENT_CHANGE_TRANSFORM |
@@ -875,7 +936,7 @@ rpir_surface_dmx_move(struct rpir_surface *surface,
/* This really is DISPMANX_TRANSFORM_T, no matter
* what the header says. */
vc_image2dispmanx_transform(flipmask));
- DBG("rpir_surface %p move\n", surface);
+ DBG("rpir_view %p move\n", view);
if (ret)
return -1;
@@ -884,15 +945,16 @@ rpir_surface_dmx_move(struct rpir_surface *surface,
}
static void
-rpir_surface_dmx_remove(struct rpir_surface *surface,
- DISPMANX_UPDATE_HANDLE_T update)
+rpir_view_dmx_remove(struct rpir_view *view,
+ DISPMANX_UPDATE_HANDLE_T update)
{
- if (surface->handle == DISPMANX_NO_HANDLE)
+ if (view->handle == DISPMANX_NO_HANDLE)
return;
- vc_dispmanx_element_remove(update, surface->handle);
- DBG("rpir_surface %p remove %u\n", surface, surface->handle);
- surface->handle = DISPMANX_NO_HANDLE;
+ vc_dispmanx_element_remove(update, view->handle);
+ DBG("rpir_view %p remove %u\n", view, view->handle);
+ view->handle = DISPMANX_NO_HANDLE;
+ view->surface->visible_views--;
}
static void
@@ -900,23 +962,31 @@ rpir_surface_swap_pointers(struct rpir_surface *surface)
{
struct rpi_resource *tmp;
- tmp = surface->front;
- surface->front = surface->back;
- surface->back = tmp;
- surface->need_swap = 0;
+ if (surface->buffer_type == BUFFER_TYPE_EGL) {
+ 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;
+ }
+ } else {
+ tmp = surface->front;
+ surface->front = surface->back;
+ surface->back = tmp;
+ }
DBG("new back %p, new front %p\n", surface->back, surface->front);
}
static int
-is_surface_not_visible(struct weston_surface *surface)
+is_view_not_visible(struct weston_view *view)
{
/* Return true, if surface is guaranteed to be totally obscured. */
int ret;
pixman_region32_t unocc;
pixman_region32_init(&unocc);
- pixman_region32_subtract(&unocc, &surface->transform.boundingbox,
- &surface->clip);
+ pixman_region32_subtract(&unocc, &view->transform.boundingbox,
+ &view->clip);
ret = !pixman_region32_not_empty(&unocc);
pixman_region32_fini(&unocc);
@@ -924,81 +994,55 @@ is_surface_not_visible(struct weston_surface *surface)
}
static void
-rpir_surface_update(struct rpir_surface *surface, struct rpir_output *output,
- DISPMANX_UPDATE_HANDLE_T update, int layer)
+rpir_view_update(struct rpir_view *view, struct rpir_output *output,
+ DISPMANX_UPDATE_HANDLE_T update, int layer)
{
- int need_swap = surface->need_swap;
int ret;
int obscured;
+
- if (surface->buffer_type == BUFFER_TYPE_EGL) {
- 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_view_not_visible(view->view);
if (obscured) {
- DBG("rpir_surface %p totally obscured.\n", surface);
+ DBG("rpir_view %p totally obscured.\n", view);
- wl_list_remove(&surface->link);
- if (surface->handle == DISPMANX_NO_HANDLE) {
- wl_list_init(&surface->link);
+ wl_list_remove(&view->link);
+ if (view->handle == DISPMANX_NO_HANDLE) {
+ wl_list_init(&view->link);
} else {
- rpir_surface_dmx_remove(surface, update);
- wl_list_insert(&output->surface_cleanup_list,
- &surface->link);
+ rpir_view_dmx_remove(view, update);
+ wl_list_insert(&output->view_cleanup_list,
+ &view->link);
}
goto out;
}
- if (surface->handle == DISPMANX_NO_HANDLE) {
- ret = rpir_surface_dmx_add(surface, output, update, layer);
+ if (view->handle == DISPMANX_NO_HANDLE) {
+ ret = rpir_view_dmx_add(view, output, update, layer);
if (ret == 0) {
- wl_list_remove(&surface->link);
- wl_list_init(&surface->link);
+ wl_list_remove(&view->link);
+ wl_list_init(&view->link);
} else if (ret < 0) {
- weston_log("ERROR rpir_surface_dmx_add() failed.\n");
+ weston_log("ERROR rpir_view_dmx_add() failed.\n");
}
} else {
- if (need_swap)
- rpir_surface_dmx_swap(surface, update);
+ if (view->surface->need_swap)
+ rpir_view_dmx_swap(view, update);
- ret = rpir_surface_dmx_move(surface, update, layer);
+ ret = rpir_view_dmx_move(view, update, layer);
if (ret == 0) {
- rpir_surface_dmx_remove(surface, update);
+ rpir_view_dmx_remove(view, update);
- wl_list_remove(&surface->link);
- wl_list_insert(&output->surface_cleanup_list,
- &surface->link);
+ wl_list_remove(&view->link);
+ wl_list_insert(&output->view_cleanup_list,
+ &view->link);
} else if (ret < 0) {
- weston_log("ERROR rpir_surface_dmx_move() failed.\n");
+ weston_log("ERROR rpir_view_dmx_move() failed.\n");
}
}
out:
- surface->layer = layer;
+ view->layer = layer;
}
static int
@@ -1105,15 +1149,15 @@ static void
rpir_output_dmx_remove_all(struct rpir_output *output,
DISPMANX_UPDATE_HANDLE_T update)
{
- struct rpir_surface *surface;
+ struct rpir_view *view;
- while (!wl_list_empty(&output->surface_list)) {
- surface = container_of(output->surface_list.next,
- struct rpir_surface, link);
- rpir_surface_dmx_remove(surface, update);
+ while (!wl_list_empty(&output->view_list)) {
+ view = container_of(output->view_list.next,
+ struct rpir_view, link);
+ rpir_view_dmx_remove(view, update);
- wl_list_remove(&surface->link);
- wl_list_insert(&output->surface_cleanup_list, &surface->link);
+ wl_list_remove(&view->link);
+ wl_list_insert(&output->view_cleanup_list, &view->link);
}
}
@@ -1186,8 +1230,8 @@ rpi_renderer_repaint_output(struct weston_output *base,
{
struct weston_compositor *compositor = base->compositor;
struct rpir_output *output = to_rpir_output(base);
- struct weston_surface *ws;
- struct rpir_surface *surface;
+ struct weston_view *wv;
+ struct rpir_view *view;
struct wl_list done_list;
int layer = 1;
@@ -1199,27 +1243,59 @@ rpi_renderer_repaint_output(struct weston_output *base,
free(output->capture_data);
output->capture_data = NULL;
+ /* Swap resources on surfaces as needed */
+ wl_list_for_each_reverse(wv, &compositor->view_list, link)
+ wv->surface->touched = 0;
+
+ wl_list_for_each_reverse(wv, &compositor->view_list, link) {
+ view = to_rpir_view(wv);
+
+ if (!wv->surface->touched) {
+ wv->surface->touched = 1;
+
+ if (view->surface->need_swap)
+ rpir_surface_swap_pointers(view->surface);
+ }
+
+ if (view->surface->egl_front->buffer_ref.buffer == NULL) {
+ weston_log("warning: client unreffed current front buffer\n");
+
+ wl_list_remove(&view->link);
+ if (view->handle == DISPMANX_NO_HANDLE) {
+ wl_list_init(&view->link);
+ } else {
+ rpir_view_dmx_remove(view, output->update);
+ wl_list_insert(&output->view_cleanup_list,
+ &view->link);
+ }
+ }
+ }
+
/* update all renderable surfaces */
wl_list_init(&done_list);
- wl_list_for_each_reverse(ws, &compositor->surface_list, link) {
- if (ws->plane != &compositor->primary_plane)
+ wl_list_for_each_reverse(wv, &compositor->view_list, link) {
+ if (wv->plane != &compositor->primary_plane)
continue;
- surface = to_rpir_surface(ws);
- assert(!wl_list_empty(&surface->link) ||
- surface->handle == DISPMANX_NO_HANDLE);
+ view = to_rpir_view(wv);
+ assert(!wl_list_empty(&view->link) ||
+ view->handle == DISPMANX_NO_HANDLE);
- wl_list_remove(&surface->link);
- wl_list_insert(&done_list, &surface->link);
- rpir_surface_update(surface, output, output->update, layer++);
+ wl_list_remove(&view->link);
+ wl_list_insert(&done_list, &view->link);
+ rpir_view_update(view, output, output->update, layer++);
}
+ /* Mark all surfaces as swapped */
+ wl_list_for_each_reverse(wv, &compositor->view_list, link)
+ to_rpir_surface(wv->surface)->need_swap = 0;
+
/* Remove all surfaces that are still on screen, but were
* not rendered this time.
*/
rpir_output_dmx_remove_all(output, output->update);
- wl_list_insert_list(&output->surface_list, &done_list);
+ wl_list_insert_list(&output->view_list, &done_list);
output->update = DISPMANX_NO_HANDLE;
/* The frame_signal is emitted in rpi_renderer_finish_frame(),
@@ -1263,7 +1339,7 @@ rpi_renderer_attach(struct weston_surface *base, struct weston_buffer *buffer)
/* XXX: need to check if in middle of update */
rpi_resource_release(surface->back);
- if (surface->handle == DISPMANX_NO_HANDLE)
+ if (!surface->visible_views)
/* XXX: cannot do this, if middle of an update */
rpi_resource_release(surface->front);
@@ -1336,6 +1412,23 @@ rpi_renderer_create_surface(struct weston_surface *base)
return 0;
}
+static int
+rpi_renderer_create_view(struct weston_view *base)
+{
+ struct rpir_surface *surface = to_rpir_surface(base->surface);
+ struct rpir_view *view;
+
+ assert(base->renderer_state == NULL);
+
+ view = rpir_view_create(surface);
+ if (!view)
+ return -1;
+
+ view->view = base;
+ base->renderer_state = view;
+ return 0;
+}
+
static void
rpi_renderer_surface_set_color(struct weston_surface *base,
float red, float green, float blue, float alpha)
@@ -1390,13 +1483,27 @@ rpi_renderer_destroy_surface(struct weston_surface *base)
surface->surface = NULL;
base->renderer_state = NULL;
- /* If guaranteed to not be on screen, just detroy it. */
- if (wl_list_empty(&surface->link))
+ if (wl_list_empty(&surface->views))
rpir_surface_destroy(surface);
+}
- /* Otherwise, the surface is either on screen and needs
+static void
+rpi_renderer_destroy_view(struct weston_view *base)
+{
+ struct rpir_view *view = to_rpir_view(base);
+
+ assert(view);
+ assert(view->view == base);
+ if (!view)
+ return;
+
+ /* If guaranteed to not be on screen, just detroy it. */
+ if (wl_list_empty(&view->link))
+ rpir_view_destroy(view);
+
+ /* Otherwise, the view is either on screen and needs
* to be removed by a repaint update, or it is in the
- * surface_cleanup_list, and will be destroyed by
+ * view_cleanup_list, and will be destroyed by
* rpi_renderer_finish_frame().
*/
}
@@ -1440,8 +1547,10 @@ rpi_renderer_create(struct weston_compositor *compositor,
renderer->base.flush_damage = rpi_renderer_flush_damage;
renderer->base.attach = rpi_renderer_attach;
renderer->base.create_surface = rpi_renderer_create_surface;
+ renderer->base.create_view = rpi_renderer_create_view;
renderer->base.surface_set_color = rpi_renderer_surface_set_color;
renderer->base.destroy_surface = rpi_renderer_destroy_surface;
+ renderer->base.destroy_view = rpi_renderer_destroy_view;
renderer->base.destroy = rpi_renderer_destroy;
#ifdef ENABLE_EGL
@@ -1504,8 +1613,8 @@ rpi_renderer_output_create(struct weston_output *base,
output->display = display;
output->update = DISPMANX_NO_HANDLE;
- wl_list_init(&output->surface_list);
- wl_list_init(&output->surface_cleanup_list);
+ wl_list_init(&output->view_list);
+ wl_list_init(&output->view_cleanup_list);
rpi_resource_init(&output->capture_buffer);
base->renderer_state = output;
@@ -1516,7 +1625,7 @@ WL_EXPORT void
rpi_renderer_output_destroy(struct weston_output *base)
{
struct rpir_output *output = to_rpir_output(base);
- struct rpir_surface *surface;
+ struct rpir_view *view;
DISPMANX_UPDATE_HANDLE_T update;
rpi_resource_release(&output->capture_buffer);
@@ -1527,12 +1636,10 @@ rpi_renderer_output_destroy(struct weston_output *base)
rpir_output_dmx_remove_all(output, update);
vc_dispmanx_update_submit_sync(update);
- while (!wl_list_empty(&output->surface_cleanup_list)) {
- surface = container_of(output->surface_cleanup_list.next,
- struct rpir_surface, link);
- if (surface->surface)
- surface->surface->renderer_state = NULL;
- rpir_surface_destroy(surface);
+ while (!wl_list_empty(&output->view_cleanup_list)) {
+ view = container_of(output->view_cleanup_list.next,
+ struct rpir_view, link);
+ rpir_view_destroy(view);
}
free(output);
@@ -1553,41 +1660,41 @@ rpi_renderer_finish_frame(struct weston_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 weston_view *wv;
+ struct rpir_view *view;
- while (!wl_list_empty(&output->surface_cleanup_list)) {
- surface = container_of(output->surface_cleanup_list.next,
- struct rpir_surface, link);
+ while (!wl_list_empty(&output->view_cleanup_list)) {
+ view = container_of(output->view_cleanup_list.next,
+ struct rpir_view, link);
- if (surface->surface) {
- /* The weston_surface still exists, but is
+ if (view->view) {
+ /* The weston_view still exists, but is
* temporarily not visible, and hence its Element
* was removed. The current front buffer contents
* must be preserved.
*/
- if (!surface->single_buffer)
- rpi_resource_release(surface->back);
+ if (!view->surface->visible_views)
+ rpi_resource_release(view->surface->back);
- wl_list_remove(&surface->link);
- wl_list_init(&surface->link);
+ wl_list_remove(&view->link);
+ wl_list_init(&view->link);
} else {
- rpir_surface_destroy(surface);
+ rpir_view_destroy(view);
}
}
- wl_list_for_each(ws, &compositor->surface_list, link) {
- surface = to_rpir_surface(ws);
+ wl_list_for_each(wv, &compositor->view_list, link) {
+ view = to_rpir_view(wv);
- if (surface->buffer_type != BUFFER_TYPE_EGL)
+ if (view->surface->buffer_type != BUFFER_TYPE_EGL)
continue;
- if(surface->egl_old_front == NULL)
+ if (view->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;
+ weston_buffer_reference(&view->surface->egl_old_front->buffer_ref, NULL);
+ free(view->surface->egl_old_front);
+ view->surface->egl_old_front = NULL;
}
wl_signal_emit(&base->frame_signal, base);
--
1.8.3.1
More information about the wayland-devel
mailing list