diff --git a/src/compositor.c b/src/compositor.c index 2ed6b1e36..563badeda 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -407,11 +407,6 @@ weston_surface_create(struct weston_compositor *compositor) surface->compositor = compositor; surface->ref_count = 1; - if (compositor->renderer->create_surface(surface) < 0) { - free(surface); - return NULL; - } - surface->buffer_transform = WL_OUTPUT_TRANSFORM_NORMAL; surface->buffer_scale = 1; surface->pending.buffer_transform = surface->buffer_transform; @@ -1220,7 +1215,6 @@ weston_view_destroy(struct weston_view *view) WL_EXPORT void weston_surface_destroy(struct weston_surface *surface) { - struct weston_compositor *compositor = surface->compositor; struct weston_frame_callback *cb, *next; struct weston_view *ev, *nv; @@ -1248,8 +1242,6 @@ weston_surface_destroy(struct weston_surface *surface) weston_buffer_reference(&surface->buffer_ref, NULL); - compositor->renderer->destroy_surface(surface); - pixman_region32_fini(&surface->damage); pixman_region32_fini(&surface->opaque); pixman_region32_fini(&surface->input); diff --git a/src/compositor.h b/src/compositor.h index 73722b5a6..e60a512f5 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -521,12 +521,10 @@ struct weston_renderer { pixman_region32_t *output_damage); 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); }; diff --git a/src/gl-renderer.c b/src/gl-renderer.c index 0f0b5f744..0c0f2d941 100644 --- a/src/gl-renderer.c +++ b/src/gl-renderer.c @@ -79,6 +79,10 @@ struct gl_surface_state { int pitch; /* in pixels */ int height; /* in pixels */ int y_inverted; + + struct weston_surface *surface; + + struct wl_listener surface_destroy_listener; }; struct gl_renderer { @@ -134,9 +138,15 @@ get_output_state(struct weston_output *output) return (struct gl_output_state *)output->renderer_state; } +static int +gl_renderer_create_surface(struct weston_surface *surface); + static inline struct gl_surface_state * get_surface_state(struct weston_surface *surface) { + if (!surface->renderer_state) + gl_renderer_create_surface(surface); + return (struct gl_surface_state *)surface->renderer_state; } @@ -997,6 +1007,8 @@ gl_renderer_attach_shm(struct weston_surface *es, struct weston_buffer *buffer, gs->needs_full_upload = 1; gs->y_inverted = 1; + gs->surface = es; + ensure_textures(gs, 1); glBindTexture(GL_TEXTURE_2D, gs->textures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, @@ -1136,6 +1148,31 @@ gl_renderer_surface_set_color(struct weston_surface *surface, gs->shader = &gr->solid_shader; } +static void +surface_state_handle_surface_destroy(struct wl_listener *listener, void *data) +{ + struct gl_surface_state *gs; + struct gl_renderer *gr; + struct weston_surface *surface = data; + int i; + + gr = get_renderer(surface->compositor); + + gs = container_of(listener, struct gl_surface_state, + surface_destroy_listener); + + gs->surface->renderer_state = NULL; + + glDeleteTextures(gs->num_textures, gs->textures); + + for (i = 0; i < gs->num_images; i++) + gr->destroy_image(gr->egl_display, gs->images[i]); + + weston_buffer_reference(&gs->buffer_ref, NULL); + pixman_region32_fini(&gs->texture_damage); + free(gs); +} + static int gl_renderer_create_surface(struct weston_surface *surface) { @@ -1155,26 +1192,14 @@ gl_renderer_create_surface(struct weston_surface *surface) pixman_region32_init(&gs->texture_damage); surface->renderer_state = gs; + gs->surface_destroy_listener.notify = + surface_state_handle_surface_destroy; + wl_signal_add(&surface->destroy_signal, + &gs->surface_destroy_listener); + return 0; } -static void -gl_renderer_destroy_surface(struct weston_surface *surface) -{ - struct gl_surface_state *gs = get_surface_state(surface); - struct gl_renderer *gr = get_renderer(surface->compositor); - int i; - - glDeleteTextures(gs->num_textures, gs->textures); - - for (i = 0; i < gs->num_images; i++) - gr->destroy_image(gr->egl_display, gs->images[i]); - - weston_buffer_reference(&gs->buffer_ref, NULL); - pixman_region32_fini(&gs->texture_damage); - free(gs); -} - static const char vertex_shader[] = "uniform mat4 proj;\n" "attribute vec2 position;\n" @@ -1655,9 +1680,7 @@ gl_renderer_create(struct weston_compositor *ec, EGLNativeDisplayType display, gr->base.repaint_output = gl_renderer_repaint_output; gr->base.flush_damage = gl_renderer_flush_damage; gr->base.attach = gl_renderer_attach; - gr->base.create_surface = gl_renderer_create_surface; gr->base.surface_set_color = gl_renderer_surface_set_color; - gr->base.destroy_surface = gl_renderer_destroy_surface; gr->base.destroy = gl_renderer_destroy; gr->egl_display = eglGetDisplay(display); diff --git a/src/noop-renderer.c b/src/noop-renderer.c index 91659f585..ad750b5ac 100644 --- a/src/noop-renderer.c +++ b/src/noop-renderer.c @@ -51,23 +51,12 @@ noop_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) { } -static int -noop_renderer_create_surface(struct weston_surface *surface) -{ - return 0; -} - static void noop_renderer_surface_set_color(struct weston_surface *surface, float red, float green, float blue, float alpha) { } -static void -noop_renderer_destroy_surface(struct weston_surface *surface) -{ -} - static void noop_renderer_destroy(struct weston_compositor *ec) { @@ -88,9 +77,7 @@ noop_renderer_init(struct weston_compositor *ec) renderer->repaint_output = noop_renderer_repaint_output; renderer->flush_damage = noop_renderer_flush_damage; renderer->attach = noop_renderer_attach; - renderer->create_surface = noop_renderer_create_surface; renderer->surface_set_color = noop_renderer_surface_set_color; - renderer->destroy_surface = noop_renderer_destroy_surface; renderer->destroy = noop_renderer_destroy; ec->renderer = renderer; diff --git a/src/pixman-renderer.c b/src/pixman-renderer.c index 0d85e07ff..98a910ceb 100644 --- a/src/pixman-renderer.c +++ b/src/pixman-renderer.c @@ -37,8 +37,12 @@ struct pixman_output_state { }; struct pixman_surface_state { + struct weston_surface *surface; + pixman_image_t *image; struct weston_buffer_reference buffer_ref; + + struct wl_listener surface_destroy_listener; }; struct pixman_renderer { @@ -55,9 +59,15 @@ get_output_state(struct weston_output *output) return (struct pixman_output_state *)output->renderer_state; } +static int +pixman_renderer_create_surface(struct weston_surface *surface); + static inline struct pixman_surface_state * get_surface_state(struct weston_surface *surface) { + if (!surface->renderer_state) + pixman_renderer_create_surface(surface); + return (struct pixman_surface_state *)surface->renderer_state; } @@ -582,6 +592,24 @@ pixman_renderer_attach(struct weston_surface *es, struct weston_buffer *buffer) wl_shm_buffer_get_stride(shm_buffer)); } +static void +surface_state_handle_surface_destroy(struct wl_listener *listener, void *data) +{ + struct pixman_surface_state *ps; + + ps = container_of(listener, struct pixman_surface_state, + surface_destroy_listener); + + ps->surface->renderer_state = NULL; + + if (ps->image) { + pixman_image_unref(ps->image); + ps->image = NULL; + } + weston_buffer_reference(&ps->buffer_ref, NULL); + free(ps); +} + static int pixman_renderer_create_surface(struct weston_surface *surface) { @@ -593,6 +621,13 @@ pixman_renderer_create_surface(struct weston_surface *surface) surface->renderer_state = ps; + ps->surface = surface; + + ps->surface_destroy_listener.notify = + surface_state_handle_surface_destroy; + wl_signal_add(&surface->destroy_signal, + &ps->surface_destroy_listener); + return 0; } @@ -616,19 +651,6 @@ pixman_renderer_surface_set_color(struct weston_surface *es, ps->image = pixman_image_create_solid_fill(&color); } -static void -pixman_renderer_destroy_surface(struct weston_surface *surface) -{ - struct pixman_surface_state *ps = get_surface_state(surface); - - if (ps->image) { - pixman_image_unref(ps->image); - ps->image = NULL; - } - weston_buffer_reference(&ps->buffer_ref, NULL); - free(ps); -} - static void pixman_renderer_destroy(struct weston_compositor *ec) { @@ -676,9 +698,7 @@ pixman_renderer_init(struct weston_compositor *ec) renderer->base.repaint_output = pixman_renderer_repaint_output; renderer->base.flush_damage = pixman_renderer_flush_damage; renderer->base.attach = pixman_renderer_attach; - renderer->base.create_surface = pixman_renderer_create_surface; renderer->base.surface_set_color = pixman_renderer_surface_set_color; - renderer->base.destroy_surface = pixman_renderer_destroy_surface; renderer->base.destroy = pixman_renderer_destroy; ec->renderer = &renderer->base; ec->capabilities |= WESTON_CAP_ROTATION_ANY; diff --git a/src/rpi-renderer.c b/src/rpi-renderer.c index 7cbb4e837..b7e948749 100644 --- a/src/rpi-renderer.c +++ b/src/rpi-renderer.c @@ -120,6 +120,8 @@ struct rpir_surface { struct weston_buffer_reference buffer_ref; enum buffer_type buffer_type; + + struct wl_listener surface_destroy_listener; }; struct rpir_view { @@ -167,9 +169,15 @@ struct rpi_renderer { int has_bind_display; }; +static int +rpi_renderer_create_surface(struct weston_surface *base); + static inline struct rpir_surface * to_rpir_surface(struct weston_surface *surface) { + if (!surface->renderer_state) + rpi_renderer_create_surface(surface); + return surface->renderer_state; } @@ -1411,6 +1419,27 @@ rpi_renderer_attach(struct weston_surface *base, struct weston_buffer *buffer) } } +static void +rpir_surface_handle_surface_destroy(struct wl_listener *listener, void *data) +{ + struct rpir_surface *surface; + struct weston_surface *base = data; + + surface = container_of(listener, struct rpir_surface, + surface_destroy_listener); + + assert(surface); + assert(surface->surface == base); + if (!surface) + return; + + surface->surface = NULL; + base->renderer_state = NULL; + + if (wl_list_empty(&surface->views)) + rpir_surface_destroy(surface); +} + static int rpi_renderer_create_surface(struct weston_surface *base) { @@ -1425,6 +1454,12 @@ rpi_renderer_create_surface(struct weston_surface *base) surface->surface = base; base->renderer_state = surface; + + surface->surface_destroy_listener.notify = + rpir_surface_handle_surface_destroy; + wl_signal_add(&base->destroy_signal, + &surface->surface_destroy_listener); + return 0; } @@ -1486,23 +1521,6 @@ rpi_renderer_surface_set_color(struct weston_surface *base, surface->need_swap = 1; } -static void -rpi_renderer_destroy_surface(struct weston_surface *base) -{ - struct rpir_surface *surface = to_rpir_surface(base); - - assert(surface); - assert(surface->surface == base); - if (!surface) - return; - - surface->surface = NULL; - base->renderer_state = NULL; - - if (wl_list_empty(&surface->views)) - rpir_surface_destroy(surface); -} - static void rpi_renderer_destroy_view(struct weston_view *base) { @@ -1564,10 +1582,8 @@ rpi_renderer_create(struct weston_compositor *compositor, renderer->base.repaint_output = rpi_renderer_repaint_output; 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;