egl: Implement EGL_NOK_texture_from_pixmap
authorKristian Høgsberg <krh@bitplanet.net>
Fri, 7 May 2010 02:40:25 +0000 (22:40 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Fri, 14 May 2010 18:47:54 +0000 (14:47 -0400)
This extension allows a color buffer to be used for both rendering and
texturing.  EGL allows the use of color buffers of pbuffer drawables
for texturing, this extension extends this to allow the use of color
buffers of pixmaps too.

include/EGL/eglext.h
src/egl/drivers/dri2/egl_dri2.c
src/egl/main/eglconfig.c
src/egl/main/eglconfig.h
src/egl/main/egldisplay.h
src/egl/main/eglmisc.c
src/egl/main/eglsurface.c
src/egl/main/eglsurface.h

index 61626d20df6f61ce3584d99b5538c3b104cfda1d..e9f5a49b488cbfc566120bbca9d5b19615189290 100644 (file)
@@ -239,6 +239,13 @@ typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSREGIONNOK) (EGLDisplay dpy, EG
 #endif
 
 
+#ifndef EGL_NOK_texture_from_pixmap
+#define EGL_NOK_texture_from_pixmap 1
+
+#define EGL_Y_INVERTED_NOK                     0x307F
+#endif /* EGL_NOK_texture_from_pixmap */
+
+
 #ifdef __cplusplus
 }
 #endif
index 82f409d294bb8524c1d5c146caa0ce7dcac75dc1..a7030f03dbd1f15023ef07b0d40899f86b57cb99 100644 (file)
@@ -165,7 +165,7 @@ EGLint dri2_to_egl_attribute_map[] = {
    0,                          /* __DRI_ATTRIB_BIND_TO_TEXTURE_RGBA */
    0,                          /* __DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE */
    0,                          /* __DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS */
-   0,                          /* __DRI_ATTRIB_YINVERTED */
+   EGL_Y_INVERTED_NOK,         /* __DRI_ATTRIB_YINVERTED */
 };
 
 static void
@@ -781,6 +781,7 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
    disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
    disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
    disp->Extensions.NOK_swap_region = EGL_TRUE;
+   disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
 
    /* we're supporting EGL 1.4 */
    *major = 1;
@@ -1229,19 +1230,8 @@ dri2_bind_tex_image(_EGLDriver *drv,
    ctx = _eglGetCurrentContext();
    dri2_ctx = dri2_egl_context(ctx);
 
-   if (buffer != EGL_BACK_BUFFER) {
-      _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
+   if (!_eglBindTexImage(drv, disp, surf, buffer))
       return EGL_FALSE;
-   }
-
-   /* We allow binding pixmaps too... Not conformat, but we can do it
-    * for free and it's useful for X compositors.  Supposedly there's
-    * a EGL_NOKIA_texture_from_pixmap extension that allows that, but
-    * I couldn't find it at this time. */
-   if ((dri2_surf->base.Type & (EGL_PBUFFER_BIT | EGL_PIXMAP_BIT)) == 0) {
-      _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
-      return EGL_FALSE;
-   }
 
    switch (dri2_surf->base.TextureFormat) {
    case EGL_TEXTURE_RGB:
@@ -1251,8 +1241,7 @@ dri2_bind_tex_image(_EGLDriver *drv,
       format = __DRI_TEXTURE_FORMAT_RGBA;
       break;
    default:
-      _eglError(EGL_BAD_MATCH, "eglBindTexImage");
-      return EGL_FALSE;
+      assert(0);
    }
 
    switch (dri2_surf->base.TextureTarget) {
@@ -1260,15 +1249,14 @@ dri2_bind_tex_image(_EGLDriver *drv,
       target = GL_TEXTURE_2D;
       break;
    default:
-      _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
-      return EGL_FALSE;
+      assert(0);
    }
 
    (*dri2_dpy->tex_buffer->setTexBuffer2)(dri2_ctx->dri_context,
                                          target, format,
                                          dri2_surf->dri_drawable);
 
-   return dri2_surf->base.BoundToTexture = EGL_TRUE;
+   return EGL_TRUE;
 }
 
 static EGLBoolean
index a659d19c3734c8141e8f9cc291f9084b3047c3d1..fa947d7688759510eb80640b8346eaf5d27ba238 100644 (file)
@@ -223,7 +223,12 @@ static const struct {
                                     0 },
    { EGL_NONE,                      ATTRIB_TYPE_PSEUDO,
                                     ATTRIB_CRITERION_IGNORE,
-                                    0 }
+                                    0 },
+
+   { EGL_Y_INVERTED_NOK,            ATTRIB_TYPE_BOOLEAN,
+                                    ATTRIB_CRITERION_EXACT,
+                                    EGL_DONT_CARE },
+
 };
 
 
