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
This commit is contained in:
parent
7c31fb2450
commit
1f0ce80fb4
9 changed files with 157 additions and 2 deletions
|
@ -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 >*/
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 *
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue