[PATCH weston] compositor: add a map ref-count for weston_surface

Giulio Camuffo giuliocamuffo at gmail.com
Thu Aug 15 08:11:19 PDT 2013


add a 'mapped' field to weston_surface so that it is initialized
to 0 on surface creation, and to 1 when the surface output is set.
One can manually increase it to make the surface remain visible
after an attach with a NULL buffer, so that it can animate it and
call weston_surface_unmap at the end. weston_surface_unmap decreases
the value of mapped and if it reaches 0 it actually unmaps the surface.
Instead of setting surface->output directly it is now preferable to
set a surface's output via the new function weston_surface_set_output,
which checks if it was mapped before, and if not it increases the
mapped value.
---
 src/compositor.c | 24 +++++++++++++++++++++---
 src/compositor.h |  5 +++++
 src/shell.c      | 14 +++++++-------
 3 files changed, 33 insertions(+), 10 deletions(-)

diff --git a/src/compositor.c b/src/compositor.c
index 8da348a..cae74e1 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -299,6 +299,7 @@ weston_surface_create(struct weston_compositor *compositor)
 	surface->pending.buffer_transform = surface->buffer_transform;
 	surface->pending.buffer_scale = surface->buffer_scale;
 	surface->output = NULL;
+	surface->mapped = 0;
 	surface->plane = &compositor->primary_plane;
 	surface->pending.newly_attached = 0;
 
@@ -567,7 +568,7 @@ weston_surface_assign_output(struct weston_surface *es)
 	}
 	pixman_region32_fini(&region);
 
-	es->output = new_output;
+	weston_surface_set_output(es, new_output);
 	weston_surface_update_output_mask(es, mask);
 }
 
@@ -885,6 +886,16 @@ weston_surface_set_transform_parent(struct weston_surface *surface,
 	weston_surface_geometry_dirty(surface);
 }
 
+WL_EXPORT void
+weston_surface_set_output(struct weston_surface *surface,
+						  struct weston_output *output)
+{
+	if (!weston_surface_is_mapped(surface))
+		++surface->mapped;
+
+	surface->output = output;
+}
+
 WL_EXPORT int
 weston_surface_is_mapped(struct weston_surface *surface)
 {
@@ -976,7 +987,11 @@ weston_surface_unmap(struct weston_surface *surface)
 {
 	struct weston_seat *seat;
 
+	if (--surface->mapped > 0)
+		return;
+
 	weston_surface_damage_below(surface);
+	surface->mapped = 0;
 	surface->output = NULL;
 	wl_list_remove(&surface->layer_link);
 
@@ -1137,9 +1152,11 @@ weston_surface_attach(struct weston_surface *surface,
 	if (!buffer) {
 		if (weston_surface_is_mapped(surface))
 			weston_surface_unmap(surface);
+	} else {
+		// Keep the old buffer around, so that it can be used to do
+		// unmap animations by the shell
+		surface->compositor->renderer->attach(surface, buffer);
 	}
-
-	surface->compositor->renderer->attach(surface, buffer);
 }
 
 WL_EXPORT void
@@ -2008,6 +2025,7 @@ subsurface_configure(struct weston_surface *surface, int32_t dx, int32_t dy,
 		assert(!wl_list_empty(&compositor->output_list));
 		surface->output = container_of(compositor->output_list.next,
 					       struct weston_output, link);
+		++surface->mapped;
 	}
 }
 
diff --git a/src/compositor.h b/src/compositor.h
index 6db3c61..891db0e 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -710,6 +710,7 @@ struct weston_surface {
 	float alpha;                     /* part of geometry, see below */
 	struct weston_plane *plane;
 	int32_t ref_count;
+	int32_t mapped;
 
 	void *renderer_state;
 
@@ -851,6 +852,10 @@ weston_surface_buffer_width(struct weston_surface *surface);
 int32_t
 weston_surface_buffer_height(struct weston_surface *surface);
 
+void
+weston_surface_set_output(struct weston_surface *surface,
+						  struct weston_output *output);
+
 WL_EXPORT void
 weston_surface_to_buffer_float(struct weston_surface *surface,
 			       float x, float y, float *bx, float *by);
diff --git a/src/shell.c b/src/shell.c
index 8f2be78..88685d0 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -1790,7 +1790,7 @@ shell_configure_fullscreen(struct shell_surface *shsurf)
 	wl_list_remove(&shsurf->fullscreen.black_surface->layer_link);
 	wl_list_insert(&surface->layer_link,
 		       &shsurf->fullscreen.black_surface->layer_link);
-	shsurf->fullscreen.black_surface->output = output;
+	weston_surface_set_output(shsurf->fullscreen.black_surface, output);
 
 	surface_subsurfaces_boundingbox(surface, &surf_x, &surf_y,
 	                                &surf_width, &surf_height);
@@ -2149,7 +2149,7 @@ shell_map_popup(struct shell_surface *shsurf)
 	struct weston_surface *es = shsurf->surface;
 	struct weston_surface *parent = shsurf->parent;
 
-	es->output = parent->output;
+	weston_surface_set_output(es, parent->output);
 
 	weston_surface_set_transform_parent(es, parent);
 	weston_surface_set_position(es, shsurf->popup.x, shsurf->popup.y);
@@ -2453,7 +2453,7 @@ desktop_shell_set_background(struct wl_client *client,
 
 	surface->configure = background_configure;
 	surface->configure_private = shell;
-	surface->output = wl_resource_get_user_data(output_resource);
+	weston_surface_set_output(surface, wl_resource_get_user_data(output_resource));
 	desktop_shell_send_configure(resource, 0,
 				     surface_resource,
 				     surface->output->width,
@@ -2487,7 +2487,7 @@ desktop_shell_set_panel(struct wl_client *client,
 
 	surface->configure = panel_configure;
 	surface->configure_private = shell;
-	surface->output = wl_resource_get_user_data(output_resource);
+	weston_surface_set_output(surface, wl_resource_get_user_data(output_resource));
 	desktop_shell_send_configure(resource, 0,
 				     surface_resource,
 				     surface->output->width,
@@ -3434,7 +3434,7 @@ map(struct desktop_shell *shell, struct weston_surface *surface,
 	if (surface_type != SHELL_SURFACE_NONE) {
 		weston_surface_update_transform(surface);
 		if (surface_type == SHELL_SURFACE_MAXIMIZED)
-			surface->output = shsurf->output;
+			weston_surface_set_output(surface, shsurf->output);
 	}
 
 	switch (surface_type) {
@@ -3509,7 +3509,7 @@ configure(struct desktop_shell *shell, struct weston_surface *surface,
 		weston_surface_update_transform(surface);
 
 		if (surface_type == SHELL_SURFACE_MAXIMIZED)
-			surface->output = shsurf->output;
+			weston_surface_set_output(surface, shsurf->output);
 	}
 }
 
@@ -3685,7 +3685,7 @@ screensaver_set_surface(struct wl_client *client,
 
 	surface->configure = screensaver_configure;
 	surface->configure_private = shell;
-	surface->output = output;
+	weston_surface_set_output(surface, output);
 }
 
 static const struct screensaver_interface screensaver_implementation = {
-- 
1.8.3.4



More information about the wayland-devel mailing list