xref: /third_party/mesa3d/src/egl/main/eglcontext.c (revision bf215546)
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 */
46static EGLint
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 */
84static EGLint
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 */
590EGLBoolean
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
630static EGLint
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
673EGLBoolean
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 *
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 */
737static EGLBoolean
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 */
808EGLBoolean
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