2010/6/4 Kristian Høgsberg <k...@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@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev > _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev