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