[PATCH 6/7] gl-renderer: Attach buffer during surface state creation if possible

Ander Conselvan de Oliveira ander.conselvan.de.oliveira at intel.com
Fri Oct 25 15:26:36 CEST 2013


When a renderer switch happen, it is possible that when the surface
state is created, a buffer for the given surface is already available.
In that case, run the attach routine so that the pixel contents are
properly set before a new attach request is made for that surface.

Also, make sure the DRM backend keeps the buffers around until it
switches from pixman to GL.

This makes the renderer transition seamless, without leaving a black
screen as before.
---
 src/compositor-drm.c |   26 ++++++++++++++++----------
 src/gl-renderer.c    |    8 +++++++-
 2 files changed, 23 insertions(+), 11 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 96065bd..5130278 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -107,6 +107,7 @@ struct drm_compositor {
 	int cursors_are_broken;
 
 	int use_pixman;
+	int renderer_switch_pending;
 
 	uint32_t prev_state;
 
@@ -1060,18 +1061,20 @@ drm_assign_planes(struct weston_output *output)
 	pixman_region32_init(&overlap);
 	primary = &c->base.primary_plane;
 
-	/* Flag all visible surfaces as keep_buffer = 1 */
-	wl_list_for_each(ev, &c->base.view_list, link)
-		ev->surface->keep_buffer = 1;
-
 	wl_list_for_each_safe(ev, next, &c->base.view_list, link) {
-		/* test whether this buffer can ever go into a plane:
-		 * non-shm, or small enough to be a cursor
+		struct weston_surface *es = ev->surface;
+
+		/* Test whether this buffer can ever go into a plane:
+		 * non-shm, or small enough to be a cursor. Also keep
+		 * the buffer around if we plan to switch renderers.
 		 */
-		if (!ev->surface->buffer_ref.buffer ||
-		    (wl_shm_buffer_get(ev->surface->buffer_ref.buffer->resource) &&
-		    (ev->geometry.width > 64 || ev->geometry.height > 64)))
-			ev->surface->keep_buffer = 0;
+		if ((es->buffer_ref.buffer &&
+		    (!wl_shm_buffer_get(es->buffer_ref.buffer->resource) ||
+		     (ev->geometry.width <= 64 && ev->geometry.height <= 64) ||
+		     c->renderer_switch_pending)))
+			es->keep_buffer = 1;
+		else
+			es->keep_buffer = 0;
 
 		pixman_region32_init(&surface_overlap);
 		pixman_region32_intersect(&surface_overlap, &overlap,
@@ -2636,6 +2639,7 @@ switch_to_gl_renderer(struct drm_compositor *c)
 		drm_output_init_egl(output, c);
 
 	c->use_pixman = 0;
+	c->renderer_switch_pending = 0;
 }
 
 struct gl_loader_thread_data {
@@ -2708,6 +2712,8 @@ prepare_renderer_switch(struct drm_compositor *ec)
 				     gl_loader_thread_done, ec);
 	ec->gl_loader_fd = sv[0];
 
+	ec->renderer_switch_pending = 1;
+
 	return 0;
 }
 
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 06815b4..e1f9841 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -886,7 +886,8 @@ gl_renderer_flush_damage(struct weston_surface *surface)
 	if (!texture_used)
 		return;
 
-	if (!pixman_region32_not_empty(&gs->texture_damage))
+	if (!pixman_region32_not_empty(&gs->texture_damage) &&
+	    !gs->needs_full_upload)
 		goto done;
 
 	switch (wl_shm_buffer_get_format(buffer->shm_buffer)) {
@@ -1237,6 +1238,11 @@ gl_renderer_create_surface(struct weston_surface *surface)
 	wl_signal_add(&gr->destroy_signal,
 		      &gs->renderer_destroy_listener);
 
+	if (surface->buffer_ref.buffer) {
+		gl_renderer_attach(surface, surface->buffer_ref.buffer);
+		gl_renderer_flush_damage(surface);
+	}
+
 	return 0;
 }
 
-- 
1.7.9.5



More information about the wayland-devel mailing list