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
