[mutter] cogl: Add support for creating custom EGL based textures



commit 1f0ce80fb4760cd55dec9da9bdf0db695f261836
Author: Jonas Ådahl <jadahl gmail com>
Date:   Thu Oct 20 15:52:57 2016 +0800

    cogl: Add support for creating custom EGL based textures
    
    Add API to enable the caller to have a custom method for allocating an
    external texture. This will enable the possibility for mutter to
    generate a texture from for example an EGLStream without having to add
    support for that in Cogl.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=773629

 cogl/cogl/cogl-context.h                 |    1 +
 cogl/cogl/cogl-gles2-types.h             |    1 +
 cogl/cogl/cogl-glsl-shader.c             |    8 ++
 cogl/cogl/cogl-texture-2d-private.h      |    6 ++
 cogl/cogl/cogl-texture-2d.c              |    4 +-
 cogl/cogl/cogl-texture-2d.h              |   21 ++++++
 cogl/cogl/cogl-texture-private.h         |   12 +++-
 cogl/cogl/cogl-texture.c                 |    1 +
 cogl/cogl/driver/gl/cogl-texture-2d-gl.c |  105 ++++++++++++++++++++++++++++++
 9 files changed, 157 insertions(+), 2 deletions(-)
---
diff --git a/cogl/cogl/cogl-context.h b/cogl/cogl/cogl-context.h
index 978c3fc..add575b 100644
--- a/cogl/cogl/cogl-context.h
+++ b/cogl/cogl/cogl-context.h
@@ -262,6 +262,7 @@ typedef enum _CoglFeatureID
   COGL_FEATURE_ID_PER_VERTEX_POINT_SIZE,
   COGL_FEATURE_ID_TEXTURE_RG,
   COGL_FEATURE_ID_BUFFER_AGE,
+  COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL,
 
   /*< private >*/
   _COGL_N_FEATURE_IDS   /*< skip >*/
diff --git a/cogl/cogl/cogl-gles2-types.h b/cogl/cogl/cogl-gles2-types.h
index 8f41bf8..d07b155 100644
--- a/cogl/cogl/cogl-gles2-types.h
+++ b/cogl/cogl/cogl-gles2-types.h
@@ -152,6 +152,7 @@ typedef long             GLsizeiptr;
 #define GL_POLYGON_OFFSET_FILL            0x8037
 #define GL_SAMPLE_ALPHA_TO_COVERAGE       0x809E
 #define GL_SAMPLE_COVERAGE                0x80A0
+#define GL_TEXTURE_EXTERNAL_OES           0x8D65
 
 /* ErrorCode */
 #define GL_NO_ERROR                       0
diff --git a/cogl/cogl/cogl-glsl-shader.c b/cogl/cogl/cogl-glsl-shader.c
index 5aadd10..d728d99 100644
--- a/cogl/cogl/cogl-glsl-shader.c
+++ b/cogl/cogl/cogl-glsl-shader.c
@@ -111,6 +111,14 @@ _cogl_glsl_shader_set_source_with_boilerplate (CoglContext *ctx,
       lengths[count++] = sizeof (texture_3d_extension) - 1;
     }
 
+  if (cogl_has_feature (ctx, COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL))
+    {
+      static const char texture_3d_extension[] =
+        "#extension GL_OES_EGL_image_external : require\n";
+      strings[count] = texture_3d_extension;
+      lengths[count++] = sizeof (texture_3d_extension) - 1;
+    }
+
   if (shader_gl_type == GL_VERTEX_SHADER)
     {
       strings[count] = vertex_boilerplate;
diff --git a/cogl/cogl/cogl-texture-2d-private.h b/cogl/cogl/cogl-texture-2d-private.h
index 3723e4c..feda782 100644
--- a/cogl/cogl/cogl-texture-2d-private.h
+++ b/cogl/cogl/cogl-texture-2d-private.h
@@ -55,11 +55,17 @@ struct _CoglTexture2D
   GLenum gl_internal_format;
   /* The texture object number */
   GLuint gl_texture;
+  GLenum gl_target;
   GLenum gl_legacy_texobj_min_filter;
   GLenum gl_legacy_texobj_mag_filter;
   GLint gl_legacy_texobj_wrap_mode_s;
   GLint gl_legacy_texobj_wrap_mode_t;
   CoglTexturePixel first_pixel;
+
+  struct {
+    void *user_data;
+    GDestroyNotify destroy;
+  } egl_image_external;
 };
 
 CoglTexture2D *
