1 /**************************************************************************
2 *
3 * Copyright 2008 VMware, Inc.
4 * Copyright 2009-2010 Chia-I Wu <[email protected]>
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 #include "eglcontext.h"
31 #include <assert.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include "util/macros.h"
35 #include "eglconfig.h"
36 #include "eglcurrent.h"
37 #include "egldisplay.h"
38 #include "egllog.h"
39 #include "eglsurface.h"
40
41 /**
42 * Return the API bit (one of EGL_xxx_BIT) of the context.
43 */
44 static EGLint
_eglGetContextAPIBit(_EGLContext * ctx)45 _eglGetContextAPIBit(_EGLContext *ctx)
46 {
47 EGLint bit = 0;
48
49 switch (ctx->ClientAPI) {
50 case EGL_OPENGL_ES_API:
51 switch (ctx->ClientMajorVersion) {
52 case 1:
53 bit = EGL_OPENGL_ES_BIT;
54 break;
55 case 2:
56 bit = EGL_OPENGL_ES2_BIT;
57 break;
58 case 3:
59 bit = EGL_OPENGL_ES3_BIT_KHR;
60 break;
61 default:
62 break;
63 }
64 break;
65 case EGL_OPENVG_API:
66 bit = EGL_OPENVG_BIT;
67 break;
68 case EGL_OPENGL_API:
69 bit = EGL_OPENGL_BIT;
70 break;
71 default:
72 break;
73 }
74
75 return bit;
76 }
77
78 /**
79 * Parse the list of context attributes and return the proper error code.
80 */
81 static EGLint
_eglParseContextAttribList(_EGLContext * ctx,_EGLDisplay * disp,const EGLint * attrib_list)82 _eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *disp,
83 const EGLint *attrib_list)
84 {
85 EGLenum api = ctx->ClientAPI;
86 EGLint i, err = EGL_SUCCESS;
87
88 if (!attrib_list)
89 return EGL_SUCCESS;
90
91 if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) {
92 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]);
93 return EGL_BAD_ATTRIBUTE;
94 }
95
96 for (i = 0; attrib_list[i] != EGL_NONE; i++) {
97 EGLint attr = attrib_list[i++];
98 EGLint val = attrib_list[i];
99
100 switch (attr) {
101 case EGL_CONTEXT_CLIENT_VERSION:
102 /* The EGL 1.4 spec says:
103 *
104 * "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the
105 * current rendering API is EGL_OPENGL_ES_API"
106 *
107 * The EGL_KHR_create_context spec says:
108 *
109 * "EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
110 * (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)"
111 *
112 * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
113 * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
114 * version. They are only meaningful for OpenGL and OpenGL ES
115 * contexts, and specifying them for other types of contexts will
116 * generate an error."
117 */
118 if ((api != EGL_OPENGL_ES_API &&
119 (!disp->Extensions.KHR_create_context ||
120 api != EGL_OPENGL_API))) {
121 err = EGL_BAD_ATTRIBUTE;
122 break;
123 }
124
125 ctx->ClientMajorVersion = val;
126 break;
127
128 case EGL_CONTEXT_MINOR_VERSION_KHR:
129 /* The EGL_KHR_create_context spec says:
130 *
131 * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
132 * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
133 * version. They are only meaningful for OpenGL and OpenGL ES
134 * contexts, and specifying them for other types of contexts will
135 * generate an error."
136 */
137 if (!disp->Extensions.KHR_create_context ||
138 (api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) {
139 err = EGL_BAD_ATTRIBUTE;
140 break;
141 }
142
143 ctx->ClientMinorVersion = val;
144 break;
145
146 case EGL_CONTEXT_FLAGS_KHR:
147 if (!disp->Extensions.KHR_create_context) {
148 err = EGL_BAD_ATTRIBUTE;
149 break;
150 }
151
152 /* The EGL_KHR_create_context spec says:
153 *
154 * "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in
155 * EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.
156 * [...]
157 * In some cases a debug context may be identical to a non-debug
158 * context. This bit is supported for OpenGL and OpenGL ES
159 * contexts."
160 */
161 if ((val & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) &&
162 (api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API)) {
163 err = EGL_BAD_ATTRIBUTE;
164 break;
165 }
166
167 /* The EGL_KHR_create_context spec says:
168 *
169 * "If the EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR flag bit
170 * is set in EGL_CONTEXT_FLAGS_KHR, then a <forward-compatible>
171 * context will be created. Forward-compatible contexts are
172 * defined only for OpenGL versions 3.0 and later. They must not
173 * support functionality marked as <deprecated> by that version of
174 * the API, while a non-forward-compatible context must support
175 * all functionality in that version, deprecated or not. This bit
176 * is supported for OpenGL contexts, and requesting a
177 * forward-compatible context for OpenGL versions less than 3.0
178 * will generate an error."
179 *
180 * Note: since the forward-compatible flag can be set more than one
181 * way, the OpenGL version check is performed once, below.
182 */
183 if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) &&
184 api != EGL_OPENGL_API) {
185 err = EGL_BAD_ATTRIBUTE;
186 break;
187 }
188
189 if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
190 api != EGL_OPENGL_API) {
191 /* The EGL_KHR_create_context spec says:
192 *
193 * 10) Which error should be generated if robust buffer access
194 * or reset notifications are requested under OpenGL ES?
195 *
196 * As per Issue 6, this extension does not support creating
197 * robust contexts for OpenGL ES. This is only supported via
198 * the EGL_EXT_create_context_robustness extension.
199 *
200 * Attempting to use this extension to create robust OpenGL
201 * ES context will generate an EGL_BAD_ATTRIBUTE error. This
202 * specific error is generated because this extension does
203 * not define the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
204 * and EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
205 * bits for OpenGL ES contexts. Thus, use of these bits fall
206 * under condition described by: "If an attribute is
207 * specified that is not meaningful for the client API
208 * type.." in the above specification.
209 *
210 * The spec requires that we emit the error even if the display
211 * supports EGL_EXT_create_context_robustness. To create a robust
212 * GLES context, the *attribute*
213 * EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT must be used, not the
214 * *flag* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR.
215 */
216 err = EGL_BAD_ATTRIBUTE;
217 break;
218 }
219
220 /* The EGL_KHR_create_context spec says:
221 * "If <config> does not support a client API context compatible
222 * with the requested API major and minor version, context flags,
223 * and context reset notification behavior (for client API types
224 * where these attributes are supported), then an EGL_BAD_MATCH
225 * error is generated."
226 */
227 if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
228 !disp->RobustBufferAccess) {
229 err = EGL_BAD_MATCH;
230 break;
231 }
232
233 ctx->Flags |= val;
234 break;
235
236 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
237 if (!disp->Extensions.KHR_create_context) {
238 err = EGL_BAD_ATTRIBUTE;
239 break;
240 }
241
242 /* The EGL_KHR_create_context spec says:
243 *
244 * "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
245 * OpenGL contexts, and specifying it for other types of
246 * contexts, including OpenGL ES contexts, will generate an
247 * error."
248 */
249 if (api != EGL_OPENGL_API) {
250 err = EGL_BAD_ATTRIBUTE;
251 break;
252 }
253
254 ctx->Profile = val;
255 break;
256
257 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
258 /* The EGL_KHR_create_context spec says:
259 *
260 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
261 * meaningful for OpenGL contexts, and specifying it for other
262 * types of contexts, including OpenGL ES contexts, will generate
263 * an error."
264 *
265 * EGL 1.5 defines EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY
266 * (without a suffix) which has the same value as the KHR token,
267 * and specifies that it now works with both GL and ES contexts:
268 *
269 * "This attribute is supported only for OpenGL and OpenGL ES
270 * contexts."
271 */
272 if (!(disp->Extensions.KHR_create_context && api == EGL_OPENGL_API) &&
273 !(disp->Version >= 15 &&
274 (api == EGL_OPENGL_API || api == EGL_OPENGL_ES_API))) {
275 err = EGL_BAD_ATTRIBUTE;
276 break;
277 }
278
279 /* The EGL 1.5 spec says:
280 * "An EGL_BAD_MATCH error is generated if an OpenGL or OpenGL ES
281 * context is requested with robust buffer access and with a
282 * specified reset notification behavior, and the implementation
283 * does not support that behavior."
284 *
285 * and the EGL_KHR_create_context spec says:
286 * "If <config> does not support a client API context compatible
287 * with the requested API major and minor version, context flags,
288 * and context reset notification behavior (for client API types
289 * where these attributes are supported), then an EGL_BAD_MATCH
290 * error is generated."
291 */
292 if (val != EGL_NO_RESET_NOTIFICATION_KHR &&
293 !disp->Extensions.EXT_create_context_robustness) {
294 err = EGL_BAD_MATCH;
295 break;
296 }
297
298 ctx->ResetNotificationStrategy = val;
299 break;
300
301 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
302 /* The EGL_EXT_create_context_robustness spec says:
303 *
304 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
305 * meaningful for OpenGL ES contexts, and specifying it for other
306 * types of contexts will generate an EGL_BAD_ATTRIBUTE error."
307 */
308 if (!disp->Extensions.EXT_create_context_robustness ||
309 api != EGL_OPENGL_ES_API) {
310 err = EGL_BAD_ATTRIBUTE;
311 break;
312 }
313
314 ctx->ResetNotificationStrategy = val;
315 break;
316
317 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
318 if (!disp->Extensions.EXT_create_context_robustness) {
319 err = EGL_BAD_ATTRIBUTE;
320 break;
321 }
322
323 /* The EGL_EXT_create_context_robustness spec says:
324 *
325 * "EGL_BAD_CONFIG is generated if
326 * [EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT] is set to EGL_TRUE and
327 * no GL context supporting the GL_EXT_robustness extension and
328 * robust access as described therein can be created."
329 */
330 if (val == EGL_TRUE && !disp->RobustBufferAccess) {
331 err = EGL_BAD_CONFIG;
332 break;
333 }
334
335 if (val == EGL_TRUE)
336 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
337 break;
338
339 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:
340 if (disp->Version < 15) {
341 err = EGL_BAD_ATTRIBUTE;
342 break;
343 }
344
345 /* The EGL 1.5 spec says:
346 * "An EGL_BAD_MATCH error is generated if an OpenGL or OpenGL ES
347 * context is requested with robust buffer access, and the
348 * implementation does not support the corresponding OpenGL or
349 * OpenGL ES extension".
350 */
351 if (val == EGL_TRUE && !disp->RobustBufferAccess) {
352 err = EGL_BAD_MATCH;
353 break;
354 }
355
356 if (val == EGL_TRUE)
357 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
358 break;
359
360 case EGL_CONTEXT_OPENGL_DEBUG:
361 if (disp->Version < 15) {
362 err = EGL_BAD_ATTRIBUTE;
363 break;
364 }
365
366 if (val == EGL_TRUE)
367 ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
368 break;
369
370 case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:
371 if (disp->Version < 15) {
372 err = EGL_BAD_ATTRIBUTE;
373 break;
374 }
375
376 if (val == EGL_TRUE)
377 ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
378 break;
379
380 case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
381 if (disp->Version < 14 ||
382 !disp->Extensions.KHR_create_context_no_error) {
383 err = EGL_BAD_ATTRIBUTE;
384 break;
385 }
386
387 /* The KHR_no_error spec only applies against OpenGL 2.0+ and
388 * OpenGL ES 2.0+
389 */
390 if (((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) ||
391 ctx->ClientMajorVersion < 2) &&
392 val == EGL_TRUE) {
393 err = EGL_BAD_ATTRIBUTE;
394 break;
395 }
396
397 /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */
398 ctx->NoError = !!val;
399 break;
400
401 case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
402 /* The EGL_IMG_context_priority spec says:
403 *
404 * "EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of
405 * the context to be created. This attribute is a hint, as an
406 * implementation may not support multiple contexts at some
407 * priority levels and system policy may limit access to high
408 * priority contexts to appropriate system privilege level. The
409 * default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is
410 * EGL_CONTEXT_PRIORITY_MEDIUM_IMG."
411 */
412 {
413 int bit;
414
415 switch (val) {
416 case EGL_CONTEXT_PRIORITY_HIGH_IMG:
417 bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT;
418 break;
419 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
420 bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT;
421 break;
422 case EGL_CONTEXT_PRIORITY_LOW_IMG:
423 bit = __EGL_CONTEXT_PRIORITY_LOW_BIT;
424 break;
425 default:
426 bit = -1;
427 break;
428 }
429
430 if (bit < 0) {
431 err = EGL_BAD_ATTRIBUTE;
432 break;
433 }
434
435 /* "This extension allows an EGLContext to be created with a
436 * priority hint. It is possible that an implementation will not
437 * honour the hint, especially if there are constraints on the
438 * number of high priority contexts available in the system, or
439 * system policy limits access to high priority contexts to
440 * appropriate system privilege level. A query is provided to find
441 * the real priority level assigned to the context after creation."
442 *
443 * We currently assume that the driver applies the priority hint
444 * and filters out any it cannot handle during the screen setup,
445 * e.g. dri2_setup_screen(). As such we can mask any change that
446 * the driver would fail, and ctx->ContextPriority matches the
447 * hint applied to the driver/hardware backend.
448 */
449 if (disp->Extensions.IMG_context_priority & (1 << bit))
450 ctx->ContextPriority = val;
451
452 break;
453 }
454
455 case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR:
456 if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR ||
457 val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) {
458 ctx->ReleaseBehavior = val;
459 } else {
460 err = EGL_BAD_ATTRIBUTE;
461 }
462 break;
463
464 case EGL_PROTECTED_CONTENT_EXT:
465 if (!disp->Extensions.EXT_protected_content) {
466 err = EGL_BAD_ATTRIBUTE;
467 break;
468 }
469 ctx->Protected = val == EGL_TRUE;
470 break;
471
472 default:
473 err = EGL_BAD_ATTRIBUTE;
474 break;
475 }
476
477 if (err != EGL_SUCCESS) {
478 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
479 break;
480 }
481 }
482
483 if (api == EGL_OPENGL_API) {
484 /* The EGL_KHR_create_context spec says:
485 *
486 * "If the requested OpenGL version is less than 3.2,
487 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
488 * functionality of the context is determined solely by the
489 * requested version."
490 *
491 * Since the value is ignored, only validate the setting if the version
492 * is >= 3.2.
493 */
494 if (ctx->ClientMajorVersion >= 4 ||
495 (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
496 switch (ctx->Profile) {
497 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
498 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
499 break;
500
501 default:
502 /* The EGL_KHR_create_context spec says:
503 *
504 * "* If an OpenGL context is requested, the requested version
505 * is greater than 3.2, and the value for attribute
506 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
507 * any bits set other than
508 * EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
509 * EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
510 * one of these bits set; or if the implementation does not support
511 * the requested profile, then an EGL_BAD_MATCH error is generated."
512 */
513 err = EGL_BAD_MATCH;
514 break;
515 }
516 }
517
518 /* The EGL_KHR_create_context spec says:
519 *
520 * "* If an OpenGL context is requested and the values for
521 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
522 * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
523 * the value for attribute
524 * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
525 * version and feature set that are not defined, than an
526 * EGL_BAD_MATCH error is generated.
527 *
528 * ... Thus, examples of invalid combinations of attributes
529 * include:
530 *
531 * - Major version < 1 or > 4
532 * - Major version == 1 and minor version < 0 or > 5
533 * - Major version == 2 and minor version < 0 or > 1
534 * - Major version == 3 and minor version < 0 or > 2
535 * - Major version == 4 and minor version < 0 or > 2
536 * - Forward-compatible flag set and major version < 3"
537 */
538 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
539 err = EGL_BAD_MATCH;
540
541 switch (ctx->ClientMajorVersion) {
542 case 1:
543 if (ctx->ClientMinorVersion > 5 ||
544 (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
545 err = EGL_BAD_MATCH;
546 break;
547
548 case 2:
549 if (ctx->ClientMinorVersion > 1 ||
550 (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
551 err = EGL_BAD_MATCH;
552 break;
553
554 case 3:
555 /* Note: The text above is incorrect. There *is* an OpenGL 3.3!
556 */
557 if (ctx->ClientMinorVersion > 3)
558 err = EGL_BAD_MATCH;
559 break;
560
561 case 4:
562 default:
563 /* Don't put additional version checks here. We don't know that
564 * there won't be versions > 4.2.
565 */
566 break;
567 }
568 } else if (api == EGL_OPENGL_ES_API) {
569 /* The EGL_KHR_create_context spec says:
570 *
571 * "* If an OpenGL ES context is requested and the values for
572 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
573 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
574 * is not defined, than an EGL_BAD_MATCH error is generated.
575 *
576 * ... Examples of invalid combinations of attributes include:
577 *
578 * - Major version < 1 or > 2
579 * - Major version == 1 and minor version < 0 or > 1
580 * - Major version == 2 and minor version != 0
581 */
582 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
583 err = EGL_BAD_MATCH;
584
585 switch (ctx->ClientMajorVersion) {
586 case 1:
587 if (ctx->ClientMinorVersion > 1)
588 err = EGL_BAD_MATCH;
589 break;
590
591 case 2:
592 if (ctx->ClientMinorVersion > 0)
593 err = EGL_BAD_MATCH;
594 break;
595
596 case 3:
597 /* Don't put additional version checks here. We don't know that
598 * there won't be versions > 3.0.
599 */
600 break;
601
602 default:
603 err = EGL_BAD_MATCH;
604 break;
605 }
606 }
607
608 switch (ctx->ResetNotificationStrategy) {
609 case EGL_NO_RESET_NOTIFICATION_KHR:
610 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
611 break;
612
613 default:
614 err = EGL_BAD_ATTRIBUTE;
615 break;
616 }
617
618 /* The EGL_KHR_create_context_no_error spec says:
619 *
620 * "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE
621 * at the same time as a debug or robustness context is specified."
622 */
623 if (ctx->NoError &&
624 (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR ||
625 ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
626 err = EGL_BAD_MATCH;
627 }
628
629 if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR |
630 EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR |
631 EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
632 err = EGL_BAD_ATTRIBUTE;
633 }
634
635 return err;
636 }
637
638 /**
639 * Initialize the given _EGLContext object to defaults and/or the values
640 * in the attrib_list.
641 *
642 * According to EGL 1.5 Section 3.7:
643 *
644 * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
645 * purposes except eglCreateContext."
646 *
647 * And since we only support GL and GLES, this is the only place where the
648 * bound API matters at all. We look up the current API from the current
649 * thread, and stash that in the context we're initializing. Our caller is
650 * responsible for determining whether that's an API it supports.
651 */
652 EGLBoolean
_eglInitContext(_EGLContext * ctx,_EGLDisplay * disp,_EGLConfig * conf,_EGLContext * share_list,const EGLint * attrib_list)653 _eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *conf,
654 _EGLContext *share_list, const EGLint *attrib_list)
655 {
656 const EGLenum api = eglQueryAPI();
657 EGLint err;
658
659 if (api == EGL_NONE)
660 return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
661
662 _eglInitResource(&ctx->Resource, sizeof(*ctx), disp);
663 ctx->ClientAPI = api;
664 ctx->Config = conf;
665 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
666
667 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
668 ctx->ClientMinorVersion = 0;
669 ctx->Flags = 0;
670 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
671 ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
672 ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR;
673
674 err = _eglParseContextAttribList(ctx, disp, attrib_list);
675 if (err == EGL_SUCCESS && ctx->Config) {
676 EGLint api_bit;
677
678 api_bit = _eglGetContextAPIBit(ctx);
679 if (!(ctx->Config->RenderableType & api_bit)) {
680 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
681 api_bit, ctx->Config->RenderableType);
682 err = EGL_BAD_CONFIG;
683 }
684 }
685 if (err != EGL_SUCCESS)
686 return _eglError(err, "eglCreateContext");
687
688 /* The EGL_EXT_create_context_robustness spec says:
689 *
690 * "Add to the eglCreateContext context creation errors: [...]
691 *
692 * * If the reset notification behavior of <share_context> and the
693 * newly created context are different then an EGL_BAD_MATCH error is
694 * generated."
695 */
696 if (share_list && share_list->ResetNotificationStrategy !=
697 ctx->ResetNotificationStrategy) {
698 return _eglError(
699 EGL_BAD_MATCH,
700 "eglCreateContext() share list notification strategy mismatch");
701 }
702
703 /* The EGL_KHR_create_context_no_error spec says:
704 *
705 * "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
706 * used to create <share_context> does not match the value of
707 * EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created."
708 */
709 if (share_list && share_list->NoError != ctx->NoError) {
710 return _eglError(EGL_BAD_MATCH,
711 "eglCreateContext() share list no-error mismatch");
712 }
713
714 return EGL_TRUE;
715 }
716
717 static EGLint
_eglQueryContextRenderBuffer(_EGLContext * ctx)718 _eglQueryContextRenderBuffer(_EGLContext *ctx)
719 {
720 _EGLSurface *surf = ctx->DrawSurface;
721
722 /* From the EGL 1.5 spec:
723 *
724 * - If the context is not bound to a surface, then EGL_NONE will be
725 * returned.
726 */
727 if (!surf)
728 return EGL_NONE;
729
730 switch (surf->Type) {
731 default:
732 unreachable("bad EGLSurface type");
733 case EGL_PIXMAP_BIT:
734 /* - If the context is bound to a pixmap surface, then EGL_SINGLE_BUFFER
735 * will be returned.
736 */
737 return EGL_SINGLE_BUFFER;
738 case EGL_PBUFFER_BIT:
739 /* - If the context is bound to a pbuffer surface, then EGL_BACK_BUFFER
740 * will be returned.
741 */
742 return EGL_BACK_BUFFER;
743 case EGL_WINDOW_BIT:
744 /* - If the context is bound to a window surface, then either
745 * EGL_BACK_BUFFER or EGL_SINGLE_BUFFER may be returned. The value
746 * returned depends on both the buffer requested by the setting of the
747 * EGL_RENDER_BUFFER property of the surface [...], and on the client
748 * API (not all client APIs support single-buffer Rendering to window
749 * surfaces). Some client APIs allow control of whether rendering goes
750 * to the front or back buffer. This client API-specific choice is not
751 * reflected in the returned value, which only describes the buffer
752 * that will be rendered to by default if not overridden by the client
753 * API.
754 */
755 return surf->ActiveRenderBuffer;
756 }
757 }
758
759 EGLBoolean
_eglQueryContext(_EGLContext * c,EGLint attribute,EGLint * value)760 _eglQueryContext(_EGLContext *c, EGLint attribute, EGLint *value)
761 {
762 _EGLDisplay *disp = c->Resource.Display;
763
764 if (!value)
765 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
766
767 switch (attribute) {
768 case EGL_CONFIG_ID:
769 /*
770 * From EGL_KHR_no_config_context:
771 *
772 * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
773 * respect to which the context was created, or zero if created
774 * without respect to an EGLConfig."
775 */
776 *value = c->Config ? c->Config->ConfigID : 0;
777 break;
778 case EGL_CONTEXT_CLIENT_VERSION:
779 *value = c->ClientMajorVersion;
780 break;
781 case EGL_CONTEXT_CLIENT_TYPE:
782 *value = c->ClientAPI;
783 break;
784 case EGL_RENDER_BUFFER:
785 *value = _eglQueryContextRenderBuffer(c);
786 break;
787 case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
788 *value = c->ContextPriority;
789 break;
790 case EGL_PROTECTED_CONTENT_EXT:
791 if (!disp->Extensions.EXT_protected_content)
792 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
793 *value = c->Protected;
794 break;
795 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
796 if (!disp->Extensions.EXT_query_reset_notification_strategy)
797 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
798 *value = c->ResetNotificationStrategy;
799 break;
800 default:
801 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
802 }
803
804 return EGL_TRUE;
805 }
806
807 /**
808 * Bind the context to the thread and return the previous context.
809 *
810 * Note that the context may be NULL.
811 */
812 _EGLContext *
_eglBindContextToThread(_EGLContext * ctx,_EGLThreadInfo * t)813 _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
814 {
815 _EGLContext *oldCtx;
816
817 oldCtx = t->CurrentContext;
818 if (ctx != oldCtx) {
819 if (oldCtx)
820 oldCtx->Binding = NULL;
821 if (ctx)
822 ctx->Binding = t;
823
824 t->CurrentContext = ctx;
825 }
826
827 return oldCtx;
828 }
829
830 /**
831 * Return true if the given context and surfaces can be made current.
832 */
833 static EGLBoolean
_eglCheckMakeCurrent(_EGLContext * ctx,_EGLSurface * draw,_EGLSurface * read)834 _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
835 {
836 _EGLThreadInfo *t = _eglGetCurrentThread();
837 _EGLDisplay *disp;
838
839 /* this is easy */
840 if (!ctx) {
841 if (draw || read)
842 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
843 return EGL_TRUE;
844 }
845
846 disp = ctx->Resource.Display;
847 if (!disp->Extensions.KHR_surfaceless_context &&
848 (draw == NULL || read == NULL))
849 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
850
851 /*
852 * The spec says
853 *
854 * "If ctx is current to some other thread, or if either draw or read are
855 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
856 * generated."
857 *
858 * and
859 *
860 * "at most one context may be bound to a particular surface at a given
861 * time"
862 */
863 if (ctx->Binding && ctx->Binding != t)
864 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
865 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
866 if (draw->CurrentContext->Binding != t)
867 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
868 }
869 if (read && read->CurrentContext && read->CurrentContext != ctx) {
870 if (read->CurrentContext->Binding != t)
871 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
872 }
873
874 /* If the context has a config then it must match that of the two
875 * surfaces */
876 if (ctx->Config) {
877 if ((draw && draw->Config != ctx->Config) ||
878 (read && read->Config != ctx->Config))
879 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
880 } else {
881 /* Otherwise we must be using the EGL_KHR_no_config_context
882 * extension */
883 assert(disp->Extensions.KHR_no_config_context);
884 }
885
886 return EGL_TRUE;
887 }
888
889 /**
890 * Bind the context to the current thread and given surfaces. Return the
891 * previous bound context and surfaces. The caller should unreference the
892 * returned context and surfaces.
893 *
894 * Making a second call with the resources returned by the first call
895 * unsurprisingly undoes the first call, except for the resource reference
896 * counts.
897 */
898 EGLBoolean
_eglBindContext(_EGLContext * ctx,_EGLSurface * draw,_EGLSurface * read,_EGLContext ** old_ctx,_EGLSurface ** old_draw,_EGLSurface ** old_read)899 _eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
900 _EGLContext **old_ctx, _EGLSurface **old_draw,
901 _EGLSurface **old_read)
902 {
903 _EGLThreadInfo *t = _eglGetCurrentThread();
904 _EGLContext *prev_ctx;
905 _EGLSurface *prev_draw, *prev_read;
906
907 if (!_eglCheckMakeCurrent(ctx, draw, read))
908 return EGL_FALSE;
909
910 /* increment refcounts before binding */
911 _eglGetContext(ctx);
912 _eglGetSurface(draw);
913 _eglGetSurface(read);
914
915 /* bind the new context */
916 prev_ctx = _eglBindContextToThread(ctx, t);
917
918 /* break previous bindings */
919 if (prev_ctx) {
920 prev_draw = prev_ctx->DrawSurface;
921 prev_read = prev_ctx->ReadSurface;
922
923 if (prev_draw)
924 prev_draw->CurrentContext = NULL;
925 if (prev_read)
926 prev_read->CurrentContext = NULL;
927
928 prev_ctx->DrawSurface = NULL;
929 prev_ctx->ReadSurface = NULL;
930 } else {
931 prev_draw = prev_read = NULL;
932 }
933
934 /* establish new bindings */
935 if (ctx) {
936 if (draw)
937 draw->CurrentContext = ctx;
938 if (read)
939 read->CurrentContext = ctx;
940
941 ctx->DrawSurface = draw;
942 ctx->ReadSurface = read;
943 }
944
945 assert(old_ctx && old_draw && old_read);
946 *old_ctx = prev_ctx;
947 *old_draw = prev_draw;
948 *old_read = prev_read;
949
950 return EGL_TRUE;
951 }
952