#include "eglcurrent.h"
#include "eglsurface.h"
#include "egllog.h"
+#include "util/macros.h"
/**
* Parse the list of context attributes and return the proper error code.
*/
static EGLint
-_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
+_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *disp,
const EGLint *attrib_list)
{
EGLenum api = ctx->ClientAPI;
* generate an error."
*/
if ((api != EGL_OPENGL_ES_API &&
- (!dpy->Extensions.KHR_create_context || api != EGL_OPENGL_API))) {
+ (!disp->Extensions.KHR_create_context || api != EGL_OPENGL_API))) {
err = EGL_BAD_ATTRIBUTE;
break;
}
* contexts, and specifying them for other types of contexts will
* generate an error."
*/
- if (!dpy->Extensions.KHR_create_context ||
+ if (!disp->Extensions.KHR_create_context ||
(api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) {
err = EGL_BAD_ATTRIBUTE;
break;
break;
case EGL_CONTEXT_FLAGS_KHR:
- if (!dpy->Extensions.KHR_create_context) {
+ if (!disp->Extensions.KHR_create_context) {
err = EGL_BAD_ATTRIBUTE;
break;
}
* is supported for OpenGL contexts, and requesting a
* forward-compatible context for OpenGL versions less than 3.0
* will generate an error."
+ *
+ * Note: since the forward-compatible flag can be set more than one way,
+ * the OpenGL version check is performed once, below.
*/
if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) &&
- (api != EGL_OPENGL_API || ctx->ClientMajorVersion < 3)) {
+ api != EGL_OPENGL_API) {
err = EGL_BAD_ATTRIBUTE;
break;
}
- /* The EGL_KHR_create_context_spec says:
- *
- * "If the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR bit is set in
- * EGL_CONTEXT_FLAGS_KHR, then a context supporting <robust buffer
- * access> will be created. Robust buffer access is defined in the
- * GL_ARB_robustness extension specification, and the resulting
- * context must also support either the GL_ARB_robustness
- * extension, or a version of OpenGL incorporating equivalent
- * functionality. This bit is supported for OpenGL contexts.
- */
if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
- (api != EGL_OPENGL_API ||
- !dpy->Extensions.EXT_create_context_robustness)) {
+ api != EGL_OPENGL_API) {
+ /* The EGL_KHR_create_context spec says:
+ *
+ * 10) Which error should be generated if robust buffer access
+ * or reset notifications are requested under OpenGL ES?
+ *
+ * As per Issue 6, this extension does not support creating
+ * robust contexts for OpenGL ES. This is only supported via
+ * the EGL_EXT_create_context_robustness extension.
+ *
+ * Attempting to use this extension to create robust OpenGL
+ * ES context will generate an EGL_BAD_ATTRIBUTE error. This
+ * specific error is generated because this extension does
+ * not define the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
+ * and EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
+ * bits for OpenGL ES contexts. Thus, use of these bits fall
+ * under condition described by: "If an attribute is
+ * specified that is not meaningful for the client API
+ * type.." in the above specification.
+ *
+ * The spec requires that we emit the error even if the display
+ * supports EGL_EXT_create_context_robustness. To create a robust
+ * GLES context, the *attribute*
+ * EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT must be used, not the
+ * *flag* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR.
+ */
err = EGL_BAD_ATTRIBUTE;
break;
}
break;
case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
- if (!dpy->Extensions.KHR_create_context) {
+ if (!disp->Extensions.KHR_create_context) {
err = EGL_BAD_ATTRIBUTE;
break;
}
* meaningful for OpenGL contexts, and specifying it for other
* types of contexts, including OpenGL ES contexts, will generate
* an error."
+ *
+ * EGL 1.5 defines EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY
+ * (without a suffix) which has the same value as the KHR token,
+ * and specifies that it now works with both GL and ES contexts:
+ *
+ * "This attribute is supported only for OpenGL and OpenGL ES
+ * contexts."
*/
- if (!dpy->Extensions.KHR_create_context
- || api != EGL_OPENGL_API) {
+ if (!(disp->Extensions.KHR_create_context && api == EGL_OPENGL_API)
+ && !(disp->Version >= 15 && (api == EGL_OPENGL_API ||
+ api == EGL_OPENGL_ES_API))) {
err = EGL_BAD_ATTRIBUTE;
break;
}
* meaningful for OpenGL ES contexts, and specifying it for other
* types of contexts will generate an EGL_BAD_ATTRIBUTE error."
*/
- if (!dpy->Extensions.EXT_create_context_robustness
+ if (!disp->Extensions.EXT_create_context_robustness
|| api != EGL_OPENGL_ES_API) {
err = EGL_BAD_ATTRIBUTE;
break;
break;
case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
- if (!dpy->Extensions.EXT_create_context_robustness) {
+ if (!disp->Extensions.EXT_create_context_robustness) {
err = EGL_BAD_ATTRIBUTE;
break;
}
break;
case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:
- if (dpy->Version < 15) {
+ if (disp->Version < 15) {
err = EGL_BAD_ATTRIBUTE;
break;
}
break;
case EGL_CONTEXT_OPENGL_DEBUG:
- if (dpy->Version < 15) {
+ if (disp->Version < 15) {
err = EGL_BAD_ATTRIBUTE;
break;
}
break;
case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:
- if (dpy->Version < 15) {
+ if (disp->Version < 15) {
err = EGL_BAD_ATTRIBUTE;
break;
}
ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
break;
+ case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
+ if (disp->Version < 14 ||
+ !disp->Extensions.KHR_create_context_no_error) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+
+ /* The KHR_no_error spec only applies against OpenGL 2.0+ and
+ * OpenGL ES 2.0+
+ */
+ if ((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) ||
+ ctx->ClientMajorVersion < 2) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+
+ /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */
+ ctx->NoError = !!val;
+ break;
+
+ case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
+ /* The EGL_IMG_context_priority spec says:
+ *
+ * "EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of
+ * the context to be created. This attribute is a hint, as an
+ * implementation may not support multiple contexts at some
+ * priority levels and system policy may limit access to high
+ * priority contexts to appropriate system privilege level. The
+ * default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is
+ * EGL_CONTEXT_PRIORITY_MEDIUM_IMG."
+ */
+ {
+ int bit;
+
+ switch (val) {
+ case EGL_CONTEXT_PRIORITY_HIGH_IMG:
+ bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT;
+ break;
+ case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
+ bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT;
+ break;
+ case EGL_CONTEXT_PRIORITY_LOW_IMG:
+ bit = __EGL_CONTEXT_PRIORITY_LOW_BIT;
+ break;
+ default:
+ bit = -1;
+ break;
+ }
+
+ if (bit < 0) {
+ err = EGL_BAD_ATTRIBUTE;
+ break;
+ }
+
+ /* "This extension allows an EGLContext to be created with a
+ * priority hint. It is possible that an implementation will not
+ * honour the hint, especially if there are constraints on the
+ * number of high priority contexts available in the system, or
+ * system policy limits access to high priority contexts to
+ * appropriate system privilege level. A query is provided to find
+ * the real priority level assigned to the context after creation."
+ *
+ * We currently assume that the driver applies the priority hint
+ * and filters out any it cannot handle during the screen setup,
+ * e.g. dri2_setup_screen(). As such we can mask any change that
+ * the driver would fail, and ctx->ContextPriority matches the
+ * hint applied to the driver/hardware backend.
+ */
+ if (disp->Extensions.IMG_context_priority & (1 << bit))
+ ctx->ContextPriority = val;
+
+ break;
+ }
+
+ case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR:
+ if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR ||
+ val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) {
+ ctx->ReleaseBehavior = val;
+ } else {
+ err = EGL_BAD_ATTRIBUTE;
+ }
+ break;
+
default:
err = EGL_BAD_ATTRIBUTE;
break;
break;
}
+ /* The EGL_KHR_create_context_no_error spec says:
+ *
+ * "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE at
+ * the same time as a debug or robustness context is specified."
+ */
+ if (ctx->NoError && (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR ||
+ ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
+ err = EGL_BAD_MATCH;
+ }
+
if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
| EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
| EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
/**
* Initialize the given _EGLContext object to defaults and/or the values
* in the attrib_list.
+ *
+ * According to EGL 1.5 Section 3.7:
+ *
+ * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
+ * purposes except eglCreateContext."
+ *
+ * And since we only support GL and GLES, this is the only place where the
+ * bound API matters at all. We look up the current API from the current
+ * thread, and stash that in the context we're initializing. Our caller is
+ * responsible for determining whether that's an API it supports.
*/
EGLBoolean
-_eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
+_eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *conf,
const EGLint *attrib_list)
{
const EGLenum api = eglQueryAPI();
EGLint err;
- if (api == EGL_NONE) {
- _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
- return EGL_FALSE;
- }
+ if (api == EGL_NONE)
+ return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
- _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
+ _eglInitResource(&ctx->Resource, sizeof(*ctx), disp);
ctx->ClientAPI = api;
ctx->Config = conf;
- ctx->WindowRenderBuffer = EGL_NONE;
ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
ctx->ClientMinorVersion = 0;
ctx->Flags = 0;
- ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
+ ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
+ ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR;
- err = _eglParseContextAttribList(ctx, dpy, attrib_list);
+ err = _eglParseContextAttribList(ctx, disp, attrib_list);
if (err == EGL_SUCCESS && ctx->Config) {
EGLint api_bit;
_eglQueryContextRenderBuffer(_EGLContext *ctx)
{
_EGLSurface *surf = ctx->DrawSurface;
- EGLint rb;
+ /* From the EGL 1.5 spec:
+ *
+ * - If the context is not bound to a surface, then EGL_NONE will be
+ * returned.
+ */
if (!surf)
return EGL_NONE;
- if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
- rb = ctx->WindowRenderBuffer;
- else
- rb = surf->RenderBuffer;
- return rb;
+
+ switch (surf->Type) {
+ default:
+ unreachable("bad EGLSurface type");
+ case EGL_PIXMAP_BIT:
+ /* - If the context is bound to a pixmap surface, then EGL_SINGLE_BUFFER
+ * will be returned.
+ */
+ return EGL_SINGLE_BUFFER;
+ case EGL_PBUFFER_BIT:
+ /* - If the context is bound to a pbuffer surface, then EGL_BACK_BUFFER
+ * will be returned.
+ */
+ return EGL_BACK_BUFFER;
+ case EGL_WINDOW_BIT:
+ /* - If the context is bound to a window surface, then either
+ * EGL_BACK_BUFFER or EGL_SINGLE_BUFFER may be returned. The value
+ * returned depends on both the buffer requested by the setting of the
+ * EGL_RENDER_BUFFER property of the surface [...], and on the client
+ * API (not all client APIs support single-buffer Rendering to window
+ * surfaces). Some client APIs allow control of whether rendering goes
+ * to the front or back buffer. This client API-specific choice is not
+ * reflected in the returned value, which only describes the buffer
+ * that will be rendered to by default if not overridden by the client
+ * API.
+ */
+ return surf->ActiveRenderBuffer;
+ }
}
EGLBoolean
-_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
- EGLint attribute, EGLint *value)
+_eglQueryContext(_EGLContext *c, EGLint attribute, EGLint *value)
{
- (void) drv;
- (void) dpy;
-
if (!value)
return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
switch (attribute) {
case EGL_CONFIG_ID:
- if (!c->Config)
- return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
- *value = c->Config->ConfigID;
+ /*
+ * From EGL_KHR_no_config_context:
+ *
+ * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
+ * respect to which the context was created, or zero if created
+ * without respect to an EGLConfig."
+ */
+ *value = c->Config ? c->Config->ConfigID : 0;
break;
case EGL_CONTEXT_CLIENT_VERSION:
*value = c->ClientMajorVersion;
case EGL_RENDER_BUFFER:
*value = _eglQueryContextRenderBuffer(c);
break;
+ case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
+ *value = c->ContextPriority;
+ break;
default:
return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
}
*
* Note that the context may be NULL.
*/
-static _EGLContext *
+_EGLContext *
_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
{
- EGLint apiIndex;
_EGLContext *oldCtx;
- apiIndex = (ctx) ?
- _eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex;
-
- oldCtx = t->CurrentContexts[apiIndex];
+ oldCtx = t->CurrentContext;
if (ctx != oldCtx) {
if (oldCtx)
oldCtx->Binding = NULL;
if (ctx)
ctx->Binding = t;
- t->CurrentContexts[apiIndex] = ctx;
+ t->CurrentContext = ctx;
}
return oldCtx;
_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
- _EGLDisplay *dpy;
- EGLint conflict_api;
+ _EGLDisplay *disp;
if (_eglIsCurrentThreadDummy())
return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
return EGL_TRUE;
}
- dpy = ctx->Resource.Display;
- if (!dpy->Extensions.KHR_surfaceless_context
+ disp = ctx->Resource.Display;
+ if (!disp->Extensions.KHR_surfaceless_context
&& (draw == NULL || read == NULL))
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
if (ctx->Binding && ctx->Binding != t)
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
- if (draw->CurrentContext->Binding != t ||
- draw->CurrentContext->ClientAPI != ctx->ClientAPI)
+ if (draw->CurrentContext->Binding != t)
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
}
if (read && read->CurrentContext && read->CurrentContext != ctx) {
- if (read->CurrentContext->Binding != t ||
- read->CurrentContext->ClientAPI != ctx->ClientAPI)
+ if (read->CurrentContext->Binding != t)
return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
}
(read && read->Config != ctx->Config))
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
} else {
- /* Otherwise we must be using the EGL_MESA_configless_context
+ /* Otherwise we must be using the EGL_KHR_no_config_context
* extension */
- assert(dpy->Extensions.MESA_configless_context);
+ assert(disp->Extensions.KHR_no_config_context);
/* The extension doesn't permit binding draw and read buffers with
* differing contexts */
return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
}
- switch (ctx->ClientAPI) {
- /* OpenGL and OpenGL ES are conflicting */
- case EGL_OPENGL_ES_API:
- conflict_api = EGL_OPENGL_API;
- break;
- case EGL_OPENGL_API:
- conflict_api = EGL_OPENGL_ES_API;
- break;
- default:
- conflict_api = -1;
- break;
- }
-
- if (conflict_api >= 0 && _eglGetAPIContext(conflict_api))
- return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
-
return EGL_TRUE;
}