eglcontext.c revision 848b8605
1848b8605Smrg/**************************************************************************
2848b8605Smrg *
3848b8605Smrg * Copyright 2008 VMware, Inc.
4848b8605Smrg * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5848b8605Smrg * Copyright 2010-2011 LunarG, Inc.
6848b8605Smrg * All Rights Reserved.
7848b8605Smrg *
8848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
9848b8605Smrg * copy of this software and associated documentation files (the
10848b8605Smrg * "Software"), to deal in the Software without restriction, including
11848b8605Smrg * without limitation the rights to use, copy, modify, merge, publish,
12848b8605Smrg * distribute, sub license, and/or sell copies of the Software, and to
13848b8605Smrg * permit persons to whom the Software is furnished to do so, subject to
14848b8605Smrg * the following conditions:
15848b8605Smrg *
16848b8605Smrg * The above copyright notice and this permission notice (including the
17848b8605Smrg * next paragraph) shall be included in all copies or substantial portions
18848b8605Smrg * of the Software.
19848b8605Smrg *
20848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
23848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26848b8605Smrg * DEALINGS IN THE SOFTWARE.
27848b8605Smrg *
28848b8605Smrg **************************************************************************/
29848b8605Smrg
30848b8605Smrg
31848b8605Smrg#include <assert.h>
32848b8605Smrg#include <stdlib.h>
33848b8605Smrg#include <string.h>
34848b8605Smrg#include "eglconfig.h"
35848b8605Smrg#include "eglcontext.h"
36848b8605Smrg#include "egldisplay.h"
37848b8605Smrg#include "eglcurrent.h"
38848b8605Smrg#include "eglsurface.h"
39848b8605Smrg#include "egllog.h"
40848b8605Smrg
41848b8605Smrg
42848b8605Smrg/**
43848b8605Smrg * Return the API bit (one of EGL_xxx_BIT) of the context.
44848b8605Smrg */
45848b8605Smrgstatic EGLint
46848b8605Smrg_eglGetContextAPIBit(_EGLContext *ctx)
47848b8605Smrg{
48848b8605Smrg   EGLint bit = 0;
49848b8605Smrg
50848b8605Smrg   switch (ctx->ClientAPI) {
51848b8605Smrg   case EGL_OPENGL_ES_API:
52848b8605Smrg      switch (ctx->ClientMajorVersion) {
53848b8605Smrg      case 1:
54848b8605Smrg         bit = EGL_OPENGL_ES_BIT;
55848b8605Smrg         break;
56848b8605Smrg      case 2:
57848b8605Smrg         bit = EGL_OPENGL_ES2_BIT;
58848b8605Smrg         break;
59848b8605Smrg      case 3:
60848b8605Smrg         bit = EGL_OPENGL_ES3_BIT_KHR;
61848b8605Smrg         break;
62848b8605Smrg      default:
63848b8605Smrg         break;
64848b8605Smrg      }
65848b8605Smrg      break;
66848b8605Smrg   case EGL_OPENVG_API:
67848b8605Smrg      bit = EGL_OPENVG_BIT;
68848b8605Smrg      break;
69848b8605Smrg   case EGL_OPENGL_API:
70848b8605Smrg      bit = EGL_OPENGL_BIT;
71848b8605Smrg      break;
72848b8605Smrg   default:
73848b8605Smrg      break;
74848b8605Smrg   }
75848b8605Smrg
76848b8605Smrg   return bit;
77848b8605Smrg}
78848b8605Smrg
79848b8605Smrg
80848b8605Smrg/**
81848b8605Smrg * Parse the list of context attributes and return the proper error code.
82848b8605Smrg */
83848b8605Smrgstatic EGLint
84848b8605Smrg_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
85848b8605Smrg                           const EGLint *attrib_list)
86848b8605Smrg{
87848b8605Smrg   EGLenum api = ctx->ClientAPI;
88848b8605Smrg   EGLint i, err = EGL_SUCCESS;
89848b8605Smrg
90848b8605Smrg   if (!attrib_list)
91848b8605Smrg      return EGL_SUCCESS;
92848b8605Smrg
93848b8605Smrg   if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) {
94848b8605Smrg      _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]);
95848b8605Smrg      return EGL_BAD_ATTRIBUTE;
96848b8605Smrg   }
97848b8605Smrg
98848b8605Smrg   for (i = 0; attrib_list[i] != EGL_NONE; i++) {
99848b8605Smrg      EGLint attr = attrib_list[i++];
100848b8605Smrg      EGLint val = attrib_list[i];
101848b8605Smrg
102848b8605Smrg      switch (attr) {
103848b8605Smrg      case EGL_CONTEXT_CLIENT_VERSION:
104848b8605Smrg         ctx->ClientMajorVersion = val;
105848b8605Smrg         break;
106848b8605Smrg
107848b8605Smrg      case EGL_CONTEXT_MINOR_VERSION_KHR:
108848b8605Smrg         if (!dpy->Extensions.KHR_create_context) {
109848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
110848b8605Smrg            break;
111848b8605Smrg         }
112848b8605Smrg
113848b8605Smrg         ctx->ClientMinorVersion = val;
114848b8605Smrg         break;
115848b8605Smrg
116848b8605Smrg      case EGL_CONTEXT_FLAGS_KHR:
117848b8605Smrg         if (!dpy->Extensions.KHR_create_context) {
118848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
119848b8605Smrg            break;
120848b8605Smrg         }
121848b8605Smrg
122848b8605Smrg         /* The EGL_KHR_create_context spec says:
123848b8605Smrg          *
124848b8605Smrg          *     "Flags are only defined for OpenGL context creation, and
125848b8605Smrg          *     specifying a flags value other than zero for other types of
126848b8605Smrg          *     contexts, including OpenGL ES contexts, will generate an
127848b8605Smrg          *     error."
128848b8605Smrg          */
129848b8605Smrg         if (api != EGL_OPENGL_API && val != 0) {
130848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
131848b8605Smrg            break;
132848b8605Smrg         }
133848b8605Smrg
134848b8605Smrg         ctx->Flags = val;
135848b8605Smrg         break;
136848b8605Smrg
137848b8605Smrg      case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
138848b8605Smrg         if (!dpy->Extensions.KHR_create_context) {
139848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
140848b8605Smrg            break;
141848b8605Smrg         }
142848b8605Smrg
143848b8605Smrg         /* The EGL_KHR_create_context spec says:
144848b8605Smrg          *
145848b8605Smrg          *     "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
146848b8605Smrg          *     OpenGL contexts, and specifying it for other types of
147848b8605Smrg          *     contexts, including OpenGL ES contexts, will generate an
148848b8605Smrg          *     error."
149848b8605Smrg          */
150848b8605Smrg         if (api != EGL_OPENGL_API) {
151848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
152848b8605Smrg            break;
153848b8605Smrg         }
154848b8605Smrg
155848b8605Smrg         ctx->Profile = val;
156848b8605Smrg         break;
157848b8605Smrg
158848b8605Smrg      case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
159848b8605Smrg         /* The EGL_KHR_create_context spec says:
160848b8605Smrg          *
161848b8605Smrg          *     "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
162848b8605Smrg          *     meaningful for OpenGL contexts, and specifying it for other
163848b8605Smrg          *     types of contexts, including OpenGL ES contexts, will generate
164848b8605Smrg          *     an error."
165848b8605Smrg          */
166848b8605Smrg           if (!dpy->Extensions.KHR_create_context
167848b8605Smrg               || api != EGL_OPENGL_API) {
168848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
169848b8605Smrg            break;
170848b8605Smrg         }
171848b8605Smrg
172848b8605Smrg         ctx->ResetNotificationStrategy = val;
173848b8605Smrg         break;
174848b8605Smrg
175848b8605Smrg      case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
176848b8605Smrg         /* The EGL_EXT_create_context_robustness spec says:
177848b8605Smrg          *
178848b8605Smrg          *     "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
179848b8605Smrg          *     meaningful for OpenGL ES contexts, and specifying it for other
180848b8605Smrg          *     types of contexts will generate an EGL_BAD_ATTRIBUTE error."
181848b8605Smrg          */
182848b8605Smrg         if (!dpy->Extensions.EXT_create_context_robustness
183848b8605Smrg             || api != EGL_OPENGL_ES_API) {
184848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
185848b8605Smrg            break;
186848b8605Smrg         }
187848b8605Smrg
188848b8605Smrg         ctx->ResetNotificationStrategy = val;
189848b8605Smrg         break;
190848b8605Smrg
191848b8605Smrg      case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
192848b8605Smrg         if (!dpy->Extensions.EXT_create_context_robustness) {
193848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
194848b8605Smrg            break;
195848b8605Smrg         }
196848b8605Smrg
197848b8605Smrg         ctx->Flags = EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
198848b8605Smrg         break;
199848b8605Smrg
200848b8605Smrg      default:
201848b8605Smrg         err = EGL_BAD_ATTRIBUTE;
202848b8605Smrg         break;
203848b8605Smrg      }
204848b8605Smrg
205848b8605Smrg      if (err != EGL_SUCCESS) {
206848b8605Smrg         _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
207848b8605Smrg         break;
208848b8605Smrg      }
209848b8605Smrg   }
210848b8605Smrg
211848b8605Smrg   if (api == EGL_OPENGL_API) {
212848b8605Smrg      /* The EGL_KHR_create_context spec says:
213848b8605Smrg       *
214848b8605Smrg       *     "If the requested OpenGL version is less than 3.2,
215848b8605Smrg       *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
216848b8605Smrg       *     functionality of the context is determined solely by the
217848b8605Smrg       *     requested version."
218848b8605Smrg       *
219848b8605Smrg       * Since the value is ignored, only validate the setting if the version
220848b8605Smrg       * is >= 3.2.
221848b8605Smrg       */
222848b8605Smrg      if (ctx->ClientMajorVersion >= 4
223848b8605Smrg          || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
224848b8605Smrg         switch (ctx->Profile) {
225848b8605Smrg         case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
226848b8605Smrg         case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
227848b8605Smrg            break;
228848b8605Smrg
229848b8605Smrg         default:
230848b8605Smrg            /* The EGL_KHR_create_context spec says:
231848b8605Smrg             *
232848b8605Smrg             *     "* If an OpenGL context is requested, the requested version
233848b8605Smrg             *        is greater than 3.2, and the value for attribute
234848b8605Smrg             *        EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
235848b8605Smrg             *        any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
236848b8605Smrg             *        and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has
237848b8605Smrg             *        more than one of these bits set; or if the implementation does
238848b8605Smrg             *        not support the requested profile, then an EGL_BAD_MATCH error
239848b8605Smrg             *        is generated."
240848b8605Smrg             */
241848b8605Smrg            err = EGL_BAD_MATCH;
242848b8605Smrg            break;
243848b8605Smrg         }
244848b8605Smrg      }
245848b8605Smrg
246848b8605Smrg      /* The EGL_KHR_create_context spec says:
247848b8605Smrg       *
248848b8605Smrg       *     "* If an OpenGL context is requested and the values for
249848b8605Smrg       *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
250848b8605Smrg       *        EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
251848b8605Smrg       *        the value for attribute
252848b8605Smrg       *        EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
253848b8605Smrg       *        version and feature set that are not defined, than an
254848b8605Smrg       *        EGL_BAD_MATCH error is generated.
255848b8605Smrg       *
256848b8605Smrg       *        ... Thus, examples of invalid combinations of attributes
257848b8605Smrg       *        include:
258848b8605Smrg       *
259848b8605Smrg       *          - Major version < 1 or > 4
260848b8605Smrg       *          - Major version == 1 and minor version < 0 or > 5
261848b8605Smrg       *          - Major version == 2 and minor version < 0 or > 1
262848b8605Smrg       *          - Major version == 3 and minor version < 0 or > 2
263848b8605Smrg       *          - Major version == 4 and minor version < 0 or > 2
264848b8605Smrg       *          - Forward-compatible flag set and major version < 3"
265848b8605Smrg       */
266848b8605Smrg      if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
267848b8605Smrg         err = EGL_BAD_MATCH;
268848b8605Smrg
269848b8605Smrg      switch (ctx->ClientMajorVersion) {
270848b8605Smrg      case 1:
271848b8605Smrg         if (ctx->ClientMinorVersion > 5
272848b8605Smrg             || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
273848b8605Smrg            err = EGL_BAD_MATCH;
274848b8605Smrg         break;
275848b8605Smrg
276848b8605Smrg      case 2:
277848b8605Smrg         if (ctx->ClientMinorVersion > 1
278848b8605Smrg             || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
279848b8605Smrg            err = EGL_BAD_MATCH;
280848b8605Smrg         break;
281848b8605Smrg
282848b8605Smrg      case 3:
283848b8605Smrg         /* Note: The text above is incorrect.  There *is* an OpenGL 3.3!
284848b8605Smrg          */
285848b8605Smrg         if (ctx->ClientMinorVersion > 3)
286848b8605Smrg            err = EGL_BAD_MATCH;
287848b8605Smrg         break;
288848b8605Smrg
289848b8605Smrg      case 4:
290848b8605Smrg      default:
291848b8605Smrg         /* Don't put additional version checks here.  We don't know that
292848b8605Smrg          * there won't be versions > 4.2.
293848b8605Smrg          */
294848b8605Smrg         break;
295848b8605Smrg      }
296848b8605Smrg   } else if (api == EGL_OPENGL_ES_API) {
297848b8605Smrg      /* The EGL_KHR_create_context spec says:
298848b8605Smrg       *
299848b8605Smrg       *     "* If an OpenGL ES context is requested and the values for
300848b8605Smrg       *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
301848b8605Smrg       *        EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
302848b8605Smrg       *        is not defined, than an EGL_BAD_MATCH error is generated.
303848b8605Smrg       *
304848b8605Smrg       *        ... Examples of invalid combinations of attributes include:
305848b8605Smrg       *
306848b8605Smrg       *          - Major version < 1 or > 2
307848b8605Smrg       *          - Major version == 1 and minor version < 0 or > 1
308848b8605Smrg       *          - Major version == 2 and minor version != 0
309848b8605Smrg       */
310848b8605Smrg      if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
311848b8605Smrg         err = EGL_BAD_MATCH;
312848b8605Smrg
313848b8605Smrg      switch (ctx->ClientMajorVersion) {
314848b8605Smrg      case 1:
315848b8605Smrg         if (ctx->ClientMinorVersion > 1)
316848b8605Smrg            err = EGL_BAD_MATCH;
317848b8605Smrg         break;
318848b8605Smrg
319848b8605Smrg      case 2:
320848b8605Smrg         if (ctx->ClientMinorVersion > 0)
321848b8605Smrg            err = EGL_BAD_MATCH;
322848b8605Smrg         break;
323848b8605Smrg
324848b8605Smrg      case 3:
325848b8605Smrg         /* Don't put additional version checks here.  We don't know that
326848b8605Smrg          * there won't be versions > 3.0.
327848b8605Smrg          */
328848b8605Smrg         break;
329848b8605Smrg
330848b8605Smrg      default:
331848b8605Smrg         err = EGL_BAD_MATCH;
332848b8605Smrg         break;
333848b8605Smrg      }
334848b8605Smrg   }
335848b8605Smrg
336848b8605Smrg   switch (ctx->ResetNotificationStrategy) {
337848b8605Smrg   case EGL_NO_RESET_NOTIFICATION_KHR:
338848b8605Smrg   case EGL_LOSE_CONTEXT_ON_RESET_KHR:
339848b8605Smrg      break;
340848b8605Smrg
341848b8605Smrg   default:
342848b8605Smrg      err = EGL_BAD_ATTRIBUTE;
343848b8605Smrg      break;
344848b8605Smrg   }
345848b8605Smrg
346848b8605Smrg   if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
347848b8605Smrg                      | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
348848b8605Smrg                      | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
349848b8605Smrg      err = EGL_BAD_ATTRIBUTE;
350848b8605Smrg   }
351848b8605Smrg
352848b8605Smrg   return err;
353848b8605Smrg}
354848b8605Smrg
355848b8605Smrg
356848b8605Smrg/**
357848b8605Smrg * Initialize the given _EGLContext object to defaults and/or the values
358848b8605Smrg * in the attrib_list.
359848b8605Smrg */
360848b8605SmrgEGLBoolean
361848b8605Smrg_eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
362848b8605Smrg                const EGLint *attrib_list)
363848b8605Smrg{
364848b8605Smrg   const EGLenum api = eglQueryAPI();
365848b8605Smrg   EGLint err;
366848b8605Smrg
367848b8605Smrg   if (api == EGL_NONE) {
368848b8605Smrg      _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
369848b8605Smrg      return EGL_FALSE;
370848b8605Smrg   }
371848b8605Smrg
372848b8605Smrg   _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
373848b8605Smrg   ctx->ClientAPI = api;
374848b8605Smrg   ctx->Config = conf;
375848b8605Smrg   ctx->WindowRenderBuffer = EGL_NONE;
376848b8605Smrg   ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
377848b8605Smrg
378848b8605Smrg   ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
379848b8605Smrg   ctx->ClientMinorVersion = 0;
380848b8605Smrg   ctx->Flags = 0;
381848b8605Smrg   ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
382848b8605Smrg   ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
383848b8605Smrg
384848b8605Smrg   err = _eglParseContextAttribList(ctx, dpy, attrib_list);
385848b8605Smrg   if (err == EGL_SUCCESS && ctx->Config) {
386848b8605Smrg      EGLint api_bit;
387848b8605Smrg
388848b8605Smrg      api_bit = _eglGetContextAPIBit(ctx);
389848b8605Smrg      if (!(ctx->Config->RenderableType & api_bit)) {
390848b8605Smrg         _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
391848b8605Smrg               api_bit, ctx->Config->RenderableType);
392848b8605Smrg         err = EGL_BAD_CONFIG;
393848b8605Smrg      }
394848b8605Smrg   }
395848b8605Smrg   if (err != EGL_SUCCESS)
396848b8605Smrg      return _eglError(err, "eglCreateContext");
397848b8605Smrg
398848b8605Smrg   return EGL_TRUE;
399848b8605Smrg}
400848b8605Smrg
401848b8605Smrg
402848b8605Smrgstatic EGLint
403848b8605Smrg_eglQueryContextRenderBuffer(_EGLContext *ctx)
404848b8605Smrg{
405848b8605Smrg   _EGLSurface *surf = ctx->DrawSurface;
406848b8605Smrg   EGLint rb;
407848b8605Smrg
408848b8605Smrg   if (!surf)
409848b8605Smrg      return EGL_NONE;
410848b8605Smrg   if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
411848b8605Smrg      rb = ctx->WindowRenderBuffer;
412848b8605Smrg   else
413848b8605Smrg      rb = surf->RenderBuffer;
414848b8605Smrg   return rb;
415848b8605Smrg}
416848b8605Smrg
417848b8605Smrg
418848b8605SmrgEGLBoolean
419848b8605Smrg_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
420848b8605Smrg                 EGLint attribute, EGLint *value)
421848b8605Smrg{
422848b8605Smrg   (void) drv;
423848b8605Smrg   (void) dpy;
424848b8605Smrg
425848b8605Smrg   if (!value)
426848b8605Smrg      return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
427848b8605Smrg
428848b8605Smrg   switch (attribute) {
429848b8605Smrg   case EGL_CONFIG_ID:
430848b8605Smrg      if (!c->Config)
431848b8605Smrg         return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
432848b8605Smrg      *value = c->Config->ConfigID;
433848b8605Smrg      break;
434848b8605Smrg   case EGL_CONTEXT_CLIENT_VERSION:
435848b8605Smrg      *value = c->ClientMajorVersion;
436848b8605Smrg      break;
437848b8605Smrg   case EGL_CONTEXT_CLIENT_TYPE:
438848b8605Smrg      *value = c->ClientAPI;
439848b8605Smrg      break;
440848b8605Smrg   case EGL_RENDER_BUFFER:
441848b8605Smrg      *value = _eglQueryContextRenderBuffer(c);
442848b8605Smrg      break;
443848b8605Smrg   default:
444848b8605Smrg      return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
445848b8605Smrg   }
446848b8605Smrg
447848b8605Smrg   return EGL_TRUE;
448848b8605Smrg}
449848b8605Smrg
450848b8605Smrg
451848b8605Smrg/**
452848b8605Smrg * Bind the context to the thread and return the previous context.
453848b8605Smrg *
454848b8605Smrg * Note that the context may be NULL.
455848b8605Smrg */
456848b8605Smrgstatic _EGLContext *
457848b8605Smrg_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
458848b8605Smrg{
459848b8605Smrg   EGLint apiIndex;
460848b8605Smrg   _EGLContext *oldCtx;
461848b8605Smrg
462848b8605Smrg   apiIndex = (ctx) ?
463848b8605Smrg      _eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex;
464848b8605Smrg
465848b8605Smrg   oldCtx = t->CurrentContexts[apiIndex];
466848b8605Smrg   if (ctx != oldCtx) {
467848b8605Smrg      if (oldCtx)
468848b8605Smrg         oldCtx->Binding = NULL;
469848b8605Smrg      if (ctx)
470848b8605Smrg         ctx->Binding = t;
471848b8605Smrg
472848b8605Smrg      t->CurrentContexts[apiIndex] = ctx;
473848b8605Smrg   }
474848b8605Smrg
475848b8605Smrg   return oldCtx;
476848b8605Smrg}
477848b8605Smrg
478848b8605Smrg
479848b8605Smrg/**
480848b8605Smrg * Return true if the given context and surfaces can be made current.
481848b8605Smrg */
482848b8605Smrgstatic EGLBoolean
483848b8605Smrg_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
484848b8605Smrg{
485848b8605Smrg   _EGLThreadInfo *t = _eglGetCurrentThread();
486848b8605Smrg   _EGLDisplay *dpy;
487848b8605Smrg   EGLint conflict_api;
488848b8605Smrg
489848b8605Smrg   if (_eglIsCurrentThreadDummy())
490848b8605Smrg      return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
491848b8605Smrg
492848b8605Smrg   /* this is easy */
493848b8605Smrg   if (!ctx) {
494848b8605Smrg      if (draw || read)
495848b8605Smrg         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
496848b8605Smrg      return EGL_TRUE;
497848b8605Smrg   }
498848b8605Smrg
499848b8605Smrg   dpy = ctx->Resource.Display;
500848b8605Smrg   if (!dpy->Extensions.KHR_surfaceless_context
501848b8605Smrg       && (draw == NULL || read == NULL))
502848b8605Smrg      return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
503848b8605Smrg
504848b8605Smrg   /*
505848b8605Smrg    * The spec says
506848b8605Smrg    *
507848b8605Smrg    * "If ctx is current to some other thread, or if either draw or read are
508848b8605Smrg    * bound to contexts in another thread, an EGL_BAD_ACCESS error is
509848b8605Smrg    * generated."
510848b8605Smrg    *
511848b8605Smrg    * and
512848b8605Smrg    *
513848b8605Smrg    * "at most one context may be bound to a particular surface at a given
514848b8605Smrg    * time"
515848b8605Smrg    */
516848b8605Smrg   if (ctx->Binding && ctx->Binding != t)
517848b8605Smrg      return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
518848b8605Smrg   if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
519848b8605Smrg      if (draw->CurrentContext->Binding != t ||
520848b8605Smrg          draw->CurrentContext->ClientAPI != ctx->ClientAPI)
521848b8605Smrg         return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
522848b8605Smrg   }
523848b8605Smrg   if (read && read->CurrentContext && read->CurrentContext != ctx) {
524848b8605Smrg      if (read->CurrentContext->Binding != t ||
525848b8605Smrg          read->CurrentContext->ClientAPI != ctx->ClientAPI)
526848b8605Smrg         return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
527848b8605Smrg   }
528848b8605Smrg
529848b8605Smrg   /* If the context has a config then it must match that of the two
530848b8605Smrg    * surfaces */
531848b8605Smrg   if (ctx->Config) {
532848b8605Smrg      if ((draw && draw->Config != ctx->Config) ||
533848b8605Smrg          (read && read->Config != ctx->Config))
534848b8605Smrg         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
535848b8605Smrg   } else {
536848b8605Smrg      /* Otherwise we must be using the EGL_MESA_configless_context
537848b8605Smrg       * extension */
538848b8605Smrg      assert(dpy->Extensions.MESA_configless_context);
539848b8605Smrg
540848b8605Smrg      /* The extension doesn't permit binding draw and read buffers with
541848b8605Smrg       * differing contexts */
542848b8605Smrg      if (draw && read && draw->Config != read->Config)
543848b8605Smrg         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
544848b8605Smrg   }
545848b8605Smrg
546848b8605Smrg   switch (ctx->ClientAPI) {
547848b8605Smrg   /* OpenGL and OpenGL ES are conflicting */
548848b8605Smrg   case EGL_OPENGL_ES_API:
549848b8605Smrg      conflict_api = EGL_OPENGL_API;
550848b8605Smrg      break;
551848b8605Smrg   case EGL_OPENGL_API:
552848b8605Smrg      conflict_api = EGL_OPENGL_ES_API;
553848b8605Smrg      break;
554848b8605Smrg   default:
555848b8605Smrg      conflict_api = -1;
556848b8605Smrg      break;
557848b8605Smrg   }
558848b8605Smrg
559848b8605Smrg   if (conflict_api >= 0 && _eglGetAPIContext(conflict_api))
560848b8605Smrg      return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
561848b8605Smrg
562848b8605Smrg   return EGL_TRUE;
563848b8605Smrg}
564848b8605Smrg
565848b8605Smrg
566848b8605Smrg/**
567848b8605Smrg * Bind the context to the current thread and given surfaces.  Return the
568848b8605Smrg * previous bound context and surfaces.  The caller should unreference the
569848b8605Smrg * returned context and surfaces.
570848b8605Smrg *
571848b8605Smrg * Making a second call with the resources returned by the first call
572848b8605Smrg * unsurprisingly undoes the first call, except for the resouce reference
573848b8605Smrg * counts.
574848b8605Smrg */
575848b8605SmrgEGLBoolean
576848b8605Smrg_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
577848b8605Smrg                _EGLContext **old_ctx,
578848b8605Smrg                _EGLSurface **old_draw, _EGLSurface **old_read)
579848b8605Smrg{
580848b8605Smrg   _EGLThreadInfo *t = _eglGetCurrentThread();
581848b8605Smrg   _EGLContext *prev_ctx;
582848b8605Smrg   _EGLSurface *prev_draw, *prev_read;
583848b8605Smrg
584848b8605Smrg   if (!_eglCheckMakeCurrent(ctx, draw, read))
585848b8605Smrg      return EGL_FALSE;
586848b8605Smrg
587848b8605Smrg   /* increment refcounts before binding */
588848b8605Smrg   _eglGetContext(ctx);
589848b8605Smrg   _eglGetSurface(draw);
590848b8605Smrg   _eglGetSurface(read);
591848b8605Smrg
592848b8605Smrg   /* bind the new context */
593848b8605Smrg   prev_ctx = _eglBindContextToThread(ctx, t);
594848b8605Smrg
595848b8605Smrg   /* break previous bindings */
596848b8605Smrg   if (prev_ctx) {
597848b8605Smrg      prev_draw = prev_ctx->DrawSurface;
598848b8605Smrg      prev_read = prev_ctx->ReadSurface;
599848b8605Smrg
600848b8605Smrg      if (prev_draw)
601848b8605Smrg         prev_draw->CurrentContext = NULL;
602848b8605Smrg      if (prev_read)
603848b8605Smrg         prev_read->CurrentContext = NULL;
604848b8605Smrg
605848b8605Smrg      prev_ctx->DrawSurface = NULL;
606848b8605Smrg      prev_ctx->ReadSurface = NULL;
607848b8605Smrg   }
608848b8605Smrg   else {
609848b8605Smrg      prev_draw = prev_read = NULL;
610848b8605Smrg   }
611848b8605Smrg
612848b8605Smrg   /* establish new bindings */
613848b8605Smrg   if (ctx) {
614848b8605Smrg      if (draw)
615848b8605Smrg         draw->CurrentContext = ctx;
616848b8605Smrg      if (read)
617848b8605Smrg         read->CurrentContext = ctx;
618848b8605Smrg
619848b8605Smrg      ctx->DrawSurface = draw;
620848b8605Smrg      ctx->ReadSurface = read;
621848b8605Smrg   }
622848b8605Smrg
623848b8605Smrg   assert(old_ctx && old_draw && old_read);
624848b8605Smrg   *old_ctx = prev_ctx;
625848b8605Smrg   *old_draw = prev_draw;
626848b8605Smrg   *old_read = prev_read;
627848b8605Smrg
628848b8605Smrg   return EGL_TRUE;
629848b8605Smrg}
630