egl: EGL_KHR_surfaceless_* extensions
authorKristian Høgsberg <krh@bitplanet.net>
Thu, 3 Jun 2010 02:48:06 +0000 (22:48 -0400)
committerKristian Høgsberg <krh@bitplanet.net>
Thu, 29 Jul 2010 03:07:00 +0000 (23:07 -0400)
These extensions allow an application to make a context current by
passing EGL_NO_SURFACE for the write and read surface in the call to
eglMakeCurrent.  The motivation is that applications that only want to
render to client API targets (such as OpenGL framebuffer objects)
should not need to create a throw-away EGL surface just to get a
current context.

src/egl/main/eglapi.c
src/egl/main/eglcontext.c
src/egl/main/egldisplay.h
src/egl/main/eglmisc.c

index 09271140b132a40e22c8ac1a3476635b329ef910..4dc8707cfbc66afaaf30bf0862748065823b3491 100644 (file)
@@ -379,7 +379,11 @@ eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
    _EGLContext *context;
    EGLContext ret;
 
-   _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv);
+   if (config)
+      _EGL_CHECK_CONFIG(disp, conf, EGL_NO_CONTEXT, drv);
+   else
+      drv = _eglCheckDisplay(disp, __FUNCTION__);
+
    if (!share && share_list != EGL_NO_CONTEXT)
       RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_NO_CONTEXT);
 
index d5a1e79a9948926a8a1d3f07f7db90a2983e9dbc..74a5a632eba1ea34c904ef07e6c5172f7e6181ec 100644 (file)
@@ -83,7 +83,7 @@ _eglParseContextAttribList(_EGLContext *ctx, const EGLint *attrib_list)
       }
    }
 
