--- /dev/null
+Name
+
+ MESA_configless_context
+
+Name Strings
+
+ EGL_MESA_configless_context
+
+Contact
+
+ Neil Roberts <neil.s.roberts@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."
+
+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
+
+ 1. What happens when an OpenGL context with a double-buffered surface and
+ draw buffer set to GL_BACK is made current with a single-buffered
+ surface?
+
+ NOT RESOLVED: There are a few options here. An implementation can
+ raise an error, change the drawbuffer state to GL_FRONT or just do
+ nothing, expecting the application to set GL_FRONT drawbuffer before
+ drawing. However, this extension deliberately does not specify any
+ required behavior in this corner case and applications should avoid
+ mixing single- and double-buffered surfaces with configless contexts.
+
+ Future extensions may specify required behavior in this case.
+
+Revision History
+
+ Version 1, February 28, 2014
+ Initial draft (Neil Roberts)
#define EGL_NATIVE_BUFFER_ANDROID 0x3140 /* eglCreateImageKHR target */
#endif
+#ifndef EGL_MESA_configless_context
+#define EGL_MESA_configless_context 1
+#define EGL_NO_CONFIG_MESA ((EGLConfig)0)
+#endif
+
#ifdef __cplusplus
}
#endif
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;
_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)
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 */
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;
_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);
__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)
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,
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.
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__);
*
* \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
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);
}
* 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.
{
struct gl_context *ctx;
- ASSERT(visual);
-
ctx = calloc(1, sizeof(struct gl_context));
if (!ctx)
return NULL;
}
}
+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
}
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;
}
}
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;