diff --git a/cogl/Makefile.am b/cogl/Makefile.am index be2759d97..9c4fff43c 100644 --- a/cogl/Makefile.am +++ b/cogl/Makefile.am @@ -335,23 +335,28 @@ cogl_sources_c += \ endif if SUPPORT_EGL_PLATFORM_POWERVR_X11 cogl_sources_c += \ - $(srcdir)/winsys/cogl-winsys-egl.c + $(srcdir)/winsys/cogl-winsys-egl.c \ + $(srcdir)/winsys/cogl-winsys-egl-private.h endif if SUPPORT_EGL_PLATFORM_POWERVR_NULL cogl_sources_c += \ - $(srcdir)/winsys/cogl-winsys-egl.c + $(srcdir)/winsys/cogl-winsys-egl.c \ + $(srcdir)/winsys/cogl-winsys-egl-private.h endif if SUPPORT_EGL_PLATFORM_GDL cogl_sources_c += \ - $(srcdir)/winsys/cogl-winsys-egl.c + $(srcdir)/winsys/cogl-winsys-egl.c \ + $(srcdir)/winsys/cogl-winsys-egl-private.h endif if SUPPORT_EGL_PLATFORM_WAYLAND cogl_sources_c += \ - $(srcdir)/winsys/cogl-winsys-egl.c + $(srcdir)/winsys/cogl-winsys-egl.c \ + $(srcdir)/winsys/cogl-winsys-egl-private.h endif if SUPPORT_EGL_PLATFORM_ANDROID cogl_sources_c += \ - $(srcdir)/winsys/cogl-winsys-egl.c + $(srcdir)/winsys/cogl-winsys-egl.c \ + $(srcdir)/winsys/cogl-winsys-egl-private.h endif EXTRA_DIST += stb_image.c diff --git a/cogl/cogl-context-private.h b/cogl/cogl-context-private.h index 2cf1be5d1..2bc652888 100644 --- a/cogl/cogl-context-private.h +++ b/cogl/cogl-context-private.h @@ -65,6 +65,7 @@ struct _CoglContext /* Features cache */ CoglFeatureFlags feature_flags; + CoglPrivateFeatureFlags private_feature_flags; CoglHandle default_pipeline; CoglHandle default_layer_0; diff --git a/cogl/cogl-context.c b/cogl/cogl-context.c index 7a0063d99..6abdfccf4 100644 --- a/cogl/cogl-context.c +++ b/cogl/cogl-context.c @@ -141,6 +141,7 @@ cogl_context_new (CoglDisplay *display, /* Init default values */ context->feature_flags = 0; + context->private_feature_flags = 0; context->texture_types = NULL; context->buffer_types = NULL; diff --git a/cogl/cogl-defines.h.in b/cogl/cogl-defines.h.in index 08226897a..3d4b17d20 100644 --- a/cogl/cogl-defines.h.in +++ b/cogl/cogl-defines.h.in @@ -41,6 +41,9 @@ G_BEGIN_DECLS #define NativeWindowType EGLNativeWindowType #endif +#ifndef GL_OES_EGL_image +#define GLeglImageOES void * +#endif G_END_DECLS #endif diff --git a/cogl/cogl-internal.h b/cogl/cogl-internal.h index eba62bf73..9f197e0ed 100644 --- a/cogl/cogl-internal.h +++ b/cogl/cogl-internal.h @@ -126,6 +126,11 @@ typedef enum { /*< prefix=COGL_DRIVER_ERROR >*/ COGL_DRIVER_ERROR_INVALID_VERSION } CoglDriverError; +typedef enum +{ + COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE = 1L<<0 +} CoglPrivateFeatureFlags; + gboolean _cogl_check_extension (const char *name, const char *ext); diff --git a/cogl/cogl-renderer.c b/cogl/cogl-renderer.c index d2badc8d2..07938700f 100644 --- a/cogl/cogl-renderer.c +++ b/cogl/cogl-renderer.c @@ -40,13 +40,11 @@ #include "cogl-display-private.h" #include "cogl-winsys-private.h" #include "cogl-winsys-stub-private.h" +#include "cogl-winsys-egl-private.h" #ifdef COGL_HAS_GLX_SUPPORT extern const CoglWinsysVtable *_cogl_winsys_glx_get_vtable (void); #endif -#ifdef COGL_HAS_EGL_SUPPORT -extern const CoglWinsysVtable *_cogl_winsys_egl_get_vtable (void); -#endif #ifdef COGL_HAS_WGL_SUPPORT extern const CoglWinsysVtable *_cogl_winsys_wgl_get_vtable (void); #endif diff --git a/cogl/cogl-texture-2d-private.h b/cogl/cogl-texture-2d-private.h index d05b342d9..97fee0745 100644 --- a/cogl/cogl-texture-2d-private.h +++ b/cogl/cogl-texture-2d-private.h @@ -61,6 +61,19 @@ _cogl_texture_2d_new_from_bitmap (CoglBitmap *bmp, CoglPixelFormat internal_format, GError **error); +#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) +/* NB: The reason we require the width, height and format to be passed + * even though they may seem redundant is because GLES 1/2 don't + * provide a way to query these properties. */ +CoglTexture2D * +_cogl_egl_texture_2d_new_from_image (CoglContext *ctx, + int width, + int height, + CoglPixelFormat format, + EGLImageKHR image, + GError **error); +#endif + /* * _cogl_texture_2d_externally_modified: * @handle: A handle to a 2D texture diff --git a/cogl/cogl-texture-2d.c b/cogl/cogl-texture-2d.c index 178bfc85d..9f2e5506a 100644 --- a/cogl/cogl-texture-2d.c +++ b/cogl/cogl-texture-2d.c @@ -39,6 +39,7 @@ #include "cogl-journal-private.h" #include "cogl-pipeline-opengl-private.h" #include "cogl-framebuffer-private.h" +#include "cogl-winsys-egl-private.h" #include #include @@ -493,6 +494,53 @@ cogl_texture_2d_new_from_foreign (CoglContext *ctx, return _cogl_texture_2d_handle_new (tex_2d); } +#if defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) +/* NB: The reason we require the width, height and format to be passed + * even though they may seem redundant is because GLES 1/2 don't + * provide a way to query these properties. */ +CoglTexture2D * +_cogl_egl_texture_2d_new_from_image (CoglContext *ctx, + int width, + int height, + CoglPixelFormat format, + EGLImageKHR image, + GError **error) +{ + CoglTexture2D *tex_2d; + GLenum gl_error; + + g_return_val_if_fail (_cogl_context_get_winsys (ctx) == + _cogl_winsys_egl_get_vtable (), + NULL); + + g_return_val_if_fail (ctx->private_feature_flags & + COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE, + NULL); + + tex_2d = _cogl_texture_2d_create_base (width, height, COGL_TEXTURE_NONE, + format); + + _cogl_texture_driver_gen (GL_TEXTURE_2D, 1, &tex_2d->gl_texture); + _cogl_bind_gl_texture_transient (GL_TEXTURE_2D, + tex_2d->gl_texture, + FALSE); + + while ((gl_error = glGetError ()) != GL_NO_ERROR) + ; + ctx->drv.pf_glEGLImageTargetTexture2D (GL_TEXTURE_2D, image); + if (glGetError () != GL_NO_ERROR) + { + g_set_error (error, + COGL_TEXTURE_ERROR, + COGL_TEXTURE_ERROR_BAD_PARAMETER, + "Could not create a CoglTexture2D from a given EGLImage"); + return NULL; + } + + return _cogl_texture_2d_handle_new (tex_2d); +} +#endif /* defined (COGL_HAS_EGL_SUPPORT) && defined (EGL_KHR_image_base) */ + void _cogl_texture_2d_externally_modified (CoglHandle handle) { diff --git a/cogl/cogl-texture.h b/cogl/cogl-texture.h index 288a25b2b..93c1c3cb0 100644 --- a/cogl/cogl-texture.h +++ b/cogl/cogl-texture.h @@ -66,7 +66,8 @@ G_BEGIN_DECLS */ typedef enum { COGL_TEXTURE_ERROR_SIZE, - COGL_TEXTURE_ERROR_FORMAT + COGL_TEXTURE_ERROR_FORMAT, + COGL_TEXTURE_ERROR_BAD_PARAMETER } CoglTextureError; GQuark cogl_texture_error_quark (void); diff --git a/cogl/driver/gl/cogl-feature-functions-gl.h b/cogl/driver/gl/cogl-feature-functions-gl.h index e26e4e988..734c76d95 100644 --- a/cogl/driver/gl/cogl-feature-functions-gl.h +++ b/cogl/driver/gl/cogl-feature-functions-gl.h @@ -421,3 +421,15 @@ COGL_FEATURE_BEGIN (point_sprites, 2, 0, COGL_FEATURE_POINT_SPRITE, 0) COGL_FEATURE_END () +COGL_FEATURE_BEGIN (EGL_image, 255, 255, + "OES\0", + "EGL_image\0", + 0, + COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE) +COGL_FEATURE_FUNCTION (void, glEGLImageTargetTexture2D, + (GLenum target, + GLeglImageOES image)) +COGL_FEATURE_FUNCTION (void, glEGLImageTargetRenderbufferStorage, + (GLenum target, + GLeglImageOES image)) +COGL_FEATURE_END () diff --git a/cogl/driver/gl/cogl-gl.c b/cogl/driver/gl/cogl-gl.c index ce81a6ac4..a0c019816 100644 --- a/cogl/driver/gl/cogl-gl.c +++ b/cogl/driver/gl/cogl-gl.c @@ -155,6 +155,7 @@ static const CoglFeatureData cogl_feature_data[] = void _cogl_gl_update_features (CoglContext *context) { + CoglPrivateFeatureFlags private_flags = 0; CoglFeatureFlags flags = 0; const char *gl_extensions; int max_clip_planes = 0; @@ -212,8 +213,12 @@ _cogl_gl_update_features (CoglContext *context) gl_major, gl_minor, gl_extensions, context)) - flags |= cogl_feature_data[i].feature_flags; + { + private_flags |= cogl_feature_data[i].feature_flags_private; + flags |= cogl_feature_data[i].feature_flags; + } /* Cache features */ + context->private_feature_flags |= private_flags; context->feature_flags |= flags; } diff --git a/cogl/driver/gles/cogl-feature-functions-gles.h b/cogl/driver/gles/cogl-feature-functions-gles.h index b70b13b43..b14c935a6 100644 --- a/cogl/driver/gles/cogl-feature-functions-gles.h +++ b/cogl/driver/gles/cogl-feature-functions-gles.h @@ -139,3 +139,15 @@ COGL_FEATURE_FUNCTION (void *, glMapBuffer, COGL_FEATURE_FUNCTION (GLboolean, glUnmapBuffer, (GLenum target)) COGL_FEATURE_END () +COGL_FEATURE_BEGIN (EGL_image, 255, 255, + "OES\0", + "EGL_image\0", + 0, + COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE) +COGL_FEATURE_FUNCTION (void, glEGLImageTargetTexture2D, + (GLenum target, + eglImageOES image)) +COGL_FEATURE_FUNCTION (void, glEGLImageTargetRenderbufferStorage, + (GLenum target, + eglImageOES image)) +COGL_FEATURE_END () diff --git a/cogl/driver/gles/cogl-gles.c b/cogl/driver/gles/cogl-gles.c index 080efeb61..2013d3e0f 100644 --- a/cogl/driver/gles/cogl-gles.c +++ b/cogl/driver/gles/cogl-gles.c @@ -77,6 +77,7 @@ static const CoglFeatureData cogl_feature_data[] = void _cogl_gl_update_features (CoglContext *context) { + CoglPrivateFeatureFlags private_flags = 0; CoglFeatureFlags flags = 0; const char *gl_extensions; #ifndef HAVE_COGL_GLES2 @@ -129,8 +130,12 @@ _cogl_gl_update_features (CoglContext *context) 0, 0, gl_extensions, context)) - flags |= cogl_feature_data[i].feature_flags; + { + private_flags |= cogl_feature_data[i].feature_flags_private; + flags |= cogl_feature_data[i].feature_flags; + } /* Cache features */ + context->private_feature_flags |= private_flags; context->feature_flags |= flags; } diff --git a/cogl/winsys/cogl-winsys-egl-feature-functions.h b/cogl/winsys/cogl-winsys-egl-feature-functions.h index 5a961ea00..410f845cf 100644 --- a/cogl/winsys/cogl-winsys-egl-feature-functions.h +++ b/cogl/winsys/cogl-winsys-egl-feature-functions.h @@ -51,3 +51,20 @@ COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglSwapBuffersRegion, EGLint numRects, const EGLint *rects)) COGL_WINSYS_FEATURE_END () +/* XXX: These macros can't handle falling back to looking for + * EGL_KHR_image if EGL_KHR_image_base and EGL_KHR_image_pixmap aren't + * found... */ +COGL_WINSYS_FEATURE_BEGIN (image_base, + "KHR\0", + "image_base\0", + 0) +COGL_WINSYS_FEATURE_FUNCTION (EGLImageKHR, eglCreateImage, + (EGLDisplay dpy, + EGLContext ctx, + EGLenum target, + EGLClientBuffer buffer, + const EGLint *attrib_list)) +COGL_WINSYS_FEATURE_FUNCTION (EGLBoolean, eglDestroyImage, + (EGLDisplay dpy, + EGLImageKHR image)) +COGL_WINSYS_FEATURE_END () diff --git a/cogl/winsys/cogl-winsys-egl-private.h b/cogl/winsys/cogl-winsys-egl-private.h new file mode 100644 index 000000000..dd2df8e5b --- /dev/null +++ b/cogl/winsys/cogl-winsys-egl-private.h @@ -0,0 +1,46 @@ +/* + * Cogl + * + * An object oriented GL/GLES Abstraction/Utility Layer + * + * Copyright (C) 2011 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * + */ + +#ifndef __COGL_WINSYS_EGL_PRIVATE_H +#define __COGL_WINSYS_EGL_PRIVATE_H + +#include "cogl-defines.h" +#include "cogl-winsys-private.h" +#include "cogl-context.h" + +const CoglWinsysVtable * +_cogl_winsys_egl_get_vtable (void); + +#ifdef EGL_KHR_image_base +EGLImageKHR +_cogl_egl_create_image (CoglContext *ctx, + EGLenum target, + EGLClientBuffer buffer, + const EGLint *attribs); + +void +_cogl_egl_destroy_image (CoglContext *ctx, + EGLImageKHR image); +#endif + +#endif /* __COGL_WINSYS_EGL_PRIVATE_H */ diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c index 3af67c1ae..d2fa23dc3 100644 --- a/cogl/winsys/cogl-winsys-egl.c +++ b/cogl/winsys/cogl-winsys-egl.c @@ -1638,3 +1638,34 @@ cogl_wayland_onscreen_get_surface (CoglOnscreen *onscreen) } #endif /* COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT */ + +#ifdef EGL_KHR_image_base +EGLImageKHR +_cogl_egl_create_image (CoglContext *ctx, + EGLenum target, + EGLClientBuffer buffer, + const EGLint *attribs) +{ + CoglDisplayEGL *egl_display = ctx->display->winsys; + CoglRendererEGL *egl_renderer = ctx->display->renderer->winsys; + + g_return_val_if_fail (egl_renderer->pf_eglCreateImage, EGL_NO_IMAGE_KHR); + + return egl_renderer->pf_eglCreateImage (egl_renderer->edpy, + egl_display->egl_context, + target, + buffer, + attribs); +} + +void +_cogl_egl_destroy_image (CoglContext *ctx, + EGLImageKHR image) +{ + CoglRendererEGL *egl_renderer = ctx->display->renderer->winsys; + + g_return_if_fail (egl_renderer->pf_eglDestroyImage); + + egl_renderer->pf_eglDestroyImage (egl_renderer->edpy, image); +} +#endif