• 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       case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
316          if (dpy->Version < 14 ||
317              !dpy->Extensions.KHR_create_context_no_error) {
318             err = EGL_BAD_ATTRIBUTE;
319             break;
320          }
321 
322          /* The KHR_no_error spec only applies against OpenGL 2.0+ and
323           * OpenGL ES 2.0+
324           */
325          if ((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) ||
326              ctx->ClientMajorVersion < 2) {
327             err = EGL_BAD_ATTRIBUTE;
328             break;
329          }
330 
331          /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */
332          ctx->NoError = !!val;
333          break;
334 
335       case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
336          /* The  EGL_IMG_context_priority spec says:
337           *
338           * "EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of
339           * the context to be created. This attribute is a hint, as an
340           * implementation may not support multiple contexts at some
341           * priority levels and system policy may limit access to high
342           * priority contexts to appropriate system privilege level. The
343           * default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is
344           * EGL_CONTEXT_PRIORITY_MEDIUM_IMG."
345           */
346          {
347             int bit;
348 
349             switch (val) {
350             case EGL_CONTEXT_PRIORITY_HIGH_IMG:
351                bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT;
352                break;
353             case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
354                bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT;
355                break;
356             case EGL_CONTEXT_PRIORITY_LOW_IMG:
357                bit = __EGL_CONTEXT_PRIORITY_LOW_BIT;
358                break;
359             default:
360                bit = -1;
361                break;
362             }
363 
364             if (bit < 0) {
365                err = EGL_BAD_ATTRIBUTE;
366                break;
367             }
368 
369             /* "This extension allows an EGLContext to be created with a
370              * priority hint. It is possible that an implementation will not
371              * honour the hint, especially if there are constraints on the
372              * number of high priority contexts available in the system, or
373              * system policy limits access to high priority contexts to
374              * appropriate system privilege level. A query is provided to find
375              * the real priority level assigned to the context after creation."
376              *
377              * We currently assume that the driver applies the priority hint
378              * and filters out any it cannot handle during the screen setup,
379              * e.g. dri2_setup_screen(). As such we can mask any change that
380              * the driver would fail, and ctx->ContextPriority matches the
381              * hint applied to the driver/hardware backend.
382              */
383             if (dpy->Extensions.IMG_context_priority & (1 << bit))
384                ctx->ContextPriority = val;
385 
386             break;
387          }
388 
389       case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR:
390          if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR ||
391              val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) {
392             ctx->ReleaseBehavior = val;
393          } else {
394             err = EGL_BAD_ATTRIBUTE;
395          }
396          break;
397 
398       default:
399          err = EGL_BAD_ATTRIBUTE;
400          break;
401       }
402 
403       if (err != EGL_SUCCESS) {
404          _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
405          break;
406       }
407    }
408 
409    if (api == EGL_OPENGL_API) {
410       /* The EGL_KHR_create_context spec says:
411        *
412        *     "If the requested OpenGL version is less than 3.2,
413        *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
414        *     functionality of the context is determined solely by the
415        *     requested version."
416        *
417        * Since the value is ignored, only validate the setting if the version
418        * is >= 3.2.
419        */
420       if (ctx->ClientMajorVersion >= 4
421           || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
422          switch (ctx->Profile) {
423          case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
424          case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
425             break;
426 
427          default:
428             /* The EGL_KHR_create_context spec says:
429              *
430              *     "* If an OpenGL context is requested, the requested version
431              *        is greater than 3.2, and the value for attribute
432              *        EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
433              *        any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
434              *        and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has
435              *        more than one of these bits set; or if the implementation does
436              *        not support the requested profile, then an EGL_BAD_MATCH error
437              *        is generated."
438              */
439             err = EGL_BAD_MATCH;
440             break;
441          }
442       }
443 
444       /* The EGL_KHR_create_context spec says:
445        *
446        *     "* If an OpenGL context is requested and the values for
447        *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
448        *        EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
449        *        the value for attribute
450        *        EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
451        *        version and feature set that are not defined, than an
452        *        EGL_BAD_MATCH error is generated.
453        *
454        *        ... Thus, examples of invalid combinations of attributes
455        *        include:
456        *
457        *          - Major version < 1 or > 4
458        *          - Major version == 1 and minor version < 0 or > 5
459        *          - Major version == 2 and minor version < 0 or > 1
460        *          - Major version == 3 and minor version < 0 or > 2
461        *          - Major version == 4 and minor version < 0 or > 2
462        *          - Forward-compatible flag set and major version < 3"
463        */
464       if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
465          err = EGL_BAD_MATCH;
466 
467       switch (ctx->ClientMajorVersion) {
468       case 1:
469          if (ctx->ClientMinorVersion > 5
470              || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
471             err = EGL_BAD_MATCH;
472          break;
473 
474       case 2:
475          if (ctx->ClientMinorVersion > 1
476              || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
477             err = EGL_BAD_MATCH;
478          break;
479 
480       case 3:
481          /* Note: The text above is incorrect.  There *is* an OpenGL 3.3!
482           */
483          if (ctx->ClientMinorVersion > 3)
484             err = EGL_BAD_MATCH;
485          break;
486 
487       case 4:
488       default:
489          /* Don't put additional version checks here.  We don't know that
490           * there won't be versions > 4.2.
491           */
492          break;
493       }
494    } else if (api == EGL_OPENGL_ES_API) {
495       /* The EGL_KHR_create_context spec says:
496        *
497        *     "* If an OpenGL ES context is requested and the values for
498        *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
499        *        EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
500        *        is not defined, than an EGL_BAD_MATCH error is generated.
501        *
502        *        ... Examples of invalid combinations of attributes include:
503        *
504        *          - Major version < 1 or > 2
505        *          - Major version == 1 and minor version < 0 or > 1
506        *          - Major version == 2 and minor version != 0
507        */
508       if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
509          err = EGL_BAD_MATCH;
510 
511       switch (ctx->ClientMajorVersion) {
512       case 1:
513          if (ctx->ClientMinorVersion > 1)
514             err = EGL_BAD_MATCH;
515          break;
516 
517       case 2:
518          if (ctx->ClientMinorVersion > 0)
519             err = EGL_BAD_MATCH;
520          break;
521 
522       case 3:
523          /* Don't put additional version checks here.  We don't know that
524           * there won't be versions > 3.0.
525           */
526          break;
527 
528       default:
529          err = EGL_BAD_MATCH;
530          break;
531       }
532    }
533 
534    switch (ctx->ResetNotificationStrategy) {
535    case EGL_NO_RESET_NOTIFICATION_KHR:
536    case EGL_LOSE_CONTEXT_ON_RESET_KHR:
537       break;
538 
539    default:
540       err = EGL_BAD_ATTRIBUTE;
541       break;
542    }
543 
544    /* The EGL_KHR_create_context_no_error spec says:
545     *
546     *    "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE at
547     *    the same time as a debug or robustness context is specified."
548     */
549    if (ctx->NoError && (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR ||
550                         ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
551       err = EGL_BAD_MATCH;
552    }
553 
554    if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
555                       | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
556                       | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
557       err = EGL_BAD_ATTRIBUTE;
558    }
559 
560    return err;
561 }
562 
563 
564 /**
565  * Initialize the given _EGLContext object to defaults and/or the values
566  * in the attrib_list.
567  *
568  * According to EGL 1.5 Section 3.7:
569  *
570  *	"EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
571  *	purposes except eglCreateContext."
572  *
573  * And since we only support GL and GLES, this is the only place where the
574  * bound API matters at all. We look up the current API from the current
575  * thread, and stash that in the context we're initializing. Our caller is
576  * responsible for determining whether that's an API it supports.
577  */
578 EGLBoolean
_eglInitContext(_EGLContext * ctx,_EGLDisplay * dpy,_EGLConfig * conf,const EGLint * attrib_list)579 _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
580                 const EGLint *attrib_list)
581 {
582    const EGLenum api = eglQueryAPI();
583    EGLint err;
584 
585    if (api == EGL_NONE)
586       return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
587 
588    _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
589    ctx->ClientAPI = api;
590    ctx->Config = conf;
591    ctx->WindowRenderBuffer = EGL_NONE;
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->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
598    ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
599    ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
600    ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR;
601 
602    err = _eglParseContextAttribList(ctx, dpy, attrib_list);
603    if (err == EGL_SUCCESS && ctx->Config) {
604       EGLint api_bit;
605 
606       api_bit = _eglGetContextAPIBit(ctx);
607       if (!(ctx->Config->RenderableType & api_bit)) {
608          _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
609                api_bit, ctx->Config->RenderableType);
610          err = EGL_BAD_CONFIG;
611       }
612    }
613    if (err != EGL_SUCCESS)
614       return _eglError(err, "eglCreateContext");
615 
616    return EGL_TRUE;
617 }
618 
619 
620 static EGLint
_eglQueryContextRenderBuffer(_EGLContext * ctx)621 _eglQueryContextRenderBuffer(_EGLContext *ctx)
622 {
623    _EGLSurface *surf = ctx->DrawSurface;
624    EGLint rb;
625 
626    if (!surf)
627       return EGL_NONE;
628    if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
629       rb = ctx->WindowRenderBuffer;
630    else
631       rb = surf->RenderBuffer;
632    return rb;
633 }
634 
635 
636 EGLBoolean
_eglQueryContext(_EGLDriver * drv,_EGLDisplay * dpy,_EGLContext * c,EGLint attribute,EGLint * value)637 _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
638                  EGLint attribute, EGLint *value)
639 {
640    (void) drv;
641    (void) dpy;
642 
643    if (!value)
644       return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
645 
646    switch (attribute) {
647    case EGL_CONFIG_ID:
648       /*
649        * From EGL_KHR_no_config_context:
650        *
651        *    "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
652        *     respect to which the context was created, or zero if created
653        *     without respect to an EGLConfig."
654        */
655       *value = c->Config ? c->Config->ConfigID : 0;
656       break;
657    case EGL_CONTEXT_CLIENT_VERSION:
658       *value = c->ClientMajorVersion;
659       break;
660    case EGL_CONTEXT_CLIENT_TYPE:
661       *value = c->ClientAPI;
662       break;
663    case EGL_RENDER_BUFFER:
664       *value = _eglQueryContextRenderBuffer(c);
665       break;
666    case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
667       *value = c->ContextPriority;
668       break;
669    default:
670       return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
671    }
672 
673    return EGL_TRUE;
674 }
675 
676 
677 /**
678  * Bind the context to the thread and return the previous context.
679  *
680  * Note that the context may be NULL.
681  */
682 _EGLContext *
_eglBindContextToThread(_EGLContext * ctx,_EGLThreadInfo * t)683 _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
684 {
685    _EGLContext *oldCtx;
686 
687    oldCtx = t->CurrentContext;
688    if (ctx != oldCtx) {
689       if (oldCtx)
690          oldCtx->Binding = NULL;
691       if (ctx)
692          ctx->Binding = t;
693 
694       t->CurrentContext = ctx;
695    }
696 
697    return oldCtx;
698 }
699 
700 
701 /**
702  * Return true if the given context and surfaces can be made current.
703  */
704 static EGLBoolean
_eglCheckMakeCurrent(_EGLContext * ctx,_EGLSurface * draw,_EGLSurface * read)705 _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
706 {
707    _EGLThreadInfo *t = _eglGetCurrentThread();
708    _EGLDisplay *dpy;
709 
710    if (_eglIsCurrentThreadDummy())
711       return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
712 
713    /* this is easy */
714    if (!ctx) {
715       if (draw || read)
716          return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
717       return EGL_TRUE;
718    }
719 
720    dpy = ctx->Resource.Display;
721    if (!dpy->Extensions.KHR_surfaceless_context
722        && (draw == NULL || read == NULL))
723       return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
724 
725    /*
726     * The spec says
727     *
728     * "If ctx is current to some other thread, or if either draw or read are
729     * bound to contexts in another thread, an EGL_BAD_ACCESS error is
730     * generated."
731     *
732     * and
733     *
734     * "at most one context may be bound to a particular surface at a given
735     * time"
736     */
737    if (ctx->Binding && ctx->Binding != t)
738       return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
739    if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
740       if (draw->CurrentContext->Binding != t)
741          return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
742    }
743    if (read && read->CurrentContext && read->CurrentContext != ctx) {
744       if (read->CurrentContext->Binding != t)
745          return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
746    }
747 
748    /* If the context has a config then it must match that of the two
749     * surfaces */
750    if (ctx->Config) {
751       if ((draw && draw->Config != ctx->Config) ||
752           (read && read->Config != ctx->Config))
753          return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
754    } else {
755       /* Otherwise we must be using the EGL_KHR_no_config_context
756        * extension */
757       assert(dpy->Extensions.KHR_no_config_context);
758 
759       /* The extension doesn't permit binding draw and read buffers with
760        * differing contexts */
761       if (draw && read && draw->Config != read->Config)
762          return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
763    }
764 
765    return EGL_TRUE;
766 }
767 
768 
769 /**
770  * Bind the context to the current thread and given surfaces.  Return the
771  * previous bound context and surfaces.  The caller should unreference the
772  * returned context and surfaces.
773  *
774  * Making a second call with the resources returned by the first call
775  * unsurprisingly undoes the first call, except for the resouce reference
776  * counts.
777  */
778 EGLBoolean
_eglBindContext(_EGLContext * ctx,_EGLSurface * draw,_EGLSurface * read,_EGLContext ** old_ctx,_EGLSurface ** old_draw,_EGLSurface ** old_read)779 _eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
780                 _EGLContext **old_ctx,
781                 _EGLSurface **old_draw, _EGLSurface **old_read)
782 {
783    _EGLThreadInfo *t = _eglGetCurrentThread();
784    _EGLContext *prev_ctx;
785    _EGLSurface *prev_draw, *prev_read;
786 
787    if (!_eglCheckMakeCurrent(ctx, draw, read))
788       return EGL_FALSE;
789 
790    /* increment refcounts before binding */
791    _eglGetContext(ctx);
792    _eglGetSurface(draw);
793    _eglGetSurface(read);
794 
795    /* bind the new context */
796    prev_ctx = _eglBindContextToThread(ctx, t);
797 
798    /* break previous bindings */
799    if (prev_ctx) {
800       prev_draw = prev_ctx->DrawSurface;
801       prev_read = prev_ctx->ReadSurface;
802 
803       if (prev_draw)
804          prev_draw->CurrentContext = NULL;
805       if (prev_read)
806          prev_read->CurrentContext = NULL;
807 
808       prev_ctx->DrawSurface = NULL;
809       prev_ctx->ReadSurface = NULL;
810    }
811    else {
812       prev_draw = prev_read = NULL;
813    }
814 
815    /* establish new bindings */
816    if (ctx) {
817       if (draw)
818          draw->CurrentContext = ctx;
819       if (read)
820          read->CurrentContext = ctx;
821 
822       ctx->DrawSurface = draw;
823       ctx->ReadSurface = read;
824    }
825 
826    assert(old_ctx && old_draw && old_read);
827    *old_ctx = prev_ctx;
828    *old_draw = prev_draw;
829    *old_read = prev_read;
830 
831    return EGL_TRUE;
832 }
833