[PATCH 1/4] compositor: prepare for multi-planar surfaces.

Gwenole Beauchesne gb.devel at gmail.com
Fri Apr 20 08:17:27 PDT 2012


Make weston_surface::texture and ::surface an array, while keeping
[0] for RGB surfaces.

Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne at intel.com>
---
 src/compositor-drm.c |   14 ++++---
 src/compositor.c     |   87 +++++++++++++++++++++++++++++++++++---------------
 src/compositor.h     |    6 ++-
 3 files changed, 73 insertions(+), 34 deletions(-)

diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index 837da8c..673497b 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -176,12 +176,12 @@ drm_output_prepare_scanout_surface(struct drm_output *output)
 	    es->geometry.width != output->base.current->width ||
 	    es->geometry.height != output->base.current->height ||
 	    es->transform.enabled ||
-	    es->image == EGL_NO_IMAGE_KHR)
+	    es->images[0] == EGL_NO_IMAGE_KHR)
 		return -1;
 
 	output->next_bo =
 		gbm_bo_create_from_egl_image(c->gbm,
-					     c->base.display, es->image,
+					     c->base.display, es->images[0],
 					     es->geometry.width,
 					     es->geometry.height,
 					     GBM_BO_USE_SCANOUT);
@@ -471,7 +471,7 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
 	if (surface_is_primary(ec, es))
 		return -1;
 
-	if (es->image == EGL_NO_IMAGE_KHR)
+	if (es->num_images != 1 || es->images[0] == EGL_NO_IMAGE_KHR)
 		return -1;
 
 	if (!drm_surface_transform_supported(es))
