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