egl: improve attribute checking for eglCreateContext
[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 * "Flags are only defined for OpenGL context creation, and
156 * specifying a flags value other than zero for other types of
157 * contexts, including OpenGL ES contexts, will generate an
158 * error."
159 */
160 if (api != EGL_OPENGL_API && val != 0) {
161 err = EGL_BAD_ATTRIBUTE;
162 break;
163 }
164
165 ctx->Flags |= val;
166 break;
167
168 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
169 if (!dpy->Extensions.KHR_create_context) {
170 err = EGL_BAD_ATTRIBUTE;
171 break;
172 }
173
174 /* The EGL_KHR_create_context spec says:
175 *
176 * "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
177 * OpenGL contexts, and specifying it for other types of
178 * contexts, including OpenGL ES contexts, will generate an
179 * error."
180 */
181 if (api != EGL_OPENGL_API) {
182 err = EGL_BAD_ATTRIBUTE;
183 break;
184 }
185
186 ctx->Profile = val;
187 break;
188
189 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
190 /* The EGL_KHR_create_context spec says:
191 *
192 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
193 * meaningful for OpenGL contexts, and specifying it for other
194 * types of contexts, including OpenGL ES contexts, will generate
195 * an error."
196 */
197 if (!dpy->Extensions.KHR_create_context
198 || api != EGL_OPENGL_API) {
199 err = EGL_BAD_ATTRIBUTE;
200 break;
201 }
202
203 ctx->ResetNotificationStrategy = val;
204 break;
205
206 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
207 /* The EGL_EXT_create_context_robustness spec says:
208 *
209 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
210 * meaningful for OpenGL ES contexts, and specifying it for other
211 * types of contexts will generate an EGL_BAD_ATTRIBUTE error."
212 */
213 if (!dpy->Extensions.EXT_create_context_robustness
214 || api != EGL_OPENGL_ES_API) {
215 err = EGL_BAD_ATTRIBUTE;
216 break;
217 }
218
219 ctx->ResetNotificationStrategy = val;
220 break;
221
222 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
223 if (!dpy->Extensions.EXT_create_context_robustness) {
224 err = EGL_BAD_ATTRIBUTE;
225 break;
226 }
227
228 if (val == EGL_TRUE)
229 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
230 break;
231
232 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:
233 if (dpy->Version < 15) {
234 err = EGL_BAD_ATTRIBUTE;
235 break;
236 }
237
238 if (val == EGL_TRUE)
239 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
240 break;
241
242 case EGL_CONTEXT_OPENGL_DEBUG:
243 if (dpy->Version < 15) {
244 err = EGL_BAD_ATTRIBUTE;
245 break;
246 }
247
248 if (val == EGL_TRUE)
249 ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
250 break;
251
252 case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:
253 if (dpy->Version < 15) {
254 err = EGL_BAD_ATTRIBUTE;
255 break;
256 }
257
258 if (val == EGL_TRUE)
259 ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
260 break;
261
262 default:
263 err = EGL_BAD_ATTRIBUTE;
264 break;
265 }
266
267 if (err != EGL_SUCCESS) {
268 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
269 break;
270 }
271 }
272
273 if (api == EGL_OPENGL_API) {
274 /* The EGL_KHR_create_context spec says:
275 *
276 * "If the requested OpenGL version is less than 3.2,
277 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
278 * functionality of the context is determined solely by the
279 * requested version."
280 *
281 * Since the value is ignored, only validate the setting if the version
282 * is >= 3.2.
283 */
284 if (ctx->ClientMajorVersion >= 4
285 || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
286 switch (ctx->Profile) {
287 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
288 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
289 break;
290
291 default:
292 /* The EGL_KHR_create_context spec says:
293 *
294 * "* If an OpenGL context is requested, the requested version
295 * is greater than 3.2, and the value for attribute
296 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
297 * any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
298 * and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has
299 * more than one of these bits set; or if the implementation does
300 * not support the requested profile, then an EGL_BAD_MATCH error
301 * is generated."
302 */
303 err = EGL_BAD_MATCH;
304 break;
305 }
306 }
307
308 /* The EGL_KHR_create_context spec says:
309 *
310 * "* If an OpenGL context is requested and the values for
311 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
312 * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
313 * the value for attribute
314 * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
315 * version and feature set that are not defined, than an
316 * EGL_BAD_MATCH error is generated.
317 *
318 * ... Thus, examples of invalid combinations of attributes
319 * include:
320 *
321 * - Major version < 1 or > 4
322 * - Major version == 1 and minor version < 0 or > 5
323 * - Major version == 2 and minor version < 0 or > 1
324 * - Major version == 3 and minor version < 0 or > 2
325 * - Major version == 4 and minor version < 0 or > 2
326 * - Forward-compatible flag set and major version < 3"
327 */
328 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
329 err = EGL_BAD_MATCH;
330
331 switch (ctx->ClientMajorVersion) {
332 case 1:
333 if (ctx->ClientMinorVersion > 5
334 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
335 err = EGL_BAD_MATCH;
336 break;
337
338 case 2:
339 if (ctx->ClientMinorVersion > 1
340 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
341 err = EGL_BAD_MATCH;
342 break;
343
344 case 3:
345 /* Note: The text above is incorrect. There *is* an OpenGL 3.3!
346 */
347 if (ctx->ClientMinorVersion > 3)
348 err = EGL_BAD_MATCH;
349 break;
350
351 case 4:
352 default:
353 /* Don't put additional version checks here. We don't know that
354 * there won't be versions > 4.2.
355 */
356 break;
357 }
358 } else if (api == EGL_OPENGL_ES_API) {
359 /* The EGL_KHR_create_context spec says:
360 *
361 * "* If an OpenGL ES context is requested and the values for
362 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
363 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
364 * is not defined, than an EGL_BAD_MATCH error is generated.
365 *
366 * ... Examples of invalid combinations of attributes include:
367 *
368 * - Major version < 1 or > 2
369 * - Major version == 1 and minor version < 0 or > 1
370 * - Major version == 2 and minor version != 0
371 */
372 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
373 err = EGL_BAD_MATCH;
374
375 switch (ctx->ClientMajorVersion) {
376 case 1:
377 if (ctx->ClientMinorVersion > 1)
378 err = EGL_BAD_MATCH;
379 break;
380
381 case 2:
382 if (ctx->ClientMinorVersion > 0)
383 err = EGL_BAD_MATCH;
384 break;
385
386 case 3:
387 /* Don't put additional version checks here. We don't know that
388 * there won't be versions > 3.0.
389 */
390 break;
391
392 default:
393 err = EGL_BAD_MATCH;
394 break;
395 }
396 }
397
398 switch (ctx->ResetNotificationStrategy) {
399 case EGL_NO_RESET_NOTIFICATION_KHR:
400 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
401 break;
402
403 default:
404 err = EGL_BAD_ATTRIBUTE;
405 break;
406 }
407
408 if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
409 | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
410 | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
411 err = EGL_BAD_ATTRIBUTE;
412 }
413
414 return err;
415 }
416
417
418 /**
419 * Initialize the given _EGLContext object to defaults and/or the values
420 * in the attrib_list.
421 */
422 EGLBoolean
423 _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
424 const EGLint *attrib_list)
425 {
426 const EGLenum api = eglQueryAPI();
427 EGLint err;
428
429 if (api == EGL_NONE) {
430 _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
431 return EGL_FALSE;
432 }
433
434 _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
435 ctx->ClientAPI = api;
436 ctx->Config = conf;
437 ctx->WindowRenderBuffer = EGL_NONE;
438 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
439
440 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
441 ctx->ClientMinorVersion = 0;
442 ctx->Flags = 0;
443 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
444 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
445
446 err = _eglParseContextAttribList(ctx, dpy, attrib_list);
447 if (err == EGL_SUCCESS && ctx->Config) {
448 EGLint api_bit;
449
450 api_bit = _eglGetContextAPIBit(ctx);
451 if (!(ctx->Config->RenderableType & api_bit)) {
452 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
453 api_bit, ctx->Config->RenderableType);
454 err = EGL_BAD_CONFIG;
455 }
456 }
457 if (err != EGL_SUCCESS)
458 return _eglError(err, "eglCreateContext");
459
460 return EGL_TRUE;
461 }
462
463
464 static EGLint
465 _eglQueryContextRenderBuffer(_EGLContext *ctx)
466 {
467 _EGLSurface *surf = ctx->DrawSurface;
468 EGLint rb;
469
470 if (!surf)
471 return EGL_NONE;
472 if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
473 rb = ctx->WindowRenderBuffer;
474 else
475 rb = surf->RenderBuffer;
476 return rb;
477 }
478
479
480 EGLBoolean
481 _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
482 EGLint attribute, EGLint *value)
483 {
484 (void) drv;
485 (void) dpy;
486
487 if (!value)
488 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
489
490 switch (attribute) {
491 case EGL_CONFIG_ID:
492 if (!c->Config)
493 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
494 *value = c->Config->ConfigID;
495 break;
496 case EGL_CONTEXT_CLIENT_VERSION:
497 *value = c->ClientMajorVersion;
498 break;
499 case EGL_CONTEXT_CLIENT_TYPE:
500 *value = c->ClientAPI;
501 break;
502 case EGL_RENDER_BUFFER:
503 *value = _eglQueryContextRenderBuffer(c);
504 break;
505 default:
506 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
507 }
508
509 return EGL_TRUE;
510 }
511
512
513 /**
514 * Bind the context to the thread and return the previous context.
515 *
516 * Note that the context may be NULL.
517 */
518 static _EGLContext *
519 _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
520 {
521 EGLint apiIndex;
522 _EGLContext *oldCtx;
523
524 apiIndex = (ctx) ?
525 _eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex;
526
527 oldCtx = t->CurrentContexts[apiIndex];
528 if (ctx != oldCtx) {
529 if (oldCtx)
530 oldCtx->Binding = NULL;
531 if (ctx)
532 ctx->Binding = t;
533
534 t->CurrentContexts[apiIndex] = ctx;
535 }
536
537 return oldCtx;
538 }
539
540
541 /**
542 * Return true if the given context and surfaces can be made current.
543 */
544 static EGLBoolean
545 _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
546 {
547 _EGLThreadInfo *t = _eglGetCurrentThread();
548 _EGLDisplay *dpy;
549 EGLint conflict_api;
550
551 if (_eglIsCurrentThreadDummy())
552 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
553
554 /* this is easy */
555 if (!ctx) {
556 if (draw || read)
557 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
558 return EGL_TRUE;
559 }
560
561 dpy = ctx->Resource.Display;
562 if (!dpy->Extensions.KHR_surfaceless_context
563 && (draw == NULL || read == NULL))
564 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
565
566 /*
567 * The spec says
568 *
569 * "If ctx is current to some other thread, or if either draw or read are
570 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
571 * generated."
572 *
573 * and
574 *
575 * "at most one context may be bound to a particular surface at a given
576 * time"
577 */
578 if (ctx->Binding && ctx->Binding != t)
579 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
580 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
581 if (draw->CurrentContext->Binding != t ||
582 draw->CurrentContext->ClientAPI != ctx->ClientAPI)
583 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
584 }
585 if (read && read->CurrentContext && read->CurrentContext != ctx) {
586 if (read->CurrentContext->Binding != t ||
587 read->CurrentContext->ClientAPI != ctx->ClientAPI)
588 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
589 }
590
591 /* If the context has a config then it must match that of the two
592 * surfaces */
593 if (ctx->Config) {
594 if ((draw && draw->Config != ctx->Config) ||
595 (read && read->Config != ctx->Config))
596 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
597 } else {
598 /* Otherwise we must be using the EGL_MESA_configless_context
599 * extension */
600 assert(dpy->Extensions.MESA_configless_context);
601
602 /* The extension doesn't permit binding draw and read buffers with
603 * differing contexts */
604 if (draw && read && draw->Config != read->Config)
605 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
606 }
607
608 switch (ctx->ClientAPI) {
609 /* OpenGL and OpenGL ES are conflicting */
610 case EGL_OPENGL_ES_API:
611 conflict_api = EGL_OPENGL_API;
612 break;
613 case EGL_OPENGL_API:
614 conflict_api = EGL_OPENGL_ES_API;
615 break;
616 default:
617 conflict_api = -1;
618 break;
619 }
620
621 if (conflict_api >= 0 && _eglGetAPIContext(conflict_api))
622 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
623
624 return EGL_TRUE;
625 }
626
627
628 /**
629 * Bind the context to the current thread and given surfaces. Return the
630 * previous bound context and surfaces. The caller should unreference the
631 * returned context and surfaces.
632 *
633 * Making a second call with the resources returned by the first call
634 * unsurprisingly undoes the first call, except for the resouce reference
635 * counts.
636 */
637 EGLBoolean
638 _eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
639 _EGLContext **old_ctx,
640 _EGLSurface **old_draw, _EGLSurface **old_read)
641 {
642 _EGLThreadInfo *t = _eglGetCurrentThread();
643 _EGLContext *prev_ctx;
644 _EGLSurface *prev_draw, *prev_read;
645
646 if (!_eglCheckMakeCurrent(ctx, draw, read))
647 return EGL_FALSE;
648
649 /* increment refcounts before binding */
650 _eglGetContext(ctx);
651 _eglGetSurface(draw);
652 _eglGetSurface(read);
653
654 /* bind the new context */
655 prev_ctx = _eglBindContextToThread(ctx, t);
656
657 /* break previous bindings */
658 if (prev_ctx) {
659 prev_draw = prev_ctx->DrawSurface;
660 prev_read = prev_ctx->ReadSurface;
661
662 if (prev_draw)
663 prev_draw->CurrentContext = NULL;
664 if (prev_read)
665 prev_read->CurrentContext = NULL;
666
667 prev_ctx->DrawSurface = NULL;
668 prev_ctx->ReadSurface = NULL;
669 }
670 else {
671 prev_draw = prev_read = NULL;
672 }
673
674 /* establish new bindings */
675 if (ctx) {
676 if (draw)
677 draw->CurrentContext = ctx;
678 if (read)
679 read->CurrentContext = ctx;
680
681 ctx->DrawSurface = draw;
682 ctx->ReadSurface = read;
683 }
684
685 assert(old_ctx && old_draw && old_read);
686 *old_ctx = prev_ctx;
687 *old_draw = prev_draw;
688 *old_read = prev_read;
689
690 return EGL_TRUE;
691 }