[Mesa-dev] [PATCH 3/6] egl: EGL_INTEL_no_surface extension

Kristian Høgsberg krh at bitplanet.net
Fri Jun 4 06:46:25 PDT 2010


This extension allows 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.
---
 include/EGL/eglext.h                       |    8 +++
 src/egl/drivers/dri2/egl_dri2.c            |   27 ++++++----
 src/egl/main/eglconfig.c                   |    6 ++
 src/egl/main/eglconfig.h                   |    6 ++-
 src/egl/main/eglcontext.c                  |   74 +++++++++++++++-------------
 src/egl/main/egldisplay.h                  |    1 +
 src/egl/main/eglmisc.c                     |    2 +
 src/mesa/drivers/dri/intel/intel_context.c |   22 ++++++--
 8 files changed, 92 insertions(+), 54 deletions(-)

diff --git a/include/EGL/eglext.h b/include/EGL/eglext.h
index bb6f6e7..a1a117a 100644
--- a/include/EGL/eglext.h
+++ b/include/EGL/eglext.h
@@ -261,6 +261,14 @@ typedef EGLDisplay (EGLAPIENTRYP PFNEGLGETTYPEDDISPLAYMESA) (EGLenum type, void
 #endif
 
 
+#ifndef EGL_INTEL_no_surface
+#define EGL_INTEL_no_surface 1
+
+#define EGL_NO_SURFACE_CAPABLE_INTEL 0xcd00	/* config attribute */
+
+#endif /* EGL_INTEL_no_surface */
+
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index f33fa5a..fdaf512 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -176,7 +176,7 @@ EGLint dri2_to_egl_attribute_map[] = {
 
 static void
 dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
-		int depth, xcb_visualtype_t *visual)
+		int depth, xcb_visualtype_t *visual, EGLint surface_type)
 {
    struct dri2_egl_config *conf;
    struct dri2_egl_display *dri2_dpy;
@@ -246,23 +246,24 @@ dri2_add_config(_EGLDisplay *disp, const __DRIconfig *dri_config, int id,
 	 return;
 
       _eglSetConfigKey(&base, EGL_SURFACE_TYPE,
-		       EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT |
+		       EGL_WINDOW_BIT | surface_type |
 		       EGL_SWAP_BEHAVIOR_PRESERVED_BIT);
 
       _eglSetConfigKey(&base, EGL_NATIVE_VISUAL_ID, visual->visual_id);
       _eglSetConfigKey(&base, EGL_NATIVE_VISUAL_TYPE, visual->_class);
    } else {
-      _eglSetConfigKey(&base, EGL_SURFACE_TYPE,
-		       EGL_PIXMAP_BIT | EGL_PBUFFER_BIT);
+      _eglSetConfigKey(&base, EGL_SURFACE_TYPE, surface_type);
    }
 
-   _eglSetConfigKey(&base, EGL_NATIVE_RENDERABLE, EGL_TRUE);
-   _eglSetConfigKey(&base, EGL_BIND_TO_TEXTURE_RGB, bind_to_texture_rgb);
-   if (_eglGetConfigKey(&base, EGL_ALPHA_SIZE) > 0)
-      _eglSetConfigKey(&base,
-		       EGL_BIND_TO_TEXTURE_RGBA, bind_to_texture_rgba);
+   if (surface_type & (EGL_PIXMAP_BIT | EGL_PBUFFER_BIT)) {
+      _eglSetConfigKey(&base, EGL_BIND_TO_TEXTURE_RGB, bind_to_texture_rgb);
+      if (_eglGetConfigKey(&base, EGL_ALPHA_SIZE) > 0)
+	 _eglSetConfigKey(&base,
+			  EGL_BIND_TO_TEXTURE_RGBA, bind_to_texture_rgba);
+   }
 
    _eglSetConfigKey(&base, EGL_RENDERABLE_TYPE, disp->ClientAPIsMask);
+   _eglSetConfigKey(&base, EGL_NO_SURFACE_CAPABLE_INTEL, disp->ClientAPIsMask);
    _eglSetConfigKey(&base, EGL_CONFORMANT, disp->ClientAPIsMask);
 
    if (!_eglValidateConfig(&base, EGL_FALSE)) {
@@ -620,7 +621,8 @@ dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
 	 class_added[visuals[i]._class] = EGL_TRUE;
 	 for (j = 0; dri2_dpy->driver_configs[j]; j++)
 	    dri2_add_config(disp, dri2_dpy->driver_configs[j],
-			    id++, d.data->depth, &visuals[i]);
+			    id++, d.data->depth, &visuals[i],
+			    EGL_PIXMAP_BIT | EGL_PBUFFER_BIT);
       }
 
       xcb_depth_next(&d);      
