[mutter] cogl: Add support for creating custom EGL based textures
- From: Jonas Ådahl <jadahl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter] cogl: Add support for creating custom EGL based textures
- Date: Thu, 17 Nov 2016 16:09:17 +0000 (UTC)
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]