blob: 8c64f9ab82e8dbe1f898b09330afa34508f7e3ff [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"
40
41
42/**
43 * Return the API bit (one of EGL_xxx_BIT) of the context.
44 */
45static EGLint
46_eglGetContextAPIBit(_EGLContext *ctx)
47{
48 EGLint bit = 0;
49
50 switch (ctx->ClientAPI) {
51 case EGL_OPENGL_ES_API:
Ian Romanick3fd79dd2012-07-18 15:59:15 -070052 switch (ctx->ClientMajorVersion) {
Chia-I Wucaa5c8d2010-01-31 12:57:53 +080053 case 1:
54 bit = EGL_OPENGL_ES_BIT;
55 break;
56 case 2:
57 bit = EGL_OPENGL_ES2_BIT;
58 break;
Chad Versaceeb099402012-11-20 13:43:11 -080059 case 3:
60 bit = EGL_OPENGL_ES3_BIT_KHR;
61 break;
Chia-I Wucaa5c8d2010-01-31 12:57:53 +080062 default:
63 break;
64 }
65 break;
66 case EGL_OPENVG_API:
67 bit = EGL_OPENVG_BIT;
68 break;
69 case EGL_OPENGL_API:
70 bit = EGL_OPENGL_BIT;
71 break;
72 default:
73 break;
74 }
75
76 return bit;
77}
78
79
80/**
81 * Parse the list of context attributes and return the proper error code.
82 */
83static EGLint
Ian Romanick63beb3d2012-07-19 11:10:15 -070084_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy,
85 const EGLint *attrib_list)
Chia-I Wucaa5c8d2010-01-31 12:57:53 +080086{
87 EGLenum api = ctx->ClientAPI;
88 EGLint i, err = EGL_SUCCESS;
89
90 if (!attrib_list)
91 return EGL_SUCCESS;
92
Ian Romanick63beb3d2012-07-19 11:10:15 -070093 if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) {
94 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]);
95 return EGL_BAD_ATTRIBUTE;
96 }
97
Chia-I Wucaa5c8d2010-01-31 12:57:53 +080098 for (i = 0; attrib_list[i] != EGL_NONE; i++) {
99 EGLint attr = attrib_list[i++];
100 EGLint val = attrib_list[i];
101
102 switch (attr) {
103 case EGL_CONTEXT_CLIENT_VERSION:
Frank Binnsd9603be2015-08-12 16:36:00 +0100104 /* The EGL 1.4 spec says:
105 *
106 * "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the
107 * current rendering API is EGL_OPENGL_ES_API"
108 *
109 * The EGL_KHR_create_context spec says:
110 *
111 * "EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098
112 * (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)"
113 *
114 * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
115 * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
116 * version. They are only meaningful for OpenGL and OpenGL ES
117 * contexts, and specifying them for other types of contexts will
118 * generate an error."
119 */
120 if ((api != EGL_OPENGL_ES_API &&
121 (!dpy->Extensions.KHR_create_context || api != EGL_OPENGL_API))) {
122 err = EGL_BAD_ATTRIBUTE;
123 break;
124 }
125
Ian Romanick3fd79dd2012-07-18 15:59:15 -0700126 ctx->ClientMajorVersion = val;
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800127 break;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700128
129 case EGL_CONTEXT_MINOR_VERSION_KHR:
Frank Binnsd9603be2015-08-12 16:36:00 +0100130 /* The EGL_KHR_create_context spec says:
131 *
132 * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
133 * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API
134 * version. They are only meaningful for OpenGL and OpenGL ES
135 * contexts, and specifying them for other types of contexts will
136 * generate an error."
137 */
138 if (!dpy->Extensions.KHR_create_context ||
139 (api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) {
Ian Romanick63beb3d2012-07-19 11:10:15 -0700140 err = EGL_BAD_ATTRIBUTE;
141 break;
142 }
143
144 ctx->ClientMinorVersion = val;
145 break;
146
147 case EGL_CONTEXT_FLAGS_KHR:
148 if (!dpy->Extensions.KHR_create_context) {
149 err = EGL_BAD_ATTRIBUTE;
150 break;
151 }
152
153 /* The EGL_KHR_create_context spec says:
154 *
Matthew Waters11cabc42015-09-14 18:35:45 +0100155 * "If the EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR flag bit is set in
156 * EGL_CONTEXT_FLAGS_KHR, then a <debug context> will be created.
157 * [...]
158 * In some cases a debug context may be identical to a non-debug
159 * context. This bit is supported for OpenGL and OpenGL ES
160 * contexts."
Ian Romanick63beb3d2012-07-19 11:10:15 -0700161 */
Matthew Waters11cabc42015-09-14 18:35:45 +0100162 if ((val & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR) &&
163 (api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API)) {
164 err = EGL_BAD_ATTRIBUTE;
165 break;
166 }
167
168 /* The EGL_KHR_create_context spec says:
169 *
170 * "If the EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR flag bit
171 * is set in EGL_CONTEXT_FLAGS_KHR, then a <forward-compatible>
172 * context will be created. Forward-compatible contexts are
173 * defined only for OpenGL versions 3.0 and later. They must not
174 * support functionality marked as <deprecated> by that version of
175 * the API, while a non-forward-compatible context must support
176 * all functionality in that version, deprecated or not. This bit
177 * is supported for OpenGL contexts, and requesting a
178 * forward-compatible context for OpenGL versions less than 3.0
179 * will generate an error."
180 */
181 if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) &&
182 (api != EGL_OPENGL_API || ctx->ClientMajorVersion < 3)) {
183 err = EGL_BAD_ATTRIBUTE;
184 break;
185 }
186
Matthew Waters11cabc42015-09-14 18:35:45 +0100187 if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) &&
Chad Versaceb85c0b52016-12-22 17:06:14 -0800188 api != EGL_OPENGL_API) {
189 /* The EGL_KHR_create_context spec says:
190 *
191 * 10) Which error should be generated if robust buffer access
192 * or reset notifications are requested under OpenGL ES?
193 *
194 * As per Issue 6, this extension does not support creating
195 * robust contexts for OpenGL ES. This is only supported via
196 * the EGL_EXT_create_context_robustness extension.
197 *
198 * Attempting to use this extension to create robust OpenGL
199 * ES context will generate an EGL_BAD_ATTRIBUTE error. This
200 * specific error is generated because this extension does
201 * not define the EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR
202 * and EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR
203 * bits for OpenGL ES contexts. Thus, use of these bits fall
204 * under condition described by: "If an attribute is
205 * specified that is not meaningful for the client API
206 * type.." in the above specification.
207 *
208 * The spec requires that we emit the error even if the display
209 * supports EGL_EXT_create_context_robustness. To create a robust
210 * GLES context, the *attribute*
211 * EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT must be used, not the
212 * *flag* EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR.
213 */
Ian Romanick63beb3d2012-07-19 11:10:15 -0700214 err = EGL_BAD_ATTRIBUTE;
215 break;
216 }
217
Marek Olšákf9f89442015-05-12 00:44:20 +0200218 ctx->Flags |= val;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700219 break;
220
221 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
222 if (!dpy->Extensions.KHR_create_context) {
223 err = EGL_BAD_ATTRIBUTE;
224 break;
225 }
226
227 /* The EGL_KHR_create_context spec says:
228 *
229 * "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
230 * OpenGL contexts, and specifying it for other types of
231 * contexts, including OpenGL ES contexts, will generate an
232 * error."
233 */
234 if (api != EGL_OPENGL_API) {
235 err = EGL_BAD_ATTRIBUTE;
236 break;
237 }
238
239 ctx->Profile = val;
240 break;
241
242 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
243 /* The EGL_KHR_create_context spec says:
244 *
245 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
246 * meaningful for OpenGL contexts, and specifying it for other
247 * types of contexts, including OpenGL ES contexts, will generate
248 * an error."
249 */
250 if (!dpy->Extensions.KHR_create_context
251 || api != EGL_OPENGL_API) {
252 err = EGL_BAD_ATTRIBUTE;
253 break;
254 }
255
256 ctx->ResetNotificationStrategy = val;
257 break;
258
Ian Romanickf1715712012-07-19 15:08:06 -0700259 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
260 /* The EGL_EXT_create_context_robustness spec says:
261 *
262 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
263 * meaningful for OpenGL ES contexts, and specifying it for other
264 * types of contexts will generate an EGL_BAD_ATTRIBUTE error."
265 */
266 if (!dpy->Extensions.EXT_create_context_robustness
267 || api != EGL_OPENGL_ES_API) {
268 err = EGL_BAD_ATTRIBUTE;
269 break;
270 }
271
272 ctx->ResetNotificationStrategy = val;
273 break;
274
275 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
276 if (!dpy->Extensions.EXT_create_context_robustness) {
277 err = EGL_BAD_ATTRIBUTE;
278 break;
279 }
280
Marek Olšákf9f89442015-05-12 00:44:20 +0200281 if (val == EGL_TRUE)
282 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
Ian Romanickf1715712012-07-19 15:08:06 -0700283 break;
284
Marek Olšák706466f2015-05-12 00:44:56 +0200285 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS:
286 if (dpy->Version < 15) {
287 err = EGL_BAD_ATTRIBUTE;
288 break;
289 }
290
291 if (val == EGL_TRUE)
292 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
293 break;
294
295 case EGL_CONTEXT_OPENGL_DEBUG:
296 if (dpy->Version < 15) {
297 err = EGL_BAD_ATTRIBUTE;
298 break;
299 }
300
301 if (val == EGL_TRUE)
302 ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR;
303 break;
304
305 case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE:
306 if (dpy->Version < 15) {
307 err = EGL_BAD_ATTRIBUTE;
308 break;
309 }
310
311 if (val == EGL_TRUE)
312 ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR;
313 break;
314
Grigori Goronzy49095192017-06-29 02:44:03 +0200315 case EGL_CONTEXT_OPENGL_NO_ERROR_KHR:
316 if (dpy->Version < 14 ||
317 !dpy->Extensions.KHR_create_context_no_error) {
318 err = EGL_BAD_ATTRIBUTE;
319 break;
320 }
321
322 /* The KHR_no_error spec only applies against OpenGL 2.0+ and
323 * OpenGL ES 2.0+
324 */
325 if ((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) ||
326 ctx->ClientMajorVersion < 2) {
327 err = EGL_BAD_ATTRIBUTE;
328 break;
329 }
330
Grigori Goronzy49095192017-06-29 02:44:03 +0200331 /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */
332 ctx->NoError = !!val;
333 break;
334
Chris Wilson95ecf3d2016-10-27 19:34:46 +0100335 case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
336 /* The EGL_IMG_context_priority spec says:
337 *
338 * "EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of
339 * the context to be created. This attribute is a hint, as an
340 * implementation may not support multiple contexts at some
341 * priority levels and system policy may limit access to high
342 * priority contexts to appropriate system privilege level. The
343 * default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is
344 * EGL_CONTEXT_PRIORITY_MEDIUM_IMG."
345 */
346 {
347 int bit;
348
349 switch (val) {
350 case EGL_CONTEXT_PRIORITY_HIGH_IMG:
351 bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT;
352 break;
353 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG:
354 bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT;
355 break;
356 case EGL_CONTEXT_PRIORITY_LOW_IMG:
357 bit = __EGL_CONTEXT_PRIORITY_LOW_BIT;
358 break;
359 default:
360 bit = -1;
361 break;
362 }
363
364 if (bit < 0) {
365 err = EGL_BAD_ATTRIBUTE;
366 break;
367 }
368
369 /* "This extension allows an EGLContext to be created with a
370 * priority hint. It is possible that an implementation will not
371 * honour the hint, especially if there are constraints on the
372 * number of high priority contexts available in the system, or
373 * system policy limits access to high priority contexts to
374 * appropriate system privilege level. A query is provided to find
375 * the real priority level assigned to the context after creation."
376 *
377 * We currently assume that the driver applies the priority hint
378 * and filters out any it cannot handle during the screen setup,
379 * e.g. dri2_setup_screen(). As such we can mask any change that
380 * the driver would fail, and ctx->ContextPriority matches the
381 * hint applied to the driver/hardware backend.
382 */
383 if (dpy->Extensions.IMG_context_priority & (1 << bit))
384 ctx->ContextPriority = val;
385
386 break;
387 }
388
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800389 default:
390 err = EGL_BAD_ATTRIBUTE;
391 break;
392 }
393
394 if (err != EGL_SUCCESS) {
395 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
396 break;
397 }
398 }
399
Ian Romanick63beb3d2012-07-19 11:10:15 -0700400 if (api == EGL_OPENGL_API) {
401 /* The EGL_KHR_create_context spec says:
402 *
403 * "If the requested OpenGL version is less than 3.2,
404 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
405 * functionality of the context is determined solely by the
406 * requested version."
407 *
408 * Since the value is ignored, only validate the setting if the version
409 * is >= 3.2.
410 */
411 if (ctx->ClientMajorVersion >= 4
412 || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
413 switch (ctx->Profile) {
414 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
415 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
416 break;
417
418 default:
419 /* The EGL_KHR_create_context spec says:
420 *
421 * "* If an OpenGL context is requested, the requested version
422 * is greater than 3.2, and the value for attribute
Matt Turner587d5db2012-10-08 17:01:34 -0700423 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
424 * any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
425 * and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has
426 * more than one of these bits set; or if the implementation does
427 * not support the requested profile, then an EGL_BAD_MATCH error
428 * is generated."
Ian Romanick63beb3d2012-07-19 11:10:15 -0700429 */
Matt Turner587d5db2012-10-08 17:01:34 -0700430 err = EGL_BAD_MATCH;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700431 break;
432 }
433 }
434
435 /* The EGL_KHR_create_context spec says:
436 *
437 * "* If an OpenGL context is requested and the values for
438 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
439 * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
440 * the value for attribute
441 * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
442 * version and feature set that are not defined, than an
443 * EGL_BAD_MATCH error is generated.
444 *
445 * ... Thus, examples of invalid combinations of attributes
446 * include:
447 *
448 * - Major version < 1 or > 4
449 * - Major version == 1 and minor version < 0 or > 5
450 * - Major version == 2 and minor version < 0 or > 1
451 * - Major version == 3 and minor version < 0 or > 2
452 * - Major version == 4 and minor version < 0 or > 2
453 * - Forward-compatible flag set and major version < 3"
454 */
455 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
456 err = EGL_BAD_MATCH;
457
458 switch (ctx->ClientMajorVersion) {
459 case 1:
460 if (ctx->ClientMinorVersion > 5
461 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
462 err = EGL_BAD_MATCH;
463 break;
464
465 case 2:
466 if (ctx->ClientMinorVersion > 1
467 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
468 err = EGL_BAD_MATCH;
469 break;
470
471 case 3:
472 /* Note: The text above is incorrect. There *is* an OpenGL 3.3!
473 */
474 if (ctx->ClientMinorVersion > 3)
475 err = EGL_BAD_MATCH;
476 break;
477
478 case 4:
479 default:
480 /* Don't put additional version checks here. We don't know that
481 * there won't be versions > 4.2.
482 */
483 break;
484 }
485 } else if (api == EGL_OPENGL_ES_API) {
486 /* The EGL_KHR_create_context spec says:
487 *
488 * "* If an OpenGL ES context is requested and the values for
489 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
490 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
491 * is not defined, than an EGL_BAD_MATCH error is generated.
492 *
493 * ... Examples of invalid combinations of attributes include:
494 *
495 * - Major version < 1 or > 2
496 * - Major version == 1 and minor version < 0 or > 1
497 * - Major version == 2 and minor version != 0
498 */
499 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
500 err = EGL_BAD_MATCH;
501
502 switch (ctx->ClientMajorVersion) {
503 case 1:
504 if (ctx->ClientMinorVersion > 1)
505 err = EGL_BAD_MATCH;
506 break;
507
508 case 2:
Ian Romanickdbecb412012-07-19 16:12:13 -0700509 if (ctx->ClientMinorVersion > 0)
510 err = EGL_BAD_MATCH;
511 break;
512
513 case 3:
Ian Romanick63beb3d2012-07-19 11:10:15 -0700514 /* Don't put additional version checks here. We don't know that
Ian Romanickdbecb412012-07-19 16:12:13 -0700515 * there won't be versions > 3.0.
Ian Romanick63beb3d2012-07-19 11:10:15 -0700516 */
517 break;
Anuj Phogatd308f572014-06-18 17:35:18 -0700518
519 default:
520 err = EGL_BAD_MATCH;
521 break;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700522 }
523 }
524
525 switch (ctx->ResetNotificationStrategy) {
526 case EGL_NO_RESET_NOTIFICATION_KHR:
527 case EGL_LOSE_CONTEXT_ON_RESET_KHR:
528 break;
529
530 default:
531 err = EGL_BAD_ATTRIBUTE;
532 break;
533 }
534
Grigori Goronzy39bf7752017-07-19 23:51:55 +0200535 /* The EGL_KHR_create_context_no_error spec says:
536 *
537 * "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE at
538 * the same time as a debug or robustness context is specified."
539 */
540 if (ctx->NoError && (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR ||
541 ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) {
542 err = EGL_BAD_MATCH;
543 }
544
Matt Turner971750e2012-08-24 16:26:54 -0700545 if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
Ian Romanick63beb3d2012-07-19 11:10:15 -0700546 | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
547 | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
548 err = EGL_BAD_ATTRIBUTE;
549 }
550
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800551 return err;
552}
Brian Pauladbff7e2005-04-22 21:09:39 +0000553
554
555/**
Brian Paul5e7dba52008-05-27 14:21:25 -0600556 * Initialize the given _EGLContext object to defaults and/or the values
557 * in the attrib_list.
Adam Jacksona2797602016-09-07 17:41:56 -0400558 *
559 * According to EGL 1.5 Section 3.7:
560 *
Adam Jacksondbda3752016-09-08 13:21:24 -0400561 * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all
562 * purposes except eglCreateContext."
Adam Jacksona2797602016-09-07 17:41:56 -0400563 *
564 * And since we only support GL and GLES, this is the only place where the
565 * bound API matters at all. We look up the current API from the current
566 * thread, and stash that in the context we're initializing. Our caller is
567 * responsible for determining whether that's an API it supports.
Brian Pauladbff7e2005-04-22 21:09:39 +0000568 */
Brian Pauld548bf42005-11-27 23:57:19 +0000569EGLBoolean
Chia-I Wud69242b2010-01-31 13:33:57 +0800570_eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
571 const EGLint *attrib_list)
Brian Pauladbff7e2005-04-22 21:09:39 +0000572{
Brian Pauld5078b92008-05-30 13:45:40 -0600573 const EGLenum api = eglQueryAPI();
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800574 EGLint err;
Brian Pauld5078b92008-05-30 13:45:40 -0600575
Emil Velikovc58af5c2017-06-20 15:40:28 +0100576 if (api == EGL_NONE)
577 return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
Brian Pauld548bf42005-11-27 23:57:19 +0000578
Chia-I Wudc97e542014-02-19 12:57:15 +0800579 _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800580 ctx->ClientAPI = api;
581 ctx->Config = conf;
582 ctx->WindowRenderBuffer = EGL_NONE;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700583 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
Brian Paul9f6a4e22008-06-19 21:19:33 -0600584
Ian Romanick3fd79dd2012-07-18 15:59:15 -0700585 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
586 ctx->ClientMinorVersion = 0;
Ian Romanick63beb3d2012-07-19 11:10:15 -0700587 ctx->Flags = 0;
588 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
589 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
Chris Wilson95ecf3d2016-10-27 19:34:46 +0100590 ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG;
Brian Paula8533d52008-06-19 16:06:56 -0600591
Ian Romanick63beb3d2012-07-19 11:10:15 -0700592 err = _eglParseContextAttribList(ctx, dpy, attrib_list);
Chia-I Wu5eb33592010-08-20 13:19:10 +0800593 if (err == EGL_SUCCESS && ctx->Config) {
Chia-I Wu3fa21882010-10-14 16:38:58 +0800594 EGLint api_bit;
Chia-I Wu5eb33592010-08-20 13:19:10 +0800595
Chia-I Wu5eb33592010-08-20 13:19:10 +0800596 api_bit = _eglGetContextAPIBit(ctx);
Chia-I Wu3fa21882010-10-14 16:38:58 +0800597 if (!(ctx->Config->RenderableType & api_bit)) {
Chia-I Wu5eb33592010-08-20 13:19:10 +0800598 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
Chia-I Wu3fa21882010-10-14 16:38:58 +0800599 api_bit, ctx->Config->RenderableType);
Chia-I Wu5eb33592010-08-20 13:19:10 +0800600 err = EGL_BAD_CONFIG;
601 }
602 }
Chia-I Wucaa5c8d2010-01-31 12:57:53 +0800603 if (err != EGL_SUCCESS)
604 return _eglError(err, "eglCreateContext");
Brian Pauld548bf42005-11-27 23:57:19 +0000605
606 return EGL_TRUE;
Brian Pauladbff7e2005-04-22 21:09:39 +0000607}
608
609
Chia-I Wud845f272009-09-27 17:00:51 +0800610static EGLint
611_eglQueryContextRenderBuffer(_EGLContext *ctx)
612{
613 _EGLSurface *surf = ctx->DrawSurface;
614 EGLint rb;
615
616 if (!surf)
617 return EGL_NONE;
618 if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
619 rb = ctx->WindowRenderBuffer;
620 else
621 rb = surf->RenderBuffer;
622 return rb;
623}
Chia-I Wud845f272009-09-27 17:00:51 +0800624
625
Brian Pauladbff7e2005-04-22 21:09:39 +0000626EGLBoolean
Chia-I Wu2f2cf462009-08-11 17:09:39 +0800627_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
Brian Pauld548bf42005-11-27 23:57:19 +0000628 EGLint attribute, EGLint *value)
Brian Pauladbff7e2005-04-22 21:09:39 +0000629{
Brian Pauladbff7e2005-04-22 21:09:39 +0000630 (void) drv;
631 (void) dpy;
632
Chia-I Wud845f272009-09-27 17:00:51 +0800633 if (!value)
634 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
635
Brian Pauladbff7e2005-04-22 21:09:39 +0000636 switch (attribute) {
637 case EGL_CONFIG_ID:
Adam Jacksoncc45a5c2016-09-09 12:25:33 -0400638 /*
639 * From EGL_KHR_no_config_context:
640 *
641 * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with
642 * respect to which the context was created, or zero if created
643 * without respect to an EGLConfig."
644 */
645 *value = c->Config ? c->Config->ConfigID : 0;
Chia-I Wud845f272009-09-27 17:00:51 +0800646 break;
647 case EGL_CONTEXT_CLIENT_VERSION:
Ian Romanick3fd79dd2012-07-18 15:59:15 -0700648 *value = c->ClientMajorVersion;
Chia-I Wud845f272009-09-27 17:00:51 +0800649 break;
Brian Paulb2006a42006-01-30 00:10:55 +0000650 case EGL_CONTEXT_CLIENT_TYPE:
651 *value = c->ClientAPI;
Chia-I Wud845f272009-09-27 17:00:51 +0800652 break;
653 case EGL_RENDER_BUFFER:
654 *value = _eglQueryContextRenderBuffer(c);
655 break;
Chris Wilson95ecf3d2016-10-27 19:34:46 +0100656 case EGL_CONTEXT_PRIORITY_LEVEL_IMG:
657 *value = c->ContextPriority;
658 break;
Brian Pauladbff7e2005-04-22 21:09:39 +0000659 default:
Chia-I Wud845f272009-09-27 17:00:51 +0800660 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
Brian Pauladbff7e2005-04-22 21:09:39 +0000661 }
Chia-I Wud845f272009-09-27 17:00:51 +0800662
663 return EGL_TRUE;
Brian Pauladbff7e2005-04-22 21:09:39 +0000664}
665
666
667/**
Chia-I Wu7c092962010-01-26 16:53:40 +0800668 * Bind the context to the thread and return the previous context.
669 *
670 * Note that the context may be NULL.
671 */
Eric Anholt3b7b6ad2012-12-27 17:39:37 -0800672_EGLContext *
Chia-I Wu7c092962010-01-26 16:53:40 +0800673_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
674{
Chia-I Wu7c092962010-01-26 16:53:40 +0800675 _EGLContext *oldCtx;
676
Kyle Brenneman6e066f72016-07-08 15:21:17 -0600677 oldCtx = t->CurrentContext;
Chia-I Wu551bfe72010-03-28 02:11:16 +0800678 if (ctx != oldCtx) {
679 if (oldCtx)
680 oldCtx->Binding = NULL;
681 if (ctx)
682 ctx->Binding = t;
Chia-I Wu7c092962010-01-26 16:53:40 +0800683
Kyle Brenneman6e066f72016-07-08 15:21:17 -0600684 t->CurrentContext = ctx;
Chia-I Wu551bfe72010-03-28 02:11:16 +0800685 }
Chia-I Wu7c092962010-01-26 16:53:40 +0800686
687 return oldCtx;
688}
689
690
691/**
692 * Return true if the given context and surfaces can be made current.
693 */
694static EGLBoolean
695_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
696{
697 _EGLThreadInfo *t = _eglGetCurrentThread();
Kristian Høgsberg2c343af2010-07-28 23:54:16 -0400698 _EGLDisplay *dpy;
Chia-I Wu7c092962010-01-26 16:53:40 +0800699
700 if (_eglIsCurrentThreadDummy())
701 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
702
703 /* this is easy */
704 if (!ctx) {
705 if (draw || read)
706 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
707 return EGL_TRUE;
708 }
709
Kristian Høgsberg2c343af2010-07-28 23:54:16 -0400710 dpy = ctx->Resource.Display;
Ian Romanickb50703a2012-07-18 09:38:34 -0700711 if (!dpy->Extensions.KHR_surfaceless_context
712 && (draw == NULL || read == NULL))
Chia-I Wu7c092962010-01-26 16:53:40 +0800713 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
714
Chia-I Wu7c092962010-01-26 16:53:40 +0800715 /*
716 * The spec says
717 *
718 * "If ctx is current to some other thread, or if either draw or read are
719 * bound to contexts in another thread, an EGL_BAD_ACCESS error is
720 * generated."
721 *
Chia-I Wu0d43cbe2010-10-23 16:51:01 +0800722 * and
Chia-I Wu7c092962010-01-26 16:53:40 +0800723 *
724 * "at most one context may be bound to a particular surface at a given
725 * time"
Chia-I Wu7c092962010-01-26 16:53:40 +0800726 */
Chia-I Wu0d43cbe2010-10-23 16:51:01 +0800727 if (ctx->Binding && ctx->Binding != t)
Chia-I Wu7c092962010-01-26 16:53:40 +0800728 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
Chia-I Wu0d43cbe2010-10-23 16:51:01 +0800729 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
Kyle Brenneman6e066f72016-07-08 15:21:17 -0600730 if (draw->CurrentContext->Binding != t)
Chia-I Wu0d43cbe2010-10-23 16:51:01 +0800731 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
732 }
733 if (read && read->CurrentContext && read->CurrentContext != ctx) {
Kyle Brenneman6e066f72016-07-08 15:21:17 -0600734 if (read->CurrentContext->Binding != t)
Chia-I Wu0d43cbe2010-10-23 16:51:01 +0800735 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
736 }
Chia-I Wu7c092962010-01-26 16:53:40 +0800737
Neil Roberts551d4592014-03-07 18:05:47 +0000738 /* If the context has a config then it must match that of the two
739 * surfaces */
740 if (ctx->Config) {
741 if ((draw && draw->Config != ctx->Config) ||
742 (read && read->Config != ctx->Config))
743 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
744 } else {
Adam Jacksond9f5b192016-09-09 12:25:34 -0400745 /* Otherwise we must be using the EGL_KHR_no_config_context
Neil Roberts551d4592014-03-07 18:05:47 +0000746 * extension */
Adam Jacksond9f5b192016-09-09 12:25:34 -0400747 assert(dpy->Extensions.KHR_no_config_context);
Neil Roberts551d4592014-03-07 18:05:47 +0000748
749 /* The extension doesn't permit binding draw and read buffers with
750 * differing contexts */
751 if (draw && read && draw->Config != read->Config)
752 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
753 }
Chia-I Wu7c092962010-01-26 16:53:40 +0800754
Chia-I Wu7c092962010-01-26 16:53:40 +0800755 return EGL_TRUE;
756}
757
758
759/**
Chia-I Wu959481a2010-01-27 23:31:20 +0800760 * Bind the context to the current thread and given surfaces. Return the
Chia-I Wud19afc52010-10-23 12:52:26 +0800761 * previous bound context and surfaces. The caller should unreference the
762 * returned context and surfaces.
763 *
764 * Making a second call with the resources returned by the first call
765 * unsurprisingly undoes the first call, except for the resouce reference
766 * counts.
Chia-I Wu959481a2010-01-27 23:31:20 +0800767 */
768EGLBoolean
Chia-I Wud19afc52010-10-23 12:52:26 +0800769_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
770 _EGLContext **old_ctx,
771 _EGLSurface **old_draw, _EGLSurface **old_read)
Chia-I Wu959481a2010-01-27 23:31:20 +0800772{
773 _EGLThreadInfo *t = _eglGetCurrentThread();
Chia-I Wud19afc52010-10-23 12:52:26 +0800774 _EGLContext *prev_ctx;
775 _EGLSurface *prev_draw, *prev_read;
Chia-I Wu959481a2010-01-27 23:31:20 +0800776
Chia-I Wud19afc52010-10-23 12:52:26 +0800777 if (!_eglCheckMakeCurrent(ctx, draw, read))
Chia-I Wu959481a2010-01-27 23:31:20 +0800778 return EGL_FALSE;
779
Chia-I Wud19afc52010-10-23 12:52:26 +0800780 /* increment refcounts before binding */
781 _eglGetContext(ctx);
782 _eglGetSurface(draw);
783 _eglGetSurface(read);
784
Chia-I Wu959481a2010-01-27 23:31:20 +0800785 /* bind the new context */
Chia-I Wud19afc52010-10-23 12:52:26 +0800786 prev_ctx = _eglBindContextToThread(ctx, t);
Chia-I Wubbe459b2010-04-05 21:26:34 +0800787
Chia-I Wud19afc52010-10-23 12:52:26 +0800788 /* break previous bindings */
789 if (prev_ctx) {
790 prev_draw = prev_ctx->DrawSurface;
791 prev_read = prev_ctx->ReadSurface;
Chia-I Wu848945e2010-04-06 11:51:25 +0800792
Chia-I Wud19afc52010-10-23 12:52:26 +0800793 if (prev_draw)
794 prev_draw->CurrentContext = NULL;
795 if (prev_read)
796 prev_read->CurrentContext = NULL;
Chia-I Wuea9e5db2010-09-10 18:26:03 +0800797
Chia-I Wud19afc52010-10-23 12:52:26 +0800798 prev_ctx->DrawSurface = NULL;
799 prev_ctx->ReadSurface = NULL;
800 }
801 else {
802 prev_draw = prev_read = NULL;
Chia-I Wubbe459b2010-04-05 21:26:34 +0800803 }
804
Chia-I Wuea9e5db2010-09-10 18:26:03 +0800805 /* establish new bindings */
Chia-I Wud19afc52010-10-23 12:52:26 +0800806 if (ctx) {
807 if (draw)
808 draw->CurrentContext = ctx;
809 if (read)
810 read->CurrentContext = ctx;
Chia-I Wuea9e5db2010-09-10 18:26:03 +0800811
Chia-I Wud19afc52010-10-23 12:52:26 +0800812 ctx->DrawSurface = draw;
813 ctx->ReadSurface = read;
Chia-I Wuea9e5db2010-09-10 18:26:03 +0800814 }
815
Chia-I Wud19afc52010-10-23 12:52:26 +0800816 assert(old_ctx && old_draw && old_read);
817 *old_ctx = prev_ctx;
818 *old_draw = prev_draw;
819 *old_read = prev_read;
Chia-I Wu959481a2010-01-27 23:31:20 +0800820
821 return EGL_TRUE;
822}