diff mbox

[weston,2/2] compositor: add support for OES_EGL_image_external

Message ID 1344897558-1976-3-git-send-email-rob.clark@linaro.org
State New
Headers show

Commit Message

Rob Clark Aug. 13, 2012, 10:39 p.m. UTC
From: Rob Clark <rob@ti.com>

In cases where the GPU can natively handle certain YUV formats,
eglQueryWaylandBufferWL() can return the value EGL_TEXTURE_EXTERNAL_OES
and the compositor will treat the buffer as a single egl-image-external.

See:
http://www.khronos.org/registry/gles/extensions/OES/OES_EGL_image_external.txt

Signed-off-by: Rob Clark <rob@ti.com>
---
 src/compositor.c     |   42 ++++++++++++++++++++++++++++++++----------
 src/compositor.h     |    2 ++
 src/weston-egl-ext.h |    1 +
 3 files changed, 35 insertions(+), 10 deletions(-)

Comments

Rob Clark Aug. 13, 2012, 11:59 p.m. UTC | #1
On Mon, Aug 13, 2012 at 5:39 PM, Rob Clark <rob.clark@linaro.org> wrote:
> From: Rob Clark <rob@ti.com>
>
> In cases where the GPU can natively handle certain YUV formats,
> eglQueryWaylandBufferWL() can return the value EGL_TEXTURE_EXTERNAL_OES
> and the compositor will treat the buffer as a single egl-image-external.
>
> See:
> http://www.khronos.org/registry/gles/extensions/OES/OES_EGL_image_external.txt
>
> Signed-off-by: Rob Clark <rob@ti.com>
> ---
>  src/compositor.c     |   42 ++++++++++++++++++++++++++++++++----------
>  src/compositor.h     |    2 ++
>  src/weston-egl-ext.h |    1 +
>  3 files changed, 35 insertions(+), 10 deletions(-)
>
> diff --git a/src/compositor.c b/src/compositor.c
> index b2a3ae9..08e575a 100644
> --- a/src/compositor.c
> +++ b/src/compositor.c
> @@ -719,14 +719,14 @@ ensure_textures(struct weston_surface *es, int num_textures)
>
>         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,
> +               glBindTexture(es->target, es->textures[i]);
> +               glTexParameteri(es->target,
>                                 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
> -               glTexParameteri(GL_TEXTURE_2D,
> +               glTexParameteri(es->target,
>                                 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
>         }
>         es->num_textures = num_textures;
> -       glBindTexture(GL_TEXTURE_2D, 0);
> +       glBindTexture(es->target, 0);
>  }
>
>  static void
> @@ -771,6 +771,7 @@ weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
>         if (wl_buffer_is_shm(buffer)) {
>                 es->pitch = wl_shm_buffer_get_stride(buffer) / 4;
>                 es->shader = &ec->texture_shader_rgba;
> +               es->target = GL_TEXTURE_2D;
>
>                 ensure_textures(es, 1);
>                 glBindTexture(GL_TEXTURE_2D, es->textures[0]);
> @@ -786,7 +787,7 @@ weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
>                 for (i = 0; i < es->num_images; i++)
>                         ec->destroy_image(ec->egl_display, es->images[i]);
>                 es->num_images = 0;
> -
> +               es->target = GL_TEXTURE_2D;
>                 switch (format) {
>                 case EGL_TEXTURE_RGB:
>                 case EGL_TEXTURE_RGBA:
> @@ -794,6 +795,11 @@ weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
>                         num_planes = 1;
>                         es->shader = &ec->texture_shader_rgba;
>                         break;
> +               case EGL_TEXTURE_EXTERNAL_OES:

Kristian pointed out to me on IRC that this should be called something
like EGL_TEXTURE_EXTERNAL_WL (or EGL_TEXTURE_EXTERNAL_OES_WL?), so
I'll resubmit these patches..


> +                       num_planes = 1;
> +                       es->target = GL_TEXTURE_EXTERNAL_OES;
> +                       es->shader = &ec->texture_shader_egl_external;
> +                       break;
>                 case EGL_TEXTURE_Y_UV_WL:
>                         num_planes = 2;
>                         es->shader = &ec->texture_shader_y_uv;
> @@ -824,8 +830,8 @@ weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
>                         es->num_images++;
>
>                         glActiveTexture(GL_TEXTURE0 + i);
> -                       glBindTexture(GL_TEXTURE_2D, es->textures[i]);
> -                       ec->image_target_texture_2d(GL_TEXTURE_2D,
> +                       glBindTexture(es->target, es->textures[i]);
> +                       ec->image_target_texture_2d(es->target,
>                                                     es->images[i]);
>                 }
>
> @@ -942,9 +948,9 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output,
>         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);
> +               glBindTexture(es->target, es->textures[i]);
> +               glTexParameteri(es->target, GL_TEXTURE_MIN_FILTER, filter);
> +               glTexParameteri(es->target, GL_TEXTURE_MAG_FILTER, filter);
>         }
>
>         v = ec->vertices.data;
> @@ -2842,6 +2848,19 @@ static const char texture_fragment_shader_rgba[] =
>         FRAGMENT_SHADER_EXIT
>         "}\n";
>
> +static const char texture_fragment_shader_egl_external[] =
> +       "#extension GL_OES_EGL_image_external : require\n"
> +       "precision mediump float;\n"
> +       "varying vec2 v_texcoord;\n"
> +       "uniform samplerExternalOES tex;\n"
> +       FRAGMENT_SHADER_UNIFORMS
> +       "void main()\n"
> +       "{\n"
> +       FRAGMENT_SHADER_INIT
> +       "   gl_FragColor = texture2D(tex, v_texcoord)\n;"
> +       FRAGMENT_SHADER_EXIT
> +       "}\n";
> +
>  static const char texture_fragment_shader_y_uv[] =
>         "precision mediump float;\n"
>         "uniform sampler2D tex;\n"
> @@ -3251,6 +3270,9 @@ weston_compositor_init_gl(struct weston_compositor *ec)
>         if (weston_shader_init(&ec->texture_shader_rgba,
>                              vertex_shader, texture_fragment_shader_rgba) < 0)
>                 return -1;
> +       if (weston_shader_init(&ec->texture_shader_egl_external,
> +                               vertex_shader, texture_fragment_shader_egl_external) < 0)

I wonder if some GL implementations would refuse to compile a shader
with '#extension GL_OES_EGL_image_external : require'.. so maybe this
shouldn't be treated as a failure case?

BR,
-R

> +               return -1;
>         if (weston_shader_init(&ec->texture_shader_y_uv,
>                                vertex_shader, texture_fragment_shader_y_uv) < 0)
>                 return -1;
> diff --git a/src/compositor.h b/src/compositor.h
> index 22c0174..be1c2d2 100644
> --- a/src/compositor.h
> +++ b/src/compositor.h
> @@ -271,6 +271,7 @@ struct weston_compositor {
>         EGLConfig egl_config;
>         GLuint fbo;
>         struct weston_shader texture_shader_rgba;
> +       struct weston_shader texture_shader_egl_external;
>         struct weston_shader texture_shader_y_uv;
>         struct weston_shader texture_shader_y_u_v;
>         struct weston_shader texture_shader_y_xuxv;
> @@ -452,6 +453,7 @@ struct weston_surface {
>         struct wl_list frame_callback_list;
>
>         EGLImageKHR images[3];
> +       GLenum target;
>         int num_images;
>
>         struct wl_buffer *buffer;
> diff --git a/src/weston-egl-ext.h b/src/weston-egl-ext.h
> index 8e132c0..5dae03e 100644
> --- a/src/weston-egl-ext.h
> +++ b/src/weston-egl-ext.h
> @@ -39,6 +39,7 @@
>  #define EGL_TEXTURE_Y_U_V_WL            0x31D7
>  #define EGL_TEXTURE_Y_UV_WL             0x31D8
>  #define EGL_TEXTURE_Y_XUXV_WL           0x31D9
> +#define EGL_TEXTURE_EXTERNAL_OES        0x31DA
>
>  struct wl_display;
>  struct wl_buffer;
> --
> 1.7.9.5
>
Pekka Paalanen Aug. 14, 2012, 7:07 a.m. UTC | #2
On Mon, 13 Aug 2012 18:59:33 -0500
Rob Clark <rob@ti.com> wrote:

> On Mon, Aug 13, 2012 at 5:39 PM, Rob Clark <rob.clark@linaro.org> wrote:
> > From: Rob Clark <rob@ti.com>
> >
> > In cases where the GPU can natively handle certain YUV formats,
> > eglQueryWaylandBufferWL() can return the value EGL_TEXTURE_EXTERNAL_OES
> > and the compositor will treat the buffer as a single egl-image-external.
> >
> > See:
> > http://www.khronos.org/registry/gles/extensions/OES/OES_EGL_image_external.txt
> >
> > Signed-off-by: Rob Clark <rob@ti.com>
> > ---
> >  src/compositor.c     |   42 ++++++++++++++++++++++++++++++++----------
> >  src/compositor.h     |    2 ++
> >  src/weston-egl-ext.h |    1 +
> >  3 files changed, 35 insertions(+), 10 deletions(-)
> >
> > diff --git a/src/compositor.c b/src/compositor.c
> > index b2a3ae9..08e575a 100644
> > --- a/src/compositor.c
> > +++ b/src/compositor.c
> > @@ -719,14 +719,14 @@ ensure_textures(struct weston_surface *es, int num_textures)
> >
> >         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,
> > +               glBindTexture(es->target, es->textures[i]);
> > +               glTexParameteri(es->target,
> >                                 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
> > -               glTexParameteri(GL_TEXTURE_2D,
> > +               glTexParameteri(es->target,
> >                                 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
> >         }
> >         es->num_textures = num_textures;
> > -       glBindTexture(GL_TEXTURE_2D, 0);
> > +       glBindTexture(es->target, 0);
> >  }
> >
> >  static void
> > @@ -771,6 +771,7 @@ weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
> >         if (wl_buffer_is_shm(buffer)) {
> >                 es->pitch = wl_shm_buffer_get_stride(buffer) / 4;
> >                 es->shader = &ec->texture_shader_rgba;
> > +               es->target = GL_TEXTURE_2D;
> >
> >                 ensure_textures(es, 1);
> >                 glBindTexture(GL_TEXTURE_2D, es->textures[0]);
> > @@ -786,7 +787,7 @@ weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
> >                 for (i = 0; i < es->num_images; i++)
> >                         ec->destroy_image(ec->egl_display, es->images[i]);
> >                 es->num_images = 0;
> > -
> > +               es->target = GL_TEXTURE_2D;
> >                 switch (format) {
> >                 case EGL_TEXTURE_RGB:
> >                 case EGL_TEXTURE_RGBA:
> > @@ -794,6 +795,11 @@ weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
> >                         num_planes = 1;
> >                         es->shader = &ec->texture_shader_rgba;
> >                         break;
> > +               case EGL_TEXTURE_EXTERNAL_OES:
> 
> Kristian pointed out to me on IRC that this should be called something
> like EGL_TEXTURE_EXTERNAL_WL (or EGL_TEXTURE_EXTERNAL_OES_WL?), so
> I'll resubmit these patches..
> 
> 
> > +                       num_planes = 1;
> > +                       es->target = GL_TEXTURE_EXTERNAL_OES;
> > +                       es->shader = &ec->texture_shader_egl_external;
> > +                       break;
> >                 case EGL_TEXTURE_Y_UV_WL:
> >                         num_planes = 2;
> >                         es->shader = &ec->texture_shader_y_uv;
> > @@ -824,8 +830,8 @@ weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
> >                         es->num_images++;
> >
> >                         glActiveTexture(GL_TEXTURE0 + i);
> > -                       glBindTexture(GL_TEXTURE_2D, es->textures[i]);
> > -                       ec->image_target_texture_2d(GL_TEXTURE_2D,
> > +                       glBindTexture(es->target, es->textures[i]);
> > +                       ec->image_target_texture_2d(es->target,
> >                                                     es->images[i]);
> >                 }
> >
> > @@ -942,9 +948,9 @@ weston_surface_draw(struct weston_surface *es, struct weston_output *output,
> >         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);
> > +               glBindTexture(es->target, es->textures[i]);
> > +               glTexParameteri(es->target, GL_TEXTURE_MIN_FILTER, filter);
> > +               glTexParameteri(es->target, GL_TEXTURE_MAG_FILTER, filter);
> >         }
> >
> >         v = ec->vertices.data;
> > @@ -2842,6 +2848,19 @@ static const char texture_fragment_shader_rgba[] =
> >         FRAGMENT_SHADER_EXIT
> >         "}\n";
> >
> > +static const char texture_fragment_shader_egl_external[] =
> > +       "#extension GL_OES_EGL_image_external : require\n"
> > +       "precision mediump float;\n"
> > +       "varying vec2 v_texcoord;\n"
> > +       "uniform samplerExternalOES tex;\n"
> > +       FRAGMENT_SHADER_UNIFORMS
> > +       "void main()\n"
> > +       "{\n"
> > +       FRAGMENT_SHADER_INIT
> > +       "   gl_FragColor = texture2D(tex, v_texcoord)\n;"
> > +       FRAGMENT_SHADER_EXIT
> > +       "}\n";
> > +
> >  static const char texture_fragment_shader_y_uv[] =
> >         "precision mediump float;\n"
> >         "uniform sampler2D tex;\n"
> > @@ -3251,6 +3270,9 @@ weston_compositor_init_gl(struct weston_compositor *ec)
> >         if (weston_shader_init(&ec->texture_shader_rgba,
> >                              vertex_shader, texture_fragment_shader_rgba) < 0)
> >                 return -1;
> > +       if (weston_shader_init(&ec->texture_shader_egl_external,
> > +                               vertex_shader, texture_fragment_shader_egl_external) < 0)
> 
> I wonder if some GL implementations would refuse to compile a shader
> with '#extension GL_OES_EGL_image_external : require'.. so maybe this
> shouldn't be treated as a failure case?

Why wouldn't they fail? They probably do not know what a
samplerExternalOES is.

Personally I would prefer to properly query the existence of
the GL extension for image_external, and run this code only if
it is supported. The existing checks are in weston_compositor_init_gl().


Thanks,
pq
diff mbox

Patch

diff --git a/src/compositor.c b/src/compositor.c
index b2a3ae9..08e575a 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -719,14 +719,14 @@  ensure_textures(struct weston_surface *es, int num_textures)
 
 	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,
+		glBindTexture(es->target, es->textures[i]);
+		glTexParameteri(es->target,
 				GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-		glTexParameteri(GL_TEXTURE_2D,
+		glTexParameteri(es->target,
 				GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 	}
 	es->num_textures = num_textures;
-	glBindTexture(GL_TEXTURE_2D, 0);
+	glBindTexture(es->target, 0);
 }
 
 static void
@@ -771,6 +771,7 @@  weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
 	if (wl_buffer_is_shm(buffer)) {
 		es->pitch = wl_shm_buffer_get_stride(buffer) / 4;
 		es->shader = &ec->texture_shader_rgba;
+		es->target = GL_TEXTURE_2D;
 
 		ensure_textures(es, 1);
 		glBindTexture(GL_TEXTURE_2D, es->textures[0]);
@@ -786,7 +787,7 @@  weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
 		for (i = 0; i < es->num_images; i++)
 			ec->destroy_image(ec->egl_display, es->images[i]);
 		es->num_images = 0;
-
+		es->target = GL_TEXTURE_2D;
 		switch (format) {
 		case EGL_TEXTURE_RGB:
 		case EGL_TEXTURE_RGBA:
@@ -794,6 +795,11 @@  weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
 			num_planes = 1;
 			es->shader = &ec->texture_shader_rgba;
 			break;
+		case EGL_TEXTURE_EXTERNAL_OES:
+			num_planes = 1;
+			es->target = GL_TEXTURE_EXTERNAL_OES;
+			es->shader = &ec->texture_shader_egl_external;
+			break;
 		case EGL_TEXTURE_Y_UV_WL:
 			num_planes = 2;
 			es->shader = &ec->texture_shader_y_uv;
@@ -824,8 +830,8 @@  weston_surface_attach(struct wl_surface *surface, struct wl_buffer *buffer)
 			es->num_images++;
 
 			glActiveTexture(GL_TEXTURE0 + i);
-			glBindTexture(GL_TEXTURE_2D, es->textures[i]);
-			ec->image_target_texture_2d(GL_TEXTURE_2D,
+			glBindTexture(es->target, es->textures[i]);
+			ec->image_target_texture_2d(es->target,
 						    es->images[i]);
 		}
 
@@ -942,9 +948,9 @@  weston_surface_draw(struct weston_surface *es, struct weston_output *output,
 	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);
+		glBindTexture(es->target, es->textures[i]);
+		glTexParameteri(es->target, GL_TEXTURE_MIN_FILTER, filter);
+		glTexParameteri(es->target, GL_TEXTURE_MAG_FILTER, filter);
 	}
 
 	v = ec->vertices.data;
@@ -2842,6 +2848,19 @@  static const char texture_fragment_shader_rgba[] =
 	FRAGMENT_SHADER_EXIT
 	"}\n";
 
+static const char texture_fragment_shader_egl_external[] =
+	"#extension GL_OES_EGL_image_external : require\n"
+	"precision mediump float;\n"
+	"varying vec2 v_texcoord;\n"
+	"uniform samplerExternalOES tex;\n"
+	FRAGMENT_SHADER_UNIFORMS
+	"void main()\n"
+	"{\n"
+	FRAGMENT_SHADER_INIT
+	"   gl_FragColor = texture2D(tex, v_texcoord)\n;"
+	FRAGMENT_SHADER_EXIT
+	"}\n";
+
 static const char texture_fragment_shader_y_uv[] =
 	"precision mediump float;\n"
 	"uniform sampler2D tex;\n"
@@ -3251,6 +3270,9 @@  weston_compositor_init_gl(struct weston_compositor *ec)
 	if (weston_shader_init(&ec->texture_shader_rgba,
 			     vertex_shader, texture_fragment_shader_rgba) < 0)
 		return -1;
+	if (weston_shader_init(&ec->texture_shader_egl_external,
+				vertex_shader, texture_fragment_shader_egl_external) < 0)
+		return -1;
 	if (weston_shader_init(&ec->texture_shader_y_uv,
 			       vertex_shader, texture_fragment_shader_y_uv) < 0)
 		return -1;
diff --git a/src/compositor.h b/src/compositor.h
index 22c0174..be1c2d2 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -271,6 +271,7 @@  struct weston_compositor {
 	EGLConfig egl_config;
 	GLuint fbo;
 	struct weston_shader texture_shader_rgba;
+	struct weston_shader texture_shader_egl_external;
 	struct weston_shader texture_shader_y_uv;
 	struct weston_shader texture_shader_y_u_v;
 	struct weston_shader texture_shader_y_xuxv;
@@ -452,6 +453,7 @@  struct weston_surface {
 	struct wl_list frame_callback_list;
 
 	EGLImageKHR images[3];
+	GLenum target;
 	int num_images;
 
 	struct wl_buffer *buffer;
diff --git a/src/weston-egl-ext.h b/src/weston-egl-ext.h
index 8e132c0..5dae03e 100644
--- a/src/weston-egl-ext.h
+++ b/src/weston-egl-ext.h
@@ -39,6 +39,7 @@ 
 #define EGL_TEXTURE_Y_U_V_WL            0x31D7
 #define EGL_TEXTURE_Y_UV_WL             0x31D8
 #define EGL_TEXTURE_Y_XUXV_WL           0x31D9
+#define EGL_TEXTURE_EXTERNAL_OES        0x31DA
 
 struct wl_display;
 struct wl_buffer;