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"
40b8e80941Smrg#include "util/macros.h"
41848b8605Smrg
42848b8605Smrg
43848b8605Smrg/**
44848b8605Smrg * Return the API bit (one of EGL_xxx_BIT) of the context.
45848b8605Smrg */
46848b8605Smrgstatic EGLint
47848b8605Smrg_eglGetContextAPIBit(_EGLContext *ctx)
48848b8605Smrg{
49848b8605Smrg   EGLint bit = 0;
50848b8605Smrg
51848b8605Smrg   switch (ctx->ClientAPI) {
52848b8605Smrg   case EGL_OPENGL_ES_API:
53848b8605Smrg      switch (ctx->ClientMajorVersion) {
54848b8605Smrg      case 1:
55848b8605Smrg         bit = EGL_OPENGL_ES_BIT;
56848b8605Smrg         break;
57848b8605Smrg      case 2:
58848b8605Smrg         bit = EGL_OPENGL_ES2_BIT;
59848b8605Smrg         break;
60848b8605Smrg      case 3:
61848b8605Smrg         bit = EGL_OPENGL_ES3_BIT_KHR;
62848b8605Smrg         break;
63848b8605Smrg      default:
64848b8605Smrg         break;
65848b8605Smrg      }
66848b8605Smrg      break;
67848b8605Smrg   case EGL_OPENVG_API:
68848b8605Smrg      bit = EGL_OPENVG_BIT;
69848b8605Smrg      break;
70848b8605Smrg   case EGL_OPENGL_API:
71848b8605Smrg      bit = EGL_OPENGL_BIT;
72848b8605Smrg      break;
73848b8605Smrg   default:
74848b8605Smrg      break;
75848b8605Smrg   }
76848b8605Smrg
77848b8605Smrg   return bit;
78848b8605Smrg}
79848b8605Smrg
80848b8605Smrg
81848b8605Smrg/**
82848b8605Smrg * Parse the list of context attributes and return the proper error code.
83848b8605Smrg */
84848b8605Smrgstatic EGLint
85b8e80941Smrg_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *disp,
86848b8605Smrg                           const EGLint *attrib_list)
87848b8605Smrg{
88848b8605Smrg   EGLenum api = ctx->ClientAPI;
89848b8605Smrg   EGLint i, err = EGL_SUCCESS;
90848b8605Smrg
91848b8605Smrg   if (!attrib_list)
92848b8605Smrg      return EGL_SUCCESS;
93848b8605Smrg
94848b8605Smrg   if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) {
95848b8605Smrg      _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]);
96848b8605Smrg      return EGL_BAD_ATTRIBUTE;
97848b8605Smrg   }
98848b8605Smrg
99848b8605Smrg   for (i = 0; attrib_list[i] != EGL_NONE; i++) {
100848b8605Smrg      EGLint attr = attrib_list[i++];
101848b8605Smrg      EGLint val = attrib_list[i];
102848b8605Smrg
103848b8605Smrg      switch (attr) {
104848b8605Smrg      case EGL_CONTEXT_CLIENT_VERSION:
105b8e80941Smrg         /* The EGL 1.4 spec says:
106b8e80941Smrg          *
107b8e80941Smrg          *     "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the
108b8e80941Smrg          *      current rendering API is EGL_OPENGL_ES_API"
109b8e80941Smrg          *
110b8e80941Smrg          * The EGL_KHR_create_context spec says:
111b8e80941Smrg          *
112b8e80941Smrg          *     "EGL_CONTEXT_MAJOR_VERSION_KHR           0x3098
113b8e80941Smrg          *      (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)"
114b8e80941Smrg          *
115b8e80941Smrg          *     "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
116b8e80941Smrg          *      EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
117b8e80941Smrg          *      version. They are only meaningful for OpenGL and OpenGL ES
118b8e80941Smrg          *      contexts, and specifying them for other types of contexts will
119b8e80941Smrg          *      generate an error."
120b8e80941Smrg          */
121b8e80941Smrg         if ((api != EGL_OPENGL_ES_API &&
122b8e80941Smrg             (!disp->Extensions.KHR_create_context || api != EGL_OPENGL_API))) {
123b8e80941Smrg               err = EGL_BAD_ATTRIBUTE;
124b8e80941Smrg               break;
125b8e80941Smrg         }
126b8e80941Smrg
127848b8605Smrg         ctx->ClientMajorVersion = val;
128848b8605Smrg         break;
129848b8605Smrg
130848b8605Smrg      case EGL_CONTEXT_MINOR_VERSION_KHR:
131b8e80941Smrg         /* The EGL_KHR_create_context spec says:
132b8e80941Smrg          *
133b8e80941Smrg          *     "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
134b8e80941Smrg          *      EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
135b8e80941Smrg          *      version. They are only meaningful for OpenGL and OpenGL ES
136b8e80941Smrg          *      contexts, and specifying them for other types of contexts will
137b8e80941Smrg          *      generate an error."
138b8e80941Smrg          */
139b8e80941Smrg         if (!disp->Extensions.KHR_create_context ||
140b8e80941Smrg             (api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) {
141848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
142848b8605Smrg            break;
143848b8605Smrg         }
144848b8605Smrg
145848b8605Smrg         ctx->ClientMinorVersion = val;
146848b8605Smrg         break;
147848b8605Smrg
148848b8605Smrg      case EGL_CONTEXT_FLAGS_KHR:
149b8e80941Smrg         if (!disp->Extensions.KHR_create_context) {
150848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
151848b8605Smrg            break;
152848b8605Smrg         }
153848b8605Smrg
154848b8605Smrg         /* The EGL_KHR_create_context spec says:
155848b8605Smrg          *
156b8e80941Smrg          *     "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in
157b8e80941Smrg          *     EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.
158b8e80941Smrg          *     [...]
159b8e80941Smrg          *     In some cases a debug context may be identical to a non-debug
160b8e80941Smrg          *     context. This bit is supported for OpenGL and OpenGL ES
161b8e80941Smrg          *     contexts."
162b8e80941Smrg          */
163b8e80941Smrg         if ((val & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) &&
164b8e80941Smrg             (api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API)) {
165b8e80941Smrg            err = EGL_BAD_ATTRIBUTE;
166b8e80941Smrg            break;
167b8e80941Smrg         }
168b8e80941Smrg
169b8e80941Smrg         /* The EGL_KHR_create_context spec says:
170b8e80941Smrg          *
171b8e80941Smrg          *     "If the EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR flag bit
172b8e80941Smrg          *     is set in EGL_CONTEXT_FLAGS_KHR, then a <forward-compatible>
173b8e80941Smrg          *     context will be created. Forward-compatible contexts are
174b8e80941Smrg          *     defined only for OpenGL versions 3.0 and later. They must not
175b8e80941Smrg          *     support functionality marked as <deprecated> by that version of
176b8e80941Smrg          *     the API, while a non-forward-compatible context must support
177b8e80941Smrg          *     all functionality in that version, deprecated or not. This bit
178b8e80941Smrg          *     is supported for OpenGL contexts, and requesting a
179b8e80941Smrg          *     forward-compatible context for OpenGL versions less than 3.0
180b8e80941Smrg          *     will generate an error."
181b8e80941Smrg          *
182b8e80941Smrg          * Note: since the forward-compatible flag can be set more than one way,
183b8e80941Smrg          *       the OpenGL version check is performed once, below.
184848b8605Smrg          */
185b8e80941Smrg         if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) &&
186b8e80941Smrg              api != EGL_OPENGL_API) {
187b8e80941Smrg            err = EGL_BAD_ATTRIBUTE;
188b8e80941Smrg            break;
189b8e80941Smrg         }
190b8e80941Smrg
191b8e80941Smrg         if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
192b8e80941Smrg             api != EGL_OPENGL_API) {
193b8e80941Smrg            /* The EGL_KHR_create_context spec says:
194b8e80941Smrg             *
195b8e80941Smrg             *   10) Which error should be generated if robust buffer access
196b8e80941Smrg             *       or reset notifications are requested under OpenGL ES?
197b8e80941Smrg             *
198b8e80941Smrg             *       As per Issue 6, this extension does not support creating
199b8e80941Smrg             *       robust contexts for OpenGL ES. This is only supported via
200b8e80941Smrg             *       the EGL_EXT_create_context_robustness extension.
201b8e80941Smrg             *
202b8e80941Smrg             *       Attempting to use this extension to create robust OpenGL
203b8e80941Smrg             *       ES context will generate an EGL_BAD_ATTRIBUTE error. This
204b8e80941Smrg             *       specific error is generated because this extension does
205b8e80941Smrg             *       not define the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
206b8e80941Smrg             *       and EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
207b8e80941Smrg             *       bits for OpenGL ES contexts. Thus, use of these bits fall
208b8e80941Smrg             *       under condition described by: "If an attribute is
209b8e80941Smrg             *       specified that is not meaningful for the client API
210b8e80941Smrg             *       type.." in the above specification.
211b8e80941Smrg             *
212b8e80941Smrg             * The spec requires that we emit the error even if the display
213b8e80941Smrg             * supports EGL_EXT_create_context_robustness. To create a robust
214b8e80941Smrg             * GLES context, the *attribute*
215b8e80941Smrg             * EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT must be used, not the
216b8e80941Smrg             * *flag* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR.
217b8e80941Smrg             */
218848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
219848b8605Smrg            break;
220848b8605Smrg         }
221848b8605Smrg
222b8e80941Smrg         ctx->Flags |= val;
223848b8605Smrg         break;
224848b8605Smrg
225848b8605Smrg      case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
226b8e80941Smrg         if (!disp->Extensions.KHR_create_context) {
227848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
228848b8605Smrg            break;
229848b8605Smrg         }
230848b8605Smrg
231848b8605Smrg         /* The EGL_KHR_create_context spec says:
232848b8605Smrg          *
233848b8605Smrg          *     "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
234848b8605Smrg          *     OpenGL contexts, and specifying it for other types of
235848b8605Smrg          *     contexts, including OpenGL ES contexts, will generate an
236848b8605Smrg          *     error."
237848b8605Smrg          */
238848b8605Smrg         if (api != EGL_OPENGL_API) {
239848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
240848b8605Smrg            break;
241848b8605Smrg         }
242848b8605Smrg
243848b8605Smrg         ctx->Profile = val;
244848b8605Smrg         break;
245848b8605Smrg
246848b8605Smrg      case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
247848b8605Smrg         /* The EGL_KHR_create_context spec says:
248848b8605Smrg          *
249848b8605Smrg          *     "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
250848b8605Smrg          *     meaningful for OpenGL contexts, and specifying it for other
251848b8605Smrg          *     types of contexts, including OpenGL ES contexts, will generate
252848b8605Smrg          *     an error."
253848b8605Smrg          */
254b8e80941Smrg           if (!disp->Extensions.KHR_create_context
255848b8605Smrg               || api != EGL_OPENGL_API) {
256848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
257848b8605Smrg            break;
258848b8605Smrg         }
259848b8605Smrg
260848b8605Smrg         ctx->ResetNotificationStrategy = val;
261848b8605Smrg         break;
262848b8605Smrg
263848b8605Smrg      case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
264848b8605Smrg         /* The EGL_EXT_create_context_robustness spec says:
265848b8605Smrg          *
266848b8605Smrg          *     "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
267848b8605Smrg          *     meaningful for OpenGL ES contexts, and specifying it for other
268848b8605Smrg          *     types of contexts will generate an EGL_BAD_ATTRIBUTE error."
269848b8605Smrg          */
270b8e80941Smrg         if (!disp->Extensions.EXT_create_context_robustness
271848b8605Smrg             || api != EGL_OPENGL_ES_API) {
272848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
273848b8605Smrg            break;
274848b8605Smrg         }
275848b8605Smrg
276848b8605Smrg         ctx->ResetNotificationStrategy = val;
277848b8605Smrg         break;
278848b8605Smrg
279848b8605Smrg      case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
280b8e80941Smrg         if (!disp->Extensions.EXT_create_context_robustness) {
281b8e80941Smrg            err = EGL_BAD_ATTRIBUTE;
282b8e80941Smrg            break;
283b8e80941Smrg         }
284b8e80941Smrg
285b8e80941Smrg         if (val == EGL_TRUE)
286b8e80941Smrg            ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
287b8e80941Smrg         break;
288b8e80941Smrg
289b8e80941Smrg      case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:
290b8e80941Smrg         if (disp->Version < 15) {
291b8e80941Smrg            err = EGL_BAD_ATTRIBUTE;
292b8e80941Smrg            break;
293b8e80941Smrg         }
294b8e80941Smrg
295b8e80941Smrg         if (val == EGL_TRUE)
296b8e80941Smrg            ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
297b8e80941Smrg         break;
298b8e80941Smrg
299b8e80941Smrg      case EGL_CONTEXT_OPENGL_DEBUG:
300b8e80941Smrg         if (disp->Version < 15) {
301848b8605Smrg            err = EGL_BAD_ATTRIBUTE;
302848b8605Smrg            break;
303848b8605Smrg         }
304848b8605Smrg
305b8e80941Smrg         if (val == EGL_TRUE)
306b8e80941Smrg            ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
307b8e80941Smrg         break;
308b8e80941Smrg
309b8e80941Smrg      case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:
310b8e80941Smrg         if (disp->Version < 15) {
311b8e80941Smrg            err = EGL_BAD_ATTRIBUTE;
312b8e80941Smrg            break;
313b8e80941Smrg         }
314b8e80941Smrg
315b8e80941Smrg         if (val == EGL_TRUE)
316b8e80941Smrg            ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
317b8e80941Smrg         break;
318b8e80941Smrg
319b8e80941Smrg      case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
320b8e80941Smrg         if (disp->Version < 14 ||
321b8e80941Smrg             !disp->Extensions.KHR_create_context_no_error) {
322b8e80941Smrg            err = EGL_BAD_ATTRIBUTE;
323b8e80941Smrg            break;
324b8e80941Smrg         }
325b8e80941Smrg
326b8e80941Smrg         /* The KHR_no_error spec only applies against OpenGL 2.0+ and
327b8e80941Smrg          * OpenGL ES 2.0+
328b8e80941Smrg          */
329b8e80941Smrg         if ((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) ||
330b8e80941Smrg             ctx->ClientMajorVersion < 2) {
331b8e80941Smrg            err = EGL_BAD_ATTRIBUTE;
332b8e80941Smrg            break;
333b8e80941Smrg         }
334b8e80941Smrg
335b8e80941Smrg         /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */
336b8e80941Smrg         ctx->NoError = !!val;
337b8e80941Smrg         break;
338b8e80941Smrg
339b8e80941Smrg      case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
340b8e80941Smrg         /* The  EGL_IMG_context_priority spec says:
341b8e80941Smrg          *
342b8e80941Smrg          * "EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of
343b8e80941Smrg          * the context to be created. This attribute is a hint, as an
344b8e80941Smrg          * implementation may not support multiple contexts at some
345b8e80941Smrg          * priority levels and system policy may limit access to high
346b8e80941Smrg          * priority contexts to appropriate system privilege level. The
347b8e80941Smrg          * default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is
348b8e80941Smrg          * EGL_CONTEXT_PRIORITY_MEDIUM_IMG."
349b8e80941Smrg          */
350b8e80941Smrg         {
351b8e80941Smrg            int bit;
352b8e80941Smrg
353b8e80941Smrg            switch (val) {
354b8e80941Smrg            case EGL_CONTEXT_PRIORITY_HIGH_IMG:
355b8e80941Smrg               bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT;
356b8e80941Smrg               break;
357b8e80941Smrg            case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
358b8e80941Smrg               bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT;
359b8e80941Smrg               break;
360b8e80941Smrg            case EGL_CONTEXT_PRIORITY_LOW_IMG:
361b8e80941Smrg               bit = __EGL_CONTEXT_PRIORITY_LOW_BIT;
362b8e80941Smrg               break;
363b8e80941Smrg            default:
364b8e80941Smrg               bit = -1;
365b8e80941Smrg               break;
366b8e80941Smrg            }
367b8e80941Smrg
368b8e80941Smrg            if (bit < 0) {
369b8e80941Smrg               err = EGL_BAD_ATTRIBUTE;
370b8e80941Smrg               break;
371b8e80941Smrg            }
372b8e80941Smrg
373b8e80941Smrg            /* "This extension allows an EGLContext to be created with a
374b8e80941Smrg             * priority hint. It is possible that an implementation will not
375b8e80941Smrg             * honour the hint, especially if there are constraints on the
376b8e80941Smrg             * number of high priority contexts available in the system, or
377b8e80941Smrg             * system policy limits access to high priority contexts to
378b8e80941Smrg             * appropriate system privilege level. A query is provided to find
379b8e80941Smrg             * the real priority level assigned to the context after creation."
380b8e80941Smrg             *
381b8e80941Smrg             * We currently assume that the driver applies the priority hint
382b8e80941Smrg             * and filters out any it cannot handle during the screen setup,
383b8e80941Smrg             * e.g. dri2_setup_screen(). As such we can mask any change that
384b8e80941Smrg             * the driver would fail, and ctx->ContextPriority matches the
385b8e80941Smrg             * hint applied to the driver/hardware backend.
386b8e80941Smrg             */
387b8e80941Smrg            if (disp->Extensions.IMG_context_priority & (1 << bit))
388b8e80941Smrg               ctx->ContextPriority = val;
389b8e80941Smrg
390b8e80941Smrg            break;
391b8e80941Smrg         }
392b8e80941Smrg
393b8e80941Smrg      case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR:
394b8e80941Smrg         if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR ||
395b8e80941Smrg             val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) {
396b8e80941Smrg            ctx->ReleaseBehavior = val;
397b8e80941Smrg         } else {
398b8e80941Smrg            err = EGL_BAD_ATTRIBUTE;
399b8e80941Smrg         }
400848b8605Smrg         break;
401848b8605Smrg
402848b8605Smrg      default:
403848b8605Smrg         err = EGL_BAD_ATTRIBUTE;
404848b8605Smrg         break;
405848b8605Smrg      }
406848b8605Smrg
407848b8605Smrg      if (err != EGL_SUCCESS) {
408848b8605Smrg         _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
409848b8605Smrg         break;
410848b8605Smrg      }
411848b8605Smrg   }
412848b8605Smrg
413848b8605Smrg   if (api == EGL_OPENGL_API) {
414848b8605Smrg      /* The EGL_KHR_create_context spec says:
415848b8605Smrg       *
416848b8605Smrg       *     "If the requested OpenGL version is less than 3.2,
417848b8605Smrg       *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
418848b8605Smrg       *     functionality of the context is determined solely by the
419848b8605Smrg       *     requested version."
420848b8605Smrg       *
421848b8605Smrg       * Since the value is ignored, only validate the setting if the version
422848b8605Smrg       * is >= 3.2.
423848b8605Smrg       */
424848b8605Smrg      if (ctx->ClientMajorVersion >= 4
425848b8605Smrg          || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
426848b8605Smrg         switch (ctx->Profile) {
427848b8605Smrg         case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
428848b8605Smrg         case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
429848b8605Smrg            break;
430848b8605Smrg
431848b8605Smrg         default:
432848b8605Smrg            /* The EGL_KHR_create_context spec says:
433848b8605Smrg             *
434848b8605Smrg             *     "* If an OpenGL context is requested, the requested version
435848b8605Smrg             *        is greater than 3.2, and the value for attribute
436848b8605Smrg             *        EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
437848b8605Smrg             *        any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
438848b8605Smrg             *        and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has
439848b8605Smrg             *        more than one of these bits set; or if the implementation does
440848b8605Smrg             *        not support the requested profile, then an EGL_BAD_MATCH error
441848b8605Smrg             *        is generated."
442848b8605Smrg             */
443848b8605Smrg            err = EGL_BAD_MATCH;
444848b8605Smrg            break;
445848b8605Smrg         }
446848b8605Smrg      }
447848b8605Smrg
448848b8605Smrg      /* The EGL_KHR_create_context spec says:
449848b8605Smrg       *
450848b8605Smrg       *     "* If an OpenGL context is requested and the values for
451848b8605Smrg       *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
452848b8605Smrg       *        EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
453848b8605Smrg       *        the value for attribute
454848b8605Smrg       *        EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
455848b8605Smrg       *        version and feature set that are not defined, than an
456848b8605Smrg       *        EGL_BAD_MATCH error is generated.
457848b8605Smrg       *
458848b8605Smrg       *        ... Thus, examples of invalid combinations of attributes
459848b8605Smrg       *        include:
460848b8605Smrg       *
461848b8605Smrg       *          - Major version < 1 or > 4
462848b8605Smrg       *          - Major version == 1 and minor version < 0 or > 5
463848b8605Smrg       *          - Major version == 2 and minor version < 0 or > 1
464848b8605Smrg       *          - Major version == 3 and minor version < 0 or > 2
465848b8605Smrg       *          - Major version == 4 and minor version < 0 or > 2
466848b8605Smrg       *          - Forward-compatible flag set and major version < 3"
467848b8605Smrg       */
468848b8605Smrg      if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
469848b8605Smrg         err = EGL_BAD_MATCH;
470848b8605Smrg
471848b8605Smrg      switch (ctx->ClientMajorVersion) {
472848b8605Smrg      case 1:
473848b8605Smrg         if (ctx->ClientMinorVersion > 5
474848b8605Smrg             || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
475848b8605Smrg            err = EGL_BAD_MATCH;
476848b8605Smrg         break;
477848b8605Smrg
478848b8605Smrg      case 2:
479848b8605Smrg         if (ctx->ClientMinorVersion > 1
480848b8605Smrg             || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
481848b8605Smrg            err = EGL_BAD_MATCH;
482848b8605Smrg         break;
483848b8605Smrg
484848b8605Smrg      case 3:
485848b8605Smrg         /* Note: The text above is incorrect.  There *is* an OpenGL 3.3!
486848b8605Smrg          */
487848b8605Smrg         if (ctx->ClientMinorVersion > 3)
488848b8605Smrg            err = EGL_BAD_MATCH;
489848b8605Smrg         break;
490848b8605Smrg
491848b8605Smrg      case 4:
492848b8605Smrg      default:
493848b8605Smrg         /* Don't put additional version checks here.  We don't know that
494848b8605Smrg          * there won't be versions > 4.2.
495848b8605Smrg          */
496848b8605Smrg         break;
497848b8605Smrg      }
498848b8605Smrg   } else if (api == EGL_OPENGL_ES_API) {
499848b8605Smrg      /* The EGL_KHR_create_context spec says:
500848b8605Smrg       *
501848b8605Smrg       *     "* If an OpenGL ES context is requested and the values for
502848b8605Smrg       *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
503848b8605Smrg       *        EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
504848b8605Smrg       *        is not defined, than an EGL_BAD_MATCH error is generated.
505848b8605Smrg       *
506848b8605Smrg       *        ... Examples of invalid combinations of attributes include:
507848b8605Smrg       *
508848b8605Smrg       *          - Major version < 1 or > 2
509848b8605Smrg       *          - Major version == 1 and minor version < 0 or > 1
510848b8605Smrg       *          - Major version == 2 and minor version != 0
511848b8605Smrg       */
512848b8605Smrg      if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
513848b8605Smrg         err = EGL_BAD_MATCH;
514848b8605Smrg
515848b8605Smrg      switch (ctx->ClientMajorVersion) {
516848b8605Smrg      case 1:
517848b8605Smrg         if (ctx->ClientMinorVersion > 1)
518848b8605Smrg            err = EGL_BAD_MATCH;
519848b8605Smrg         break;
520848b8605Smrg
521848b8605Smrg      case 2:
522848b8605Smrg         if (ctx->ClientMinorVersion > 0)
523848b8605Smrg            err = EGL_BAD_MATCH;
524848b8605Smrg         break;
525848b8605Smrg
526848b8605Smrg      case 3:
527848b8605Smrg         /* Don't put additional version checks here.  We don't know that
528848b8605Smrg          * there won't be versions > 3.0.
529848b8605Smrg          */
530848b8605Smrg         break;
531848b8605Smrg
532848b8605Smrg      default:
533848b8605Smrg         err = EGL_BAD_MATCH;
534848b8605Smrg         break;
535848b8605Smrg      }
536848b8605Smrg   }
537848b8605Smrg
538848b8605Smrg   switch (ctx->ResetNotificationStrategy) {
539848b8605Smrg   case EGL_NO_RESET_NOTIFICATION_KHR:
540848b8605Smrg   case EGL_LOSE_CONTEXT_ON_RESET_KHR:
541848b8605Smrg      break;
542848b8605Smrg
543848b8605Smrg   default:
544848b8605Smrg      err = EGL_BAD_ATTRIBUTE;
545848b8605Smrg      break;
546848b8605Smrg   }
547848b8605Smrg
548b8e80941Smrg   /* The EGL_KHR_create_context_no_error spec says:
549b8e80941Smrg    *
550b8e80941Smrg    *    "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE at
551b8e80941Smrg    *    the same time as a debug or robustness context is specified."
552b8e80941Smrg    */
553b8e80941Smrg   if (ctx->NoError && (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR ||
554b8e80941Smrg                        ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
555b8e80941Smrg      err = EGL_BAD_MATCH;
556b8e80941Smrg   }
557b8e80941Smrg
558848b8605Smrg   if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
559848b8605Smrg                      | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
560848b8605Smrg                      | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
561848b8605Smrg      err = EGL_BAD_ATTRIBUTE;
562848b8605Smrg   }
563848b8605Smrg
564848b8605Smrg   return err;
565848b8605Smrg}
566848b8605Smrg
567848b8605Smrg
568848b8605Smrg/**
569848b8605Smrg * Initialize the given _EGLContext object to defaults and/or the values
570848b8605Smrg * in the attrib_list.
571b8e80941Smrg *
572b8e80941Smrg * According to EGL 1.5 Section 3.7:
573b8e80941Smrg *
574b8e80941Smrg *	"EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
575b8e80941Smrg *	purposes except eglCreateContext."
576b8e80941Smrg *
577b8e80941Smrg * And since we only support GL and GLES, this is the only place where the
578b8e80941Smrg * bound API matters at all. We look up the current API from the current
579b8e80941Smrg * thread, and stash that in the context we're initializing. Our caller is
580b8e80941Smrg * responsible for determining whether that's an API it supports.
581848b8605Smrg */
582848b8605SmrgEGLBoolean
583b8e80941Smrg_eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *conf,
584848b8605Smrg                const EGLint *attrib_list)
585848b8605Smrg{
586848b8605Smrg   const EGLenum api = eglQueryAPI();
587848b8605Smrg   EGLint err;
588848b8605Smrg
589b8e80941Smrg   if (api == EGL_NONE)
590b8e80941Smrg      return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
591848b8605Smrg
592b8e80941Smrg   _eglInitResource(&ctx->Resource, sizeof(*ctx), disp);
593848b8605Smrg   ctx->ClientAPI = api;
594848b8605Smrg   ctx->Config = conf;
595848b8605Smrg   ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
596848b8605Smrg
597848b8605Smrg   ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
598848b8605Smrg   ctx->ClientMinorVersion = 0;
599848b8605Smrg   ctx->Flags = 0;
600848b8605Smrg   ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
601b8e80941Smrg   ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
602b8e80941Smrg   ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR;
603848b8605Smrg
604b8e80941Smrg   err = _eglParseContextAttribList(ctx, disp, attrib_list);
605848b8605Smrg   if (err == EGL_SUCCESS && ctx->Config) {
606848b8605Smrg      EGLint api_bit;
607848b8605Smrg
608848b8605Smrg      api_bit = _eglGetContextAPIBit(ctx);
609848b8605Smrg      if (!(ctx->Config->RenderableType & api_bit)) {
610848b8605Smrg         _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
611848b8605Smrg               api_bit, ctx->Config->RenderableType);
612848b8605Smrg         err = EGL_BAD_CONFIG;
613848b8605Smrg      }
614848b8605Smrg   }
615848b8605Smrg   if (err != EGL_SUCCESS)
616848b8605Smrg      return _eglError(err, "eglCreateContext");
617848b8605Smrg
618848b8605Smrg   return EGL_TRUE;
619848b8605Smrg}
620848b8605Smrg
621848b8605Smrg
622848b8605Smrgstatic EGLint
623848b8605Smrg_eglQueryContextRenderBuffer(_EGLContext *ctx)
624848b8605Smrg{
625848b8605Smrg   _EGLSurface *surf = ctx->DrawSurface;
626848b8605Smrg
627b8e80941Smrg   /* From the EGL 1.5 spec:
628b8e80941Smrg    *
629b8e80941Smrg    *    - If the context is not bound to a surface, then EGL_NONE will be
630b8e80941Smrg    *      returned.
631b8e80941Smrg    */
632848b8605Smrg   if (!surf)
633848b8605Smrg      return EGL_NONE;
634b8e80941Smrg
635b8e80941Smrg   switch (surf->Type) {
636b8e80941Smrg   default:
637b8e80941Smrg      unreachable("bad EGLSurface type");
638b8e80941Smrg   case EGL_PIXMAP_BIT:
639b8e80941Smrg      /* - If the context is bound to a pixmap surface, then EGL_SINGLE_BUFFER
640b8e80941Smrg       *   will be returned.
641b8e80941Smrg       */
642b8e80941Smrg      return EGL_SINGLE_BUFFER;
643b8e80941Smrg   case EGL_PBUFFER_BIT:
644b8e80941Smrg      /* - If the context is bound to a pbuffer surface, then EGL_BACK_BUFFER
645b8e80941Smrg       *   will be returned.
646b8e80941Smrg       */
647b8e80941Smrg      return EGL_BACK_BUFFER;
648b8e80941Smrg   case EGL_WINDOW_BIT:
649b8e80941Smrg      /* - If the context is bound to a window surface, then either
650b8e80941Smrg       *   EGL_BACK_BUFFER or EGL_SINGLE_BUFFER may be returned. The value
651b8e80941Smrg       *   returned depends on both the buffer requested by the setting of the
652b8e80941Smrg       *   EGL_RENDER_BUFFER property of the surface [...], and on the client
653b8e80941Smrg       *   API (not all client APIs support single-buffer Rendering to window
654b8e80941Smrg       *   surfaces). Some client APIs allow control of whether rendering goes
655b8e80941Smrg       *   to the front or back buffer. This client API-specific choice is not
656b8e80941Smrg       *   reflected in the returned value, which only describes the buffer
657b8e80941Smrg       *   that will be rendered to by default if not overridden by the client
658b8e80941Smrg       *   API.
659b8e80941Smrg       */
660b8e80941Smrg      return surf->ActiveRenderBuffer;
661b8e80941Smrg   }
662848b8605Smrg}
663848b8605Smrg
664848b8605Smrg
665848b8605SmrgEGLBoolean
666b8e80941Smrg_eglQueryContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *c,
667848b8605Smrg                 EGLint attribute, EGLint *value)
668848b8605Smrg{
669848b8605Smrg   (void) drv;
670b8e80941Smrg   (void) disp;
671848b8605Smrg
672848b8605Smrg   if (!value)
673848b8605Smrg      return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
674848b8605Smrg
675848b8605Smrg   switch (attribute) {
676848b8605Smrg   case EGL_CONFIG_ID:
677b8e80941Smrg      /*
678b8e80941Smrg       * From EGL_KHR_no_config_context:
679b8e80941Smrg       *
680b8e80941Smrg       *    "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
681b8e80941Smrg       *     respect to which the context was created, or zero if created
682b8e80941Smrg       *     without respect to an EGLConfig."
683b8e80941Smrg       */
684b8e80941Smrg      *value = c->Config ? c->Config->ConfigID : 0;
685848b8605Smrg      break;
686848b8605Smrg   case EGL_CONTEXT_CLIENT_VERSION:
687848b8605Smrg      *value = c->ClientMajorVersion;
688848b8605Smrg      break;
689848b8605Smrg   case EGL_CONTEXT_CLIENT_TYPE:
690848b8605Smrg      *value = c->ClientAPI;
691848b8605Smrg      break;
692848b8605Smrg   case EGL_RENDER_BUFFER:
693848b8605Smrg      *value = _eglQueryContextRenderBuffer(c);
694848b8605Smrg      break;
695b8e80941Smrg   case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
696b8e80941Smrg      *value = c->ContextPriority;
697b8e80941Smrg      break;
698848b8605Smrg   default:
699848b8605Smrg      return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
700848b8605Smrg   }
701848b8605Smrg
702848b8605Smrg   return EGL_TRUE;
703848b8605Smrg}
704848b8605Smrg
705848b8605Smrg
706848b8605Smrg/**
707848b8605Smrg * Bind the context to the thread and return the previous context.
708848b8605Smrg *
709848b8605Smrg * Note that the context may be NULL.
710848b8605Smrg */
711b8e80941Smrg_EGLContext *
712848b8605Smrg_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
713848b8605Smrg{
714848b8605Smrg   _EGLContext *oldCtx;
715848b8605Smrg
716b8e80941Smrg   oldCtx = t->CurrentContext;
717848b8605Smrg   if (ctx != oldCtx) {
718848b8605Smrg      if (oldCtx)
719848b8605Smrg         oldCtx->Binding = NULL;
720848b8605Smrg      if (ctx)
721848b8605Smrg         ctx->Binding = t;
722848b8605Smrg
723b8e80941Smrg      t->CurrentContext = ctx;
724848b8605Smrg   }
725848b8605Smrg
726848b8605Smrg   return oldCtx;
727848b8605Smrg}
728848b8605Smrg
729848b8605Smrg
730848b8605Smrg/**
731848b8605Smrg * Return true if the given context and surfaces can be made current.
732848b8605Smrg */
733848b8605Smrgstatic EGLBoolean
734848b8605Smrg_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
735848b8605Smrg{
736848b8605Smrg   _EGLThreadInfo *t = _eglGetCurrentThread();
737b8e80941Smrg   _EGLDisplay *disp;
738848b8605Smrg
739848b8605Smrg   if (_eglIsCurrentThreadDummy())
740848b8605Smrg      return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
741848b8605Smrg
742848b8605Smrg   /* this is easy */
743848b8605Smrg   if (!ctx) {
744848b8605Smrg      if (draw || read)
745848b8605Smrg         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
746848b8605Smrg      return EGL_TRUE;
747848b8605Smrg   }
748848b8605Smrg
749b8e80941Smrg   disp = ctx->Resource.Display;
750b8e80941Smrg   if (!disp->Extensions.KHR_surfaceless_context
751848b8605Smrg       && (draw == NULL || read == NULL))
752848b8605Smrg      return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
753848b8605Smrg
754848b8605Smrg   /*
755848b8605Smrg    * The spec says
756848b8605Smrg    *
757848b8605Smrg    * "If ctx is current to some other thread, or if either draw or read are
758848b8605Smrg    * bound to contexts in another thread, an EGL_BAD_ACCESS error is
759848b8605Smrg    * generated."
760848b8605Smrg    *
761848b8605Smrg    * and
762848b8605Smrg    *
763848b8605Smrg    * "at most one context may be bound to a particular surface at a given
764848b8605Smrg    * time"
765848b8605Smrg    */
766848b8605Smrg   if (ctx->Binding && ctx->Binding != t)
767848b8605Smrg      return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
768848b8605Smrg   if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
769b8e80941Smrg      if (draw->CurrentContext->Binding != t)
770848b8605Smrg         return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
771848b8605Smrg   }
772848b8605Smrg   if (read && read->CurrentContext && read->CurrentContext != ctx) {
773b8e80941Smrg      if (read->CurrentContext->Binding != t)
774848b8605Smrg         return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
775848b8605Smrg   }
776848b8605Smrg
777848b8605Smrg   /* If the context has a config then it must match that of the two
778848b8605Smrg    * surfaces */
779848b8605Smrg   if (ctx->Config) {
780848b8605Smrg      if ((draw && draw->Config != ctx->Config) ||
781848b8605Smrg          (read && read->Config != ctx->Config))
782848b8605Smrg         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
783848b8605Smrg   } else {
784b8e80941Smrg      /* Otherwise we must be using the EGL_KHR_no_config_context
785848b8605Smrg       * extension */
786b8e80941Smrg      assert(disp->Extensions.KHR_no_config_context);
787848b8605Smrg
788848b8605Smrg      /* The extension doesn't permit binding draw and read buffers with
789848b8605Smrg       * differing contexts */
790848b8605Smrg      if (draw && read && draw->Config != read->Config)
791848b8605Smrg         return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
792848b8605Smrg   }
793848b8605Smrg
794848b8605Smrg   return EGL_TRUE;
795848b8605Smrg}
796848b8605Smrg
797848b8605Smrg
798848b8605Smrg/**
799848b8605Smrg * Bind the context to the current thread and given surfaces.  Return the
800848b8605Smrg * previous bound context and surfaces.  The caller should unreference the
801848b8605Smrg * returned context and surfaces.
802848b8605Smrg *
803848b8605Smrg * Making a second call with the resources returned by the first call
804848b8605Smrg * unsurprisingly undoes the first call, except for the resouce reference
805848b8605Smrg * counts.
806848b8605Smrg */
807848b8605SmrgEGLBoolean
808848b8605Smrg_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
809848b8605Smrg                _EGLContext **old_ctx,
810848b8605Smrg                _EGLSurface **old_draw, _EGLSurface **old_read)
811848b8605Smrg{
812848b8605Smrg   _EGLThreadInfo *t = _eglGetCurrentThread();
813848b8605Smrg   _EGLContext *prev_ctx;
814848b8605Smrg   _EGLSurface *prev_draw, *prev_read;
815848b8605Smrg
816848b8605Smrg   if (!_eglCheckMakeCurrent(ctx, draw, read))
817848b8605Smrg      return EGL_FALSE;
818848b8605Smrg
819848b8605Smrg   /* increment refcounts before binding */
820848b8605Smrg   _eglGetContext(ctx);
821848b8605Smrg   _eglGetSurface(draw);
822848b8605Smrg   _eglGetSurface(read);
823848b8605Smrg
824848b8605Smrg   /* bind the new context */
825848b8605Smrg   prev_ctx = _eglBindContextToThread(ctx, t);
826848b8605Smrg
827848b8605Smrg   /* break previous bindings */
828848b8605Smrg   if (prev_ctx) {
829848b8605Smrg      prev_draw = prev_ctx->DrawSurface;
830848b8605Smrg      prev_read = prev_ctx->ReadSurface;
831848b8605Smrg
832848b8605Smrg      if (prev_draw)
833848b8605Smrg         prev_draw->CurrentContext = NULL;
834848b8605Smrg      if (prev_read)
835848b8605Smrg         prev_read->CurrentContext = NULL;
836848b8605Smrg
837848b8605Smrg      prev_ctx->DrawSurface = NULL;
838848b8605Smrg      prev_ctx->ReadSurface = NULL;
839848b8605Smrg   }
840848b8605Smrg   else {
841848b8605Smrg      prev_draw = prev_read = NULL;
842848b8605Smrg   }
843848b8605Smrg
844848b8605Smrg   /* establish new bindings */
845848b8605Smrg   if (ctx) {
846848b8605Smrg      if (draw)
847848b8605Smrg         draw->CurrentContext = ctx;
848848b8605Smrg      if (read)
849848b8605Smrg         read->CurrentContext = ctx;
850848b8605Smrg
851848b8605Smrg      ctx->DrawSurface = draw;
852848b8605Smrg      ctx->ReadSurface = read;
853848b8605Smrg   }
854848b8605Smrg
855848b8605Smrg   assert(old_ctx && old_draw && old_read);
856848b8605Smrg   *old_ctx = prev_ctx;
857848b8605Smrg   *old_draw = prev_draw;
858848b8605Smrg   *old_read = prev_read;
859848b8605Smrg
860848b8605Smrg   return EGL_TRUE;
861848b8605Smrg}
862