egl: QueryContext on a configless context returns zero
[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 * According to EGL 1.5 Section 3.7:
462 *
463 * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
464 * purposes except eglCreateContext."
465 *
466 * And since we only support GL and GLES, this is the only place where the
467 * bound API matters at all. We look up the current API from the current
468 * thread, and stash that in the context we're initializing. Our caller is
469 * responsible for determining whether that's an API it supports.
470 */
471 EGLBoolean
472 _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
473 const EGLint *attrib_list)
474 {
475 const EGLenum api = eglQueryAPI();
476 EGLint err;
477
478 if (api == EGL_NONE) {
479 _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
480 return EGL_FALSE;
481 }
482
483 _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
484 ctx->ClientAPI = api;
485 ctx->Config = conf;
486 ctx->WindowRenderBuffer = EGL_NONE;
487 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
488
489 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
490 ctx->ClientMinorVersion = 0;
491 ctx->Flags = 0;
492 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
493 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
494
495 err = _eglParseContextAttribList(ctx, dpy, attrib_list);
496 if (err == EGL_SUCCESS && ctx->Config) {
497 EGLint api_bit;
498
499 api_bit = _eglGetContextAPIBit(ctx);
500 if (!(ctx->Config->RenderableType & api_bit)) {
501 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
502 api_bit, ctx->Config->RenderableType);
503 err = EGL_BAD_CONFIG;
504 }
505 }
506 if (err != EGL_SUCCESS)
507 return _eglError(err, "eglCreateContext");
508
509 return EGL_TRUE;
510 }
511
512
513 static EGLint
514 _eglQueryContextRenderBuffer(_EGLContext *ctx)
515 {
516 _EGLSurface *surf = ctx->DrawSurface;
517 EGLint rb;
518
519 if (!surf)
520 return EGL_NONE;
521 if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
522 rb = ctx->WindowRenderBuffer;
523 else
524 rb = surf->RenderBuffer;
525 return rb;
526 }
527
528
529 EGLBoolean
530 _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
531 EGLint attribute, EGLint *value)
532 {
533 (void) drv;
534 (void) dpy;
535
536 if (!value)
537 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
538
539 switch (attribute) {
540 case EGL_CONFIG_ID:
541 /*
542 * From EGL_KHR_no_config_context:
543 *
544 * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
545 * respect to which the context was created, or zero if created
546 * without respect to an EGLConfig."
547 */
548 *value = c->Config ? c->Config->ConfigID : 0;
549 break;
550 case EGL_CONTEXT_CLIENT_VERSION:
551 *value = c->ClientMajorVersion;
552 break;
553 case EGL_CONTEXT_CLIENT_TYPE:
554 *value = c->ClientAPI;
555 break;
556 case EGL_RENDER_BUFFER:
557 *value = _eglQueryContextRenderBuffer(c);
558 break;
559 default:
560 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
561 }
562
563 return EGL_TRUE;
564 }
565
566
567 /**
568 * Bind the context to the thread and return the previous context.
569 *
570 * Note that the context may be NULL.
571 */
572 static _EGLContext *
573 _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
574 {
575 _EGLContext *oldCtx;
576
577 oldCtx = t->CurrentContext;
578 if (ctx != oldCtx) {
579 if (oldCtx)
580 oldCtx->Binding = NULL;
581 if (ctx)
582 ctx->Binding = t;
583
584 t->CurrentContext = ctx;
585 }
586
587 return oldCtx;
588 }
589
590
591 /**
592 * Return true if the given context and surfaces can be made current.
593 */
594 static EGLBoolean
595 _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
596 {
597 _EGLThreadInfo *t = _eglGetCurrentThread();
598 _EGLDisplay *dpy;
599
600 if (_eglIsCurrentThreadDummy())
601 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
602
603 /* this is easy */
604 if (!ctx) {
605 if (draw || read)
606 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
607 return EGL_TRUE;
608 }
609
610 dpy = ctx->Resource.Display;
611 if (!dpy->Extensions.KHR_surfaceless_context
612 && (draw == NULL || read == NULL))
613 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
614
615 /*
616 * The spec says
617 *
618 * "If ctx is current to some other thread, or if either draw or read are
619 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
620 * generated."
621 *
622 * and
623 *
624 * "at most one context may be bound to a particular surface at a given
625 * time"
626 */
627 if (ctx->Binding && ctx->Binding != t)
628 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
629 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
630 if (draw->CurrentContext->Binding != t)
631 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
632 }
633 if (read && read->CurrentContext && read->CurrentContext != ctx) {
634 if (read->CurrentContext->Binding != t)
635 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
636 }
637
638 /* If the context has a config then it must match that of the two
639 * surfaces */
640 if (ctx->Config) {
641 if ((draw && draw->Config != ctx->Config) ||
642 (read && read->Config != ctx->Config))
643 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
644 } else {
645 /* Otherwise we must be using the EGL_MESA_configless_context
646 * extension */
647 assert(dpy->Extensions.MESA_configless_context);
648
649 /* The extension doesn't permit binding draw and read buffers with
650 * differing contexts */
651 if (draw && read && draw->Config != read->Config)
652 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
653 }
654
655 return EGL_TRUE;
656 }
657
658
659 /**
660 * Bind the context to the current thread and given surfaces. Return the
661 * previous bound context and surfaces. The caller should unreference the
662 * returned context and surfaces.
663 *
664 * Making a second call with the resources returned by the first call
665 * unsurprisingly undoes the first call, except for the resouce reference
666 * counts.
667 */
668 EGLBoolean
669 _eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
670 _EGLContext **old_ctx,
671 _EGLSurface **old_draw, _EGLSurface **old_read)
672 {
673 _EGLThreadInfo *t = _eglGetCurrentThread();
674 _EGLContext *prev_ctx;
675 _EGLSurface *prev_draw, *prev_read;
676
677 if (!_eglCheckMakeCurrent(ctx, draw, read))
678 return EGL_FALSE;
679
680 /* increment refcounts before binding */
681 _eglGetContext(ctx);
682 _eglGetSurface(draw);
683 _eglGetSurface(read);
684
685 /* bind the new context */
686 prev_ctx = _eglBindContextToThread(ctx, t);
687
688 /* break previous bindings */
689 if (prev_ctx) {
690 prev_draw = prev_ctx->DrawSurface;
691 prev_read = prev_ctx->ReadSurface;
692
693 if (prev_draw)
694 prev_draw->CurrentContext = NULL;
695 if (prev_read)
696 prev_read->CurrentContext = NULL;
697
698 prev_ctx->DrawSurface = NULL;
699 prev_ctx->ReadSurface = NULL;
700 }
701 else {
702 prev_draw = prev_read = NULL;
703 }
704
705 /* establish new bindings */
706 if (ctx) {
707 if (draw)
708 draw->CurrentContext = ctx;
709 if (read)
710 read->CurrentContext = ctx;
711
712 ctx->DrawSurface = draw;
713 ctx->ReadSurface = read;
714 }
715
716 assert(old_ctx && old_draw && old_read);
717 *old_ctx = prev_ctx;
718 *old_draw = prev_draw;
719 *old_read = prev_read;
720
721 return EGL_TRUE;
722 }