@@ -905,6 +907,7 @@ dri2_initialize_xcb(_EGLDisplay *disp)
    disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
    disp->Extensions.NOK_swap_region = EGL_TRUE;
    disp->Extensions.NOK_texture_from_pixmap = EGL_TRUE;
+   disp->Extensions.INTEL_no_surface = EGL_TRUE;
 
    return EGL_TRUE;
 
@@ -928,6 +931,7 @@ static EGLBoolean
 dri2_initialize_drm(_EGLDisplay *disp)
 {
    struct dri2_egl_display *dri2_dpy;
+   int i;
 
    dri2_dpy = disp->DriverData;
    dri2_dpy->fd = (int) disp->VoidDisplay;
@@ -949,7 +953,8 @@ dri2_initialize_drm(_EGLDisplay *disp)
    if (!dri2_create_screen(disp))
       goto cleanup_driver;
 
-   /* FIXME: Visuals */
+   for (i = 0; dri2_dpy->driver_configs[i]; i++)
+      dri2_add_config(disp, dri2_dpy->driver_configs[i], i + 1, 0, NULL, 0);
 
    disp->Extensions.KHR_image_base = EGL_TRUE;
    disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index fa947d7..e178f3e 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -229,6 +229,10 @@ static const struct {
                                     ATTRIB_CRITERION_EXACT,
                                     EGL_DONT_CARE },
 
+   { EGL_NO_SURFACE_CAPABLE_INTEL,  ATTRIB_TYPE_BITMASK,
+                                    ATTRIB_CRITERION_MASK,
+                                    EGL_DONT_CARE },
+
 };
 
 
@@ -499,6 +503,8 @@ _eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
       return EGL_FALSE;
    case EGL_Y_INVERTED_NOK:
       return conf->Display->Extensions.NOK_texture_from_pixmap;
+   case EGL_NO_SURFACE_CAPABLE_INTEL:
+      return conf->Display->Extensions.INTEL_no_surface;
    default:
       break;
    }
diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h
index ca63c40..eff570c 100644
--- a/src/egl/main/eglconfig.h
+++ b/src/egl/main/eglconfig.h
@@ -13,10 +13,10 @@
 
 /* Attributes outside the contiguous block:
  *
- *   EGL_Y_INVERTED_NOK
+ *   EGL_Y_INVERTED_NOK, EGL_NO_SURFACE_CAPABLE_INTEL
  */
 #define _EGL_CONFIG_FIRST_EXTRA_ATTRIB _EGL_CONFIG_NUM_CONTIGUOUS_ATTRIBS
-#define _EGL_CONFIG_NUM_EXTRA_ATTRIBS 1
+#define _EGL_CONFIG_NUM_EXTRA_ATTRIBS 2
 
 #define _EGL_CONFIG_NUM_ATTRIBS \
    _EGL_CONFIG_NUM_CONTIGUOUS_ATTRIBS + _EGL_CONFIG_NUM_EXTRA_ATTRIBS
@@ -51,6 +51,8 @@ _eglIndexConfig(const _EGLConfig *conf, EGLint key)
    switch (key) {
    case EGL_Y_INVERTED_NOK:
       return _EGL_CONFIG_FIRST_EXTRA_ATTRIB;
+   case EGL_NO_SURFACE_CAPABLE_INTEL:
+      return _EGL_CONFIG_FIRST_EXTRA_ATTRIB + 1;
    default:
       return -1;
    }
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index d5a1e79..9b6774c 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -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,7 @@ static EGLBoolean
 _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
 {
    _EGLThreadInfo *t = _eglGetCurrentThread();
-   EGLint conflict_api;
+   EGLint conflict_api, type;
 
    if (_eglIsCurrentThreadDummy())
       return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
@@ -309,8 +313,8 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
       return EGL_TRUE;
    }
 
