• 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 #include "eglcontext.h"
31 #include <assert.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include "util/macros.h"
35 #include "eglconfig.h"
36 #include "eglcurrent.h"
37 #include "egldisplay.h"
38 #include "egllog.h"
39 #include "eglsurface.h"
40 
41 /**
42  * Return the API bit (one of EGL_xxx_BIT) of the context.
43  */
44 static EGLint
_eglGetContextAPIBit(_EGLContext * ctx)45 _eglGetContextAPIBit(_EGLContext *ctx)
46 {
47    EGLint bit = 0;
48 
49    switch (ctx->ClientAPI) {
50    case EGL_OPENGL_ES_API:
51       switch (ctx->ClientMajorVersion) {
52       case 1:
53          bit = EGL_OPENGL_ES_BIT;
54          break;
55       case 2:
56          bit = EGL_OPENGL_ES2_BIT;
57          break;
58       case 3:
59          bit = EGL_OPENGL_ES3_BIT_KHR;
60          break;
61       default:
62          break;
63       }
64       break;
65    case EGL_OPENVG_API:
66       bit = EGL_OPENVG_BIT;
67       break;
68    case EGL_OPENGL_API:
69       bit = EGL_OPENGL_BIT;
70       break;
71    default:
72       break;
73    }
74 
75    return bit;
76 }
77 
78 /**
79  * Parse the list of context attributes and return the proper error code.
80  */
81 static EGLint
_eglParseContextAttribList(_EGLContext * ctx,_EGLDisplay * disp,const EGLint * attrib_list)82 _eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *disp,
83                            const EGLint *attrib_list)
84 {
85    EGLenum api = ctx->ClientAPI;
86    EGLint i, err = EGL_SUCCESS;
87 
88    if (!attrib_list)
89       return EGL_SUCCESS;
90 
91    if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) {
92       _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]);
93       return EGL_BAD_ATTRIBUTE;
94    }
95 
96    for (i = 0; attrib_list[i] != EGL_NONE; i++) {
97       EGLint attr = attrib_list[i++];
98       EGLint val = attrib_list[i];
99 
100       switch (attr) {
101       case EGL_CONTEXT_CLIENT_VERSION:
102          /* The EGL 1.4 spec says:
103           *
104           *     "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the
105           *      current rendering API is EGL_OPENGL_ES_API"
106           *
107           * The EGL_KHR_create_context spec says:
108           *
109           *     "EGL_CONTEXT_MAJOR_VERSION_KHR           0x3098
110           *      (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)"
111           *
112           *     "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
113           *      EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
114           *      version. They are only meaningful for OpenGL and OpenGL ES
115           *      contexts, and specifying them for other types of contexts will
116           *      generate an error."
117           */
118          if ((api != EGL_OPENGL_ES_API &&
119               (!disp->Extensions.KHR_create_context ||
120                api != EGL_OPENGL_API))) {
121             err = EGL_BAD_ATTRIBUTE;
122             break;
123          }
124 
125          ctx->ClientMajorVersion = val;
126          break;
127 
128       case EGL_CONTEXT_MINOR_VERSION_KHR:
129          /* The EGL_KHR_create_context spec says:
130           *
131           *     "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
132           *      EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
133           *      version. They are only meaningful for OpenGL and OpenGL ES
134           *      contexts, and specifying them for other types of contexts will
135           *      generate an error."
136           */
137          if (!disp->Extensions.KHR_create_context ||
138              (api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) {
139             err = EGL_BAD_ATTRIBUTE;
140             break;
141          }
142 
143          ctx->ClientMinorVersion = val;
144          break;
145 
146       case EGL_CONTEXT_FLAGS_KHR:
147          if (!disp->Extensions.KHR_create_context) {
148             err = EGL_BAD_ATTRIBUTE;
149             break;
150          }
151 
152          /* The EGL_KHR_create_context spec says:
153           *
154           *     "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in
155           *     EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.
156           *     [...]
157           *     In some cases a debug context may be identical to a non-debug
158           *     context. This bit is supported for OpenGL and OpenGL ES
159           *     contexts."
160           */
161          if ((val & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) &&
162              (api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API)) {
163             err = EGL_BAD_ATTRIBUTE;
164             break;
165          }
166 
167          /* The EGL_KHR_create_context spec says:
168           *
169           *     "If the EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR flag bit
170           *     is set in EGL_CONTEXT_FLAGS_KHR, then a <forward-compatible>
171           *     context will be created. Forward-compatible contexts are
172           *     defined only for OpenGL versions 3.0 and later. They must not
173           *     support functionality marked as <deprecated> by that version of
174           *     the API, while a non-forward-compatible context must support
175           *     all functionality in that version, deprecated or not. This bit
176           *     is supported for OpenGL contexts, and requesting a
177           *     forward-compatible context for OpenGL versions less than 3.0
178           *     will generate an error."
179           *
180           * Note: since the forward-compatible flag can be set more than one
181           * way, the OpenGL version check is performed once, below.
182           */
183          if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) &&
184              api != EGL_OPENGL_API) {
185             err = EGL_BAD_ATTRIBUTE;
186             break;
187          }
188 
189          if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
190              api != EGL_OPENGL_API) {
191             /* The EGL_KHR_create_context spec says:
192              *
193              *   10) Which error should be generated if robust buffer access
194              *       or reset notifications are requested under OpenGL ES?
195              *
196              *       As per Issue 6, this extension does not support creating
197              *       robust contexts for OpenGL ES. This is only supported via
198              *       the EGL_EXT_create_context_robustness extension.
199              *
200              *       Attempting to use this extension to create robust OpenGL
201              *       ES context will generate an EGL_BAD_ATTRIBUTE error. This
202              *       specific error is generated because this extension does
203              *       not define the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
204              *       and EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
205              *       bits for OpenGL ES contexts. Thus, use of these bits fall
206              *       under condition described by: "If an attribute is
207              *       specified that is not meaningful for the client API
208              *       type.." in the above specification.
209              *
210              * The spec requires that we emit the error even if the display
211              * supports EGL_EXT_create_context_robustness. To create a robust
212              * GLES context, the *attribute*
213              * EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT must be used, not the
214              * *flag* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR.
215              */
216             err = EGL_BAD_ATTRIBUTE;
217             break;
218          }
219 
220          /* The EGL_KHR_create_context spec says:
221           *     "If <config> does not support a client API context compatible
222           *     with the requested API major and minor version, context flags,
223           *     and context reset notification behavior (for client API types
224           *     where these attributes are supported), then an EGL_BAD_MATCH
225           *     error is generated."
226           */
227          if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
228              !disp->RobustBufferAccess) {
229             err = EGL_BAD_MATCH;
230             break;
231          }
232 
233          ctx->Flags |= val;
234          break;
235 
236       case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
237          if (!disp->Extensions.KHR_create_context) {
238             err = EGL_BAD_ATTRIBUTE;
239             break;
240          }
241 
242          /* The EGL_KHR_create_context spec says:
243           *
244           *     "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
245           *     OpenGL contexts, and specifying it for other types of
246           *     contexts, including OpenGL ES contexts, will generate an
247           *     error."
248           */
249          if (api != EGL_OPENGL_API) {
250             err = EGL_BAD_ATTRIBUTE;
251             break;
252          }
253 
254          ctx->Profile = val;
255          break;
256 
257       case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
258          /* The EGL_KHR_create_context spec says:
259           *
260           *     "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
261           *     meaningful for OpenGL contexts, and specifying it for other
262           *     types of contexts, including OpenGL ES contexts, will generate
263           *     an error."
264           *
265           * EGL 1.5 defines EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY
266           * (without a suffix) which has the same value as the KHR token,
267           * and specifies that it now works with both GL and ES contexts:
268           *
269           *    "This attribute is supported only for OpenGL and OpenGL ES
270           *     contexts."
271           */
272          if (!(disp->Extensions.KHR_create_context && api == EGL_OPENGL_API) &&
273              !(disp->Version >= 15 &&
274                (api == EGL_OPENGL_API || api == EGL_OPENGL_ES_API))) {
275             err = EGL_BAD_ATTRIBUTE;
276             break;
277          }
278 
279          /* The EGL 1.5 spec says:
280           *     "An EGL_BAD_MATCH error is generated if an OpenGL or OpenGL ES
281           *     context is requested with robust buffer access and with a
282           *     specified reset notification behavior, and the implementation
283           *     does not support that behavior."
284           *
285           * and the EGL_KHR_create_context spec says:
286           *     "If <config> does not support a client API context compatible
287           *     with the requested API major and minor version, context flags,
288           *     and context reset notification behavior (for client API types
289           *     where these attributes are supported), then an EGL_BAD_MATCH
290           *     error is generated."
291           */
292          if (val != EGL_NO_RESET_NOTIFICATION_KHR &&
293              !disp->Extensions.EXT_create_context_robustness) {
294             err = EGL_BAD_MATCH;
295             break;
296          }
297 
298          ctx->ResetNotificationStrategy = val;
299          break;
300 
301       case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
302          /* The EGL_EXT_create_context_robustness spec says:
303           *
304           *     "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
305           *     meaningful for OpenGL ES contexts, and specifying it for other
306           *     types of contexts will generate an EGL_BAD_ATTRIBUTE error."
307           */
308          if (!disp->Extensions.EXT_create_context_robustness ||
309              api != EGL_OPENGL_ES_API) {
310             err = EGL_BAD_ATTRIBUTE;
311             break;
312          }
313 
314          ctx->ResetNotificationStrategy = val;
315          break;
316 
317       case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
318          if (!disp->Extensions.EXT_create_context_robustness) {
319             err = EGL_BAD_ATTRIBUTE;
320             break;
321          }
322 
323          /* The EGL_EXT_create_context_robustness spec says:
324           *
325           *     "EGL_BAD_CONFIG is generated if
326           *     [EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT] is set to EGL_TRUE and
327           *     no GL context supporting the GL_EXT_robustness extension and
328           *     robust access as described therein can be created."
329           */
330          if (val == EGL_TRUE && !disp->RobustBufferAccess) {
331             err = EGL_BAD_CONFIG;
332             break;
333          }
334 
335          if (val == EGL_TRUE)
336             ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
337          break;
338 
339       case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:
340          if (disp->Version < 15) {
341             err = EGL_BAD_ATTRIBUTE;
342             break;
343          }
344 
345          /* The EGL 1.5 spec says:
346           *     "An EGL_BAD_MATCH error is generated if an OpenGL or OpenGL ES
347           *     context is requested with robust buffer access, and the
348           *     implementation does not support the corresponding OpenGL or
349           *     OpenGL ES extension".
350           */
351          if (val == EGL_TRUE && !disp->RobustBufferAccess) {
352             err = EGL_BAD_MATCH;
353             break;
354          }
355 
356          if (val == EGL_TRUE)
357             ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
358          break;
359 
360       case EGL_CONTEXT_OPENGL_DEBUG:
361          if (disp->Version < 15) {
362             err = EGL_BAD_ATTRIBUTE;
363             break;
364          }
365 
366          if (val == EGL_TRUE)
367             ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
368          break;
369 
370       case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:
371          if (disp->Version < 15) {
372             err = EGL_BAD_ATTRIBUTE;
373             break;
374          }
375 
376          if (val == EGL_TRUE)
377             ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
378          break;
379 
380       case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
381          if (disp->Version < 14 ||
382              !disp->Extensions.KHR_create_context_no_error) {
383             err = EGL_BAD_ATTRIBUTE;
384             break;
385          }
386 
387          /* The KHR_no_error spec only applies against OpenGL 2.0+ and
388           * OpenGL ES 2.0+
389           */
390          if (((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) ||
391               ctx->ClientMajorVersion < 2) &&
392              val == EGL_TRUE) {
393             err = EGL_BAD_ATTRIBUTE;
394             break;
395          }
396 
397          /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */
398          ctx->NoError = !!val;
399          break;
400 
401       case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
402          /* The  EGL_IMG_context_priority spec says:
403           *
404           * "EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of
405           * the context to be created. This attribute is a hint, as an
406           * implementation may not support multiple contexts at some
407           * priority levels and system policy may limit access to high
408           * priority contexts to appropriate system privilege level. The
409           * default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is
410           * EGL_CONTEXT_PRIORITY_MEDIUM_IMG."
411           */
412          {
413             int bit;
414 
415             switch (val) {
416             case EGL_CONTEXT_PRIORITY_REALTIME_NV:
417                if (disp->Extensions.NV_context_priority_realtime)
418                   bit = __EGL_CONTEXT_PRIORITY_REALTIME_BIT;
419                else
420                   bit = -1;
421                break;
422             case EGL_CONTEXT_PRIORITY_HIGH_IMG:
423                bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT;
424                break;
425             case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
426                bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT;
427                break;
428             case EGL_CONTEXT_PRIORITY_LOW_IMG:
429                bit = __EGL_CONTEXT_PRIORITY_LOW_BIT;
430                break;
431             default:
432                bit = -1;
433                break;
434             }
435 
436             if (bit < 0) {
437                err = EGL_BAD_ATTRIBUTE;
438                break;
439             }
440 
441             /* "This extension allows an EGLContext to be created with a
442              * priority hint. It is possible that an implementation will not
443              * honour the hint, especially if there are constraints on the
444              * number of high priority contexts available in the system, or
445              * system policy limits access to high priority contexts to
446              * appropriate system privilege level. A query is provided to find
447              * the real priority level assigned to the context after creation."
448              *
449              * We currently assume that the driver applies the priority hint
450              * and filters out any it cannot handle during the screen setup,
451              * e.g. dri2_setup_screen(). As such we can mask any change that
452              * the driver would fail, and ctx->ContextPriority matches the
453              * hint applied to the driver/hardware backend.
454              */
455             if (disp->Extensions.IMG_context_priority & (1 << bit))
456                ctx->ContextPriority = val;
457 
458             break;
459          }
460 
461       case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR:
462          if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR ||
463              val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) {
464             ctx->ReleaseBehavior = val;
465          } else {
466             err = EGL_BAD_ATTRIBUTE;
467          }
468          break;
469 
470       case EGL_PROTECTED_CONTENT_EXT:
471          if (!disp->Extensions.EXT_protected_content) {
472             err = EGL_BAD_ATTRIBUTE;
473             break;
474          }
475          ctx->Protected = val == EGL_TRUE;
476          break;
477 
478       default:
479          err = EGL_BAD_ATTRIBUTE;
480          break;
481       }
482 
483       if (err != EGL_SUCCESS) {
484          _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
485          break;
486       }
487    }
488 
489    if (api == EGL_OPENGL_API) {
490       /* The EGL_KHR_create_context spec says:
491        *
492        *     "If the requested OpenGL version is less than 3.2,
493        *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
494        *     functionality of the context is determined solely by the
495        *     requested version."
496        *
497        * Since the value is ignored, only validate the setting if the version
498        * is >= 3.2.
499        */
500       if (ctx->ClientMajorVersion >= 4 ||
501           (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
502          switch (ctx->Profile) {
503          case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
504          case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
505             break;
506 
507          default:
508             /* The EGL_KHR_create_context spec says:
509              *
510              *     "* If an OpenGL context is requested, the requested version
511              *        is greater than 3.2, and the value for attribute
512              *        EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
513              *        any bits set other than
514              * EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR and
515              * EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has more than
516              * one of these bits set; or if the implementation does not support
517              * the requested profile, then an EGL_BAD_MATCH error is generated."
518              */
519             err = EGL_BAD_MATCH;
520             break;
521          }
522       }
523 
524       /* The EGL_KHR_create_context spec says:
525        *
526        *     "* If an OpenGL context is requested and the values for
527        *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
528        *        EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
529        *        the value for attribute
530        *        EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
531        *        version and feature set that are not defined, than an
532        *        EGL_BAD_MATCH error is generated.
533        *
534        *        ... Thus, examples of invalid combinations of attributes
535        *        include:
536        *
537        *          - Major version < 1 or > 4
538        *          - Major version == 1 and minor version < 0 or > 5
539        *          - Major version == 2 and minor version < 0 or > 1
540        *          - Major version == 3 and minor version < 0 or > 2
541        *          - Major version == 4 and minor version < 0 or > 2
542        *          - Forward-compatible flag set and major version < 3"
543        */
544       if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
545          err = EGL_BAD_MATCH;
546 
547       switch (ctx->ClientMajorVersion) {
548       case 1:
549          if (ctx->ClientMinorVersion > 5 ||
550              (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
551             err = EGL_BAD_MATCH;
552          break;
553 
554       case 2:
555          if (ctx->ClientMinorVersion > 1 ||
556              (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
557             err = EGL_BAD_MATCH;
558          break;
559 
560       case 3:
561          /* Note: The text above is incorrect.  There *is* an OpenGL 3.3!
562           */
563          if (ctx->ClientMinorVersion > 3)
564             err = EGL_BAD_MATCH;
565          break;
566 
567       case 4:
568       default:
569          /* Don't put additional version checks here.  We don't know that
570           * there won't be versions > 4.2.
571           */
572          break;
573       }
574    } else if (api == EGL_OPENGL_ES_API) {
575       /* The EGL_KHR_create_context spec says:
576        *
577        *     "* If an OpenGL ES context is requested and the values for
578        *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
579        *        EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
580        *        is not defined, than an EGL_BAD_MATCH error is generated.
581        *
582        *        ... Examples of invalid combinations of attributes include:
583        *
584        *          - Major version < 1 or > 2
585        *          - Major version == 1 and minor version < 0 or > 1
586        *          - Major version == 2 and minor version != 0
587        */
588       if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
589          err = EGL_BAD_MATCH;
590 
591       switch (ctx->ClientMajorVersion) {
592       case 1:
593          if (ctx->ClientMinorVersion > 1)
594             err = EGL_BAD_MATCH;
595          break;
596 
597       case 2:
598          if (ctx->ClientMinorVersion > 0)
599             err = EGL_BAD_MATCH;
600          break;
601 
602       case 3:
603          /* Don't put additional version checks here.  We don't know that
604           * there won't be versions > 3.0.
605           */
606          break;
607 
608       default:
609          err = EGL_BAD_MATCH;
610          break;
611       }
612    }
613 
614    switch (ctx->ResetNotificationStrategy) {
615    case EGL_NO_RESET_NOTIFICATION_KHR:
616    case EGL_LOSE_CONTEXT_ON_RESET_KHR:
617       break;
618 
619    default:
620       err = EGL_BAD_ATTRIBUTE;
621       break;
622    }
623 
624    /* The EGL_KHR_create_context_no_error spec says:
625     *
626     *    "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE
627     * at the same time as a debug or robustness context is specified."
628     */
629    if (ctx->NoError &&
630        (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR ||
631         ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
632       err = EGL_BAD_MATCH;
633    }
634 
635    if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR |
636                        EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR |
637                        EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
638       err = EGL_BAD_ATTRIBUTE;
639    }
640 
641    return err;
642 }
643 
644 /**
645  * Initialize the given _EGLContext object to defaults and/or the values
646  * in the attrib_list.
647  *
648  * According to EGL 1.5 Section 3.7:
649  *
650  *	"EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
651  *	purposes except eglCreateContext."
652  *
653  * And since we only support GL and GLES, this is the only place where the
654  * bound API matters at all. We look up the current API from the current
655  * thread, and stash that in the context we're initializing. Our caller is
656  * responsible for determining whether that's an API it supports.
657  */
658 EGLBoolean
_eglInitContext(_EGLContext * ctx,_EGLDisplay * disp,_EGLConfig * conf,_EGLContext * share_list,const EGLint * attrib_list)659 _eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *conf,
660                 _EGLContext *share_list, const EGLint *attrib_list)
661 {
662    const EGLenum api = eglQueryAPI();
663    EGLint err;
664 
665    if (api == EGL_NONE)
666       return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
667 
668    _eglInitResource(&ctx->Resource, sizeof(*ctx), disp);
669    ctx->ClientAPI = api;
670    ctx->Config = conf;
671    ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
672 
673    ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
674    ctx->ClientMinorVersion = 0;
675    ctx->Flags = 0;
676    ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
677    ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
678    ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR;
679 
680    err = _eglParseContextAttribList(ctx, disp, attrib_list);
681    if (err == EGL_SUCCESS && ctx->Config) {
682       EGLint api_bit;
683 
684       api_bit = _eglGetContextAPIBit(ctx);
685       if (!(ctx->Config->RenderableType & api_bit)) {
686          _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
687                  api_bit, ctx->Config->RenderableType);
688          err = EGL_BAD_CONFIG;
689       }
690    }
691    if (err != EGL_SUCCESS)
692       return _eglError(err, "eglCreateContext");
693 
694    /* The EGL_EXT_create_context_robustness spec says:
695     *
696     *    "Add to the eglCreateContext context creation errors: [...]
697     *
698     *     * If the reset notification behavior of <share_context> and the
699     *       newly created context are different then an EGL_BAD_MATCH error is
700     *       generated."
701     */
702    if (share_list && share_list->ResetNotificationStrategy !=
703                         ctx->ResetNotificationStrategy) {
704       return _eglError(
705          EGL_BAD_MATCH,
706          "eglCreateContext() share list notification strategy mismatch");
707    }
708 
709    /* The EGL_KHR_create_context_no_error spec says:
710     *
711     *    "BAD_MATCH is generated if the value of EGL_CONTEXT_OPENGL_NO_ERROR_KHR
712     *    used to create <share_context> does not match the value of
713     *    EGL_CONTEXT_OPENGL_NO_ERROR_KHR for the context being created."
714     */
715    if (share_list && share_list->NoError != ctx->NoError) {
716       return _eglError(EGL_BAD_MATCH,
717                        "eglCreateContext() share list no-error mismatch");
718    }
719 
720    return EGL_TRUE;
721 }
722 
723 static EGLint
_eglQueryContextRenderBuffer(_EGLContext * ctx)724 _eglQueryContextRenderBuffer(_EGLContext *ctx)
725 {
726    _EGLSurface *surf = ctx->DrawSurface;
727 
728    /* From the EGL 1.5 spec:
729     *
730     *    - If the context is not bound to a surface, then EGL_NONE will be
731     *      returned.
732     */
733    if (!surf)
734       return EGL_NONE;
735 
736    switch (surf->Type) {
737    default:
738       unreachable("bad EGLSurface type");
739    case EGL_PIXMAP_BIT:
740       /* - If the context is bound to a pixmap surface, then EGL_SINGLE_BUFFER
741        *   will be returned.
742        */
743       return EGL_SINGLE_BUFFER;
744    case EGL_PBUFFER_BIT:
745       /* - If the context is bound to a pbuffer surface, then EGL_BACK_BUFFER
746        *   will be returned.
747        */
748       return EGL_BACK_BUFFER;
749    case EGL_WINDOW_BIT:
750       /* - If the context is bound to a window surface, then either
751        *   EGL_BACK_BUFFER or EGL_SINGLE_BUFFER may be returned. The value
752        *   returned depends on both the buffer requested by the setting of the
753        *   EGL_RENDER_BUFFER property of the surface [...], and on the client
754        *   API (not all client APIs support single-buffer Rendering to window
755        *   surfaces). Some client APIs allow control of whether rendering goes
756        *   to the front or back buffer. This client API-specific choice is not
757        *   reflected in the returned value, which only describes the buffer
758        *   that will be rendered to by default if not overridden by the client
759        *   API.
760        */
761       return surf->ActiveRenderBuffer;
762    }
763 }
764 
765 EGLBoolean
_eglQueryContext(_EGLContext * c,EGLint attribute,EGLint * value)766 _eglQueryContext(_EGLContext *c, EGLint attribute, EGLint *value)
767 {
768    _EGLDisplay *disp = c->Resource.Display;
769 
770    if (!value)
771       return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
772 
773    switch (attribute) {
774    case EGL_CONFIG_ID:
775       /*
776        * From EGL_KHR_no_config_context:
777        *
778        *    "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
779        *     respect to which the context was created, or zero if created
780        *     without respect to an EGLConfig."
781        */
782       *value = c->Config ? c->Config->ConfigID : 0;
783       break;
784    case EGL_CONTEXT_CLIENT_VERSION:
785       *value = c->ClientMajorVersion;
786       break;
787    case EGL_CONTEXT_CLIENT_TYPE:
788       *value = c->ClientAPI;
789       break;
790    case EGL_RENDER_BUFFER:
791       *value = _eglQueryContextRenderBuffer(c);
792       break;
793    case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
794       *value = c->ContextPriority;
795       break;
796    case EGL_PROTECTED_CONTENT_EXT:
797       if (!disp->Extensions.EXT_protected_content)
798          return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
799       *value = c->Protected;
800       break;
801    case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
802       if (!disp->Extensions.EXT_query_reset_notification_strategy)
803          return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
804       *value = c->ResetNotificationStrategy;
805       break;
806    default:
807       return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
808    }
809 
810    return EGL_TRUE;
811 }
812 
813 /**
814  * Bind the context to the thread and return the previous context.
815  *
816  * Note that the context may be NULL.
817  */
818 _EGLContext *
_eglBindContextToThread(_EGLContext * ctx,_EGLThreadInfo * t)819 _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
820 {
821    _EGLContext *oldCtx;
822 
823    oldCtx = t->CurrentContext;
824    if (ctx != oldCtx) {
825       if (oldCtx)
826          oldCtx->Binding = NULL;
827       if (ctx)
828          ctx->Binding = t;
829 
830       t->CurrentContext = ctx;
831    }
832 
833    return oldCtx;
834 }
835 
836 /**
837  * Return true if the given context and surfaces can be made current.
838  */
839 static EGLBoolean
_eglCheckMakeCurrent(_EGLContext * ctx,_EGLSurface * draw,_EGLSurface * read)840 _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
841 {
842    _EGLThreadInfo *t = _eglGetCurrentThread();
843    _EGLDisplay *disp;
844 
845    /* this is easy */
846    if (!ctx) {
847       if (draw || read)
848          return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
849       return EGL_TRUE;
850    }
851 
852    disp = ctx->Resource.Display;
853    if (!disp->Extensions.KHR_surfaceless_context &&
854        (draw == NULL || read == NULL))
855       return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
856 
857    /*
858     * The spec says
859     *
860     * "If ctx is current to some other thread, or if either draw or read are
861     * bound to contexts in another thread, an EGL_BAD_ACCESS error is
862     * generated."
863     *
864     * and
865     *
866     * "at most one context may be bound to a particular surface at a given
867     * time"
868     */
869    if (ctx->Binding && ctx->Binding != t)
870       return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
871    if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
872       if (draw->CurrentContext->Binding != t)
873          return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
874    }
875    if (read && read->CurrentContext && read->CurrentContext != ctx) {
876       if (read->CurrentContext->Binding != t)
877          return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
878    }
879 
880    /* If the context has a config then it must match that of the two
881     * surfaces */
882    if (ctx->Config) {
883       if ((draw && draw->Config != ctx->Config) ||
884           (read && read->Config != ctx->Config))
885          return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
886    } else {
887       /* Otherwise we must be using the EGL_KHR_no_config_context
888        * extension */
889       assert(disp->Extensions.KHR_no_config_context);
890    }
891 
892    return EGL_TRUE;
893 }
894 
895 /**
896  * Bind the context to the current thread and given surfaces.  Return the
897  * previous bound context and surfaces.  The caller should unreference the
898  * returned context and surfaces.
899  *
900  * Making a second call with the resources returned by the first call
901  * unsurprisingly undoes the first call, except for the resource reference
902  * counts.
903  */
904 EGLBoolean
_eglBindContext(_EGLContext * ctx,_EGLSurface * draw,_EGLSurface * read,_EGLContext ** old_ctx,_EGLSurface ** old_draw,_EGLSurface ** old_read)905 _eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
906                 _EGLContext **old_ctx, _EGLSurface **old_draw,
907                 _EGLSurface **old_read)
908 {
909    _EGLThreadInfo *t = _eglGetCurrentThread();
910    _EGLContext *prev_ctx;
911    _EGLSurface *prev_draw, *prev_read;
912 
913    if (!_eglCheckMakeCurrent(ctx, draw, read))
914       return EGL_FALSE;
915 
916    /* increment refcounts before binding */
917    _eglGetContext(ctx);
918    _eglGetSurface(draw);
919    _eglGetSurface(read);
920 
921    /* bind the new context */
922    prev_ctx = _eglBindContextToThread(ctx, t);
923 
924    /* break previous bindings */
925    if (prev_ctx) {
926       prev_draw = prev_ctx->DrawSurface;
927       prev_read = prev_ctx->ReadSurface;
928 
929       if (prev_draw)
930          prev_draw->CurrentContext = NULL;
931       if (prev_read)
932          prev_read->CurrentContext = NULL;
933 
934       prev_ctx->DrawSurface = NULL;
935       prev_ctx->ReadSurface = NULL;
936    } else {
937       prev_draw = prev_read = NULL;
938    }
939 
940    /* establish new bindings */
941    if (ctx) {
942       if (draw)
943          draw->CurrentContext = ctx;
944       if (read)
945          read->CurrentContext = ctx;
946 
947       ctx->DrawSurface = draw;
948       ctx->ReadSurface = read;
949    }
950 
951    assert(old_ctx && old_draw && old_read);
952    *old_ctx = prev_ctx;
953    *old_draw = prev_draw;
954    *old_read = prev_read;
955 
956    return EGL_TRUE;
957 }
958