compositor: add support for OES_EGL_image_external
authorRob Clark <rob@ti.com>
Fri, 31 Aug 2012 21:42:18 +0000 (16:42 -0500)
committerKristian Høgsberg <krh@bitplanet.net>
Fri, 31 Aug 2012 21:51:42 +0000 (17:51 -0400)
In cases where the GPU can natively handle certain YUV formats,
eglQueryWaylandBufferWL() can return the value EGL_TEXTURE_EXTERNAL_WL
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

v1: original
v2: rename EGL_TEXTURE_EXTERNAL_OES -> EGL_TEXTURE_EXTERNAL_WL and query
    for the extension
v3: fix build without updated mesa headers, if EGL_TEXTURE_EXTERNAL_WL
    #define is missing from older mesa headers.
v4: resend without missing parts

Signed-off-by: Rob Clark <rob@ti.com>
src/compositor.c
src/compositor.h
src/weston-egl-ext.h

index df28cb7..9271b71 100644 (file)
@@ -739,14 +739,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
@@ -791,6 +791,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]);
@@ -806,7 +807,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:
@@ -814,6 +815,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_WL:
+                       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;
@@ -844,8 +850,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]);
                }
 
@@ -965,9 +971,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;
@@ -2848,6 +2854,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"
@@ -3287,6 +3306,7 @@ WL_EXPORT int
 weston_compositor_init_gl(struct weston_compositor *ec)
 {
        const char *extensions;
+       int has_egl_image_external = 0;
 
        log_egl_gl_info(ec->egl_display);
 
@@ -3322,6 +3342,9 @@ weston_compositor_init_gl(struct weston_compositor *ec)
        if (strstr(extensions, "GL_EXT_unpack_subimage"))
                ec->has_unpack_subimage = 1;
 
+       if (strstr(extensions, "GL_OES_EGL_image_external"))
+               has_egl_image_external = 1;
+
        extensions =
                (const char *) eglQueryString(ec->egl_display, EGL_EXTENSIONS);
        if (!extensions) {
@@ -3345,6 +3368,10 @@ 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 (has_egl_image_external &&
+                       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;
index ac887ee..070d1ca 100644 (file)
@@ -277,6 +277,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;
@@ -448,6 +449,7 @@ struct weston_surface {
        struct wl_list frame_callback_list;
 
        EGLImageKHR images[3];
+       GLenum target;
        int num_images;
 
        struct wl_buffer *buffer;
index 8e132c0..1d4b76b 100644 (file)
@@ -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_WL         0x31DA
 
 struct wl_display;
 struct wl_buffer;
@@ -53,4 +54,8 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay dpy, st
 
 #endif
 
+#ifndef EGL_TEXTURE_EXTERNAL_WL
+#define EGL_TEXTURE_EXTERNAL_WL         0x31DA
+#endif
+
 #endif