[Mesa-dev] [PATCH mesa 4/7] Add the EGL_MESA_configless_context extension
John Kåre Alsaker
john.kare.alsaker at gmail.com
Sat May 3 05:40:25 PDT 2014
This commit results in garbage output for r600g when building with
OpenGL (not ES) as enabled by my patches:
https://github.com/Zoxc/weston/commits/gl-rebase. (--enable-opengl on
configure)
It works on i965 so I was wondering how well tested this is on Gallium drivers?
On Fri, Mar 7, 2014 at 7:05 PM, Neil Roberts <neil at linux.intel.com> wrote:
> This extension provides a way for an application to render to multiple
> surfaces with different buffer formats without having to use multiple
> contexts. An EGLContext can be created without an EGLConfig by passing
> EGL_NO_CONFIG_MESA. In that case there are no restrictions on the surfaces
> that can be used with the context apart from that they must be using the same
> EGLDisplay.
>
> _mesa_initialze_context can now take a NULL gl_config which will mark the
> context as ‘configless’. It will memset the visual to zero in that case.
> Previously the i965 and i915 drivers were explicitly creating a zeroed visual
> whenever 0 is passed for the EGLConfig. Mesa needs to be aware that the
> context is configless because it affects the initial value to use for
> glDrawBuffer. The first time the context is bound it will set the initial
> value for configless contexts depending on whether the framebuffer used is
> double-buffered.
> ---
> docs/specs/MESA_configless_context.spec | 120 ++++++++++++++++++++++++++++++
> include/EGL/eglext.h | 5 ++
> src/egl/drivers/dri2/egl_dri2.c | 1 +
> src/egl/main/eglapi.c | 2 +-
> src/egl/main/eglcontext.c | 20 ++++-
> src/egl/main/egldisplay.h | 1 +
> src/egl/main/eglmisc.c | 1 +
> src/mesa/drivers/dri/i915/intel_context.c | 6 --
> src/mesa/drivers/dri/i965/brw_context.c | 6 --
> src/mesa/main/context.c | 82 +++++++++++++++-----
> src/mesa/main/mtypes.h | 6 ++
> 11 files changed, 213 insertions(+), 37 deletions(-)
> create mode 100644 docs/specs/MESA_configless_context.spec
>
> diff --git a/docs/specs/MESA_configless_context.spec b/docs/specs/MESA_configless_context.spec
> new file mode 100644
> index 0000000..8bed90d
> --- /dev/null
> +++ b/docs/specs/MESA_configless_context.spec
> @@ -0,0 +1,120 @@
> +Name
> +
> + MESA_configless_context
> +
> +Name Strings
> +
> + EGL_MESA_configless_context
> +
> +Contact
> +
> + Neil Roberts <neil.s.roberts at intel.com>
> +
> +Status
> +
> + Proposal
> +
> +Version
> +
> + Version 1, February 28, 2014
> +
> +Number
> +
> + EGL Extension #not assigned
> +
> +Dependencies
> +
> + Requires EGL 1.4 or later. This extension is written against the
> + wording of the EGL 1.4 specification.
> +
> +Overview
> +
> + This extension provides a means to use a single context to render to
> + multiple surfaces which have different EGLConfigs. Without this extension
> + the EGLConfig for every surface used by the context must be compatible
> + with the one used by the context. The only way to render to surfaces with
> + different formats would be to create multiple contexts but this is
> + inefficient with modern GPUs where this restriction is unnecessary.
> +
> +IP Status
> +
> + Open-source; freely implementable.
> +
> +New Procedures and Functions
> +
> + None.
> +
> +New Tokens
> +
> + Accepted as <config> in eglCreateContext
> +
> + EGL_NO_CONFIG_MESA ((EGLConfig)0)
> +
> +Additions to the EGL Specification section "2.2 Rendering Contexts and Drawing
> +Surfaces"
> +
> + Add the following to the 3rd paragraph:
> +
> + "EGLContexts can also optionally be created with respect to an EGLConfig
> + depending on the parameters used at creation time. If a config is provided
> + then additional restrictions apply on what surfaces can be used with the
> + context."
> +
> + Replace the last sentence of the 6th paragraph with:
> +
> + "In order for a context to be compatible with a surface they both must have
> + been created with respect to the same EGLDisplay. If the context was
> + created without respect to an EGLConfig then there are no further
> + constraints. Otherwise they are only compatible if:"
> +
> + Remove the last bullet point in the list of constraints.
> +
> +Additions to the EGL Specification section "3.7.1 Creating Rendering Contexts"
> +
> + Replace the paragraph starting "If config is not a valid EGLConfig..."
> + with
> +
> + "The config argument can either be a valid EGLConfig or EGL_NO_CONFIG_MESA.
> + If it is neither of these then an EGL_BAD_CONFIG error is generated. If a
> + valid config is passed then the error will also be generated if the config
> + does not support the requested client API (this includes requesting
> + creation of an OpenGL ES 1.x context when the EGL_RENDERABLE_TYPE
> + attribute of config does not contain EGL_OPENGL_ES_BIT, or creation of an
> + OpenGL ES 2.x context when the attribute does not contain
> + EGL_OPENGL_ES2_BIT).
> +
> + Passing EGL_NO_CONFIG_MESA will create a configless context. When a
> + configless context is used with the OpenGL API it can be assumed that the
> + initial values of the context's state will be decided when the context is
> + first made current. In particular this means that the decision of whether
> + to use GL_BACK or GL_FRONT for the initial value of the first output in
> + glDrawBuffers will be decided based on the config of the draw surface when
> + it is first bound. If the context is later bound to another surface with a
> + different config it will not alter the context's state. This means that is
> + possible to have the draw buffer set to GL_BACK with a single-buffered
> + surface. The results of drawing in this case are undefined. The OpenGL ES
> + 3.0 API does not have this problem and instead the default is always
> + GL_BACK which has a special interpretation depending on how many buffers
> + the surface has."
> +
> +Additions to the EGL Specification section "3.7.3 Binding Contexts and
> +Drawables"
> +
> + Replace the first bullet point with the following:
> +
> + "* If draw or read are not compatible with ctx as described in section 2.2,
> + then an EGL_BAD_MATCH error is generated."
> +
> + Add a second bullet point after that:
> +
> + "* If draw and read are not compatible with each other as described in
> + section 2.2, then an EGL_BAD_MATCH error is generated."
> +
> +Issues
> +
> + None.
> +
> +Revision History
> +
> + Version 1, February 28, 2014
> + Initial draft (Neil Roberts)
> diff --git a/include/EGL/eglext.h b/include/EGL/eglext.h
> index 1d68178..fc53914 100644
> --- a/include/EGL/eglext.h
> +++ b/include/EGL/eglext.h
> @@ -571,6 +571,11 @@ EGLAPI EGLBoolean EGLAPIENTRY eglSwapBuffersWithDamageEXT( EGLDisplay dpy, EGLSu
> typedef EGLBoolean (EGLAPIENTRYP PFNEGLSWAPBUFFERSWITHDAMAGEEXTPROC)(EGLDisplay dpy, EGLSurface surface, EGLint *rects, EGLint n_rects);
> #endif
>
> +#ifndef EGL_MESA_configless_context
> +#define EGL_MESA_configless_context 1
> +#define EGL_NO_CONFIG_MESA ((EGLConfig)0)
> +#endif
> +
> #include <EGL/eglmesaext.h>
>
> #ifdef __cplusplus
> diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
> index 892f1f4..f304075 100644
> --- a/src/egl/drivers/dri2/egl_dri2.c
> +++ b/src/egl/drivers/dri2/egl_dri2.c
> @@ -508,6 +508,7 @@ dri2_setup_screen(_EGLDisplay *disp)
>
> assert(dri2_dpy->dri2 || dri2_dpy->swrast);
> disp->Extensions.KHR_surfaceless_context = EGL_TRUE;
> + disp->Extensions.MESA_configless_context = EGL_TRUE;
>
> if (dri2_dpy->dri2 && dri2_dpy->dri2->base.version >= 3) {
> disp->Extensions.KHR_create_context = EGL_TRUE;
> diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
> index 42bcb72..950c447 100644
> --- a/src/egl/main/eglapi.c
> +++ b/src/egl/main/eglapi.c
> @@ -431,7 +431,7 @@ eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list,
>
> _EGL_CHECK_DISPLAY(disp, EGL_NO_CONTEXT, drv);
>
> - if (!config)
> + if (!config && !disp->Extensions.MESA_configless_context)
> RETURN_EGL_ERROR(disp, EGL_BAD_CONFIG, EGL_NO_CONTEXT);
>
> if (!share && share_list != EGL_NO_CONTEXT)
> diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
> index 79a92c7..70277ab 100644
> --- a/src/egl/main/eglcontext.c
> +++ b/src/egl/main/eglcontext.c
> @@ -523,10 +523,22 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
> return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
> }
>
> - /* simply require the configs to be equal */
> - if ((draw && draw->Config != ctx->Config) ||
> - (read && read->Config != ctx->Config))
> - return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
> + /* If the context has a config then it must match that of the two
> + * surfaces */
> + if (ctx->Config) {
> + if ((draw && draw->Config != ctx->Config) ||
> + (read && read->Config != ctx->Config))
> + return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
> + } else {
> + /* Otherwise we must be using the EGL_MESA_configless_context
> + * extension */
> + assert(dpy->Extensions.MESA_configless_context);
> +
> + /* The extension doesn't permit binding draw and read buffers with
> + * differing contexts */
> + if (draw && read && draw->Config != read->Config)
> + return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
> + }
>
> switch (ctx->ClientAPI) {
> /* OpenGL and OpenGL ES are conflicting */
> diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
> index 66aaff5..0952bc9 100644
> --- a/src/egl/main/egldisplay.h
> +++ b/src/egl/main/egldisplay.h
> @@ -89,6 +89,7 @@ struct _egl_extensions
> EGLBoolean MESA_copy_context;
> EGLBoolean MESA_drm_display;
> EGLBoolean MESA_drm_image;
> + EGLBoolean MESA_configless_context;
>
> EGLBoolean WL_bind_wayland_display;
> EGLBoolean WL_create_wayland_buffer_from_image;
> diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
> index 341a723..65669d8 100644
> --- a/src/egl/main/eglmisc.c
> +++ b/src/egl/main/eglmisc.c
> @@ -90,6 +90,7 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
> _EGL_CHECK_EXTENSION(MESA_copy_context);
> _EGL_CHECK_EXTENSION(MESA_drm_display);
> _EGL_CHECK_EXTENSION(MESA_drm_image);
> + _EGL_CHECK_EXTENSION(MESA_configless_context);
>
> _EGL_CHECK_EXTENSION(WL_bind_wayland_display);
> _EGL_CHECK_EXTENSION(WL_create_wayland_buffer_from_image);
> diff --git a/src/mesa/drivers/dri/i915/intel_context.c b/src/mesa/drivers/dri/i915/intel_context.c
> index 0cb1fea..a6057d3 100644
> --- a/src/mesa/drivers/dri/i915/intel_context.c
> +++ b/src/mesa/drivers/dri/i915/intel_context.c
> @@ -410,7 +410,6 @@ intelInitContext(struct intel_context *intel,
> __DRIscreen *sPriv = driContextPriv->driScreenPriv;
> struct intel_screen *intelScreen = sPriv->driverPrivate;
> int bo_reuse_mode;
> - struct gl_config visual;
>
> /* Can't rely on invalidate events, fall back to glViewport hack */
> if (!driContextPriv->driScreenPriv->dri2.useInvalidate)
> @@ -418,11 +417,6 @@ intelInitContext(struct intel_context *intel,
> else
> functions->Viewport = intel_viewport;
>
> - if (mesaVis == NULL) {
> - memset(&visual, 0, sizeof visual);
> - mesaVis = &visual;
> - }
> -
> intel->intelScreen = intelScreen;
>
> if (!_mesa_initialize_context(&intel->ctx, api, mesaVis, shareCtx,
> diff --git a/src/mesa/drivers/dri/i965/brw_context.c b/src/mesa/drivers/dri/i965/brw_context.c
> index 1441b46..ad5e729 100644
> --- a/src/mesa/drivers/dri/i965/brw_context.c
> +++ b/src/mesa/drivers/dri/i965/brw_context.c
> @@ -584,7 +584,6 @@ brwCreateContext(gl_api api,
> struct intel_screen *screen = sPriv->driverPrivate;
> const struct brw_device_info *devinfo = screen->devinfo;
> struct dd_function_table functions;
> - struct gl_config visual;
>
> /* Only allow the __DRI_CTX_FLAG_ROBUST_BUFFER_ACCESS flag if the kernel
> * provides us with context reset notifications.
> @@ -651,11 +650,6 @@ brwCreateContext(gl_api api,
>
> struct gl_context *ctx = &brw->ctx;
>
> - if (mesaVis == NULL) {
> - memset(&visual, 0, sizeof visual);
> - mesaVis = &visual;
> - }
> -
> if (!_mesa_initialize_context(ctx, api, mesaVis, shareCtx, &functions)) {
> *dri_ctx_error = __DRI_CTX_ERROR_NO_MEMORY;
> fprintf(stderr, "%s: failed to init mesa context\n", __FUNCTION__);
> diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
> index 5b77ce1..cd009c1 100644
> --- a/src/mesa/main/context.c
> +++ b/src/mesa/main/context.c
> @@ -1013,7 +1013,8 @@ _mesa_initialize_dispatch_tables(struct gl_context *ctx)
> *
> * \param ctx the context to initialize
> * \param api the GL API type to create the context for
> - * \param visual describes the visual attributes for this context
> + * \param visual describes the visual attributes for this context or NULL to
> + * create a configless context
> * \param share_list points to context to share textures, display lists,
> * etc with, or NULL
> * \param driverFunctions table of device driver functions for this context
> @@ -1033,12 +1034,20 @@ _mesa_initialize_context(struct gl_context *ctx,
> assert(driverFunctions->FreeTextureImageBuffer);
>
> ctx->API = api;
> - ctx->Visual = *visual;
> ctx->DrawBuffer = NULL;
> ctx->ReadBuffer = NULL;
> ctx->WinSysDrawBuffer = NULL;
> ctx->WinSysReadBuffer = NULL;
>
> + if (visual) {
> + ctx->Visual = *visual;
> + ctx->HasConfig = GL_TRUE;
> + }
> + else {
> + memset(&ctx->Visual, 0, sizeof ctx->Visual);
> + ctx->HasConfig = GL_FALSE;
> + }
> +
> if (_mesa_is_desktop_gl(ctx)) {
> _mesa_override_gl_version(ctx);
> }
> @@ -1145,7 +1154,8 @@ fail:
> * the rendering context.
> *
> * \param api the GL API type to create the context for
> - * \param visual a struct gl_config pointer (we copy the struct contents)
> + * \param visual a struct gl_config pointer (we copy the struct contents) or
> + * NULL to create a configless context
> * \param share_list another context to share display lists with or NULL
> * \param driverFunctions points to the dd_function_table into which the
> * driver has plugged in all its special functions.
> @@ -1160,8 +1170,6 @@ _mesa_create_context(gl_api api,
> {
> struct gl_context *ctx;
>
> - ASSERT(visual);
> -
> ctx = calloc(1, sizeof(struct gl_context));
> if (!ctx)
> return NULL;
> @@ -1475,6 +1483,54 @@ _mesa_check_init_viewport(struct gl_context *ctx, GLuint width, GLuint height)
> }
> }
>
> +static void
> +handle_first_current(struct gl_context *ctx)
> +{
> + GLenum buffer;
> + GLint bufferIndex;
> +
> + assert(ctx->Version > 0);
> +
> + ctx->Extensions.String = _mesa_make_extension_string(ctx);
> +
> + check_context_limits(ctx);
> +
> + /* According to GL_MESA_configless_context the default value of
> + * glDrawBuffers depends on the config of the first surface it is bound to.
> + * For GLES it is always GL_BACK which has a magic interpretation */
> + if (!ctx->HasConfig && _mesa_is_desktop_gl(ctx)) {
> + if (ctx->DrawBuffer != _mesa_get_incomplete_framebuffer()) {
> + if (ctx->DrawBuffer->Visual.doubleBufferMode)
> + buffer = GL_BACK;
> + else
> + buffer = GL_FRONT;
> +
> + _mesa_drawbuffers(ctx, 1, &buffer, NULL /* destMask */);
> + }
> +
> + if (ctx->ReadBuffer != _mesa_get_incomplete_framebuffer()) {
> + if (ctx->ReadBuffer->Visual.doubleBufferMode) {
> + buffer = GL_BACK;
> + bufferIndex = BUFFER_BACK_LEFT;
> + }
> + else {
> + buffer = GL_FRONT;
> + bufferIndex = BUFFER_FRONT_LEFT;
> + }
> +
> + _mesa_readbuffer(ctx, buffer, bufferIndex);
> + }
> + }
> +
> + /* We can use this to help debug user's problems. Tell them to set
> + * the MESA_INFO env variable before running their app. Then the
> + * first time each context is made current we'll print some useful
> + * information.
> + */
> + if (_mesa_getenv("MESA_INFO")) {
> + _mesa_print_info(ctx);
> + }
> +}
>
> /**
> * Bind the given context to the given drawBuffer and readBuffer and
> @@ -1567,21 +1623,7 @@ _mesa_make_current( struct gl_context *newCtx,
> }
>
> if (newCtx->FirstTimeCurrent) {
> - assert(newCtx->Version > 0);
> -
> - newCtx->Extensions.String = _mesa_make_extension_string(newCtx);
> -
> - check_context_limits(newCtx);
> -
> - /* We can use this to help debug user's problems. Tell them to set
> - * the MESA_INFO env variable before running their app. Then the
> - * first time each context is made current we'll print some useful
> - * information.
> - */
> - if (_mesa_getenv("MESA_INFO")) {
> - _mesa_print_info(newCtx);
> - }
> -
> + handle_first_current(newCtx);
> newCtx->FirstTimeCurrent = GL_FALSE;
> }
> }
> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
> index d05649c..d18082f 100644
> --- a/src/mesa/main/mtypes.h
> +++ b/src/mesa/main/mtypes.h
> @@ -4220,6 +4220,12 @@ struct gl_context
> GLboolean FirstTimeCurrent;
> /*@}*/
>
> + /**
> + * False if this context was created without a config. This is needed
> + * because the initial state of glDrawBuffers depends on this
> + */
> + GLboolean HasConfig;
> +
> /** software compression/decompression supported or not */
> GLboolean Mesa_DXTn;
>
> --
> 1.8.5.3
>
> _______________________________________________
> wayland-devel mailing list
> wayland-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/wayland-devel
More information about the mesa-dev
mailing list