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