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