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