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