1 /************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 4 * Copyright 2009-2010 Chia-I Wu <olvaffe (at) 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 41 42 /** 43 * Return the API bit (one of EGL_xxx_BIT) of the context. 44 */ 45 static EGLint 46 _eglGetContextAPIBit(_EGLContext *ctx) 47 { 48 EGLint bit = 0; 49 50 switch (ctx->ClientAPI) { 51 case EGL_OPENGL_ES_API: 52 switch (ctx->ClientMajorVersion) { 53 case 1: 54 bit = EGL_OPENGL_ES_BIT; 55 break; 56 case 2: 57 bit = EGL_OPENGL_ES2_BIT; 58 break; 59 case 3: 60 bit = EGL_OPENGL_ES3_BIT_KHR; 61 break; 62 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 */ 83 static EGLint 84 _eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy, 85 const EGLint *attrib_list) 86 { 87 EGLenum api = ctx->ClientAPI; 88 EGLint i, err = EGL_SUCCESS; 89 90 if (!attrib_list) 91 return EGL_SUCCESS; 92 93 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 98 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: 104 /* 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 126 ctx->ClientMajorVersion = val; 127 break; 128 129 case EGL_CONTEXT_MINOR_VERSION_KHR: 130 /* 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)) { 140 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 * 155 * "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." 161 */ 162 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 187 if ((val & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) && 188 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 */ 214 err = EGL_BAD_ATTRIBUTE; 215 break; 216 } 217 218 ctx->Flags |= val; 219 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 259 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 281 if (val == EGL_TRUE) 282 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; 283 break; 284 285 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 315 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 331 /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */ 332 ctx->NoError = !!val; 333 break; 334 335 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 389 case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR: 390 if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR || 391 val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) { 392 ctx->ReleaseBehavior = val; 393 } else { 394 err = EGL_BAD_ATTRIBUTE; 395 } 396 break; 397 398 default: 399 err = EGL_BAD_ATTRIBUTE; 400 break; 401 } 402 403 if (err != EGL_SUCCESS) { 404 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr); 405 break; 406 } 407 } 408 409 if (api == EGL_OPENGL_API) { 410 /* The EGL_KHR_create_context spec says: 411 * 412 * "If the requested OpenGL version is less than 3.2, 413 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the 414 * functionality of the context is determined solely by the 415 * requested version." 416 * 417 * Since the value is ignored, only validate the setting if the version 418 * is >= 3.2. 419 */ 420 if (ctx->ClientMajorVersion >= 4 421 || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) { 422 switch (ctx->Profile) { 423 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR: 424 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR: 425 break; 426 427 default: 428 /* The EGL_KHR_create_context spec says: 429 * 430 * "* If an OpenGL context is requested, the requested version 431 * is greater than 3.2, and the value for attribute 432 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has 433 * any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 434 * and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has 435 * more than one of these bits set; or if the implementation does 436 * not support the requested profile, then an EGL_BAD_MATCH error 437 * is generated." 438 */ 439 err = EGL_BAD_MATCH; 440 break; 441 } 442 } 443 444 /* The EGL_KHR_create_context spec says: 445 * 446 * "* If an OpenGL context is requested and the values for 447 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 448 * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with 449 * the value for attribute 450 * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL 451 * version and feature set that are not defined, than an 452 * EGL_BAD_MATCH error is generated. 453 * 454 * ... Thus, examples of invalid combinations of attributes 455 * include: 456 * 457 * - Major version < 1 or > 4 458 * - Major version == 1 and minor version < 0 or > 5 459 * - Major version == 2 and minor version < 0 or > 1 460 * - Major version == 3 and minor version < 0 or > 2 461 * - Major version == 4 and minor version < 0 or > 2 462 * - Forward-compatible flag set and major version < 3" 463 */ 464 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) 465 err = EGL_BAD_MATCH; 466 467 switch (ctx->ClientMajorVersion) { 468 case 1: 469 if (ctx->ClientMinorVersion > 5 470 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) 471 err = EGL_BAD_MATCH; 472 break; 473 474 case 2: 475 if (ctx->ClientMinorVersion > 1 476 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) 477 err = EGL_BAD_MATCH; 478 break; 479 480 case 3: 481 /* Note: The text above is incorrect. There *is* an OpenGL 3.3! 482 */ 483 if (ctx->ClientMinorVersion > 3) 484 err = EGL_BAD_MATCH; 485 break; 486 487 case 4: 488 default: 489 /* Don't put additional version checks here. We don't know that 490 * there won't be versions > 4.2. 491 */ 492 break; 493 } 494 } else if (api == EGL_OPENGL_ES_API) { 495 /* The EGL_KHR_create_context spec says: 496 * 497 * "* If an OpenGL ES context is requested and the values for 498 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 499 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that 500 * is not defined, than an EGL_BAD_MATCH error is generated. 501 * 502 * ... Examples of invalid combinations of attributes include: 503 * 504 * - Major version < 1 or > 2 505 * - Major version == 1 and minor version < 0 or > 1 506 * - Major version == 2 and minor version != 0 507 */ 508 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) 509 err = EGL_BAD_MATCH; 510 511 switch (ctx->ClientMajorVersion) { 512 case 1: 513 if (ctx->ClientMinorVersion > 1) 514 err = EGL_BAD_MATCH; 515 break; 516 517 case 2: 518 if (ctx->ClientMinorVersion > 0) 519 err = EGL_BAD_MATCH; 520 break; 521 522 case 3: 523 /* Don't put additional version checks here. We don't know that 524 * there won't be versions > 3.0. 525 */ 526 break; 527 528 default: 529 err = EGL_BAD_MATCH; 530 break; 531 } 532 } 533 534 switch (ctx->ResetNotificationStrategy) { 535 case EGL_NO_RESET_NOTIFICATION_KHR: 536 case EGL_LOSE_CONTEXT_ON_RESET_KHR: 537 break; 538 539 default: 540 err = EGL_BAD_ATTRIBUTE; 541 break; 542 } 543 544 /* The EGL_KHR_create_context_no_error spec says: 545 * 546 * "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE at 547 * the same time as a debug or robustness context is specified." 548 */ 549 if (ctx->NoError && (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR || 550 ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) { 551 err = EGL_BAD_MATCH; 552 } 553 554 if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 555 | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 556 | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) { 557 err = EGL_BAD_ATTRIBUTE; 558 } 559 560 return err; 561 } 562 563 564 /** 565 * Initialize the given _EGLContext object to defaults and/or the values 566 * in the attrib_list. 567 * 568 * According to EGL 1.5 Section 3.7: 569 * 570 * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all 571 * purposes except eglCreateContext." 572 * 573 * And since we only support GL and GLES, this is the only place where the 574 * bound API matters at all. We look up the current API from the current 575 * thread, and stash that in the context we're initializing. Our caller is 576 * responsible for determining whether that's an API it supports. 577 */ 578 EGLBoolean 579 _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf, 580 const EGLint *attrib_list) 581 { 582 const EGLenum api = eglQueryAPI(); 583 EGLint err; 584 585 if (api == EGL_NONE) 586 return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); 587 588 _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy); 589 ctx->ClientAPI = api; 590 ctx->Config = conf; 591 ctx->WindowRenderBuffer = EGL_NONE; 592 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 593 594 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */ 595 ctx->ClientMinorVersion = 0; 596 ctx->Flags = 0; 597 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 598 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR; 599 ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; 600 ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR; 601 602 err = _eglParseContextAttribList(ctx, dpy, attrib_list); 603 if (err == EGL_SUCCESS && ctx->Config) { 604 EGLint api_bit; 605 606 api_bit = _eglGetContextAPIBit(ctx); 607 if (!(ctx->Config->RenderableType & api_bit)) { 608 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x", 609 api_bit, ctx->Config->RenderableType); 610 err = EGL_BAD_CONFIG; 611 } 612 } 613 if (err != EGL_SUCCESS) 614 return _eglError(err, "eglCreateContext"); 615 616 return EGL_TRUE; 617 } 618 619 620 static EGLint 621 _eglQueryContextRenderBuffer(_EGLContext *ctx) 622 { 623 _EGLSurface *surf = ctx->DrawSurface; 624 EGLint rb; 625 626 if (!surf) 627 return EGL_NONE; 628 if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE) 629 rb = ctx->WindowRenderBuffer; 630 else 631 rb = surf->RenderBuffer; 632 return rb; 633 } 634 635 636 EGLBoolean 637 _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c, 638 EGLint attribute, EGLint *value) 639 { 640 (void) drv; 641 (void) dpy; 642 643 if (!value) 644 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext"); 645 646 switch (attribute) { 647 case EGL_CONFIG_ID: 648 /* 649 * From EGL_KHR_no_config_context: 650 * 651 * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with 652 * respect to which the context was created, or zero if created 653 * without respect to an EGLConfig." 654 */ 655 *value = c->Config ? c->Config->ConfigID : 0; 656 break; 657 case EGL_CONTEXT_CLIENT_VERSION: 658 *value = c->ClientMajorVersion; 659 break; 660 case EGL_CONTEXT_CLIENT_TYPE: 661 *value = c->ClientAPI; 662 break; 663 case EGL_RENDER_BUFFER: 664 *value = _eglQueryContextRenderBuffer(c); 665 break; 666 case EGL_CONTEXT_PRIORITY_LEVEL_IMG: 667 *value = c->ContextPriority; 668 break; 669 default: 670 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); 671 } 672 673 return EGL_TRUE; 674 } 675 676 677 /** 678 * Bind the context to the thread and return the previous context. 679 * 680 * Note that the context may be NULL. 681 */ 682 _EGLContext * 683 _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t) 684 { 685 _EGLContext *oldCtx; 686 687 oldCtx = t->CurrentContext; 688 if (ctx != oldCtx) { 689 if (oldCtx) 690 oldCtx->Binding = NULL; 691 if (ctx) 692 ctx->Binding = t; 693 694 t->CurrentContext = ctx; 695 } 696 697 return oldCtx; 698 } 699 700 701 /** 702 * Return true if the given context and surfaces can be made current. 703 */ 704 static EGLBoolean 705 _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) 706 { 707 _EGLThreadInfo *t = _eglGetCurrentThread(); 708 _EGLDisplay *dpy; 709 710 if (_eglIsCurrentThreadDummy()) 711 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); 712 713 /* this is easy */ 714 if (!ctx) { 715 if (draw || read) 716 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 717 return EGL_TRUE; 718 } 719 720 dpy = ctx->Resource.Display; 721 if (!dpy->Extensions.KHR_surfaceless_context 722 && (draw == NULL || read == NULL)) 723 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 724 725 /* 726 * The spec says 727 * 728 * "If ctx is current to some other thread, or if either draw or read are 729 * bound to contexts in another thread, an EGL_BAD_ACCESS error is 730 * generated." 731 * 732 * and 733 * 734 * "at most one context may be bound to a particular surface at a given 735 * time" 736 */ 737 if (ctx->Binding && ctx->Binding != t) 738 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 739 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) { 740 if (draw->CurrentContext->Binding != t) 741 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 742 } 743 if (read && read->CurrentContext && read->CurrentContext != ctx) { 744 if (read->CurrentContext->Binding != t) 745 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 746 } 747 748 /* If the context has a config then it must match that of the two 749 * surfaces */ 750 if (ctx->Config) { 751 if ((draw && draw->Config != ctx->Config) || 752 (read && read->Config != ctx->Config)) 753 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 754 } else { 755 /* Otherwise we must be using the EGL_KHR_no_config_context 756 * extension */ 757 assert(dpy->Extensions.KHR_no_config_context); 758 759 /* The extension doesn't permit binding draw and read buffers with 760 * differing contexts */ 761 if (draw && read && draw->Config != read->Config) 762 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 763 } 764 765 return EGL_TRUE; 766 } 767 768 769 /** 770 * Bind the context to the current thread and given surfaces. Return the 771 * previous bound context and surfaces. The caller should unreference the 772 * returned context and surfaces. 773 * 774 * Making a second call with the resources returned by the first call 775 * unsurprisingly undoes the first call, except for the resouce reference 776 * counts. 777 */ 778 EGLBoolean 779 _eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read, 780 _EGLContext **old_ctx, 781 _EGLSurface **old_draw, _EGLSurface **old_read) 782 { 783 _EGLThreadInfo *t = _eglGetCurrentThread(); 784 _EGLContext *prev_ctx; 785 _EGLSurface *prev_draw, *prev_read; 786 787 if (!_eglCheckMakeCurrent(ctx, draw, read)) 788 return EGL_FALSE; 789 790 /* increment refcounts before binding */ 791 _eglGetContext(ctx); 792 _eglGetSurface(draw); 793 _eglGetSurface(read); 794 795 /* bind the new context */ 796 prev_ctx = _eglBindContextToThread(ctx, t); 797 798 /* break previous bindings */ 799 if (prev_ctx) { 800 prev_draw = prev_ctx->DrawSurface; 801 prev_read = prev_ctx->ReadSurface; 802 803 if (prev_draw) 804 prev_draw->CurrentContext = NULL; 805 if (prev_read) 806 prev_read->CurrentContext = NULL; 807 808 prev_ctx->DrawSurface = NULL; 809 prev_ctx->ReadSurface = NULL; 810 } 811 else { 812 prev_draw = prev_read = NULL; 813 } 814 815 /* establish new bindings */ 816 if (ctx) { 817 if (draw) 818 draw->CurrentContext = ctx; 819 if (read) 820 read->CurrentContext = ctx; 821 822 ctx->DrawSurface = draw; 823 ctx->ReadSurface = read; 824 } 825 826 assert(old_ctx && old_draw && old_read); 827 *old_ctx = prev_ctx; 828 *old_draw = prev_draw; 829 *old_read = prev_read; 830 831 return EGL_TRUE; 832 } 833