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