diff --git a/cogl/cogl/cogl-texture-2d.c b/cogl/cogl/cogl-texture-2d.c
index dbfc090..6631258 100644
--- a/cogl/cogl/cogl-texture-2d.c
+++ b/cogl/cogl/cogl-texture-2d.c
@@ -110,6 +110,8 @@ _cogl_texture_2d_create_base (CoglContext *ctx,
   tex_2d->mipmaps_dirty = TRUE;
   tex_2d->auto_mipmap = TRUE;
 
+  tex_2d->gl_target = GL_TEXTURE_2D;
+
   tex_2d->is_foreign = FALSE;
 
   ctx->driver_vtable->texture_2d_init (tex_2d);
@@ -557,7 +559,7 @@ _cogl_texture_2d_get_gl_texture (CoglTexture *tex,
       GLuint handle;
 
       if (out_gl_target)
-        *out_gl_target = GL_TEXTURE_2D;
+        *out_gl_target = tex_2d->gl_target;
 
       handle = ctx->driver_vtable->texture_2d_get_gl_handle (tex_2d);
 
diff --git a/cogl/cogl/cogl-texture-2d.h b/cogl/cogl/cogl-texture-2d.h
index 0da74ab..405fb5f 100644
--- a/cogl/cogl/cogl-texture-2d.h
+++ b/cogl/cogl/cogl-texture-2d.h
@@ -242,6 +242,27 @@ cogl_egl_texture_2d_new_from_image (CoglContext *ctx,
                                     CoglPixelFormat format,
                                     EGLImageKHR image,
                                     CoglError **error);
+
+typedef gboolean (*CoglTexture2DEGLImageExternalAlloc) (CoglTexture2D *tex_2d,
+                                                        gpointer user_data,
+                                                        GError **error);
+
+CoglTexture2D *
+cogl_texture_2d_new_from_egl_image_external (CoglContext *ctx,
+                                             int width,
+                                             int height,
+                                             CoglTexture2DEGLImageExternalAlloc alloc,
+                                             gpointer user_data,
+                                             GDestroyNotify destroy,
+                                             CoglError **error);
+
+void
+cogl_texture_2d_egl_image_external_bind (CoglTexture2D *tex_2d);
+
+void
+cogl_texture_2d_egl_image_external_alloc_finish (CoglTexture2D *tex_2d,
+                                                void *user_data,
+                                                GDestroyNotify destroy);
 #endif
 
 COGL_END_DECLS
diff --git a/cogl/cogl/cogl-texture-private.h b/cogl/cogl/cogl-texture-private.h
index 472c41d..742983e 100644
--- a/cogl/cogl/cogl-texture-private.h
+++ b/cogl/cogl/cogl-texture-private.h
@@ -37,6 +37,7 @@
 #include "cogl-spans.h"
 #include "cogl-meta-texture.h"
 #include "cogl-framebuffer.h"
+#include "cogl-texture-2d.h"
 
 #ifdef COGL_HAS_EGL_SUPPORT
 #include "cogl-egl-defines.h"
@@ -154,7 +155,8 @@ typedef enum _CoglTextureSoureType {
   COGL_TEXTURE_SOURCE_TYPE_SIZED = 1,
   COGL_TEXTURE_SOURCE_TYPE_BITMAP,
   COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE,
-  COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN
+  COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN,
+  COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE_EXTERNAL
 } CoglTextureSourceType;
 
 typedef struct _CoglTextureLoader
@@ -180,6 +182,14 @@ typedef struct _CoglTextureLoader
       CoglPixelFormat format;
     } egl_image;
 #endif
+#if defined (COGL_HAS_EGL_SUPPORT)
+    struct {
+      int width;
+      int height;
+      CoglTexture2DEGLImageExternalAlloc alloc;
+      CoglPixelFormat format;
+    } egl_image_external;
+#endif
     struct {
       int width;
       int height;
diff --git a/cogl/cogl/cogl-texture.c b/cogl/cogl/cogl-texture.c
index 40aaa3b..877d1d7 100644
--- a/cogl/cogl/cogl-texture.c
+++ b/cogl/cogl/cogl-texture.c
@@ -160,6 +160,7 @@ _cogl_texture_free_loader (CoglTexture *texture)
         case COGL_TEXTURE_SOURCE_TYPE_SIZED:
         case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE:
         case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN:
+        case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE_EXTERNAL:
           break;
         case COGL_TEXTURE_SOURCE_TYPE_BITMAP:
           cogl_object_unref (loader->src.bitmap.bitmap);
diff --git a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
index 1193df4..d75a391 100644
--- a/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
+++ b/cogl/cogl/driver/gl/cogl-texture-2d-gl.c
@@ -46,11 +46,21 @@
 #include "cogl-error-private.h"
 #include "cogl-util-gl-private.h"
 
+#if defined (COGL_HAS_EGL_SUPPORT)
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#endif
+
 void
 _cogl_texture_2d_gl_free (CoglTexture2D *tex_2d)
 {
   if (!tex_2d->is_foreign && tex_2d->gl_texture)
     _cogl_delete_gl_texture (tex_2d->gl_texture);
+
+#if defined (COGL_HAS_EGL_SUPPORT)
+  g_clear_pointer (&tex_2d->egl_image_external.user_data,
+                   tex_2d->egl_image_external.destroy);
+#endif
 }
 
 CoglBool
@@ -101,6 +111,9 @@ _cogl_texture_2d_gl_init (CoglTexture2D *tex_2d)
   /* Wrap mode not yet set */
   tex_2d->gl_legacy_texobj_wrap_mode_s = GL_FALSE;
   tex_2d->gl_legacy_texobj_wrap_mode_t = GL_FALSE;
+
+  tex_2d->egl_image_external.user_data = NULL;
+  tex_2d->egl_image_external.destroy = NULL;
 }
 
 static CoglBool
@@ -439,6 +452,96 @@ allocate_from_gl_foreign (CoglTexture2D *tex_2d,
   return TRUE;
 }
 
+#if defined (COGL_HAS_EGL_SUPPORT)
+static CoglBool
+allocate_custom_egl_image_external (CoglTexture2D *tex_2d,
+                                    CoglTextureLoader *loader,
+                                    CoglError **error)
+{
+  CoglTexture *tex = COGL_TEXTURE (tex_2d);
+  CoglContext *ctx = tex->context;
+  CoglPixelFormat internal_format = loader->src.egl_image_external.format;
+
+  _cogl_gl_util_clear_gl_errors (ctx);
+
+  GE (ctx, glActiveTexture (GL_TEXTURE0));
+  GE (ctx, glGenTextures (1, &tex_2d->gl_texture));
+
+  GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES,
+                          tex_2d->gl_texture));
+
+  if (_cogl_gl_util_get_error (ctx) != GL_NO_ERROR)
+    {
+      _cogl_set_error (error,
+                       COGL_TEXTURE_ERROR,
+                       COGL_TEXTURE_ERROR_BAD_PARAMETER,
+                       "Could not create a CoglTexture2D from a given "
+                       "EGLImage");
+      GE( ctx, glDeleteTextures (1, &tex_2d->gl_texture) );
+      return FALSE;
+    }
+
+  GE (ctx, glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
+                           GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
+  GE (ctx, glTexParameteri(GL_TEXTURE_EXTERNAL_OES,
+                           GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+
+  if (!loader->src.egl_image_external.alloc (tex_2d,
+                                             tex_2d->egl_image_external.user_data,
+                                             error))
+    {
+      GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES, 0));
+      GE (ctx, glDeleteTextures (1, &tex_2d->gl_texture));
+      return FALSE;
+    }
+
+  GE (ctx, glBindTexture (GL_TEXTURE_EXTERNAL_OES, 0));
+
+  tex_2d->internal_format = internal_format;
+  tex_2d->gl_target = GL_TEXTURE_EXTERNAL_OES;
+
+  return TRUE;
+}
+
+CoglTexture2D *
+cogl_texture_2d_new_from_egl_image_external (CoglContext *ctx,
+                                             int width,
+                                             int height,
+                                             CoglTexture2DEGLImageExternalAlloc alloc,
+                                             gpointer user_data,
+                                             GDestroyNotify destroy,
+                                             CoglError **error)
+{
+  CoglTextureLoader *loader;
+  CoglTexture2D *tex_2d;
+  CoglPixelFormat internal_format = COGL_PIXEL_FORMAT_ANY;
+
+  _COGL_RETURN_VAL_IF_FAIL (_cogl_context_get_winsys (ctx)->constraints &
+                            COGL_RENDERER_CONSTRAINT_USES_EGL,
+                            NULL);
+
+  _COGL_RETURN_VAL_IF_FAIL (cogl_has_feature (ctx,
+                                              COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL),
+                            NULL);
+
+  loader = _cogl_texture_create_loader ();
+  loader->src_type = COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE_EXTERNAL;
+  loader->src.egl_image_external.width = width;
+  loader->src.egl_image_external.height = height;
+  loader->src.egl_image_external.alloc = alloc;
+  loader->src.egl_image_external.format = internal_format;
+
+  tex_2d = _cogl_texture_2d_create_base (ctx, width, height,
+                                         internal_format, loader);
+
+
+  tex_2d->egl_image_external.user_data = user_data;
+  tex_2d->egl_image_external.destroy = destroy;
+
+  return tex_2d;
+}
+#endif /* defined (COGL_HAS_EGL_SUPPORT) */
+
 CoglBool
 _cogl_texture_2d_gl_allocate (CoglTexture *tex,
                               CoglError **error)
@@ -462,6 +565,8 @@ _cogl_texture_2d_gl_allocate (CoglTexture *tex,
 #endif
     case COGL_TEXTURE_SOURCE_TYPE_GL_FOREIGN:
       return allocate_from_gl_foreign (tex_2d, loader, error);
+    case COGL_TEXTURE_SOURCE_TYPE_EGL_IMAGE_EXTERNAL:
+      return allocate_custom_egl_image_external (tex_2d, loader, error);
     }
 
   g_return_val_if_reached (FALSE);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]