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 <[email protected]>
---
 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

_______________________________________________
wayland-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/wayland-devel

Reply via email to