egl: move KHR_no_error vs debug/robustness check further down
[mesa.git] / src / egl / main / eglcontext.c
1 /**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010-2011 LunarG, Inc.
6 * All Rights Reserved.
7 *
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:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
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.
27 *
28 **************************************************************************/
29
30
31 #include <assert.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include "eglconfig.h"
35 #include "eglcontext.h"
36 #include "egldisplay.h"
37 #include "eglcurrent.h"
38 #include "eglsurface.h"
39 #include "egllog.h"
40
41
42 /**
43 * Return the API bit (one of EGL_xxx_BIT) of the context.
44 */
45 static EGLint
46 _eglGetContextAPIBit(_EGLContext *ctx)
47 {
48 EGLint bit = 0;
49
50 switch (ctx->ClientAPI) {
51 case EGL_OPENGL_ES_API:
52 switch (ctx->ClientMajorVersion) {
53 case 1:
54 bit = EGL_OPENGL_ES_BIT;
55 break;
56 case 2:
57 bit = EGL_OPENGL_ES2_BIT;
58 break;
59 case 3:
60 bit = EGL_OPENGL_ES3_BIT_KHR;
61 break;
62 default:
63 break;
64 }
65 break;
66 case EGL_OPENVG_API:
67 bit = EGL_OPENVG_BIT;
68 break;
69 case EGL_OPENGL_API:
70 bit = EGL_OPENGL_BIT;
71 break;
72 default:
73 break;
74 }
75
76 return bit;
77 }
78
79
80 /**
81 * Parse the list of context attributes and return the proper error code.
82 */
83 static EGLint
84 _eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
85 const EGLint *attrib_list)
86 {
87 EGLenum api = ctx->ClientAPI;
88 EGLint i, err = EGL_SUCCESS;
89
90 if (!attrib_list)
91 return EGL_SUCCESS;
92
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;
96 }
97
98 for (i = 0; attrib_list[i] != EGL_NONE; i++) {
99 EGLint attr = attrib_list[i++];
100 EGLint val = attrib_list[i];
101
102 switch (attr) {
103 case EGL_CONTEXT_CLIENT_VERSION:
104 /* The EGL 1.4 spec says:
105 *
106 * "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the
107 * current rendering API is EGL_OPENGL_ES_API"
108 *
109 * The EGL_KHR_create_context spec says:
110 *
111 * "EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
112 * (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)"
113 *
114 * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
115 * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
116 * version. They are only meaningful for OpenGL and OpenGL ES
117 * contexts, and specifying them for other types of contexts will
118 * generate an error."
119 */
120 if ((api != EGL_OPENGL_ES_API &&
121 (!dpy->Extensions.KHR_create_context || api != EGL_OPENGL_API))) {
122 err = EGL_BAD_ATTRIBUTE;
123 break;
124 }
125
126 ctx->ClientMajorVersion = val;
127 break;
128
129 case EGL_CONTEXT_MINOR_VERSION_KHR:
130 /* The EGL_KHR_create_context spec says:
131 *
132 * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
133 * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
134 * version. They are only meaningful for OpenGL and OpenGL ES
135 * contexts, and specifying them for other types of contexts will
136 * generate an error."
137 */
138 if (!dpy->Extensions.KHR_create_context ||
139 (api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) {
140 err = EGL_BAD_ATTRIBUTE;
141 break;
142 }
143
144 ctx->ClientMinorVersion = val;
145 break;
146
147 case EGL_CONTEXT_FLAGS_KHR:
148 if (!dpy->Extensions.KHR_create_context) {
149 err = EGL_BAD_ATTRIBUTE;
150 break;
151 }
152
153 /* The EGL_KHR_create_context spec says:
154 *
155 * "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in
156 * EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.
157 * [...]
158 * In some cases a debug context may be identical to a non-debug
159 * context. This bit is supported for OpenGL and OpenGL ES
160 * contexts."
161 */
162 if ((val & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) &&
163 (api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API)) {
164 err = EGL_BAD_ATTRIBUTE;
165 break;
166 }
167
168 /* The EGL_KHR_create_context spec says:
169 *
170 * "If the EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR flag bit
171 * is set in EGL_CONTEXT_FLAGS_KHR, then a <forward-compatible>
172 * context will be created. Forward-compatible contexts are
173 * defined only for OpenGL versions 3.0 and later. They must not
174 * support functionality marked as <deprecated> by that version of
175 * the API, while a non-forward-compatible context must support
176 * all functionality in that version, deprecated or not. This bit
177 * is supported for OpenGL contexts, and requesting a
178 * forward-compatible context for OpenGL versions less than 3.0
179 * will generate an error."
180 */
181 if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) &&
182 (api != EGL_OPENGL_API || ctx->ClientMajorVersion < 3)) {
183 err = EGL_BAD_ATTRIBUTE;
184 break;
185 }
186
187 if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
188 api != EGL_OPENGL_API) {
189 /* The EGL_KHR_create_context spec says:
190 *
191 * 10) Which error should be generated if robust buffer access
192 * or reset notifications are requested under OpenGL ES?
193 *
194 * As per Issue 6, this extension does not support creating
195 * robust contexts for OpenGL ES. This is only supported via
196 * the EGL_EXT_create_context_robustness extension.
197 *
198 * Attempting to use this extension to create robust OpenGL
199 * ES context will generate an EGL_BAD_ATTRIBUTE error. This
200 * specific error is generated because this extension does
201 * not define the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
202 * and EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
203 * bits for OpenGL ES contexts. Thus, use of these bits fall
204 * under condition described by: "If an attribute is
205 * specified that is not meaningful for the client API
206 * type.." in the above specification.
207 *
208 * The spec requires that we emit the error even if the display
209 * supports EGL_EXT_create_context_robustness. To create a robust
210 * GLES context, the *attribute*
211 * EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT must be used, not the
212 * *flag* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR.
213 */
214 err = EGL_BAD_ATTRIBUTE;
215 break;
216 }
217
218 ctx->Flags |= val;
219 break;
220
221 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
222 if (!dpy->Extensions.KHR_create_context) {
223 err = EGL_BAD_ATTRIBUTE;
224 break;
225 }
226
227 /* The EGL_KHR_create_context spec says:
228 *
229 * "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
230 * OpenGL contexts, and specifying it for other types of
231 * contexts, including OpenGL ES contexts, will generate an
232 * error."
233 */
234 if (api != EGL_OPENGL_API) {
235 err = EGL_BAD_ATTRIBUTE;
236 break;
237 }
238
239 ctx->Profile = val;
240 break;
241
242 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
243 /* The EGL_KHR_create_context spec says:
244 *
245 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
246 * meaningful for OpenGL contexts, and specifying it for other
247 * types of contexts, including OpenGL ES contexts, will generate
248 * an error."
249 */
250 if (!dpy->Extensions.KHR_create_context
251 || api != EGL_OPENGL_API) {
252 err = EGL_BAD_ATTRIBUTE;
253 break;
254 }
255
256 ctx->ResetNotificationStrategy = val;
257 break;
258
259 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
260 /* The EGL_EXT_create_context_robustness spec says:
261 *
262 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
263 * meaningful for OpenGL ES contexts, and specifying it for other
264 * types of contexts will generate an EGL_BAD_ATTRIBUTE error."
265 */
266 if (!dpy->Extensions.EXT_create_context_robustness
267 || api != EGL_OPENGL_ES_API) {
268 err = EGL_BAD_ATTRIBUTE;
269 break;
270 }
271
272 ctx->ResetNotificationStrategy = val;
273 break;
274
275 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
276 if (!dpy->Extensions.EXT_create_context_robustness) {
277 err = EGL_BAD_ATTRIBUTE;
278 break;
279 }
280
281 if (val == EGL_TRUE)
282 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
283 break;
284
285 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:
286 if (dpy->Version < 15) {
287 err = EGL_BAD_ATTRIBUTE;
288 break;
289 }
290
291 if (val == EGL_TRUE)
292 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
293 break;
294
295 case EGL_CONTEXT_OPENGL_DEBUG:
296 if (dpy->Version < 15) {
297 err = EGL_BAD_ATTRIBUTE;
298 break;
299 }
300
301 if (val == EGL_TRUE)
302 ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
303 break;
304
305 case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:
306 if (dpy->Version < 15) {
307 err = EGL_BAD_ATTRIBUTE;
308 break;
309 }
310
311 if (val == EGL_TRUE)
312 ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
313 break;
314
315 case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
316 if (dpy->Version < 14 ||
317 !dpy->Extensions.KHR_create_context_no_error) {
318 err = EGL_BAD_ATTRIBUTE;
319 break;
320 }
321
322 /* The KHR_no_error spec only applies against OpenGL 2.0+ and
323 * OpenGL ES 2.0+
324 */
325 if ((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) ||
326 ctx->ClientMajorVersion < 2) {
327 err = EGL_BAD_ATTRIBUTE;
328 break;
329 }
330
331 /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */
332 ctx->NoError = !!val;
333 break;
334
335 default:
336 err = EGL_BAD_ATTRIBUTE;
337 break;
338 }
339
340 if (err != EGL_SUCCESS) {
341 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
342 break;
343 }
344 }
345
346 if (api == EGL_OPENGL_API) {
347 /* The EGL_KHR_create_context spec says:
348 *
349 * "If the requested OpenGL version is less than 3.2,
350 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
351 * functionality of the context is determined solely by the
352 * requested version."
353 *
354 * Since the value is ignored, only validate the setting if the version
355 * is >= 3.2.
356 */
357 if (ctx->ClientMajorVersion >= 4
358 || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
359 switch (ctx->Profile) {
360 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
361 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
362 break;
363
364 default:
365 /* The EGL_KHR_create_context spec says:
366 *
367 * "* If an OpenGL context is requested, the requested version
368 * is greater than 3.2, and the value for attribute
369 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
370 * any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
371 * and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has
372 * more than one of these bits set; or if the implementation does
373 * not support the requested profile, then an EGL_BAD_MATCH error
374 * is generated."
375 */
376 err = EGL_BAD_MATCH;
377 break;
378 }
379 }
380
381 /* The EGL_KHR_create_context spec says:
382 *
383 * "* If an OpenGL context is requested and the values for
384 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
385 * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
386 * the value for attribute
387 * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
388 * version and feature set that are not defined, than an
389 * EGL_BAD_MATCH error is generated.
390 *
391 * ... Thus, examples of invalid combinations of attributes
392 * include:
393 *
394 * - Major version < 1 or > 4
395 * - Major version == 1 and minor version < 0 or > 5
396 * - Major version == 2 and minor version < 0 or > 1
397 * - Major version == 3 and minor version < 0 or > 2
398 * - Major version == 4 and minor version < 0 or > 2
399 * - Forward-compatible flag set and major version < 3"
400 */
401 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
402 err = EGL_BAD_MATCH;
403
404 switch (ctx->ClientMajorVersion) {
405 case 1:
406 if (ctx->ClientMinorVersion > 5
407 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
408 err = EGL_BAD_MATCH;
409 break;
410
411 case 2:
412 if (ctx->ClientMinorVersion > 1
413 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
414 err = EGL_BAD_MATCH;
415 break;
416
417 case 3:
418 /* Note: The text above is incorrect. There *is* an OpenGL 3.3!
419 */
420 if (ctx->ClientMinorVersion > 3)
421 err = EGL_BAD_MATCH;
422 break;
423
424 case 4:
425 default:
426 /* Don't put additional version checks here. We don't know that
427 * there won't be versions > 4.2.
428 */
429 break;
430 }
431 } else if (api == EGL_OPENGL_ES_API) {
432 /* The EGL_KHR_create_context spec says:
433 *
434 * "* If an OpenGL ES context is requested and the values for
435 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
436 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
437 * is not defined, than an EGL_BAD_MATCH error is generated.
438 *
439 * ... Examples of invalid combinations of attributes include:
440 *
441 * - Major version < 1 or > 2
442 * - Major version == 1 and minor version < 0 or > 1
443 * - Major version == 2 and minor version != 0
444 */
445 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
446 err = EGL_BAD_MATCH;
447
448 switch (ctx->ClientMajorVersion) {
449 case 1:
450 if (ctx->ClientMinorVersion > 1)
451 err = EGL_BAD_MATCH;
452 break;
453
454 case 2:
455 if (ctx->ClientMinorVersion > 0)
456 err = EGL_BAD_MATCH;
457 break;
458
459 case 3:
460 /* Don't put additional version checks here. We don't know that
461 * there won't be versions > 3.0.
462 */
463 break;
464
465 default:
466 err = EGL_BAD_MATCH;
467 break;
468 }
469 }
470
471 switch (ctx->ResetNotificationStrategy) {
472 case EGL_NO_RESET_NOTIFICATION_KHR:
473 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
474 break;
475
476 default:
477 err = EGL_BAD_ATTRIBUTE;
478 break;
479 }
480
481 /* The EGL_KHR_create_context_no_error spec says:
482 *
483 * "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE at
484 * the same time as a debug or robustness context is specified."
485 */
486 if (ctx->NoError && (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR ||
487 ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
488 err = EGL_BAD_MATCH;
489 }
490
491 if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
492 | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
493 | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
494 err = EGL_BAD_ATTRIBUTE;
495 }
496
497 return err;
498 }
499
500
501 /**
502 * Initialize the given _EGLContext object to defaults and/or the values
503 * in the attrib_list.
504 *
505 * According to EGL 1.5 Section 3.7:
506 *
507 * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
508 * purposes except eglCreateContext."
509 *
510 * And since we only support GL and GLES, this is the only place where the
511 * bound API matters at all. We look up the current API from the current
512 * thread, and stash that in the context we're initializing. Our caller is
513 * responsible for determining whether that's an API it supports.
514 */
515 EGLBoolean
516 _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
517 const EGLint *attrib_list)
518 {
519 const EGLenum api = eglQueryAPI();
520 EGLint err;
521
522 if (api == EGL_NONE)
523 return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
524
525 _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
526 ctx->ClientAPI = api;
527 ctx->Config = conf;
528 ctx->WindowRenderBuffer = EGL_NONE;
529 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
530
531 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
532 ctx->ClientMinorVersion = 0;
533 ctx->Flags = 0;
534 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
535 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
536
537 err = _eglParseContextAttribList(ctx, dpy, attrib_list);
538 if (err == EGL_SUCCESS && ctx->Config) {
539 EGLint api_bit;
540
541 api_bit = _eglGetContextAPIBit(ctx);
542 if (!(ctx->Config->RenderableType & api_bit)) {
543 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
544 api_bit, ctx->Config->RenderableType);
545 err = EGL_BAD_CONFIG;
546 }
547 }
548 if (err != EGL_SUCCESS)
549 return _eglError(err, "eglCreateContext");
550
551 return EGL_TRUE;
552 }
553
554
555 static EGLint
556 _eglQueryContextRenderBuffer(_EGLContext *ctx)
557 {
558 _EGLSurface *surf = ctx->DrawSurface;
559 EGLint rb;
560
561 if (!surf)
562 return EGL_NONE;
563 if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
564 rb = ctx->WindowRenderBuffer;
565 else
566 rb = surf->RenderBuffer;
567 return rb;
568 }
569
570
571 EGLBoolean
572 _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
573 EGLint attribute, EGLint *value)
574 {
575 (void) drv;
576 (void) dpy;
577
578 if (!value)
579 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
580
581 switch (attribute) {
582 case EGL_CONFIG_ID:
583 /*
584 * From EGL_KHR_no_config_context:
585 *
586 * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
587 * respect to which the context was created, or zero if created
588 * without respect to an EGLConfig."
589 */
590 *value = c->Config ? c->Config->ConfigID : 0;
591 break;
592 case EGL_CONTEXT_CLIENT_VERSION:
593 *value = c->ClientMajorVersion;
594 break;
595 case EGL_CONTEXT_CLIENT_TYPE:
596 *value = c->ClientAPI;
597 break;
598 case EGL_RENDER_BUFFER:
599 *value = _eglQueryContextRenderBuffer(c);
600 break;
601 default:
602 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
603 }
604
605 return EGL_TRUE;
606 }
607
608
609 /**
610 * Bind the context to the thread and return the previous context.
611 *
612 * Note that the context may be NULL.
613 */
614 _EGLContext *
615 _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
616 {
617 _EGLContext *oldCtx;
618
619 oldCtx = t->CurrentContext;
620 if (ctx != oldCtx) {
621 if (oldCtx)
622 oldCtx->Binding = NULL;
623 if (ctx)
624 ctx->Binding = t;
625
626 t->CurrentContext = ctx;
627 }
628
629 return oldCtx;
630 }
631
632
633 /**
634 * Return true if the given context and surfaces can be made current.
635 */
636 static EGLBoolean
637 _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
638 {
639 _EGLThreadInfo *t = _eglGetCurrentThread();
640 _EGLDisplay *dpy;
641
642 if (_eglIsCurrentThreadDummy())
643 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
644
645 /* this is easy */
646 if (!ctx) {
647 if (draw || read)
648 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
649 return EGL_TRUE;
650 }
651
652 dpy = ctx->Resource.Display;
653 if (!dpy->Extensions.KHR_surfaceless_context
654 && (draw == NULL || read == NULL))
655 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
656
657 /*
658 * The spec says
659 *
660 * "If ctx is current to some other thread, or if either draw or read are
661 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
662 * generated."
663 *
664 * and
665 *
666 * "at most one context may be bound to a particular surface at a given
667 * time"
668 */
669 if (ctx->Binding && ctx->Binding != t)
670 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
671 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
672 if (draw->CurrentContext->Binding != t)
673 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
674 }
675 if (read && read->CurrentContext && read->CurrentContext != ctx) {
676 if (read->CurrentContext->Binding != t)
677 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
678 }
679
680 /* If the context has a config then it must match that of the two
681 * surfaces */
682 if (ctx->Config) {
683 if ((draw && draw->Config != ctx->Config) ||
684 (read && read->Config != ctx->Config))
685 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
686 } else {
687 /* Otherwise we must be using the EGL_KHR_no_config_context
688 * extension */
689 assert(dpy->Extensions.KHR_no_config_context);
690
691 /* The extension doesn't permit binding draw and read buffers with
692 * differing contexts */
693 if (draw && read && draw->Config != read->Config)
694 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
695 }
696
697 return EGL_TRUE;
698 }
699
700
701 /**
702 * Bind the context to the current thread and given surfaces. Return the
703 * previous bound context and surfaces. The caller should unreference the
704 * returned context and surfaces.
705 *
706 * Making a second call with the resources returned by the first call
707 * unsurprisingly undoes the first call, except for the resouce reference
708 * counts.
709 */
710 EGLBoolean
711 _eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
712 _EGLContext **old_ctx,
713 _EGLSurface **old_draw, _EGLSurface **old_read)
714 {
715 _EGLThreadInfo *t = _eglGetCurrentThread();
716 _EGLContext *prev_ctx;
717 _EGLSurface *prev_draw, *prev_read;
718
719 if (!_eglCheckMakeCurrent(ctx, draw, read))
720 return EGL_FALSE;
721
722 /* increment refcounts before binding */
723 _eglGetContext(ctx);
724 _eglGetSurface(draw);
725 _eglGetSurface(read);
726
727 /* bind the new context */
728 prev_ctx = _eglBindContextToThread(ctx, t);
729
730 /* break previous bindings */
731 if (prev_ctx) {
732 prev_draw = prev_ctx->DrawSurface;
733 prev_read = prev_ctx->ReadSurface;
734
735 if (prev_draw)
736 prev_draw->CurrentContext = NULL;
737 if (prev_read)
738 prev_read->CurrentContext = NULL;
739
740 prev_ctx->DrawSurface = NULL;
741 prev_ctx->ReadSurface = NULL;
742 }
743 else {
744 prev_draw = prev_read = NULL;
745 }
746
747 /* establish new bindings */
748 if (ctx) {
749 if (draw)
750 draw->CurrentContext = ctx;
751 if (read)
752 read->CurrentContext = ctx;
753
754 ctx->DrawSurface = draw;
755 ctx->ReadSurface = read;
756 }
757
758 assert(old_ctx && old_draw && old_read);
759 *old_ctx = prev_ctx;
760 *old_draw = prev_draw;
761 *old_read = prev_read;
762
763 return EGL_TRUE;
764 }