1 /**************************************************************************
3 * Copyright 2008 VMware, Inc.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010-2011 LunarG, Inc.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
34 #include "eglconfig.h"
35 #include "eglcontext.h"
36 #include "egldisplay.h"
37 #include "eglcurrent.h"
38 #include "eglsurface.h"
43 * Return the API bit (one of EGL_xxx_BIT) of the context.
46 _eglGetContextAPIBit(_EGLContext *ctx)
50 switch (ctx->ClientAPI) {
51 case EGL_OPENGL_ES_API:
52 switch (ctx->ClientMajorVersion) {
54 bit = EGL_OPENGL_ES_BIT;
57 bit = EGL_OPENGL_ES2_BIT;
60 bit = EGL_OPENGL_ES3_BIT_KHR;
81 * Parse the list of context attributes and return the proper error code.
84 _eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
85 const EGLint *attrib_list)
87 EGLenum api = ctx->ClientAPI;
88 EGLint i, err = EGL_SUCCESS;
93 if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) {
94 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]);
95 return EGL_BAD_ATTRIBUTE;
98 for (i = 0; attrib_list[i] != EGL_NONE; i++) {
99 EGLint attr = attrib_list[i++];
100 EGLint val = attrib_list[i];
103 case EGL_CONTEXT_CLIENT_VERSION:
104 ctx->ClientMajorVersion = val;
107 case EGL_CONTEXT_MINOR_VERSION_KHR:
108 if (!dpy->Extensions.KHR_create_context) {
109 err = EGL_BAD_ATTRIBUTE;
113 ctx->ClientMinorVersion = val;
116 case EGL_CONTEXT_FLAGS_KHR:
117 if (!dpy->Extensions.KHR_create_context) {
118 err = EGL_BAD_ATTRIBUTE;
122 /* The EGL_KHR_create_context spec says:
124 * "Flags are only defined for OpenGL context creation, and
125 * specifying a flags value other than zero for other types of
126 * contexts, including OpenGL ES contexts, will generate an
129 if (api != EGL_OPENGL_API && val != 0) {
130 err = EGL_BAD_ATTRIBUTE;
137 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
138 if (!dpy->Extensions.KHR_create_context) {
139 err = EGL_BAD_ATTRIBUTE;
143 /* The EGL_KHR_create_context spec says:
145 * "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
146 * OpenGL contexts, and specifying it for other types of
147 * contexts, including OpenGL ES contexts, will generate an
150 if (api != EGL_OPENGL_API) {
151 err = EGL_BAD_ATTRIBUTE;
158 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
159 /* The EGL_KHR_create_context spec says:
161 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
162 * meaningful for OpenGL contexts, and specifying it for other
163 * types of contexts, including OpenGL ES contexts, will generate
166 if (!dpy->Extensions.KHR_create_context
167 || api != EGL_OPENGL_API) {
168 err = EGL_BAD_ATTRIBUTE;
172 ctx->ResetNotificationStrategy = val;
175 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
176 /* The EGL_EXT_create_context_robustness spec says:
178 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
179 * meaningful for OpenGL ES contexts, and specifying it for other
180 * types of contexts will generate an EGL_BAD_ATTRIBUTE error."
182 if (!dpy->Extensions.EXT_create_context_robustness
183 || api != EGL_OPENGL_ES_API) {
184 err = EGL_BAD_ATTRIBUTE;
188 ctx->ResetNotificationStrategy = val;
191 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
192 if (!dpy->Extensions.EXT_create_context_robustness) {
193 err = EGL_BAD_ATTRIBUTE;
198 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
202 err = EGL_BAD_ATTRIBUTE;
206 if (err != EGL_SUCCESS) {
207 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
212 if (api == EGL_OPENGL_API) {
213 /* The EGL_KHR_create_context spec says:
215 * "If the requested OpenGL version is less than 3.2,
216 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
217 * functionality of the context is determined solely by the
218 * requested version."
220 * Since the value is ignored, only validate the setting if the version
223 if (ctx->ClientMajorVersion >= 4
224 || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
225 switch (ctx->Profile) {
226 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
227 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
231 /* The EGL_KHR_create_context spec says:
233 * "* If an OpenGL context is requested, the requested version
234 * is greater than 3.2, and the value for attribute
235 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
236 * any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
237 * and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has
238 * more than one of these bits set; or if the implementation does
239 * not support the requested profile, then an EGL_BAD_MATCH error
247 /* The EGL_KHR_create_context spec says:
249 * "* If an OpenGL context is requested and the values for
250 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
251 * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
252 * the value for attribute
253 * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
254 * version and feature set that are not defined, than an
255 * EGL_BAD_MATCH error is generated.
257 * ... Thus, examples of invalid combinations of attributes
260 * - Major version < 1 or > 4
261 * - Major version == 1 and minor version < 0 or > 5
262 * - Major version == 2 and minor version < 0 or > 1
263 * - Major version == 3 and minor version < 0 or > 2
264 * - Major version == 4 and minor version < 0 or > 2
265 * - Forward-compatible flag set and major version < 3"
267 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
270 switch (ctx->ClientMajorVersion) {
272 if (ctx->ClientMinorVersion > 5
273 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
278 if (ctx->ClientMinorVersion > 1
279 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
284 /* Note: The text above is incorrect. There *is* an OpenGL 3.3!
286 if (ctx->ClientMinorVersion > 3)
292 /* Don't put additional version checks here. We don't know that
293 * there won't be versions > 4.2.
297 } else if (api == EGL_OPENGL_ES_API) {
298 /* The EGL_KHR_create_context spec says:
300 * "* If an OpenGL ES context is requested and the values for
301 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
302 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
303 * is not defined, than an EGL_BAD_MATCH error is generated.
305 * ... Examples of invalid combinations of attributes include:
307 * - Major version < 1 or > 2
308 * - Major version == 1 and minor version < 0 or > 1
309 * - Major version == 2 and minor version != 0
311 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
314 switch (ctx->ClientMajorVersion) {
316 if (ctx->ClientMinorVersion > 1)
321 if (ctx->ClientMinorVersion > 0)
326 /* Don't put additional version checks here. We don't know that
327 * there won't be versions > 3.0.
337 switch (ctx->ResetNotificationStrategy) {
338 case EGL_NO_RESET_NOTIFICATION_KHR:
339 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
343 err = EGL_BAD_ATTRIBUTE;
347 if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
348 | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
349 | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
350 err = EGL_BAD_ATTRIBUTE;
358 * Initialize the given _EGLContext object to defaults and/or the values
359 * in the attrib_list.
362 _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
363 const EGLint *attrib_list)
365 const EGLenum api = eglQueryAPI();
368 if (api == EGL_NONE) {
369 _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
373 _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
374 ctx->ClientAPI = api;
376 ctx->WindowRenderBuffer = EGL_NONE;
377 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
379 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
380 ctx->ClientMinorVersion = 0;
382 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
383 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
385 err = _eglParseContextAttribList(ctx, dpy, attrib_list);
386 if (err == EGL_SUCCESS && ctx->Config) {
389 api_bit = _eglGetContextAPIBit(ctx);
390 if (!(ctx->Config->RenderableType & api_bit)) {
391 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
392 api_bit, ctx->Config->RenderableType);
393 err = EGL_BAD_CONFIG;
396 if (err != EGL_SUCCESS)
397 return _eglError(err, "eglCreateContext");
404 _eglQueryContextRenderBuffer(_EGLContext *ctx)
406 _EGLSurface *surf = ctx->DrawSurface;
411 if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
412 rb = ctx->WindowRenderBuffer;
414 rb = surf->RenderBuffer;
420 _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
421 EGLint attribute, EGLint *value)
427 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
432 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
433 *value = c->Config->ConfigID;
435 case EGL_CONTEXT_CLIENT_VERSION:
436 *value = c->ClientMajorVersion;
438 case EGL_CONTEXT_CLIENT_TYPE:
439 *value = c->ClientAPI;
441 case EGL_RENDER_BUFFER:
442 *value = _eglQueryContextRenderBuffer(c);
445 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
453 * Bind the context to the thread and return the previous context.
455 * Note that the context may be NULL.
458 _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
464 _eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex;
466 oldCtx = t->CurrentContexts[apiIndex];
469 oldCtx->Binding = NULL;
473 t->CurrentContexts[apiIndex] = ctx;
481 * Return true if the given context and surfaces can be made current.
484 _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
486 _EGLThreadInfo *t = _eglGetCurrentThread();
490 if (_eglIsCurrentThreadDummy())
491 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
496 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
500 dpy = ctx->Resource.Display;
501 if (!dpy->Extensions.KHR_surfaceless_context
502 && (draw == NULL || read == NULL))
503 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
508 * "If ctx is current to some other thread, or if either draw or read are
509 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
514 * "at most one context may be bound to a particular surface at a given
517 if (ctx->Binding && ctx->Binding != t)
518 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
519 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
520 if (draw->CurrentContext->Binding != t ||
521 draw->CurrentContext->ClientAPI != ctx->ClientAPI)
522 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
524 if (read && read->CurrentContext && read->CurrentContext != ctx) {
525 if (read->CurrentContext->Binding != t ||
526 read->CurrentContext->ClientAPI != ctx->ClientAPI)
527 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
530 /* If the context has a config then it must match that of the two
533 if ((draw && draw->Config != ctx->Config) ||
534 (read && read->Config != ctx->Config))
535 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
537 /* Otherwise we must be using the EGL_MESA_configless_context
539 assert(dpy->Extensions.MESA_configless_context);
541 /* The extension doesn't permit binding draw and read buffers with
542 * differing contexts */
543 if (draw && read && draw->Config != read->Config)
544 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
547 switch (ctx->ClientAPI) {
548 /* OpenGL and OpenGL ES are conflicting */
549 case EGL_OPENGL_ES_API:
550 conflict_api = EGL_OPENGL_API;
553 conflict_api = EGL_OPENGL_ES_API;
560 if (conflict_api >= 0 && _eglGetAPIContext(conflict_api))
561 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
568 * Bind the context to the current thread and given surfaces. Return the
569 * previous bound context and surfaces. The caller should unreference the
570 * returned context and surfaces.
572 * Making a second call with the resources returned by the first call
573 * unsurprisingly undoes the first call, except for the resouce reference
577 _eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
578 _EGLContext **old_ctx,
579 _EGLSurface **old_draw, _EGLSurface **old_read)
581 _EGLThreadInfo *t = _eglGetCurrentThread();
582 _EGLContext *prev_ctx;
583 _EGLSurface *prev_draw, *prev_read;
585 if (!_eglCheckMakeCurrent(ctx, draw, read))
588 /* increment refcounts before binding */
590 _eglGetSurface(draw);
591 _eglGetSurface(read);
593 /* bind the new context */
594 prev_ctx = _eglBindContextToThread(ctx, t);
596 /* break previous bindings */
598 prev_draw = prev_ctx->DrawSurface;
599 prev_read = prev_ctx->ReadSurface;
602 prev_draw->CurrentContext = NULL;
604 prev_read->CurrentContext = NULL;
606 prev_ctx->DrawSurface = NULL;
607 prev_ctx->ReadSurface = NULL;
610 prev_draw = prev_read = NULL;
613 /* establish new bindings */
616 draw->CurrentContext = ctx;
618 read->CurrentContext = ctx;
620 ctx->DrawSurface = draw;
621 ctx->ReadSurface = read;
624 assert(old_ctx && old_draw && old_read);
626 *old_draw = prev_draw;
627 *old_read = prev_read;