diff --git a/cogl/cogl/cogl-context.h b/cogl/cogl/cogl-context.h index 978c3fcba..add575b49 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 8f41bf8a7..d07b1552f 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 5aadd1074..d728d99e6 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 3723e4cd4..feda782c1 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 dbfc09003..663125890 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 0da74abcf..405fb5f6a 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 472c41d9d..742983e2d 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 @@ -179,6 +181,14 @@ typedef struct _CoglTextureLoader int height; 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; diff --git a/cogl/cogl/cogl-texture.c b/cogl/cogl/cogl-texture.c index 40aaa3b3a..877d1d75d 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 1193df41d..d75a3918c 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 +#include +#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);