@@ -492,6 +497,8 @@ _eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
    case EGL_MATCH_NATIVE_PIXMAP:
 #endif
       return EGL_FALSE;
+   case EGL_Y_INVERTED_NOK:
+      return conf->Display->Extensions.NOK_texture_from_pixmap;
    default:
       break;
    }
index ced060f7797bece2408a75b15645ca418403b45c..ca63c40d3d78b26468638bc58b61eaa4fd4706f8 100644 (file)
@@ -8,16 +8,24 @@
 
 #define _EGL_CONFIG_FIRST_ATTRIB EGL_BUFFER_SIZE
 #define _EGL_CONFIG_LAST_ATTRIB EGL_CONFORMANT
-#define _EGL_CONFIG_NUM_ATTRIBS \
+#define _EGL_CONFIG_NUM_CONTIGUOUS_ATTRIBS \
    (_EGL_CONFIG_LAST_ATTRIB - _EGL_CONFIG_FIRST_ATTRIB + 1)
 
-#define _EGL_CONFIG_STORAGE_SIZE _EGL_CONFIG_NUM_ATTRIBS
+/* Attributes outside the contiguous block:
+ *
+ *   EGL_Y_INVERTED_NOK
+ */
+#define _EGL_CONFIG_FIRST_EXTRA_ATTRIB _EGL_CONFIG_NUM_CONTIGUOUS_ATTRIBS
+#define _EGL_CONFIG_NUM_EXTRA_ATTRIBS 1
+
+#define _EGL_CONFIG_NUM_ATTRIBS \
+   _EGL_CONFIG_NUM_CONTIGUOUS_ATTRIBS + _EGL_CONFIG_NUM_EXTRA_ATTRIBS
 
 
 struct _egl_config
 {
    _EGLDisplay *Display;
-   EGLint Storage[_EGL_CONFIG_STORAGE_SIZE];
+   EGLint Storage[_EGL_CONFIG_NUM_ATTRIBS];
 };
 
 
@@ -37,10 +45,15 @@ _eglIndexConfig(const _EGLConfig *conf, EGLint key)
 {
    (void) conf;
    if (key >= _EGL_CONFIG_FIRST_ATTRIB &&
-       key < _EGL_CONFIG_FIRST_ATTRIB + _EGL_CONFIG_NUM_ATTRIBS)
+       key < _EGL_CONFIG_FIRST_ATTRIB + _EGL_CONFIG_NUM_CONTIGUOUS_ATTRIBS)
       return key - _EGL_CONFIG_FIRST_ATTRIB;
-   else
+   
+   switch (key) {
+   case EGL_Y_INVERTED_NOK:
+      return _EGL_CONFIG_FIRST_EXTRA_ATTRIB;
+   default:
       return -1;
+   }
 }
 
 
index 0b7f9d83036c072e3cd5ffb077b01296ae7319a9..42e305f91ac34073d248f6ad19ff86377d782b1b 100644 (file)
@@ -47,6 +47,7 @@ struct _egl_extensions
    EGLBoolean KHR_gl_texture_3D_image;
    EGLBoolean KHR_gl_renderbuffer_image;
    EGLBoolean NOK_swap_region;