-   /* ctx/draw/read must be all given */
-   if (draw == NULL || read == NULL)
+   type = _eglGetConfigKey(ctx->Config, EGL_NO_SURFACE_CAPABLE_INTEL);
+   if (!(_eglGetContextAPIBit(ctx) & type) && (draw == NULL || read == NULL))
       return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
 
    /* context stealing from another thread is not allowed */
@@ -331,12 +335,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 +392,6 @@ _eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read)
 
       *draw = oldCtx->DrawSurface;
       *read = oldCtx->ReadSurface;
-      assert(*draw && *read);
 
       _eglBindContextToSurfaces(NULL, draw, read);
    }
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 0749edd..70c98f7 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -53,6 +53,7 @@ struct _egl_extensions
    EGLBoolean KHR_gl_renderbuffer_image;
    EGLBoolean NOK_swap_region;
    EGLBoolean NOK_texture_from_pixmap;
+   EGLBoolean INTEL_no_surface;
 
    char String[_EGL_MAX_EXTENSIONS_LEN];
 };
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index 4652969..3aa8cc1 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -98,6 +98,8 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
 
    _EGL_CHECK_EXTENSION(NOK_swap_region);
    _EGL_CHECK_EXTENSION(NOK_texture_from_pixmap);
+
+   _EGL_CHECK_EXTENSION(INTEL_no_surface);
 #undef _EGL_CHECK_EXTENSION
 }
 
diff --git a/src/mesa/drivers/dri/intel/intel_context.c b/src/mesa/drivers/dri/intel/intel_context.c
index 9159f6e..620977b 100644
--- a/src/mesa/drivers/dri/intel/intel_context.c
+++ b/src/mesa/drivers/dri/intel/intel_context.c
@@ -420,7 +420,7 @@ intel_prepare_render(struct intel_context *intel)
    __DRIdrawable *drawable;
 
    drawable = driContext->driDrawablePriv;
-   if (drawable->dri2.stamp != driContext->dri2.draw_stamp) {
+   if (drawable && drawable->dri2.stamp != driContext->dri2.draw_stamp) {
       if (drawable->lastStamp != drawable->dri2.stamp)
 	 intel_update_renderbuffers(driContext, drawable);
       intel_draw_buffer(&intel->ctx, intel->ctx.DrawBuffer);
@@ -428,7 +428,7 @@ intel_prepare_render(struct intel_context *intel)
    }
 
    drawable = driContext->driReadablePriv;
-   if (drawable->dri2.stamp != driContext->dri2.read_stamp) {
+   if (drawable && drawable->dri2.stamp != driContext->dri2.read_stamp) {
       if (drawable->lastStamp != drawable->dri2.stamp)
 	 intel_update_renderbuffers(driContext, drawable);
       driContext->dri2.read_stamp = drawable->dri2.stamp;
@@ -900,13 +900,23 @@ intelMakeCurrent(__DRIcontext * driContextPriv,
    }
 
    if (driContextPriv) {
-      struct gl_framebuffer *fb = driDrawPriv->driverPrivate;
-      struct gl_framebuffer *readFb = driReadPriv->driverPrivate;
+      struct gl_framebuffer *fb, *readFb;
+      
+      if (driDrawPriv == NULL && driReadPriv == NULL) {
+	 fb = _mesa_create_framebuffer(&intel->ctx.Visual);
+	 readFb = fb;
+      } else {
+	 fb = driDrawPriv->driverPrivate;
+	 readFb = driReadPriv->driverPrivate;
+	 driContextPriv->dri2.draw_stamp = driReadPriv->dri2.stamp - 1;
+	 driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1;
+      }
 
-      driContextPriv->dri2.draw_stamp = driDrawPriv->dri2.stamp - 1;
-      driContextPriv->dri2.read_stamp = driReadPriv->dri2.stamp - 1;
       intel_prepare_render(intel);
       _mesa_make_current(&intel->ctx, fb, readFb);
+      
+      if (driDrawPriv == NULL && driReadPriv == NULL)
+         _mesa_reference_framebuffer(&fb, NULL);
 
       /* We do this in intel_prepare_render() too, but intel->ctx.DrawBuffer
        * is NULL at that point.  We can't call _mesa_makecurrent()
-- 
1.7.1



More information about the mesa-dev mailing list