-   if (err == EGL_SUCCESS) {
+   if (err == EGL_SUCCESS && ctx->Config) {
       EGLint renderable_type, api_bit;
 
       renderable_type = GET_CONFIG_ATTRIB(ctx->Config, EGL_RENDERABLE_TYPE);
@@ -220,45 +220,49 @@ _eglBindContextToSurfaces(_EGLContext *newCtx,
     * surface (oldDraw), the old bindings are broken first and the new one is
     * created.
     */
-   oldCtx = newDraw->CurrentContext;
-   if (newCtx != oldCtx) {
-      if (oldCtx) {
-         assert(oldCtx->DrawSurface == newDraw);
-         oldCtx->DrawSurface = NULL;
+   if (newDraw) {
+      oldCtx = newDraw->CurrentContext;
+      if (newCtx != oldCtx) {
+        if (oldCtx) {
+           assert(oldCtx->DrawSurface == newDraw);
+           oldCtx->DrawSurface = NULL;
+        }
+      
+        newDraw->CurrentContext = newCtx;
       }
+   }
 
-      if (newCtx) {
-         _EGLSurface *oldDraw = newCtx->DrawSurface;
-         if (oldDraw)
-            oldDraw->CurrentContext = NULL;
-
-         newCtx->DrawSurface = newDraw;
-         *draw = oldDraw;
-      }
+   if (newCtx) {
+      _EGLSurface *oldDraw = newCtx->DrawSurface;
+      if (oldDraw)
+        oldDraw->CurrentContext = NULL;
 
-      newDraw->CurrentContext = newCtx;
+      newCtx->DrawSurface = newDraw;
+      *draw = oldDraw;
    }
 
    /* likewise */
-   if (newRead != newDraw)
+   if (newRead && newRead != newDraw) {
       oldCtx = newRead->CurrentContext;
-   if (newCtx != oldCtx) {
-      if (oldCtx) {
-         assert(oldCtx->ReadSurface == newRead);
-         oldCtx->ReadSurface = NULL;
-      }
+      if (newCtx != oldCtx) {
+        if (oldCtx) {
+           assert(oldCtx->ReadSurface == newRead);
+           oldCtx->ReadSurface = NULL;
+        }
 
-      if (newCtx) {
-         _EGLSurface *oldRead = newCtx->ReadSurface;
-         if (oldRead)
-            oldRead->CurrentContext = NULL;
-
-         newCtx->ReadSurface = newRead;
-         *read = oldRead;
+        newRead->CurrentContext = newCtx;
       }
+   }
 
-      newRead->CurrentContext = newCtx;
+   if (newCtx) {
+      _EGLSurface *oldRead = newCtx->ReadSurface;
+      if (oldRead)
+        oldRead->CurrentContext = NULL;
+
+      newCtx->ReadSurface = newRead;
+      *read = oldRead;
    }
+
 }
 
 
@@ -297,7 +301,9 @@ static EGLBoolean
 _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
 {
    _EGLThreadInfo *t = _eglGetCurrentThread();
+   _EGLDisplay *dpy = ctx->Resource.Display;
    EGLint conflict_api;
+   EGLBoolean surfaceless;
 
    if (_eglIsCurrentThreadDummy())
       return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
@@ -309,8 +315,22 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
       return EGL_TRUE;
    }
 
-   /* ctx/draw/read must be all given */
-   if (draw == NULL || read == NULL)
+   switch (_eglGetContextAPIBit(ctx)) {
+   case EGL_OPENGL_ES_BIT:
+      surfaceless = dpy->Extensions.KHR_surfaceless_gles1;
+      break;
+   case EGL_OPENGL_ES2_BIT:
+      surfaceless = dpy->Extensions.KHR_surfaceless_gles2;
+      break;
+   case EGL_OPENGL_BIT:
+      surfaceless = dpy->Extensions.KHR_surfaceless_opengl;
+      break;
+   default:
+      surfaceless = EGL_FALSE;
+      break;
+   }
+
+   if (!surfaceless && (draw == NULL || read == NULL))
       return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
 
    /* context stealing from another thread is not allowed */
@@ -331,12 +351,13 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
     *
     * The latter is more restrictive so we can check only the latter case.
     */
-   if ((draw->CurrentContext && draw->CurrentContext != ctx) ||
-       (read->CurrentContext && read->CurrentContext != ctx))
+   if ((draw && draw->CurrentContext && draw->CurrentContext != ctx) ||
+       (read && read->CurrentContext && read->CurrentContext != ctx))
       return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
 
    /* simply require the configs to be equal */
-   if (draw->Config != ctx->Config || read->Config != ctx->Config)
+   if ((draw && draw->Config != ctx->Config) ||
+       (read && read->Config != ctx->Config))
       return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
 
    switch (ctx->ClientAPI) {
@@ -387,7 +408,6 @@ _eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read)
 
       *draw = oldCtx->DrawSurface;
       *read = oldCtx->ReadSurface;
-      assert(*draw && *read);
 
       _eglBindContextToSurfaces(NULL, draw, read);
    }
index 0b2f26a4c07f6611157fd8b127a4c81731f41b07..a2cee08bf6f76d07b1702b9abf0e84ab17e59b45 100644 (file)
@@ -60,6 +60,9 @@ struct _egl_extensions
    EGLBoolean KHR_gl_texture_cubemap_image;
    EGLBoolean KHR_gl_texture_3D_image;
    EGLBoolean KHR_gl_renderbuffer_image;
+   EGLBoolean KHR_surfaceless_gles1;
+   EGLBoolean KHR_surfaceless_gles2;
+   EGLBoolean KHR_surfaceless_opengl;
    EGLBoolean NOK_swap_region;
    EGLBoolean NOK_texture_from_pixmap;
 
index 281138c7523b408470404eddaa361e227ccd991a..985d1e0069d723f6d3571de77c930e34bbfb3427 100644 (file)
@@ -97,6 +97,10 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
    _EGL_CHECK_EXTENSION(KHR_gl_texture_3D_image);
    _EGL_CHECK_EXTENSION(KHR_gl_renderbuffer_image);
 
+   _EGL_CHECK_EXTENSION(KHR_surfaceless_gles1);
+   _EGL_CHECK_EXTENSION(KHR_surfaceless_gles2);
+   _EGL_CHECK_EXTENSION(KHR_surfaceless_opengl);
+
    _EGL_CHECK_EXTENSION(NOK_swap_region);
    _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
 #undef _EGL_CHECK_EXTENSION