@@ -494,7 +494,7 @@ drm_output_prepare_overlay_surface(struct weston_output *output_base,
 	if (!found)
 		return -1;
 
-	bo = gbm_bo_create_from_egl_image(c->gbm, c->base.display, es->image,
+	bo = gbm_bo_create_from_egl_image(c->gbm, c->base.display, es->images[0],
 					  es->geometry.width, es->geometry.height,
 					  GBM_BO_USE_SCANOUT);
 	format = gbm_bo_get_format(bo);
@@ -681,7 +681,9 @@ drm_output_set_cursor(struct weston_output *output_base,
 		return 0;
 	}
 
-	if (eid->sprite->image == EGL_NO_IMAGE_KHR)
+	if (eid->sprite->num_images != 1)
+		goto out;
+	if (eid->sprite->images[0] == EGL_NO_IMAGE_KHR)
 		goto out;
 
 	if (eid->sprite->geometry.width > 64 ||
@@ -690,7 +692,7 @@ drm_output_set_cursor(struct weston_output *output_base,
 
 	bo = gbm_bo_create_from_egl_image(c->gbm,
 					  c->base.display,
-					  eid->sprite->image, 64, 64,
+					  eid->sprite->images[0], 64, 64,
 					  GBM_BO_USE_CURSOR_64X64);
 	/* Not suitable for hw cursor, fall back */
 	if (bo == NULL)
diff --git a/src/compositor.c b/src/compositor.c
index abf5ce9..58cc894 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -211,6 +211,7 @@ WL_EXPORT struct weston_surface *
 weston_surface_create(struct weston_compositor *compositor)
 {
 	struct weston_surface *surface;
+	unsigned int i;
 
 	surface = calloc(1, sizeof *surface);
 	if (surface == NULL)
@@ -224,12 +225,19 @@ weston_surface_create(struct weston_compositor *compositor)
 	surface->surface.resource.client = NULL;
 
 	surface->compositor = compositor;
-	surface->image = EGL_NO_IMAGE_KHR;
 	surface->alpha = 255;
 	surface->brightness = 255;
 	surface->saturation = 255;
 	surface->pitch = 1;
 
+	for (i = 0; i < ARRAY_LENGTH(surface->textures); i++)
+		surface->textures[i] = 0;
+	surface->num_textures = 0;
+
+	for (i = 0; i < ARRAY_LENGTH(surface->images); i++)
+		surface->images[i] = EGL_NO_IMAGE_KHR;
+	surface->num_images = 0;
+
 	surface->buffer = NULL;
 	surface->output = NULL;
 
@@ -638,25 +646,37 @@ weston_surface_unmap(struct weston_surface *surface)
 }
 
 static void
+destroy_image(struct weston_compositor *compositor, EGLImageKHR *image_ptr)
+{
+	EGLImageKHR const image = *image_ptr;
+
+	if (image != EGL_NO_IMAGE_KHR) {
+		compositor->destroy_image(compositor->display, image);
+		*image_ptr = EGL_NO_IMAGE_KHR;
+	}
+}
+
+static void
 destroy_surface(struct wl_resource *resource)
 {
 	struct weston_surface *surface =
 		container_of(resource,
 			     struct weston_surface, surface.resource);
 	struct weston_compositor *compositor = surface->compositor;
+	unsigned int i;
 
 	if (weston_surface_is_mapped(surface))
 		weston_surface_unmap(surface);
 
-	if (surface->texture)
-		glDeleteTextures(1, &surface->texture);
+	glDeleteTextures(surface->num_textures, surface->textures);
+	surface->num_textures = 0;
 
 	if (surface->buffer)
 		wl_list_remove(&surface->buffer_destroy_listener.link);
 
-	if (surface->image != EGL_NO_IMAGE_KHR)
-		compositor->destroy_image(compositor->display,
-					  surface->image);
+	for (i = 0; i < surface->num_images; i++)
+		destroy_image(compositor, &surface->images[i]);
+	surface->num_images = 0;
 
 	pixman_region32_fini(&surface->transform.boundingbox);
 	pixman_region32_fini(&surface->damage);
@@ -678,6 +698,26 @@ weston_surface_destroy(struct weston_surface *surface)
 }
 
 static void
+ensure_textures(struct weston_surface *es, unsigned int num_textures)
+{
+	unsigned int i;
+
+	if (num_textures <= es->num_textures)
+		return;
+
+	for (i = es->num_textures; i < num_textures; i++) {
+		glGenTextures(1, &es->textures[i]);
+		glBindTexture(GL_TEXTURE_2D, es->textures[i]);
+		glTexParameteri(GL_TEXTURE_2D,
+				GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+		glTexParameteri(GL_TEXTURE_2D,
+				GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+	}
+	es->num_textures = num_textures;
+	glBindTexture(GL_TEXTURE_2D, 0);
+}
+
+static void
 weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
 {
 	struct weston_surface *es = (struct weston_surface *) surface;
@@ -707,33 +747,28 @@ weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
 		pixman_region32_init(&es->opaque);
 	}
 
-	if (!es->texture) {
-		glGenTextures(1, &es->texture);
-		glBindTexture(GL_TEXTURE_2D, es->texture);
-		glTexParameteri(GL_TEXTURE_2D,
-				GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-		glTexParameteri(GL_TEXTURE_2D,
-				GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-		es->shader = &ec->texture_shader;
-	} else {
-		glBindTexture(GL_TEXTURE_2D, es->texture);
-	}
-
 	if (wl_buffer_is_shm(buffer)) {
 		es->pitch = wl_shm_buffer_get_stride(buffer) / 4;
+		es->shader = &ec->texture_shader;
+
+		ensure_textures(es, 1);
+		glBindTexture(GL_TEXTURE_2D, es->textures[0]);
 		glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
 			     es->pitch, es->buffer->height, 0,
 			     GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
 	} else {
-		if (es->image != EGL_NO_IMAGE_KHR)
-			ec->destroy_image(ec->display, es->image);
-		es->image = ec->create_image(ec->display, NULL,
-					     EGL_WAYLAND_BUFFER_WL,
-					     buffer, NULL);
+		destroy_image(ec, &es->images[0]);
+		es->images[0] = ec->create_image(ec->display, NULL,
+						 EGL_WAYLAND_BUFFER_WL,
+						 buffer, NULL);
+		es->num_images = 1;
 
-		ec->image_target_texture_2d(GL_TEXTURE_2D, es->image);
+		ensure_textures(es, 1);
+		glBindTexture(GL_TEXTURE_2D, es->textures[0]);
+		ec->image_target_texture_2d(GL_TEXTURE_2D, es->images[0]);
 
 		es->pitch = buffer->width;
+		es->shader = &ec->texture_shader;
 	}
 }
 
@@ -836,7 +871,7 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output,
 
 	n = texture_region(es, &repaint);
 
-	glBindTexture(GL_TEXTURE_2D, es->texture);
+	glBindTexture(GL_TEXTURE_2D, es->textures[0]);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
 
@@ -1182,7 +1217,7 @@ static void
 texture_set_subimage(struct weston_surface *surface,
 		     int32_t x, int32_t y, int32_t width, int32_t height)
 {
-	glBindTexture(GL_TEXTURE_2D, surface->texture);
+	glBindTexture(GL_TEXTURE_2D, surface->textures[0]);
 
 #ifdef GL_UNPACK_ROW_LENGTH
 	/* Mesa does not define GL_EXT_unpack_subimage */
diff --git a/src/compositor.h b/src/compositor.h
index b19900b..a5eea05 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -283,7 +283,8 @@ struct weston_region {
 struct weston_surface {
 	struct wl_surface surface;
 	struct weston_compositor *compositor;
-	GLuint texture;
+	GLuint textures[WL_BUFFER_MAX_PLANES];
+	uint32_t num_textures;
 	pixman_region32_t clip;
 	pixman_region32_t damage;
 	pixman_region32_t opaque;
@@ -337,7 +338,8 @@ struct weston_surface {
 
 	struct wl_list frame_callback_list;
 
-	EGLImageKHR image;
+	EGLImageKHR images[WL_BUFFER_MAX_PLANES];
+	uint32_t num_images;
 
 	struct wl_buffer *buffer;
 	struct wl_listener buffer_destroy_listener;
-- 
1.7.5.4



More information about the wayland-devel mailing list