+   EGLBoolean NOK_texture_from_pixmap;
 
    char String[_EGL_MAX_EXTENSIONS_LEN];
 };
index 82ddb6cad99e633274d9aadecaefbfa99105550c..e62a9e7de8ce1e13bede66e6be4fc0cbca432f19 100644 (file)
@@ -97,6 +97,7 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
    _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
 
    _EGL_CHECK_EXTENSION(NOK_swap_region);
+   _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
 #undef _EGL_CHECK_EXTENSION
 }
 
index 8026a6314d3629e83acd47f1fea527770528b35a..d46bdb0672e9659901196ab9b974c9ef433cbd3b 100644 (file)
@@ -36,12 +36,17 @@ _eglClampSwapInterval(_EGLSurface *surf, EGLint interval)
 static EGLint
 _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
 {
+   _EGLDisplay *dpy = surf->Resource.Display;
    EGLint type = surf->Type;
+   EGLint texture_type = EGL_PBUFFER_BIT;
    EGLint i, err = EGL_SUCCESS;
 
    if (!attrib_list)
       return EGL_SUCCESS;
 
+   if (dpy->Extensions.NOK_texture_from_pixmap)
+      texture_type |= EGL_PIXMAP_BIT;
+
    for (i = 0; attrib_list[i] != EGL_NONE; i++) {
       EGLint attr = attrib_list[i++];
       EGLint val = attrib_list[i];
@@ -125,7 +130,7 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
          surf->LargestPbuffer = !!val;
          break;
       case EGL_TEXTURE_FORMAT:
-         if (type != EGL_PBUFFER_BIT) {
+         if (!(type & texture_type)) {
             err = EGL_BAD_ATTRIBUTE;
             break;
          }
@@ -143,7 +148,7 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
          surf->TextureFormat = val;
          break;
       case EGL_TEXTURE_TARGET:
-         if (type != EGL_PBUFFER_BIT) {
+         if (!(type & texture_type)) {
             err = EGL_BAD_ATTRIBUTE;
             break;
          }
@@ -160,7 +165,7 @@ _eglParseSurfaceAttribList(_EGLSurface *surf, const EGLint *attrib_list)
          surf->TextureTarget = val;
          break;
       case EGL_MIPMAP_TEXTURE:
-         if (type != EGL_PBUFFER_BIT) {
+         if (!(type & texture_type)) {
             err = EGL_BAD_ATTRIBUTE;
             break;
          }
@@ -452,11 +457,16 @@ EGLBoolean
 _eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
                  EGLint buffer)
 {
+   EGLint texture_type = EGL_PBUFFER_BIT;
+
    /* Just do basic error checking and return success/fail.
     * Drivers must implement the real stuff.
     */
 
-   if (surface->Type != EGL_PBUFFER_BIT) {
+   if (dpy->Extensions.NOK_texture_from_pixmap)
+      texture_type |= EGL_PIXMAP_BIT;
+
+   if (!(surface->Type & texture_type)) {
       _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
       return EGL_FALSE;
    }
@@ -466,6 +476,11 @@ _eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
       return EGL_FALSE;
    }
 
+   if (surface->TextureTarget == EGL_NO_TEXTURE) {
+      _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+      return EGL_FALSE;
+   }
+
    if (buffer != EGL_BACK_BUFFER) {
       _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
       return EGL_FALSE;
index 0a00035730f73731fa5ecdb89e24500e19a49171..8f520dcdf650f606d0cdf54d0879be2772df0159 100644 (file)
@@ -83,7 +83,7 @@ extern EGLBoolean
 _eglSurfaceAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint attribute, EGLint value);
 
 
-extern EGLBoolean
+PUBLIC extern EGLBoolean
 _eglBindTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint buffer);