[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