blob: 63035a3312e3f4047004294f13115b8d7de43d40 [file] [log] [blame]
Chia-I Wuf2001df2011-07-02 17:57:30 +09001/**************************************************************************
2 *
José Fonseca87712852014-01-17 16:27:50 +00003 * Copyright 2008 VMware, Inc.
Chia-I Wuf2001df2011-07-02 17:57:30 +09004 * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
5 * Copyright 2010-2011 LunarG, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 **************************************************************************/
29
30
Brian Pauladbff7e2005-04-22 21:09:39 +000031#include <assert.h>
32#include <stdlib.h>
33#include <string.h>
34#include "eglconfig.h"
35#include "eglcontext.h"
Brian Pauld548bf42005-11-27 23:57:19 +000036#include "egldisplay.h"
Chia-I Wu94cb3212010-01-29 09:00:30 +080037#include "eglcurrent.h"
Brian Pauladbff7e2005-04-22 21:09:39 +000038#include "eglsurface.h"
Chia-I Wucaa5c8d2010-01-31 12:57:53 +080039#include "egllog.h"
Eric Engestromd75fbff2018-05-16 14:17:30 +010040#include "util/macros.h"
Chia-I Wucaa5c8d2010-01-31 12:57:53 +080041
42
43/**
44 * Return the API bit (one of EGL_xxx_BIT) of the context.
45 */
46static EGLint
47_eglGetContextAPIBit(_EGLContext *ctx)
48{
49 EGLint bit = 0;
50
51 switch (ctx->ClientAPI) {
52 case EGL_OPENGL_ES_API:
Ian Romanick3fd79dd2012-07-18 15:59:15 -070053 switch (ctx->ClientMajorVersion) {
Chia-I Wucaa5c8d2010-01-31 12:57:53 +080054 case 1:
55 bit = EGL_OPENGL_ES_BIT;
56 break;
57 case 2:
58 bit = EGL_OPENGL_ES2_BIT;
59 break;
Chad Versaceeb099402012-11-20 13:43:11 -080060 case 3:
61 bit = EGL_OPENGL_ES3_BIT_KHR;
62 break;
Chia-I Wucaa5c8d2010-01-31 12:57:53 +080063 default:
64 break;
65 }
66 break;
67 case EGL_OPENVG_API:
68 bit = EGL_OPENVG_BIT;
69 break;
70 case EGL_OPENGL_API:
71 bit = EGL_OPENGL_BIT;
72 break;
73 default:
74 break;
75 }
76
77 return bit;
78}
79
80
81/**
82 * Parse the list of context attributes and return the proper error code.
83 */
84static EGLint
Eric Engestrom54fa5ec2019-02-02 11:38:45 +000085_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *disp,
Ian Romanick63beb3d2012-07-19 11:10:15 -070086 const EGLint *attrib_list)
Chia-I Wucaa5c8d2010-01-31 12:57:53 +080087{
88 EGLenum api = ctx->ClientAPI;
89 EGLint i, err = EGL_SUCCESS;
90
91 if (!attrib_list)
92 return EGL_SUCCESS;
93
Ian Romanick63beb3d2012-07-19 11:10:15 -070094 if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) {
95 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]);
96 return EGL_BAD_ATTRIBUTE;
97 }
98
Chia-I Wucaa5c8d2010-01-31 12:57:53 +080099 for (i = 0; attrib_list[i] != EGL_NONE; i++) {
100 EGLint attr = attrib_list[i++];
101 EGLint val = attrib_list[i];
102
103 switch (attr) {
104 case EGL_CONTEXT_CLIENT_VERSION:
Frank Binnsd9603be2015-08-12 16:36:00 +0100105 /* The EGL 1.4 spec says:
106 *
107 * "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the
108 * current rendering API is EGL_OPENGL_ES_API"
109 *
110 * The EGL_KHR_create_context spec says:
111 *
112 * "EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
113 * (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)"
114 *
115 * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
116 * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
117 * version. They are only meaningful for OpenGL and OpenGL ES
118 * contexts, and specifying them for other types of contexts will
119 * generate an error."
120 */
121 if ((api != EGL_OPENGL_ES_API &&
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000122 (!disp->Extensions.KHR_create_context || api != EGL_OPENGL_API))) {
Frank Binnsd9603be2015-08-12 16:36:00 +0100123 err = EGL_BAD_ATTRIBUTE;
124 break;
125 }
126
Ian Romanick3fd79dd2012-07-18 15:59:15 -0700127 ctx->ClientMajorVersion = val;
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800128 break;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700129
130 case EGL_CONTEXT_MINOR_VERSION_KHR:
Frank Binnsd9603be2015-08-12 16:36:00 +0100131 /* The EGL_KHR_create_context spec says:
132 *
133 * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
134 * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
135 * version. They are only meaningful for OpenGL and OpenGL ES
136 * contexts, and specifying them for other types of contexts will
137 * generate an error."
138 */
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000139 if (!disp->Extensions.KHR_create_context ||
Frank Binnsd9603be2015-08-12 16:36:00 +0100140 (api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) {
Ian Romanick63beb3d2012-07-19 11:10:15 -0700141 err = EGL_BAD_ATTRIBUTE;
142 break;
143 }
144
145 ctx->ClientMinorVersion = val;
146 break;
147
148 case EGL_CONTEXT_FLAGS_KHR:
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000149 if (!disp->Extensions.KHR_create_context) {
Ian Romanick63beb3d2012-07-19 11:10:15 -0700150 err = EGL_BAD_ATTRIBUTE;
151 break;
152 }
153
154 /* The EGL_KHR_create_context spec says:
155 *
Matthew Waters11cabc42015-09-14 18:35:45 +0100156 * "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in
157 * EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.
158 * [...]
159 * In some cases a debug context may be identical to a non-debug
160 * context. This bit is supported for OpenGL and OpenGL ES
161 * contexts."
Ian Romanick63beb3d2012-07-19 11:10:15 -0700162 */
Matthew Waters11cabc42015-09-14 18:35:45 +0100163 if ((val & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) &&
164 (api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API)) {
165 err = EGL_BAD_ATTRIBUTE;
166 break;
167 }
168
169 /* The EGL_KHR_create_context spec says:
170 *
171 * "If the EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR flag bit
172 * is set in EGL_CONTEXT_FLAGS_KHR, then a <forward-compatible>
173 * context will be created. Forward-compatible contexts are
174 * defined only for OpenGL versions 3.0 and later. They must not
175 * support functionality marked as <deprecated> by that version of
176 * the API, while a non-forward-compatible context must support
177 * all functionality in that version, deprecated or not. This bit
178 * is supported for OpenGL contexts, and requesting a
179 * forward-compatible context for OpenGL versions less than 3.0
180 * will generate an error."
Andrii Simiklit5c581b32018-10-11 13:53:21 +0300181 *
182 * Note: since the forward-compatible flag can be set more than one way,
183 * the OpenGL version check is performed once, below.
Matthew Waters11cabc42015-09-14 18:35:45 +0100184 */
185 if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) &&
Andrii Simiklit5c581b32018-10-11 13:53:21 +0300186 api != EGL_OPENGL_API) {
Matthew Waters11cabc42015-09-14 18:35:45 +0100187 err = EGL_BAD_ATTRIBUTE;
188 break;
189 }
190
Matthew Waters11cabc42015-09-14 18:35:45 +0100191 if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
Chad Versaceb85c0b52016-12-22 17:06:14 -0800192 api != EGL_OPENGL_API) {
193 /* The EGL_KHR_create_context spec says:
194 *
195 * 10) Which error should be generated if robust buffer access
196 * or reset notifications are requested under OpenGL ES?
197 *
198 * As per Issue 6, this extension does not support creating
199 * robust contexts for OpenGL ES. This is only supported via
200 * the EGL_EXT_create_context_robustness extension.
201 *
202 * Attempting to use this extension to create robust OpenGL
203 * ES context will generate an EGL_BAD_ATTRIBUTE error. This
204 * specific error is generated because this extension does
205 * not define the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
206 * and EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
207 * bits for OpenGL ES contexts. Thus, use of these bits fall
208 * under condition described by: "If an attribute is
209 * specified that is not meaningful for the client API
210 * type.." in the above specification.
211 *
212 * The spec requires that we emit the error even if the display
213 * supports EGL_EXT_create_context_robustness. To create a robust
214 * GLES context, the *attribute*
215 * EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT must be used, not the
216 * *flag* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR.
217 */
Ian Romanick63beb3d2012-07-19 11:10:15 -0700218 err = EGL_BAD_ATTRIBUTE;
219 break;
220 }
221
Marek Olšákf9f89442015-05-12 00:44:20 +0200222 ctx->Flags |= val;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700223 break;
224
225 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000226 if (!disp->Extensions.KHR_create_context) {
Ian Romanick63beb3d2012-07-19 11:10:15 -0700227 err = EGL_BAD_ATTRIBUTE;
228 break;
229 }
230
231 /* The EGL_KHR_create_context spec says:
232 *
233 * "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
234 * OpenGL contexts, and specifying it for other types of
235 * contexts, including OpenGL ES contexts, will generate an
236 * error."
237 */
238 if (api != EGL_OPENGL_API) {
239 err = EGL_BAD_ATTRIBUTE;
240 break;
241 }
242
243 ctx->Profile = val;
244 break;
245
246 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
247 /* The EGL_KHR_create_context spec says:
248 *
249 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
250 * meaningful for OpenGL contexts, and specifying it for other
251 * types of contexts, including OpenGL ES contexts, will generate
252 * an error."
Kenneth Graunke28c2ce72019-05-16 22:05:51 -0700253 *
254 * EGL 1.5 defines EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY
255 * (without a suffix) which has the same value as the KHR token,
256 * and specifies that it now works with both GL and ES contexts:
257 *
258 * "This attribute is supported only for OpenGL and OpenGL ES
259 * contexts."
Ian Romanick63beb3d2012-07-19 11:10:15 -0700260 */
Kenneth Graunke28c2ce72019-05-16 22:05:51 -0700261 if (!(disp->Extensions.KHR_create_context && api == EGL_OPENGL_API)
262 && !(disp->Version >= 15 && (api == EGL_OPENGL_API ||
263 api == EGL_OPENGL_ES_API))) {
Ian Romanick63beb3d2012-07-19 11:10:15 -0700264 err = EGL_BAD_ATTRIBUTE;
265 break;
266 }
267
268 ctx->ResetNotificationStrategy = val;
269 break;
270
Ian Romanickf1715712012-07-19 15:08:06 -0700271 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
272 /* The EGL_EXT_create_context_robustness spec says:
273 *
274 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
275 * meaningful for OpenGL ES contexts, and specifying it for other
276 * types of contexts will generate an EGL_BAD_ATTRIBUTE error."
277 */
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000278 if (!disp->Extensions.EXT_create_context_robustness
Ian Romanickf1715712012-07-19 15:08:06 -0700279 || api != EGL_OPENGL_ES_API) {
280 err = EGL_BAD_ATTRIBUTE;
281 break;
282 }
283
284 ctx->ResetNotificationStrategy = val;
285 break;
286
287 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000288 if (!disp->Extensions.EXT_create_context_robustness) {
Ian Romanickf1715712012-07-19 15:08:06 -0700289 err = EGL_BAD_ATTRIBUTE;
290 break;
291 }
292
Marek Olšákf9f89442015-05-12 00:44:20 +0200293 if (val == EGL_TRUE)
294 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
Ian Romanickf1715712012-07-19 15:08:06 -0700295 break;
296
Marek Olšák706466f2015-05-12 00:44:56 +0200297 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000298 if (disp->Version < 15) {
Marek Olšák706466f2015-05-12 00:44:56 +0200299 err = EGL_BAD_ATTRIBUTE;
300 break;
301 }
302
303 if (val == EGL_TRUE)
304 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
305 break;
306
307 case EGL_CONTEXT_OPENGL_DEBUG:
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000308 if (disp->Version < 15) {
Marek Olšák706466f2015-05-12 00:44:56 +0200309 err = EGL_BAD_ATTRIBUTE;
310 break;
311 }
312
313 if (val == EGL_TRUE)
314 ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
315 break;
316
317 case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000318 if (disp->Version < 15) {
Marek Olšák706466f2015-05-12 00:44:56 +0200319 err = EGL_BAD_ATTRIBUTE;
320 break;
321 }
322
323 if (val == EGL_TRUE)
324 ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
325 break;
326
Grigori Goronzy49095192017-06-29 02:44:03 +0200327 case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000328 if (disp->Version < 14 ||
329 !disp->Extensions.KHR_create_context_no_error) {
Grigori Goronzy49095192017-06-29 02:44:03 +0200330 err = EGL_BAD_ATTRIBUTE;
331 break;
332 }
333
334 /* The KHR_no_error spec only applies against OpenGL 2.0+ and
335 * OpenGL ES 2.0+
336 */
337 if ((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) ||
338 ctx->ClientMajorVersion < 2) {
339 err = EGL_BAD_ATTRIBUTE;
340 break;
341 }
342
Grigori Goronzy49095192017-06-29 02:44:03 +0200343 /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */
344 ctx->NoError = !!val;
345 break;
346
Chris Wilson95ecf3d2016-10-27 19:34:46 +0100347 case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
348 /* The EGL_IMG_context_priority spec says:
349 *
350 * "EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of
351 * the context to be created. This attribute is a hint, as an
352 * implementation may not support multiple contexts at some
353 * priority levels and system policy may limit access to high
354 * priority contexts to appropriate system privilege level. The
355 * default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is
356 * EGL_CONTEXT_PRIORITY_MEDIUM_IMG."
357 */
358 {
359 int bit;
360
361 switch (val) {
362 case EGL_CONTEXT_PRIORITY_HIGH_IMG:
363 bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT;
364 break;
365 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
366 bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT;
367 break;
368 case EGL_CONTEXT_PRIORITY_LOW_IMG:
369 bit = __EGL_CONTEXT_PRIORITY_LOW_BIT;
370 break;
371 default:
372 bit = -1;
373 break;
374 }
375
376 if (bit < 0) {
377 err = EGL_BAD_ATTRIBUTE;
378 break;
379 }
380
381 /* "This extension allows an EGLContext to be created with a
382 * priority hint. It is possible that an implementation will not
383 * honour the hint, especially if there are constraints on the
384 * number of high priority contexts available in the system, or
385 * system policy limits access to high priority contexts to
386 * appropriate system privilege level. A query is provided to find
387 * the real priority level assigned to the context after creation."
388 *
389 * We currently assume that the driver applies the priority hint
390 * and filters out any it cannot handle during the screen setup,
391 * e.g. dri2_setup_screen(). As such we can mask any change that
392 * the driver would fail, and ctx->ContextPriority matches the
393 * hint applied to the driver/hardware backend.
394 */
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000395 if (disp->Extensions.IMG_context_priority & (1 << bit))
Chris Wilson95ecf3d2016-10-27 19:34:46 +0100396 ctx->ContextPriority = val;
397
398 break;
399 }
400
Adam Jacksonc0be3aa2016-09-22 03:47:55 -0400401 case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR:
402 if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR ||
403 val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) {
404 ctx->ReleaseBehavior = val;
405 } else {
406 err = EGL_BAD_ATTRIBUTE;
407 }
408 break;
409
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800410 default:
411 err = EGL_BAD_ATTRIBUTE;
412 break;
413 }
414
415 if (err != EGL_SUCCESS) {
416 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
417 break;
418 }
419 }
420
Ian Romanick63beb3d2012-07-19 11:10:15 -0700421 if (api == EGL_OPENGL_API) {
422 /* The EGL_KHR_create_context spec says:
423 *
424 * "If the requested OpenGL version is less than 3.2,
425 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
426 * functionality of the context is determined solely by the
427 * requested version."
428 *
429 * Since the value is ignored, only validate the setting if the version
430 * is >= 3.2.
431 */
432 if (ctx->ClientMajorVersion >= 4
433 || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
434 switch (ctx->Profile) {
435 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
436 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
437 break;
438
439 default:
440 /* The EGL_KHR_create_context spec says:
441 *
442 * "* If an OpenGL context is requested, the requested version
443 * is greater than 3.2, and the value for attribute
Matt Turner587d5db2012-10-08 17:01:34 -0700444 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
445 * any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
446 * and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has
447 * more than one of these bits set; or if the implementation does
448 * not support the requested profile, then an EGL_BAD_MATCH error
449 * is generated."
Ian Romanick63beb3d2012-07-19 11:10:15 -0700450 */
Matt Turner587d5db2012-10-08 17:01:34 -0700451 err = EGL_BAD_MATCH;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700452 break;
453 }
454 }
455
456 /* The EGL_KHR_create_context spec says:
457 *
458 * "* If an OpenGL context is requested and the values for
459 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
460 * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
461 * the value for attribute
462 * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
463 * version and feature set that are not defined, than an
464 * EGL_BAD_MATCH error is generated.
465 *
466 * ... Thus, examples of invalid combinations of attributes
467 * include:
468 *
469 * - Major version < 1 or > 4
470 * - Major version == 1 and minor version < 0 or > 5
471 * - Major version == 2 and minor version < 0 or > 1
472 * - Major version == 3 and minor version < 0 or > 2
473 * - Major version == 4 and minor version < 0 or > 2
474 * - Forward-compatible flag set and major version < 3"
475 */
476 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
477 err = EGL_BAD_MATCH;
478
479 switch (ctx->ClientMajorVersion) {
480 case 1:
481 if (ctx->ClientMinorVersion > 5
482 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
483 err = EGL_BAD_MATCH;
484 break;
485
486 case 2:
487 if (ctx->ClientMinorVersion > 1
488 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
489 err = EGL_BAD_MATCH;
490 break;
491
492 case 3:
493 /* Note: The text above is incorrect. There *is* an OpenGL 3.3!
494 */
495 if (ctx->ClientMinorVersion > 3)
496 err = EGL_BAD_MATCH;
497 break;
498
499 case 4:
500 default:
501 /* Don't put additional version checks here. We don't know that
502 * there won't be versions > 4.2.
503 */
504 break;
505 }
506 } else if (api == EGL_OPENGL_ES_API) {
507 /* The EGL_KHR_create_context spec says:
508 *
509 * "* If an OpenGL ES context is requested and the values for
510 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
511 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
512 * is not defined, than an EGL_BAD_MATCH error is generated.
513 *
514 * ... Examples of invalid combinations of attributes include:
515 *
516 * - Major version < 1 or > 2
517 * - Major version == 1 and minor version < 0 or > 1
518 * - Major version == 2 and minor version != 0
519 */
520 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
521 err = EGL_BAD_MATCH;
522
523 switch (ctx->ClientMajorVersion) {
524 case 1:
525 if (ctx->ClientMinorVersion > 1)
526 err = EGL_BAD_MATCH;
527 break;
528
529 case 2:
Ian Romanickdbecb412012-07-19 16:12:13 -0700530 if (ctx->ClientMinorVersion > 0)
531 err = EGL_BAD_MATCH;
532 break;
533
534 case 3:
Ian Romanick63beb3d2012-07-19 11:10:15 -0700535 /* Don't put additional version checks here. We don't know that
Ian Romanickdbecb412012-07-19 16:12:13 -0700536 * there won't be versions > 3.0.
Ian Romanick63beb3d2012-07-19 11:10:15 -0700537 */
538 break;
Anuj Phogatd308f572014-06-18 17:35:18 -0700539
540 default:
541 err = EGL_BAD_MATCH;
542 break;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700543 }
544 }
545
546 switch (ctx->ResetNotificationStrategy) {
547 case EGL_NO_RESET_NOTIFICATION_KHR:
548 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
549 break;
550
551 default:
552 err = EGL_BAD_ATTRIBUTE;
553 break;
554 }
555
Grigori Goronzy39bf7752017-07-19 23:51:55 +0200556 /* The EGL_KHR_create_context_no_error spec says:
557 *
558 * "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE at
559 * the same time as a debug or robustness context is specified."
560 */
561 if (ctx->NoError && (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR ||
562 ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
563 err = EGL_BAD_MATCH;
564 }
565
Matt Turner971750e2012-08-24 16:26:54 -0700566 if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
Ian Romanick63beb3d2012-07-19 11:10:15 -0700567 | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
568 | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
569 err = EGL_BAD_ATTRIBUTE;
570 }
571
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800572 return err;
573}
Brian Pauladbff7e2005-04-22 21:09:39 +0000574
575
576/**
Brian Paul5e7dba52008-05-27 14:21:25 -0600577 * Initialize the given _EGLContext object to defaults and/or the values
578 * in the attrib_list.
Adam Jacksona2797602016-09-07 17:41:56 -0400579 *
580 * According to EGL 1.5 Section 3.7:
581 *
Adam Jacksondbda3752016-09-08 13:21:24 -0400582 * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
583 * purposes except eglCreateContext."
Adam Jacksona2797602016-09-07 17:41:56 -0400584 *
585 * And since we only support GL and GLES, this is the only place where the
586 * bound API matters at all. We look up the current API from the current
587 * thread, and stash that in the context we're initializing. Our caller is
588 * responsible for determining whether that's an API it supports.
Brian Pauladbff7e2005-04-22 21:09:39 +0000589 */
Brian Pauld548bf42005-11-27 23:57:19 +0000590EGLBoolean
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000591_eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *conf,
Chia-I Wud69242b2010-01-31 13:33:57 +0800592 const EGLint *attrib_list)
Brian Pauladbff7e2005-04-22 21:09:39 +0000593{
Brian Pauld5078b92008-05-30 13:45:40 -0600594 const EGLenum api = eglQueryAPI();
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800595 EGLint err;
Brian Pauld5078b92008-05-30 13:45:40 -0600596
Emil Velikovc58af5c2017-06-20 15:40:28 +0100597 if (api == EGL_NONE)
598 return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
Brian Pauld548bf42005-11-27 23:57:19 +0000599
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000600 _eglInitResource(&ctx->Resource, sizeof(*ctx), disp);
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800601 ctx->ClientAPI = api;
602 ctx->Config = conf;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700603 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
Brian Paul9f6a4e22008-06-19 21:19:33 -0600604
Ian Romanick3fd79dd2012-07-18 15:59:15 -0700605 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
606 ctx->ClientMinorVersion = 0;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700607 ctx->Flags = 0;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700608 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
Chris Wilson95ecf3d2016-10-27 19:34:46 +0100609 ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
Adam Jacksonc0be3aa2016-09-22 03:47:55 -0400610 ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR;
Brian Paula8533d52008-06-19 16:06:56 -0600611
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000612 err = _eglParseContextAttribList(ctx, disp, attrib_list);
Chia-I Wu5eb33592010-08-20 13:19:10 +0800613 if (err == EGL_SUCCESS && ctx->Config) {
Chia-I Wu3fa21882010-10-14 16:38:58 +0800614 EGLint api_bit;
Chia-I Wu5eb33592010-08-20 13:19:10 +0800615
Chia-I Wu5eb33592010-08-20 13:19:10 +0800616 api_bit = _eglGetContextAPIBit(ctx);
Chia-I Wu3fa21882010-10-14 16:38:58 +0800617 if (!(ctx->Config->RenderableType & api_bit)) {
Chia-I Wu5eb33592010-08-20 13:19:10 +0800618 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
Chia-I Wu3fa21882010-10-14 16:38:58 +0800619 api_bit, ctx->Config->RenderableType);
Chia-I Wu5eb33592010-08-20 13:19:10 +0800620 err = EGL_BAD_CONFIG;
621 }
622 }
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800623 if (err != EGL_SUCCESS)
624 return _eglError(err, "eglCreateContext");
Brian Pauld548bf42005-11-27 23:57:19 +0000625
626 return EGL_TRUE;
Brian Pauladbff7e2005-04-22 21:09:39 +0000627}
628
629
Chia-I Wud845f272009-09-27 17:00:51 +0800630static EGLint
631_eglQueryContextRenderBuffer(_EGLContext *ctx)
632{
633 _EGLSurface *surf = ctx->DrawSurface;
Chia-I Wud845f272009-09-27 17:00:51 +0800634
Chad Versacef48f9a72018-04-07 14:23:48 -0700635 /* From the EGL 1.5 spec:
636 *
637 * - If the context is not bound to a surface, then EGL_NONE will be
638 * returned.
639 */
Chia-I Wud845f272009-09-27 17:00:51 +0800640 if (!surf)
641 return EGL_NONE;
Chad Versacef48f9a72018-04-07 14:23:48 -0700642
643 switch (surf->Type) {
644 default:
645 unreachable("bad EGLSurface type");
646 case EGL_PIXMAP_BIT:
647 /* - If the context is bound to a pixmap surface, then EGL_SINGLE_BUFFER
648 * will be returned.
649 */
650 return EGL_SINGLE_BUFFER;
651 case EGL_PBUFFER_BIT:
652 /* - If the context is bound to a pbuffer surface, then EGL_BACK_BUFFER
653 * will be returned.
654 */
655 return EGL_BACK_BUFFER;
656 case EGL_WINDOW_BIT:
657 /* - If the context is bound to a window surface, then either
658 * EGL_BACK_BUFFER or EGL_SINGLE_BUFFER may be returned. The value
659 * returned depends on both the buffer requested by the setting of the
660 * EGL_RENDER_BUFFER property of the surface [...], and on the client
661 * API (not all client APIs support single-buffer Rendering to window
662 * surfaces). Some client APIs allow control of whether rendering goes
663 * to the front or back buffer. This client API-specific choice is not
664 * reflected in the returned value, which only describes the buffer
665 * that will be rendered to by default if not overridden by the client
666 * API.
667 */
668 return surf->ActiveRenderBuffer;
669 }
Chia-I Wud845f272009-09-27 17:00:51 +0800670}
Chia-I Wud845f272009-09-27 17:00:51 +0800671
672
Brian Pauladbff7e2005-04-22 21:09:39 +0000673EGLBoolean
Eric Engestrom9c6fa942020-07-31 01:38:41 +0200674_eglQueryContext(const _EGLDriver *drv, _EGLDisplay *disp, _EGLContext *c,
Brian Pauld548bf42005-11-27 23:57:19 +0000675 EGLint attribute, EGLint *value)
Brian Pauladbff7e2005-04-22 21:09:39 +0000676{
Brian Pauladbff7e2005-04-22 21:09:39 +0000677 (void) drv;
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000678 (void) disp;
Brian Pauladbff7e2005-04-22 21:09:39 +0000679
Chia-I Wud845f272009-09-27 17:00:51 +0800680 if (!value)
681 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
682
Brian Pauladbff7e2005-04-22 21:09:39 +0000683 switch (attribute) {
684 case EGL_CONFIG_ID:
Adam Jacksoncc45a5c2016-09-09 12:25:33 -0400685 /*
686 * From EGL_KHR_no_config_context:
687 *
688 * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
689 * respect to which the context was created, or zero if created
690 * without respect to an EGLConfig."
691 */
692 *value = c->Config ? c->Config->ConfigID : 0;
Chia-I Wud845f272009-09-27 17:00:51 +0800693 break;
694 case EGL_CONTEXT_CLIENT_VERSION:
Ian Romanick3fd79dd2012-07-18 15:59:15 -0700695 *value = c->ClientMajorVersion;
Chia-I Wud845f272009-09-27 17:00:51 +0800696 break;
Brian Paulb2006a42006-01-30 00:10:55 +0000697 case EGL_CONTEXT_CLIENT_TYPE:
698 *value = c->ClientAPI;
Chia-I Wud845f272009-09-27 17:00:51 +0800699 break;
700 case EGL_RENDER_BUFFER:
701 *value = _eglQueryContextRenderBuffer(c);
702 break;
Chris Wilson95ecf3d2016-10-27 19:34:46 +0100703 case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
704 *value = c->ContextPriority;
705 break;
Brian Pauladbff7e2005-04-22 21:09:39 +0000706 default:
Chia-I Wud845f272009-09-27 17:00:51 +0800707 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
Brian Pauladbff7e2005-04-22 21:09:39 +0000708 }
Chia-I Wud845f272009-09-27 17:00:51 +0800709
710 return EGL_TRUE;
Brian Pauladbff7e2005-04-22 21:09:39 +0000711}
712
713
714/**
Chia-I Wu7c092962010-01-26 16:53:40 +0800715 * Bind the context to the thread and return the previous context.
716 *
717 * Note that the context may be NULL.
718 */
Eric Anholt3b7b6ad2012-12-27 17:39:37 -0800719_EGLContext *
Chia-I Wu7c092962010-01-26 16:53:40 +0800720_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
721{
Chia-I Wu7c092962010-01-26 16:53:40 +0800722 _EGLContext *oldCtx;
723
Kyle Brenneman6e066f72016-07-08 15:21:17 -0600724 oldCtx = t->CurrentContext;
Chia-I Wu551bfe72010-03-28 02:11:16 +0800725 if (ctx != oldCtx) {
726 if (oldCtx)
727 oldCtx->Binding = NULL;
728 if (ctx)
729 ctx->Binding = t;
Chia-I Wu7c092962010-01-26 16:53:40 +0800730
Kyle Brenneman6e066f72016-07-08 15:21:17 -0600731 t->CurrentContext = ctx;
Chia-I Wu551bfe72010-03-28 02:11:16 +0800732 }
Chia-I Wu7c092962010-01-26 16:53:40 +0800733
734 return oldCtx;
735}
736
737
738/**
739 * Return true if the given context and surfaces can be made current.
740 */
741static EGLBoolean
742_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
743{
744 _EGLThreadInfo *t = _eglGetCurrentThread();
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000745 _EGLDisplay *disp;
Chia-I Wu7c092962010-01-26 16:53:40 +0800746
747 if (_eglIsCurrentThreadDummy())
748 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
749
750 /* this is easy */
751 if (!ctx) {
752 if (draw || read)
753 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
754 return EGL_TRUE;
755 }
756
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000757 disp = ctx->Resource.Display;
758 if (!disp->Extensions.KHR_surfaceless_context
Ian Romanickb50703a2012-07-18 09:38:34 -0700759 && (draw == NULL || read == NULL))
Chia-I Wu7c092962010-01-26 16:53:40 +0800760 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
761
Chia-I Wu7c092962010-01-26 16:53:40 +0800762 /*
763 * The spec says
764 *
765 * "If ctx is current to some other thread, or if either draw or read are
766 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
767 * generated."
768 *
Chia-I Wu0d43cbe2010-10-23 16:51:01 +0800769 * and
Chia-I Wu7c092962010-01-26 16:53:40 +0800770 *
771 * "at most one context may be bound to a particular surface at a given
772 * time"
Chia-I Wu7c092962010-01-26 16:53:40 +0800773 */
Chia-I Wu0d43cbe2010-10-23 16:51:01 +0800774 if (ctx->Binding && ctx->Binding != t)
Chia-I Wu7c092962010-01-26 16:53:40 +0800775 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
Chia-I Wu0d43cbe2010-10-23 16:51:01 +0800776 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
Kyle Brenneman6e066f72016-07-08 15:21:17 -0600777 if (draw->CurrentContext->Binding != t)
Chia-I Wu0d43cbe2010-10-23 16:51:01 +0800778 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
779 }
780 if (read && read->CurrentContext && read->CurrentContext != ctx) {
Kyle Brenneman6e066f72016-07-08 15:21:17 -0600781 if (read->CurrentContext->Binding != t)
Chia-I Wu0d43cbe2010-10-23 16:51:01 +0800782 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
783 }
Chia-I Wu7c092962010-01-26 16:53:40 +0800784
Neil Roberts551d4592014-03-07 18:05:47 +0000785 /* If the context has a config then it must match that of the two
786 * surfaces */
787 if (ctx->Config) {
788 if ((draw && draw->Config != ctx->Config) ||
789 (read && read->Config != ctx->Config))
790 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
791 } else {
Adam Jacksond9f5b192016-09-09 12:25:34 -0400792 /* Otherwise we must be using the EGL_KHR_no_config_context
Neil Roberts551d4592014-03-07 18:05:47 +0000793 * extension */
Eric Engestrom54fa5ec2019-02-02 11:38:45 +0000794 assert(disp->Extensions.KHR_no_config_context);
Neil Roberts551d4592014-03-07 18:05:47 +0000795
796 /* The extension doesn't permit binding draw and read buffers with
797 * differing contexts */
798 if (draw && read && draw->Config != read->Config)
799 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
800 }
Chia-I Wu7c092962010-01-26 16:53:40 +0800801
Chia-I Wu7c092962010-01-26 16:53:40 +0800802 return EGL_TRUE;
803}
804
805
806/**
Chia-I Wu959481a2010-01-27 23:31:20 +0800807 * Bind the context to the current thread and given surfaces. Return the
Chia-I Wud19afc52010-10-23 12:52:26 +0800808 * previous bound context and surfaces. The caller should unreference the
809 * returned context and surfaces.
810 *
811 * Making a second call with the resources returned by the first call
812 * unsurprisingly undoes the first call, except for the resouce reference
813 * counts.
Chia-I Wu959481a2010-01-27 23:31:20 +0800814 */
815EGLBoolean
Chia-I Wud19afc52010-10-23 12:52:26 +0800816_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
817 _EGLContext **old_ctx,
818 _EGLSurface **old_draw, _EGLSurface **old_read)
Chia-I Wu959481a2010-01-27 23:31:20 +0800819{
820 _EGLThreadInfo *t = _eglGetCurrentThread();
Chia-I Wud19afc52010-10-23 12:52:26 +0800821 _EGLContext *prev_ctx;
822 _EGLSurface *prev_draw, *prev_read;
Chia-I Wu959481a2010-01-27 23:31:20 +0800823
Chia-I Wud19afc52010-10-23 12:52:26 +0800824 if (!_eglCheckMakeCurrent(ctx, draw, read))
Chia-I Wu959481a2010-01-27 23:31:20 +0800825 return EGL_FALSE;
826
Chia-I Wud19afc52010-10-23 12:52:26 +0800827 /* increment refcounts before binding */
828 _eglGetContext(ctx);
829 _eglGetSurface(draw);
830 _eglGetSurface(read);
831
Chia-I Wu959481a2010-01-27 23:31:20 +0800832 /* bind the new context */
Chia-I Wud19afc52010-10-23 12:52:26 +0800833 prev_ctx = _eglBindContextToThread(ctx, t);
Chia-I Wubbe459b2010-04-05 21:26:34 +0800834
Chia-I Wud19afc52010-10-23 12:52:26 +0800835 /* break previous bindings */
836 if (prev_ctx) {
837 prev_draw = prev_ctx->DrawSurface;
838 prev_read = prev_ctx->ReadSurface;
Chia-I Wu848945e2010-04-06 11:51:25 +0800839
Chia-I Wud19afc52010-10-23 12:52:26 +0800840 if (prev_draw)
841 prev_draw->CurrentContext = NULL;
842 if (prev_read)
843 prev_read->CurrentContext = NULL;
Chia-I Wuea9e5db2010-09-10 18:26:03 +0800844
Chia-I Wud19afc52010-10-23 12:52:26 +0800845 prev_ctx->DrawSurface = NULL;
846 prev_ctx->ReadSurface = NULL;
847 }
848 else {
849 prev_draw = prev_read = NULL;
Chia-I Wubbe459b2010-04-05 21:26:34 +0800850 }
851
Chia-I Wuea9e5db2010-09-10 18:26:03 +0800852 /* establish new bindings */
Chia-I Wud19afc52010-10-23 12:52:26 +0800853 if (ctx) {
854 if (draw)
855 draw->CurrentContext = ctx;
856 if (read)
857 read->CurrentContext = ctx;
Chia-I Wuea9e5db2010-09-10 18:26:03 +0800858
Chia-I Wud19afc52010-10-23 12:52:26 +0800859 ctx->DrawSurface = draw;
860 ctx->ReadSurface = read;
Chia-I Wuea9e5db2010-09-10 18:26:03 +0800861 }
862
Chia-I Wud19afc52010-10-23 12:52:26 +0800863 assert(old_ctx && old_draw && old_read);
864 *old_ctx = prev_ctx;
865 *old_draw = prev_draw;
866 *old_read = prev_read;
Chia-I Wu959481a2010-01-27 23:31:20 +0800867
868 return EGL_TRUE;
869}