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

Jakob Bornecrantz wallbraker at gmail.com
Fri Jun 4 07:24:59 PDT 2010


2010/6/4 Kristian Høgsberg <krh at bitplanet.net>:
> 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.

Looks good.

Any reason this is a intel extension instead of a Mesa one?

Can you add a small spec file explaning it? Not that it needs much
explaining. Tho it would be nice to know if glDrawBuffers(0, NULL) and
then drawing something should raise a error? Or if rendering will be
skipped?

Feel like taking a stab at adding this to st/mesa, st/dri & st/egl?

Cheers Jakob.

> ---
>  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
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/mesa-dev
>


More information about the mesa-dev mailing list