[PATCH 4/4] compositor: handle YUV buffers.

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


Signed-off-by: Gwenole Beauchesne <gwenole.beauchesne at intel.com>
---
 src/compositor-wayland.c |    2 +-
 src/compositor.c         |   80 ++++++++++++++++++++++++++++++++++++---------
 src/compositor.h         |    2 +-
 3 files changed, 66 insertions(+), 18 deletions(-)

diff --git a/src/compositor-wayland.c b/src/compositor-wayland.c
index d40b40b..7b924ef 100644
--- a/src/compositor-wayland.c
+++ b/src/compositor-wayland.c
@@ -182,7 +182,7 @@ draw_border(struct wayland_output *output)
 	glUniformMatrix4fv(shader->proj_uniform,
 			   1, GL_FALSE, output->base.matrix.d);
 
-	glUniform1i(shader->tex_uniform, 0);
+	glUniform1i(shader->tex_uniforms[0], 0);
 	glUniform1f(shader->alpha_uniform, 1);
 	glUniform1f(shader->texwidth_uniform, 1);
 
diff --git a/src/compositor.c b/src/compositor.c
index 74aee25..acf5bdf 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -722,6 +722,9 @@ weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
 {
 	struct weston_surface *es = (struct weston_surface *) surface;
 	struct weston_compositor *ec = es->compositor;
+	struct wl_buffer_layout layout;
+	EGLint *attribs, attrib_list[2*4+1];
+	unsigned int i;
 
 	if (es->buffer) {
 		weston_buffer_post_release(es->buffer);
@@ -757,18 +760,57 @@ weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
 			     es->pitch, es->buffer->height, 0,
 			     GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
 	} else {
-		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;
-
-		ensure_textures(es, 1);
-		glBindTexture(GL_TEXTURE_2D, es->textures[0]);
-		ec->image_target_texture_2d(GL_TEXTURE_2D, es->images[0]);
-
+		for (i = 0; i < es->num_images; i++)
+			destroy_image(ec, &es->images[i]);
+		es->num_images = 0;
+
+		wl_buffer_get_layout(buffer, &layout);
+		switch (layout.format) {
+		case WL_BUFFER_FORMAT_ARGB32:
+		case WL_BUFFER_FORMAT_XRGB32:
+			assert(layout.num_planes == 1);
+			es->shader = &ec->texture_shader_rgba;
+			break;
+		case WL_BUFFER_FORMAT_NV12:
+			assert(layout.num_planes == 2);
+			es->shader = &ec->texture_shader_nv12;
+			break;
+		case WL_BUFFER_FORMAT_YUV410:
+		case WL_BUFFER_FORMAT_YUV411:
+		case WL_BUFFER_FORMAT_YUV420:
+		case WL_BUFFER_FORMAT_YUV422:
+		case WL_BUFFER_FORMAT_YUV444:
+			assert(layout.num_planes == 3);
+			es->shader = &ec->texture_shader_yuv8;
+			break;
+		default:
+			es->shader = NULL;
+			assert(0 && "unsupported buffer format");
+			break;
+		}
 		es->pitch = buffer->width;
-		es->shader = &ec->texture_shader_rgba;
+
+		ensure_textures(es, layout.num_planes);
+		for (i = 0; i < layout.num_planes; i++) {
+			attribs = attrib_list;
+			*attribs++ = EGL_WAYLAND_BUFFER_PLANE_WL;
+			*attribs++ = i;
+			*attribs++ = EGL_NONE;
+			es->images[i] = ec->create_image(
+				ec->display, NULL,
+				EGL_WAYLAND_BUFFER_WL,
+				buffer, attrib_list
+			);
+			if (!es->images[i])
+				continue;
+			es->num_images++;
+
+			glActiveTexture(GL_TEXTURE0 + i);
+			glBindTexture(GL_TEXTURE_2D, es->textures[i]);
+			ec->image_target_texture_2d(GL_TEXTURE_2D, es->images[i]);
+			glBindTexture(GL_TEXTURE_2D, 0);
+		}
+		glActiveTexture(GL_TEXTURE0);
 	}
 }
 
@@ -836,6 +878,7 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output,
 	GLfloat *v;
 	pixman_region32_t repaint;
 	GLint filter;
+	unsigned int i;
 	int n;
 
 	pixman_region32_init(&repaint);
@@ -856,7 +899,6 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output,
 
 	glUniformMatrix4fv(es->shader->proj_uniform,
 			   1, GL_FALSE, output->matrix.d);
-	glUniform1i(es->shader->tex_uniform, 0);
 	glUniform4fv(es->shader->color_uniform, 1, es->color);
 	glUniform1f(es->shader->alpha_uniform, es->alpha / 255.0);
 	glUniform1f(es->shader->brightness_uniform, es->brightness / 255.0);
@@ -871,9 +913,13 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output,
 
 	n = texture_region(es, &repaint);
 
-	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);
+	for (i = 0; i < es->num_textures; i++) {
+		glUniform1i(es->shader->tex_uniforms[i], i);
+		glActiveTexture(GL_TEXTURE0 + i);
+		glBindTexture(GL_TEXTURE_2D, es->textures[i]);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filter);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filter);
+	}
 
 	v = ec->vertices.data;
 	glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof *v, &v[0]);
@@ -2345,7 +2391,9 @@ weston_shader_init(struct weston_shader *shader,
 	}
 
 	shader->proj_uniform = glGetUniformLocation(shader->program, "proj");
-	shader->tex_uniform = glGetUniformLocation(shader->program, "tex");
+	shader->tex_uniforms[0] = glGetUniformLocation(shader->program, "tex");
+	shader->tex_uniforms[1] = glGetUniformLocation(shader->program, "tex1");
+	shader->tex_uniforms[2] = glGetUniformLocation(shader->program, "tex2");
 	shader->alpha_uniform = glGetUniformLocation(shader->program, "alpha");
 	shader->brightness_uniform = glGetUniformLocation(shader->program, "bright");
 	shader->saturation_uniform = glGetUniformLocation(shader->program, "saturation");
diff --git a/src/compositor.h b/src/compositor.h
index e45c377..4335d62 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -134,7 +134,7 @@ struct weston_shader {
 	GLuint program;
 	GLuint vertex_shader, fragment_shader;
 	GLint proj_uniform;
-	GLint tex_uniform;
+	GLint tex_uniforms[WL_BUFFER_MAX_PLANES];
 	GLint alpha_uniform;
 	GLint brightness_uniform;
 	GLint saturation_uniform;
-- 
1.7.5.4



More information about the wayland-devel mailing list