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 if (!disp->Extensions.KHR_create_context 255 || api != EGL_OPENGL_API) { 256 err = EGL_BAD_ATTRIBUTE; 257 break; 258 } 259 260 ctx->ResetNotificationStrategy = val; 261 break; 262 263 case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: 264 /* The EGL_EXT_create_context_robustness spec says: 265 * 266 * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only 267 * meaningful for OpenGL ES contexts, and specifying it for other 268 * types of contexts will generate an EGL_BAD_ATTRIBUTE error." 269 */ 270 if (!disp->Extensions.EXT_create_context_robustness 271 || api != EGL_OPENGL_ES_API) { 272 err = EGL_BAD_ATTRIBUTE; 273 break; 274 } 275 276 ctx->ResetNotificationStrategy = val; 277 break; 278 279 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: 280 if (!disp->Extensions.EXT_create_context_robustness) { 281 err = EGL_BAD_ATTRIBUTE; 282 break; 283 } 284 285 if (val == EGL_TRUE) 286 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; 287 break; 288 289 case EGL_CONTEXT_OPENGL_ROBUST_ACCESS: 290 if (disp->Version < 15) { 291 err = EGL_BAD_ATTRIBUTE; 292 break; 293 } 294 295 if (val == EGL_TRUE) 296 ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; 297 break; 298 299 case EGL_CONTEXT_OPENGL_DEBUG: 300 if (disp->Version < 15) { 301 err = EGL_BAD_ATTRIBUTE; 302 break; 303 } 304 305 if (val == EGL_TRUE) 306 ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; 307 break; 308 309 case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE: 310 if (disp->Version < 15) { 311 err = EGL_BAD_ATTRIBUTE; 312 break; 313 } 314 315 if (val == EGL_TRUE) 316 ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; 317 break; 318 319 case EGL_CONTEXT_OPENGL_NO_ERROR_KHR: 320 if (disp->Version < 14 || 321 !disp->Extensions.KHR_create_context_no_error) { 322 err = EGL_BAD_ATTRIBUTE; 323 break; 324 } 325 326 /* The KHR_no_error spec only applies against OpenGL 2.0+ and 327 * OpenGL ES 2.0+ 328 */ 329 if ((api != EGL_OPENGL_API && api != EGL_OPENGL_ES_API) || 330 ctx->ClientMajorVersion < 2) { 331 err = EGL_BAD_ATTRIBUTE; 332 break; 333 } 334 335 /* Canonicalize value to EGL_TRUE/EGL_FALSE definitions */ 336 ctx->NoError = !!val; 337 break; 338 339 case EGL_CONTEXT_PRIORITY_LEVEL_IMG: 340 /* The EGL_IMG_context_priority spec says: 341 * 342 * "EGL_CONTEXT_PRIORITY_LEVEL_IMG determines the priority level of 343 * the context to be created. This attribute is a hint, as an 344 * implementation may not support multiple contexts at some 345 * priority levels and system policy may limit access to high 346 * priority contexts to appropriate system privilege level. The 347 * default value for EGL_CONTEXT_PRIORITY_LEVEL_IMG is 348 * EGL_CONTEXT_PRIORITY_MEDIUM_IMG." 349 */ 350 { 351 int bit; 352 353 switch (val) { 354 case EGL_CONTEXT_PRIORITY_HIGH_IMG: 355 bit = __EGL_CONTEXT_PRIORITY_HIGH_BIT; 356 break; 357 case EGL_CONTEXT_PRIORITY_MEDIUM_IMG: 358 bit = __EGL_CONTEXT_PRIORITY_MEDIUM_BIT; 359 break; 360 case EGL_CONTEXT_PRIORITY_LOW_IMG: 361 bit = __EGL_CONTEXT_PRIORITY_LOW_BIT; 362 break; 363 default: 364 bit = -1; 365 break; 366 } 367 368 if (bit < 0) { 369 err = EGL_BAD_ATTRIBUTE; 370 break; 371 } 372 373 /* "This extension allows an EGLContext to be created with a 374 * priority hint. It is possible that an implementation will not 375 * honour the hint, especially if there are constraints on the 376 * number of high priority contexts available in the system, or 377 * system policy limits access to high priority contexts to 378 * appropriate system privilege level. A query is provided to find 379 * the real priority level assigned to the context after creation." 380 * 381 * We currently assume that the driver applies the priority hint 382 * and filters out any it cannot handle during the screen setup, 383 * e.g. dri2_setup_screen(). As such we can mask any change that 384 * the driver would fail, and ctx->ContextPriority matches the 385 * hint applied to the driver/hardware backend. 386 */ 387 if (disp->Extensions.IMG_context_priority & (1 << bit)) 388 ctx->ContextPriority = val; 389 390 break; 391 } 392 393 case EGL_CONTEXT_RELEASE_BEHAVIOR_KHR: 394 if (val == EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR || 395 val == EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR) { 396 ctx->ReleaseBehavior = val; 397 } else { 398 err = EGL_BAD_ATTRIBUTE; 399 } 400 break; 401 402 default: 403 err = EGL_BAD_ATTRIBUTE; 404 break; 405 } 406 407 if (err != EGL_SUCCESS) { 408 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr); 409 break; 410 } 411 } 412 413 if (api == EGL_OPENGL_API) { 414 /* The EGL_KHR_create_context spec says: 415 * 416 * "If the requested OpenGL version is less than 3.2, 417 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the 418 * functionality of the context is determined solely by the 419 * requested version." 420 * 421 * Since the value is ignored, only validate the setting if the version 422 * is >= 3.2. 423 */ 424 if (ctx->ClientMajorVersion >= 4 425 || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) { 426 switch (ctx->Profile) { 427 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR: 428 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR: 429 break; 430 431 default: 432 /* The EGL_KHR_create_context spec says: 433 * 434 * "* If an OpenGL context is requested, the requested version 435 * is greater than 3.2, and the value for attribute 436 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has 437 * any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 438 * and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has 439 * more than one of these bits set; or if the implementation does 440 * not support the requested profile, then an EGL_BAD_MATCH error 441 * is generated." 442 */ 443 err = EGL_BAD_MATCH; 444 break; 445 } 446 } 447 448 /* The EGL_KHR_create_context spec says: 449 * 450 * "* If an OpenGL context is requested and the values for 451 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 452 * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with 453 * the value for attribute 454 * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL 455 * version and feature set that are not defined, than an 456 * EGL_BAD_MATCH error is generated. 457 * 458 * ... Thus, examples of invalid combinations of attributes 459 * include: 460 * 461 * - Major version < 1 or > 4 462 * - Major version == 1 and minor version < 0 or > 5 463 * - Major version == 2 and minor version < 0 or > 1 464 * - Major version == 3 and minor version < 0 or > 2 465 * - Major version == 4 and minor version < 0 or > 2 466 * - Forward-compatible flag set and major version < 3" 467 */ 468 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) 469 err = EGL_BAD_MATCH; 470 471 switch (ctx->ClientMajorVersion) { 472 case 1: 473 if (ctx->ClientMinorVersion > 5 474 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) 475 err = EGL_BAD_MATCH; 476 break; 477 478 case 2: 479 if (ctx->ClientMinorVersion > 1 480 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) 481 err = EGL_BAD_MATCH; 482 break; 483 484 case 3: 485 /* Note: The text above is incorrect. There *is* an OpenGL 3.3! 486 */ 487 if (ctx->ClientMinorVersion > 3) 488 err = EGL_BAD_MATCH; 489 break; 490 491 case 4: 492 default: 493 /* Don't put additional version checks here. We don't know that 494 * there won't be versions > 4.2. 495 */ 496 break; 497 } 498 } else if (api == EGL_OPENGL_ES_API) { 499 /* The EGL_KHR_create_context spec says: 500 * 501 * "* If an OpenGL ES context is requested and the values for 502 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 503 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that 504 * is not defined, than an EGL_BAD_MATCH error is generated. 505 * 506 * ... Examples of invalid combinations of attributes include: 507 * 508 * - Major version < 1 or > 2 509 * - Major version == 1 and minor version < 0 or > 1 510 * - Major version == 2 and minor version != 0 511 */ 512 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) 513 err = EGL_BAD_MATCH; 514 515 switch (ctx->ClientMajorVersion) { 516 case 1: 517 if (ctx->ClientMinorVersion > 1) 518 err = EGL_BAD_MATCH; 519 break; 520 521 case 2: 522 if (ctx->ClientMinorVersion > 0) 523 err = EGL_BAD_MATCH; 524 break; 525 526 case 3: 527 /* Don't put additional version checks here. We don't know that 528 * there won't be versions > 3.0. 529 */ 530 break; 531 532 default: 533 err = EGL_BAD_MATCH; 534 break; 535 } 536 } 537 538 switch (ctx->ResetNotificationStrategy) { 539 case EGL_NO_RESET_NOTIFICATION_KHR: 540 case EGL_LOSE_CONTEXT_ON_RESET_KHR: 541 break; 542 543 default: 544 err = EGL_BAD_ATTRIBUTE; 545 break; 546 } 547 548 /* The EGL_KHR_create_context_no_error spec says: 549 * 550 * "BAD_MATCH is generated if the EGL_CONTEXT_OPENGL_NO_ERROR_KHR is TRUE at 551 * the same time as a debug or robustness context is specified." 552 */ 553 if (ctx->NoError && (ctx->Flags & EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR || 554 ctx->Flags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) { 555 err = EGL_BAD_MATCH; 556 } 557 558 if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 559 | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 560 | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) { 561 err = EGL_BAD_ATTRIBUTE; 562 } 563 564 return err; 565} 566 567 568/** 569 * Initialize the given _EGLContext object to defaults and/or the values 570 * in the attrib_list. 571 * 572 * According to EGL 1.5 Section 3.7: 573 * 574 * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all 575 * purposes except eglCreateContext." 576 * 577 * And since we only support GL and GLES, this is the only place where the 578 * bound API matters at all. We look up the current API from the current 579 * thread, and stash that in the context we're initializing. Our caller is 580 * responsible for determining whether that's an API it supports. 581 */ 582EGLBoolean 583_eglInitContext(_EGLContext *ctx, _EGLDisplay *disp, _EGLConfig *conf, 584 const EGLint *attrib_list) 585{ 586 const EGLenum api = eglQueryAPI(); 587 EGLint err; 588 589 if (api == EGL_NONE) 590 return _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); 591 592 _eglInitResource(&ctx->Resource, sizeof(*ctx), disp); 593 ctx->ClientAPI = api; 594 ctx->Config = conf; 595 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 596 597 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */ 598 ctx->ClientMinorVersion = 0; 599 ctx->Flags = 0; 600 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR; 601 ctx->ContextPriority = EGL_CONTEXT_PRIORITY_MEDIUM_IMG; 602 ctx->ReleaseBehavior = EGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR; 603 604 err = _eglParseContextAttribList(ctx, disp, attrib_list); 605 if (err == EGL_SUCCESS && ctx->Config) { 606 EGLint api_bit; 607 608 api_bit = _eglGetContextAPIBit(ctx); 609 if (!(ctx->Config->RenderableType & api_bit)) { 610 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x", 611 api_bit, ctx->Config->RenderableType); 612 err = EGL_BAD_CONFIG; 613 } 614 } 615 if (err != EGL_SUCCESS) 616 return _eglError(err, "eglCreateContext"); 617 618 return EGL_TRUE; 619} 620 621 622static EGLint 623_eglQueryContextRenderBuffer(_EGLContext *ctx) 624{ 625 _EGLSurface *surf = ctx->DrawSurface; 626 627 /* From the EGL 1.5 spec: 628 * 629 * - If the context is not bound to a surface, then EGL_NONE will be 630 * returned. 631 */ 632 if (!surf) 633 return EGL_NONE; 634 635 switch (surf->Type) { 636 default: 637 unreachable("bad EGLSurface type"); 638 case EGL_PIXMAP_BIT: 639 /* - If the context is bound to a pixmap surface, then EGL_SINGLE_BUFFER 640 * will be returned. 641 */ 642 return EGL_SINGLE_BUFFER; 643 case EGL_PBUFFER_BIT: 644 /* - If the context is bound to a pbuffer surface, then EGL_BACK_BUFFER 645 * will be returned. 646 */ 647 return EGL_BACK_BUFFER; 648 case EGL_WINDOW_BIT: 649 /* - If the context is bound to a window surface, then either 650 * EGL_BACK_BUFFER or EGL_SINGLE_BUFFER may be returned. The value 651 * returned depends on both the buffer requested by the setting of the 652 * EGL_RENDER_BUFFER property of the surface [...], and on the client 653 * API (not all client APIs support single-buffer Rendering to window 654 * surfaces). Some client APIs allow control of whether rendering goes 655 * to the front or back buffer. This client API-specific choice is not 656 * reflected in the returned value, which only describes the buffer 657 * that will be rendered to by default if not overridden by the client 658 * API. 659 */ 660 return surf->ActiveRenderBuffer; 661 } 662} 663 664 665EGLBoolean 666_eglQueryContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLContext *c, 667 EGLint attribute, EGLint *value) 668{ 669 (void) drv; 670 (void) disp; 671 672 if (!value) 673 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext"); 674 675 switch (attribute) { 676 case EGL_CONFIG_ID: 677 /* 678 * From EGL_KHR_no_config_context: 679 * 680 * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with 681 * respect to which the context was created, or zero if created 682 * without respect to an EGLConfig." 683 */ 684 *value = c->Config ? c->Config->ConfigID : 0; 685 break; 686 case EGL_CONTEXT_CLIENT_VERSION: 687 *value = c->ClientMajorVersion; 688 break; 689 case EGL_CONTEXT_CLIENT_TYPE: 690 *value = c->ClientAPI; 691 break; 692 case EGL_RENDER_BUFFER: 693 *value = _eglQueryContextRenderBuffer(c); 694 break; 695 case EGL_CONTEXT_PRIORITY_LEVEL_IMG: 696 *value = c->ContextPriority; 697 break; 698 default: 699 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); 700 } 701 702 return EGL_TRUE; 703} 704 705 706/** 707 * Bind the context to the thread and return the previous context. 708 * 709 * Note that the context may be NULL. 710 */ 711_EGLContext * 712_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t) 713{ 714 _EGLContext *oldCtx; 715 716 oldCtx = t->CurrentContext; 717 if (ctx != oldCtx) { 718 if (oldCtx) 719 oldCtx->Binding = NULL; 720 if (ctx) 721 ctx->Binding = t; 722 723 t->CurrentContext = ctx; 724 } 725 726 return oldCtx; 727} 728 729 730/** 731 * Return true if the given context and surfaces can be made current. 732 */ 733static EGLBoolean 734_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) 735{ 736 _EGLThreadInfo *t = _eglGetCurrentThread(); 737 _EGLDisplay *disp; 738 739 if (_eglIsCurrentThreadDummy()) 740 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); 741 742 /* this is easy */ 743 if (!ctx) { 744 if (draw || read) 745 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 746 return EGL_TRUE; 747 } 748 749 disp = ctx->Resource.Display; 750 if (!disp->Extensions.KHR_surfaceless_context 751 && (draw == NULL || read == NULL)) 752 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 753 754 /* 755 * The spec says 756 * 757 * "If ctx is current to some other thread, or if either draw or read are 758 * bound to contexts in another thread, an EGL_BAD_ACCESS error is 759 * generated." 760 * 761 * and 762 * 763 * "at most one context may be bound to a particular surface at a given 764 * time" 765 */ 766 if (ctx->Binding && ctx->Binding != t) 767 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 768 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) { 769 if (draw->CurrentContext->Binding != t) 770 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 771 } 772 if (read && read->CurrentContext && read->CurrentContext != ctx) { 773 if (read->CurrentContext->Binding != t) 774 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 775 } 776 777 /* If the context has a config then it must match that of the two 778 * surfaces */ 779 if (ctx->Config) { 780 if ((draw && draw->Config != ctx->Config) || 781 (read && read->Config != ctx->Config)) 782 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 783 } else { 784 /* Otherwise we must be using the EGL_KHR_no_config_context 785 * extension */ 786 assert(disp->Extensions.KHR_no_config_context); 787 788 /* The extension doesn't permit binding draw and read buffers with 789 * differing contexts */ 790 if (draw && read && draw->Config != read->Config) 791 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 792 } 793 794 return EGL_TRUE; 795} 796 797 798/** 799 * Bind the context to the current thread and given surfaces. Return the 800 * previous bound context and surfaces. The caller should unreference the 801 * returned context and surfaces. 802 * 803 * Making a second call with the resources returned by the first call 804 * unsurprisingly undoes the first call, except for the resouce reference 805 * counts. 806 */ 807EGLBoolean 808_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read, 809 _EGLContext **old_ctx, 810 _EGLSurface **old_draw, _EGLSurface **old_read) 811{ 812 _EGLThreadInfo *t = _eglGetCurrentThread(); 813 _EGLContext *prev_ctx; 814 _EGLSurface *prev_draw, *prev_read; 815 816 if (!_eglCheckMakeCurrent(ctx, draw, read)) 817 return EGL_FALSE; 818 819 /* increment refcounts before binding */ 820 _eglGetContext(ctx); 821 _eglGetSurface(draw); 822 _eglGetSurface(read); 823 824 /* bind the new context */ 825 prev_ctx = _eglBindContextToThread(ctx, t); 826 827 /* break previous bindings */ 828 if (prev_ctx) { 829 prev_draw = prev_ctx->DrawSurface; 830 prev_read = prev_ctx->ReadSurface; 831 832 if (prev_draw) 833 prev_draw->CurrentContext = NULL; 834 if (prev_read) 835 prev_read->CurrentContext = NULL; 836 837 prev_ctx->DrawSurface = NULL; 838 prev_ctx->ReadSurface = NULL; 839 } 840 else { 841 prev_draw = prev_read = NULL; 842 } 843 844 /* establish new bindings */ 845 if (ctx) { 846 if (draw) 847 draw->CurrentContext = ctx; 848 if (read) 849 read->CurrentContext = ctx; 850 851 ctx->DrawSurface = draw; 852 ctx->ReadSurface = read; 853 } 854 855 assert(old_ctx && old_draw && old_read); 856 *old_ctx = prev_ctx; 857 *old_draw = prev_draw; 858 *old_read = prev_read; 859 860 return EGL_TRUE; 861} 862