1/************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 4 * 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 31#include <assert.h> 32#include <stdlib.h> 33#include <string.h> 34#include "eglconfig.h" 35#include "eglcontext.h" 36#include "egldisplay.h" 37#include "eglcurrent.h" 38#include "eglsurface.h" 39#include "egllog.h" 40#include "util/macros.h" 41 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: 53 switch (ctx->ClientMajorVersion) { 54 case 1: 55 bit = EGL_OPENGL_ES_BIT; 56 break; 57 case 2: 58 bit = EGL_OPENGL_ES2_BIT; 59 break; 60 case 3: 61 bit = EGL_OPENGL_ES3_BIT_KHR; 62 break; 63 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 85_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *disp, 86 const EGLint *attrib_list) 87{ 88 EGLenum api = ctx->ClientAPI; 89 EGLint i, err = EGL_SUCCESS; 90 91 if (!attrib_list) 92 return EGL_SUCCESS; 93 94 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 99 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: 105 /* 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 && 122 (!disp->Extensions.KHR_create_context || api != EGL_OPENGL_API))) { 123 err = EGL_BAD_ATTRIBUTE; 124 break; 125 } 126 127 ctx->ClientMajorVersion = val; 128 break; 129 130 case EGL_CONTEXT_MINOR_VERSION_KHR: 131 /* 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 */ 139 if (!disp->Extensions.KHR_create_context || 140 (api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) { 141 err = EGL_BAD_ATTRIBUTE; 142 break; 143 } 144 145 ctx->ClientMinorVersion = val; 146 break; 147 148 case EGL_CONTEXT_FLAGS_KHR: 149 if (!disp->Extensions.KHR_create_context) { 150 err = EGL_BAD_ATTRIBUTE; 151 break; 152 } 153 154 /* The EGL_KHR_create_context spec says: 155 * 156 * "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." 162 */ 163 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." 181 * 182 * Note: since the forward-compatible flag can be set more than one way, 183 * the OpenGL version check is performed once, below. 184 */ 185 if ((val & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) && 186 api != EGL_OPENGL_API) { 187 err = EGL_BAD_ATTRIBUTE; 188 break; 189 } 190 191 if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) && 192 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 */ 218 err = EGL_BAD_ATTRIBUTE; 219 break; 220 } 221 222 ctx->Flags |= val; 223 break; 224 225 case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR: 226 if (!disp->Extensions.KHR_create_context) { 227 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." 253 * 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." 260 */ 261 if (!(disp->Extensions.KHR_create_context && api == EGL_OPENGL_API) 262 && !(disp->Version >= 15 && (api == EGL_OPENGL_API || 263 api == EGL_OPENGL_ES_API))) { 264 err = EGL_BAD_ATTRIBUTE; 265 break; 266 } 267 268 ctx->ResetNotificationStrategy = val; 269 break; 270 271 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 */ 278 if (!disp->Extensions.EXT_create_context_robustness 279 || 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: 288 if (!disp->Extensions.EXT_create_context_robustness) { 289 err = EGL_BAD_ATTRIBUTE; 290 break; 291 } 292 293 if (val == EGL_TRUE) 294 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; 295 break; 296 297 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS: 298 if (disp->Version < 15) { 299 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: 308 if (disp->Version < 15) { 309 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: 318 if (disp->Version < 15) { 319 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 327 case EGL_CONTEXT_OPENGL_NO_ERROR_KHR: 328 if (disp->Version < 14 || 329 !disp->Extensions.KHR_create_context_no_error) { 330 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) && val == EGL_TRUE) { 339 err = EGL_BAD_ATTRIBUTE; 340 break; 341 } 342 343 /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */ 344 ctx->NoError = !!val; 345 break; 346 347 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 */ 395 if (disp->Extensions.IMG_context_priority & (1 << bit)) 396 ctx->ContextPriority = val; 397 398 break; 399 } 400 401 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 410 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 421 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 444 * 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." 450 */ 451 err = EGL_BAD_MATCH; 452 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: 530 if (ctx->ClientMinorVersion > 0) 531 err = EGL_BAD_MATCH; 532 break; 533 534 case 3: 535 /* Don't put additional version checks here. We don't know that 536 * there won't be versions > 3.0. 537 */ 538 break; 539 540 default: 541 err = EGL_BAD_MATCH; 542 break; 543 } 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 556 /* 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 566 if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 567 | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 568 | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) { 569 err = EGL_BAD_ATTRIBUTE; 570 } 571 572 return err; 573} 574 575 576/** 577 * Initialize the given _EGLContext object to defaults and/or the values 578 * in the attrib_list. 579 * 580 * According to EGL 1.5 Section 3.7: 581 * 582 * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all 583 * purposes except eglCreateContext." 584 * 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. 589 */ 590EGLBoolean 591_eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *conf, 592 const EGLint *attrib_list) 593{ 594 const EGLenum api = eglQueryAPI(); 595 EGLint err; 596 597 if (api == EGL_NONE) 598 return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); 599 600 _eglInitResource(&ctx->Resource, sizeof(*ctx), disp); 601 ctx->ClientAPI = api; 602 ctx->Config = conf; 603 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 604 605 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */ 606 ctx->ClientMinorVersion = 0; 607 ctx->Flags = 0; 608 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR; 609 ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; 610 ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR; 611 612 err = _eglParseContextAttribList(ctx, disp, attrib_list); 613 if (err == EGL_SUCCESS && ctx->Config) { 614 EGLint api_bit; 615 616 api_bit = _eglGetContextAPIBit(ctx); 617 if (!(ctx->Config->RenderableType & api_bit)) { 618 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x", 619 api_bit, ctx->Config->RenderableType); 620 err = EGL_BAD_CONFIG; 621 } 622 } 623 if (err != EGL_SUCCESS) 624 return _eglError(err, "eglCreateContext"); 625 626 return EGL_TRUE; 627} 628 629 630static EGLint 631_eglQueryContextRenderBuffer(_EGLContext *ctx) 632{ 633 _EGLSurface *surf = ctx->DrawSurface; 634 635 /* 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 */ 640 if (!surf) 641 return EGL_NONE; 642 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 } 670} 671 672 673EGLBoolean 674_eglQueryContext(_EGLContext *c, EGLint attribute, EGLint *value) 675{ 676 if (!value) 677 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext"); 678 679 switch (attribute) { 680 case EGL_CONFIG_ID: 681 /* 682 * From EGL_KHR_no_config_context: 683 * 684 * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with 685 * respect to which the context was created, or zero if created 686 * without respect to an EGLConfig." 687 */ 688 *value = c->Config ? c->Config->ConfigID : 0; 689 break; 690 case EGL_CONTEXT_CLIENT_VERSION: 691 *value = c->ClientMajorVersion; 692 break; 693 case EGL_CONTEXT_CLIENT_TYPE: 694 *value = c->ClientAPI; 695 break; 696 case EGL_RENDER_BUFFER: 697 *value = _eglQueryContextRenderBuffer(c); 698 break; 699 case EGL_CONTEXT_PRIORITY_LEVEL_IMG: 700 *value = c->ContextPriority; 701 break; 702 default: 703 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); 704 } 705 706 return EGL_TRUE; 707} 708 709 710/** 711 * Bind the context to the thread and return the previous context. 712 * 713 * Note that the context may be NULL. 714 */ 715_EGLContext * 716_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t) 717{ 718 _EGLContext *oldCtx; 719 720 oldCtx = t->CurrentContext; 721 if (ctx != oldCtx) { 722 if (oldCtx) 723 oldCtx->Binding = NULL; 724 if (ctx) 725 ctx->Binding = t; 726 727 t->CurrentContext = ctx; 728 } 729 730 return oldCtx; 731} 732 733 734/** 735 * Return true if the given context and surfaces can be made current. 736 */ 737static EGLBoolean 738_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) 739{ 740 _EGLThreadInfo *t = _eglGetCurrentThread(); 741 _EGLDisplay *disp; 742 743 /* this is easy */ 744 if (!ctx) { 745 if (draw || read) 746 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 747 return EGL_TRUE; 748 } 749 750 disp = ctx->Resource.Display; 751 if (!disp->Extensions.KHR_surfaceless_context 752 && (draw == NULL || read == NULL)) 753 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 754 755 /* 756 * The spec says 757 * 758 * "If ctx is current to some other thread, or if either draw or read are 759 * bound to contexts in another thread, an EGL_BAD_ACCESS error is 760 * generated." 761 * 762 * and 763 * 764 * "at most one context may be bound to a particular surface at a given 765 * time" 766 */ 767 if (ctx->Binding && ctx->Binding != t) 768 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 769 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) { 770 if (draw->CurrentContext->Binding != t) 771 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 772 } 773 if (read && read->CurrentContext && read->CurrentContext != ctx) { 774 if (read->CurrentContext->Binding != t) 775 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 776 } 777 778 /* If the context has a config then it must match that of the two 779 * surfaces */ 780 if (ctx->Config) { 781 if ((draw && draw->Config != ctx->Config) || 782 (read && read->Config != ctx->Config)) 783 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 784 } else { 785 /* Otherwise we must be using the EGL_KHR_no_config_context 786 * extension */ 787 assert(disp->Extensions.KHR_no_config_context); 788 789 /* The extension doesn't permit binding draw and read buffers with 790 * differing contexts */ 791 if (draw && read && draw->Config != read->Config) 792 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 793 } 794 795 return EGL_TRUE; 796} 797 798 799/** 800 * Bind the context to the current thread and given surfaces. Return the 801 * previous bound context and surfaces. The caller should unreference the 802 * returned context and surfaces. 803 * 804 * Making a second call with the resources returned by the first call 805 * unsurprisingly undoes the first call, except for the resouce reference 806 * counts. 807 */ 808EGLBoolean 809_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read, 810 _EGLContext **old_ctx, 811 _EGLSurface **old_draw, _EGLSurface **old_read) 812{ 813 _EGLThreadInfo *t = _eglGetCurrentThread(); 814 _EGLContext *prev_ctx; 815 _EGLSurface *prev_draw, *prev_read; 816 817 if (!_eglCheckMakeCurrent(ctx, draw, read)) 818 return EGL_FALSE; 819 820 /* increment refcounts before binding */ 821 _eglGetContext(ctx); 822 _eglGetSurface(draw); 823 _eglGetSurface(read); 824 825 /* bind the new context */ 826 prev_ctx = _eglBindContextToThread(ctx, t); 827 828 /* break previous bindings */ 829 if (prev_ctx) { 830 prev_draw = prev_ctx->DrawSurface; 831 prev_read = prev_ctx->ReadSurface; 832 833 if (prev_draw) 834 prev_draw->CurrentContext = NULL; 835 if (prev_read) 836 prev_read->CurrentContext = NULL; 837 838 prev_ctx->DrawSurface = NULL; 839 prev_ctx->ReadSurface = NULL; 840 } 841 else { 842 prev_draw = prev_read = NULL; 843 } 844 845 /* establish new bindings */ 846 if (ctx) { 847 if (draw) 848 draw->CurrentContext = ctx; 849 if (read) 850 read->CurrentContext = ctx; 851 852 ctx->DrawSurface = draw; 853 ctx->ReadSurface = read; 854 } 855 856 assert(old_ctx && old_draw && old_read); 857 *old_ctx = prev_ctx; 858 *old_draw = prev_draw; 859 *old_read = prev_read; 860 861 return EGL_TRUE; 862} 863