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 #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_REALTIME_NV:
417 if (disp->Extensions.NV_context_priority_realtime)
418 bit = __EGL_CONTEXT_PRIORITY_REALTIME_BIT;
419 else
420 bit = -1;
421 break;
422 case EGL_CONTEXT_PRIORITY_HIGH_IMG:
423 bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT;
424 break;
425 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
426 bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT;
427 break;
428 case EGL_CONTEXT_PRIORITY_LOW_IMG:
429 bit = __EGL_CONTEXT_PRIORITY_LOW_BIT;
430 break;
431 default:
432 bit = -1;
433 break;
434 }
435
436 if (bit < 0) {
437 err = EGL_BAD_ATTRIBUTE;
438 break;
439 }
440
441 /* "This extension allows an EGLContext to be created with a
442 * priority hint. It is possible that an implementation will not
443 * honour the hint, especially if there are constraints on the
444 * number of high priority contexts available in the system, or
445 * system policy limits access to high priority contexts to
446 * appropriate system privilege level. A query is provided to find
447 * the real priority level assigned to the context after creation."
448 *
449 * We currently assume that the driver applies the priority hint
450 * and filters out any it cannot handle during the screen setup,
451 * e.g. dri2_setup_screen(). As such we can mask any change that
452 * the driver would fail, and ctx->ContextPriority matches the
453 * hint applied to the driver/hardware backend.
454 */
455 if (disp->Extensions.IMG_context_priority & (1 << bit))
456 ctx->ContextPriority = val;
457
458 break;
459 }
460
461 case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR:
462 if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR ||
463 val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) {
464 ctx->ReleaseBehavior = val;
465 } else {
466 err = EGL_BAD_ATTRIBUTE;
467 }
468 break;
469
470 case EGL_PROTECTED_CONTENT_EXT:
471 if (!disp->Extensions.EXT_protected_content) {
472 err = EGL_BAD_ATTRIBUTE;
473 break;
474 }
475 ctx->Protected = val == EGL_TRUE;
476 break;
477
478 default:
479 err = EGL_BAD_ATTRIBUTE;
480 break;
481 }
482
483 if (err != EGL_SUCCESS) {
484 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
485 break;
486 }
487 }
488
489 if (api == EGL_OPENGL_API) {
490 /* The EGL_KHR_create_context spec says:
491 *
492 * "If the requested OpenGL version is less than 3.2,
493 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
494 * functionality of the context is determined solely by the
495 * requested version."
496 *
497 * Since the value is ignored, only validate the setting if the version
498 * is >= 3.2.
499 */
500 if (ctx->ClientMajorVersion >= 4 ||
501 (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
502 switch (ctx->Profile) {
503 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
504 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
505 break;
506
507 default:
508 /* The EGL_KHR_create_context spec says:
509 *
510 * "* If an OpenGL context is requested, the requested version
511 * is greater than 3.2, and the value for attribute
512 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
513 * any bits set other than
514 * EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
515 * EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
516 * one of these bits set; or if the implementation does not support
517 * the requested profile, then an EGL_BAD_MATCH error is generated."
518 */
519 err = EGL_BAD_MATCH;
520 break;
521 }
522 }
523
524 /* The EGL_KHR_create_context spec says:
525 *
526 * "* If an OpenGL context is requested and the values for
527 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
528 * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
529 * the value for attribute
530 * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
531 * version and feature set that are not defined, than an
532 * EGL_BAD_MATCH error is generated.
533 *
534 * ... Thus, examples of invalid combinations of attributes
535 * include:
536 *
537 * - Major version < 1 or > 4
538 * - Major version == 1 and minor version < 0 or > 5
539 * - Major version == 2 and minor version < 0 or > 1
540 * - Major version == 3 and minor version < 0 or > 2
541 * - Major version == 4 and minor version < 0 or > 2
542 * - Forward-compatible flag set and major version < 3"
543 */
544 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
545 err = EGL_BAD_MATCH;
546
547 switch (ctx->ClientMajorVersion) {
548 case 1:
549 if (ctx->ClientMinorVersion > 5 ||
550 (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
551 err = EGL_BAD_MATCH;
552 break;
553
554 case 2:
555 if (ctx->ClientMinorVersion > 1 ||
556 (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
557 err = EGL_BAD_MATCH;
558 break;
559
560 case 3:
561 /* Note: The text above is incorrect. There *is* an OpenGL 3.3!
562 */
563 if (ctx->ClientMinorVersion > 3)
564 err = EGL_BAD_MATCH;
565 break;
566
567 case 4:
568 default:
569 /* Don't put additional version checks here. We don't know that
570 * there won't be versions > 4.2.
571 */
572 break;
573 }
574 } else if (api == EGL_OPENGL_ES_API) {
575 /* The EGL_KHR_create_context spec says:
576 *
577 * "* If an OpenGL ES context is requested and the values for
578 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
579 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
580 * is not defined, than an EGL_BAD_MATCH error is generated.
581 *
582 * ... Examples of invalid combinations of attributes include:
583 *
584 * - Major version < 1 or > 2
585 * - Major version == 1 and minor version < 0 or > 1
586 * - Major version == 2 and minor version != 0
587 */
588 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
589 err = EGL_BAD_MATCH;
590
591 switch (ctx->ClientMajorVersion) {
592 case 1:
593 if (ctx->ClientMinorVersion > 1)
594 err = EGL_BAD_MATCH;
595 break;
596
597 case 2:
598 if (ctx->ClientMinorVersion > 0)
599 err = EGL_BAD_MATCH;
600 break;
601
602 case 3:
603 /* Don't put additional version checks here. We don't know that
604 * there won't be versions > 3.0.
605 */
606 break;
607
608 default:
609 err = EGL_BAD_MATCH;
610 break;
611 }
612 }
613
614 switch (ctx->ResetNotificationStrategy) {
615 case EGL_NO_RESET_NOTIFICATION_KHR:
616 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
617 break;
618
619 default:
620 err = EGL_BAD_ATTRIBUTE;
621 break;
622 }
623
624 /* The EGL_KHR_create_context_no_error spec says:
625 *
626 * "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE
627 * at the same time as a debug or robustness context is specified."
628 */
629 if (ctx->NoError &&
630 (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR ||
631 ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
632 err = EGL_BAD_MATCH;
633 }
634
635 if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR |
636 EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR |
637 EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
638 err = EGL_BAD_ATTRIBUTE;
639 }
640
641 return err;
642 }
643
644 /**
645 * Initialize the given _EGLContext object to defaults and/or the values
646 * in the attrib_list.
647 *
648 * According to EGL 1.5 Section 3.7:
649 *
650 * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
651 * purposes except eglCreateContext."
652 *
653 * And since we only support GL and GLES, this is the only place where the
654 * bound API matters at all. We look up the current API from the current
655 * thread, and stash that in the context we're initializing. Our caller is
656 * responsible for determining whether that's an API it supports.
657 */
658 EGLBoolean
_eglInitContext(_EGLContext * ctx,_EGLDisplay * disp,_EGLConfig * conf,_EGLContext * share_list,const EGLint * attrib_list)659 _eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *conf,
660 _EGLContext *share_list, const EGLint *attrib_list)
661 {
662 const EGLenum api = eglQueryAPI();
663 EGLint err;
664
665 if (api == EGL_NONE)
666 return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
667
668 _eglInitResource(&ctx->Resource, sizeof(*ctx), disp);
669 ctx->ClientAPI = api;
670 ctx->Config = conf;
671 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
672
673 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
674 ctx->ClientMinorVersion = 0;
675 ctx->Flags = 0;
676 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
677 ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
678 ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR;
679
680 err = _eglParseContextAttribList(ctx, disp, attrib_list);
681 if (err == EGL_SUCCESS && ctx->Config) {
682 EGLint api_bit;
683
684 api_bit = _eglGetContextAPIBit(ctx);
685 if (!(ctx->Config->RenderableType & api_bit)) {
686 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
687 api_bit, ctx->Config->RenderableType);
688 err = EGL_BAD_CONFIG;
689 }
690 }
691 if (err != EGL_SUCCESS)
692 return _eglError(err, "eglCreateContext");
693
694 /* The EGL_EXT_create_context_robustness spec says:
695 *
696 * "Add to the eglCreateContext context creation errors: [...]
697 *
698 * * If the reset notification behavior of <share_context> and the
699 * newly created context are different then an EGL_BAD_MATCH error is
700 * generated."
701 */
702 if (share_list && share_list->ResetNotificationStrategy !=
703 ctx->ResetNotificationStrategy) {
704 return _eglError(
705 EGL_BAD_MATCH,
706 "eglCreateContext() share list notification strategy mismatch");
707 }
708
709 /* The EGL_KHR_create_context_no_error spec says:
710 *
711 * "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
712 * used to create <share_context> does not match the value of
713 * EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created."
714 */
715 if (share_list && share_list->NoError != ctx->NoError) {
716 return _eglError(EGL_BAD_MATCH,
717 "eglCreateContext() share list no-error mismatch");
718 }
719
720 return EGL_TRUE;
721 }
722
723 static EGLint
_eglQueryContextRenderBuffer(_EGLContext * ctx)724 _eglQueryContextRenderBuffer(_EGLContext *ctx)
725 {
726 _EGLSurface *surf = ctx->DrawSurface;
727
728 /* From the EGL 1.5 spec:
729 *
730 * - If the context is not bound to a surface, then EGL_NONE will be
731 * returned.
732 */
733 if (!surf)
734 return EGL_NONE;
735
736 switch (surf->Type) {
737 default:
738 unreachable("bad EGLSurface type");
739 case EGL_PIXMAP_BIT:
740 /* - If the context is bound to a pixmap surface, then EGL_SINGLE_BUFFER
741 * will be returned.
742 */
743 return EGL_SINGLE_BUFFER;
744 case EGL_PBUFFER_BIT:
745 /* - If the context is bound to a pbuffer surface, then EGL_BACK_BUFFER
746 * will be returned.
747 */
748 return EGL_BACK_BUFFER;
749 case EGL_WINDOW_BIT:
750 /* - If the context is bound to a window surface, then either
751 * EGL_BACK_BUFFER or EGL_SINGLE_BUFFER may be returned. The value
752 * returned depends on both the buffer requested by the setting of the
753 * EGL_RENDER_BUFFER property of the surface [...], and on the client
754 * API (not all client APIs support single-buffer Rendering to window
755 * surfaces). Some client APIs allow control of whether rendering goes
756 * to the front or back buffer. This client API-specific choice is not
757 * reflected in the returned value, which only describes the buffer
758 * that will be rendered to by default if not overridden by the client
759 * API.
760 */
761 return surf->ActiveRenderBuffer;
762 }
763 }
764
765 EGLBoolean
_eglQueryContext(_EGLContext * c,EGLint attribute,EGLint * value)766 _eglQueryContext(_EGLContext *c, EGLint attribute, EGLint *value)
767 {
768 _EGLDisplay *disp = c->Resource.Display;
769
770 if (!value)
771 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
772
773 switch (attribute) {
774 case EGL_CONFIG_ID:
775 /*
776 * From EGL_KHR_no_config_context:
777 *
778 * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
779 * respect to which the context was created, or zero if created
780 * without respect to an EGLConfig."
781 */
782 *value = c->Config ? c->Config->ConfigID : 0;
783 break;
784 case EGL_CONTEXT_CLIENT_VERSION:
785 *value = c->ClientMajorVersion;
786 break;
787 case EGL_CONTEXT_CLIENT_TYPE:
788 *value = c->ClientAPI;
789 break;
790 case EGL_RENDER_BUFFER:
791 *value = _eglQueryContextRenderBuffer(c);
792 break;
793 case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
794 *value = c->ContextPriority;
795 break;
796 case EGL_PROTECTED_CONTENT_EXT:
797 if (!disp->Extensions.EXT_protected_content)
798 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
799 *value = c->Protected;
800 break;
801 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
802 if (!disp->Extensions.EXT_query_reset_notification_strategy)
803 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
804 *value = c->ResetNotificationStrategy;
805 break;
806 default:
807 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
808 }
809
810 return EGL_TRUE;
811 }
812
813 /**
814 * Bind the context to the thread and return the previous context.
815 *
816 * Note that the context may be NULL.
817 */
818 _EGLContext *
_eglBindContextToThread(_EGLContext * ctx,_EGLThreadInfo * t)819 _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
820 {
821 _EGLContext *oldCtx;
822
823 oldCtx = t->CurrentContext;
824 if (ctx != oldCtx) {
825 if (oldCtx)
826 oldCtx->Binding = NULL;
827 if (ctx)
828 ctx->Binding = t;
829
830 t->CurrentContext = ctx;
831 }
832
833 return oldCtx;
834 }
835
836 /**
837 * Return true if the given context and surfaces can be made current.
838 */
839 static EGLBoolean
_eglCheckMakeCurrent(_EGLContext * ctx,_EGLSurface * draw,_EGLSurface * read)840 _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
841 {
842 _EGLThreadInfo *t = _eglGetCurrentThread();
843 _EGLDisplay *disp;
844
845 /* this is easy */
846 if (!ctx) {
847 if (draw || read)
848 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
849 return EGL_TRUE;
850 }
851
852 disp = ctx->Resource.Display;
853 if (!disp->Extensions.KHR_surfaceless_context &&
854 (draw == NULL || read == NULL))
855 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
856
857 /*
858 * The spec says
859 *
860 * "If ctx is current to some other thread, or if either draw or read are
861 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
862 * generated."
863 *
864 * and
865 *
866 * "at most one context may be bound to a particular surface at a given
867 * time"
868 */
869 if (ctx->Binding && ctx->Binding != t)
870 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
871 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
872 if (draw->CurrentContext->Binding != t)
873 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
874 }
875 if (read && read->CurrentContext && read->CurrentContext != ctx) {
876 if (read->CurrentContext->Binding != t)
877 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
878 }
879
880 /* If the context has a config then it must match that of the two
881 * surfaces */
882 if (ctx->Config) {
883 if ((draw && draw->Config != ctx->Config) ||
884 (read && read->Config != ctx->Config))
885 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
886 } else {
887 /* Otherwise we must be using the EGL_KHR_no_config_context
888 * extension */
889 assert(disp->Extensions.KHR_no_config_context);
890 }
891
892 return EGL_TRUE;
893 }
894
895 /**
896 * Bind the context to the current thread and given surfaces. Return the
897 * previous bound context and surfaces. The caller should unreference the
898 * returned context and surfaces.
899 *
900 * Making a second call with the resources returned by the first call
901 * unsurprisingly undoes the first call, except for the resource reference
902 * counts.
903 */
904 EGLBoolean
_eglBindContext(_EGLContext * ctx,_EGLSurface * draw,_EGLSurface * read,_EGLContext ** old_ctx,_EGLSurface ** old_draw,_EGLSurface ** old_read)905 _eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
906 _EGLContext **old_ctx, _EGLSurface **old_draw,
907 _EGLSurface **old_read)
908 {
909 _EGLThreadInfo *t = _eglGetCurrentThread();
910 _EGLContext *prev_ctx;
911 _EGLSurface *prev_draw, *prev_read;
912
913 if (!_eglCheckMakeCurrent(ctx, draw, read))
914 return EGL_FALSE;
915
916 /* increment refcounts before binding */
917 _eglGetContext(ctx);
918 _eglGetSurface(draw);
919 _eglGetSurface(read);
920
921 /* bind the new context */
922 prev_ctx = _eglBindContextToThread(ctx, t);
923
924 /* break previous bindings */
925 if (prev_ctx) {
926 prev_draw = prev_ctx->DrawSurface;
927 prev_read = prev_ctx->ReadSurface;
928
929 if (prev_draw)
930 prev_draw->CurrentContext = NULL;
931 if (prev_read)
932 prev_read->CurrentContext = NULL;
933
934 prev_ctx->DrawSurface = NULL;
935 prev_ctx->ReadSurface = NULL;
936 } else {
937 prev_draw = prev_read = NULL;
938 }
939
940 /* establish new bindings */
941 if (ctx) {
942 if (draw)
943 draw->CurrentContext = ctx;
944 if (read)
945 read->CurrentContext = ctx;
946
947 ctx->DrawSurface = draw;
948 ctx->ReadSurface = read;
949 }
950
951 assert(old_ctx && old_draw && old_read);
952 *old_ctx = prev_ctx;
953 *old_draw = prev_draw;
954 *old_read = prev_read;
955
956 return EGL_TRUE;
957 }
958