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 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: 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 */ 83static 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 default: 316 err = EGL_BAD_ATTRIBUTE; 317 break; 318 } 319 320 if (err != EGL_SUCCESS) { 321 _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr); 322 break; 323 } 324 } 325 326 if (api == EGL_OPENGL_API) { 327 /* The EGL_KHR_create_context spec says: 328 * 329 * "If the requested OpenGL version is less than 3.2, 330 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the 331 * functionality of the context is determined solely by the 332 * requested version." 333 * 334 * Since the value is ignored, only validate the setting if the version 335 * is >= 3.2. 336 */ 337 if (ctx->ClientMajorVersion >= 4 338 || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) { 339 switch (ctx->Profile) { 340 case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR: 341 case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR: 342 break; 343 344 default: 345 /* The EGL_KHR_create_context spec says: 346 * 347 * "* If an OpenGL context is requested, the requested version 348 * is greater than 3.2, and the value for attribute 349 * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has 350 * any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR 351 * and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has 352 * more than one of these bits set; or if the implementation does 353 * not support the requested profile, then an EGL_BAD_MATCH error 354 * is generated." 355 */ 356 err = EGL_BAD_MATCH; 357 break; 358 } 359 } 360 361 /* The EGL_KHR_create_context spec says: 362 * 363 * "* If an OpenGL context is requested and the values for 364 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 365 * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with 366 * the value for attribute 367 * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL 368 * version and feature set that are not defined, than an 369 * EGL_BAD_MATCH error is generated. 370 * 371 * ... Thus, examples of invalid combinations of attributes 372 * include: 373 * 374 * - Major version < 1 or > 4 375 * - Major version == 1 and minor version < 0 or > 5 376 * - Major version == 2 and minor version < 0 or > 1 377 * - Major version == 3 and minor version < 0 or > 2 378 * - Major version == 4 and minor version < 0 or > 2 379 * - Forward-compatible flag set and major version < 3" 380 */ 381 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) 382 err = EGL_BAD_MATCH; 383 384 switch (ctx->ClientMajorVersion) { 385 case 1: 386 if (ctx->ClientMinorVersion > 5 387 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) 388 err = EGL_BAD_MATCH; 389 break; 390 391 case 2: 392 if (ctx->ClientMinorVersion > 1 393 || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) 394 err = EGL_BAD_MATCH; 395 break; 396 397 case 3: 398 /* Note: The text above is incorrect. There *is* an OpenGL 3.3! 399 */ 400 if (ctx->ClientMinorVersion > 3) 401 err = EGL_BAD_MATCH; 402 break; 403 404 case 4: 405 default: 406 /* Don't put additional version checks here. We don't know that 407 * there won't be versions > 4.2. 408 */ 409 break; 410 } 411 } else if (api == EGL_OPENGL_ES_API) { 412 /* The EGL_KHR_create_context spec says: 413 * 414 * "* If an OpenGL ES context is requested and the values for 415 * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and 416 * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that 417 * is not defined, than an EGL_BAD_MATCH error is generated. 418 * 419 * ... Examples of invalid combinations of attributes include: 420 * 421 * - Major version < 1 or > 2 422 * - Major version == 1 and minor version < 0 or > 1 423 * - Major version == 2 and minor version != 0 424 */ 425 if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) 426 err = EGL_BAD_MATCH; 427 428 switch (ctx->ClientMajorVersion) { 429 case 1: 430 if (ctx->ClientMinorVersion > 1) 431 err = EGL_BAD_MATCH; 432 break; 433 434 case 2: 435 if (ctx->ClientMinorVersion > 0) 436 err = EGL_BAD_MATCH; 437 break; 438 439 case 3: 440 /* Don't put additional version checks here. We don't know that 441 * there won't be versions > 3.0. 442 */ 443 break; 444 445 default: 446 err = EGL_BAD_MATCH; 447 break; 448 } 449 } 450 451 switch (ctx->ResetNotificationStrategy) { 452 case EGL_NO_RESET_NOTIFICATION_KHR: 453 case EGL_LOSE_CONTEXT_ON_RESET_KHR: 454 break; 455 456 default: 457 err = EGL_BAD_ATTRIBUTE; 458 break; 459 } 460 461 if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR 462 | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR 463 | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) { 464 err = EGL_BAD_ATTRIBUTE; 465 } 466 467 return err; 468} 469 470 471/** 472 * Initialize the given _EGLContext object to defaults and/or the values 473 * in the attrib_list. 474 * 475 * According to EGL 1.5 Section 3.7: 476 * 477 * "EGL_OPENGL_API and EGL_OPENGL_ES_API are interchangeable for all 478 * purposes except eglCreateContext." 479 * 480 * And since we only support GL and GLES, this is the only place where the 481 * bound API matters at all. We look up the current API from the current 482 * thread, and stash that in the context we're initializing. Our caller is 483 * responsible for determining whether that's an API it supports. 484 */ 485EGLBoolean 486_eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf, 487 const EGLint *attrib_list) 488{ 489 const EGLenum api = eglQueryAPI(); 490 EGLint err; 491 492 if (api == EGL_NONE) { 493 _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)"); 494 return EGL_FALSE; 495 } 496 497 _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy); 498 ctx->ClientAPI = api; 499 ctx->Config = conf; 500 ctx->WindowRenderBuffer = EGL_NONE; 501 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 502 503 ctx->ClientMajorVersion = 1; /* the default, per EGL spec */ 504 ctx->ClientMinorVersion = 0; 505 ctx->Flags = 0; 506 ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; 507 ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR; 508 509 err = _eglParseContextAttribList(ctx, dpy, attrib_list); 510 if (err == EGL_SUCCESS && ctx->Config) { 511 EGLint api_bit; 512 513 api_bit = _eglGetContextAPIBit(ctx); 514 if (!(ctx->Config->RenderableType & api_bit)) { 515 _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x", 516 api_bit, ctx->Config->RenderableType); 517 err = EGL_BAD_CONFIG; 518 } 519 } 520 if (err != EGL_SUCCESS) 521 return _eglError(err, "eglCreateContext"); 522 523 return EGL_TRUE; 524} 525 526 527static EGLint 528_eglQueryContextRenderBuffer(_EGLContext *ctx) 529{ 530 _EGLSurface *surf = ctx->DrawSurface; 531 EGLint rb; 532 533 if (!surf) 534 return EGL_NONE; 535 if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE) 536 rb = ctx->WindowRenderBuffer; 537 else 538 rb = surf->RenderBuffer; 539 return rb; 540} 541 542 543EGLBoolean 544_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c, 545 EGLint attribute, EGLint *value) 546{ 547 (void) drv; 548 (void) dpy; 549 550 if (!value) 551 return _eglError(EGL_BAD_PARAMETER, "eglQueryContext"); 552 553 switch (attribute) { 554 case EGL_CONFIG_ID: 555 /* 556 * From EGL_KHR_no_config_context: 557 * 558 * "Querying EGL_CONFIG_ID returns the ID of the EGLConfig with 559 * respect to which the context was created, or zero if created 560 * without respect to an EGLConfig." 561 */ 562 *value = c->Config ? c->Config->ConfigID : 0; 563 break; 564 case EGL_CONTEXT_CLIENT_VERSION: 565 *value = c->ClientMajorVersion; 566 break; 567 case EGL_CONTEXT_CLIENT_TYPE: 568 *value = c->ClientAPI; 569 break; 570 case EGL_RENDER_BUFFER: 571 *value = _eglQueryContextRenderBuffer(c); 572 break; 573 default: 574 return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); 575 } 576 577 return EGL_TRUE; 578} 579 580 581/** 582 * Bind the context to the thread and return the previous context. 583 * 584 * Note that the context may be NULL. 585 */ 586static _EGLContext * 587_eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t) 588{ 589 _EGLContext *oldCtx; 590 591 oldCtx = t->CurrentContext; 592 if (ctx != oldCtx) { 593 if (oldCtx) 594 oldCtx->Binding = NULL; 595 if (ctx) 596 ctx->Binding = t; 597 598 t->CurrentContext = ctx; 599 } 600 601 return oldCtx; 602} 603 604 605/** 606 * Return true if the given context and surfaces can be made current. 607 */ 608static EGLBoolean 609_eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) 610{ 611 _EGLThreadInfo *t = _eglGetCurrentThread(); 612 _EGLDisplay *dpy; 613 614 if (_eglIsCurrentThreadDummy()) 615 return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); 616 617 /* this is easy */ 618 if (!ctx) { 619 if (draw || read) 620 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 621 return EGL_TRUE; 622 } 623 624 dpy = ctx->Resource.Display; 625 if (!dpy->Extensions.KHR_surfaceless_context 626 && (draw == NULL || read == NULL)) 627 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 628 629 /* 630 * The spec says 631 * 632 * "If ctx is current to some other thread, or if either draw or read are 633 * bound to contexts in another thread, an EGL_BAD_ACCESS error is 634 * generated." 635 * 636 * and 637 * 638 * "at most one context may be bound to a particular surface at a given 639 * time" 640 */ 641 if (ctx->Binding && ctx->Binding != t) 642 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 643 if (draw && draw->CurrentContext && draw->CurrentContext != ctx) { 644 if (draw->CurrentContext->Binding != t) 645 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 646 } 647 if (read && read->CurrentContext && read->CurrentContext != ctx) { 648 if (read->CurrentContext->Binding != t) 649 return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); 650 } 651 652 /* If the context has a config then it must match that of the two 653 * surfaces */ 654 if (ctx->Config) { 655 if ((draw && draw->Config != ctx->Config) || 656 (read && read->Config != ctx->Config)) 657 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 658 } else { 659 /* Otherwise we must be using the EGL_KHR_no_config_context 660 * extension */ 661 assert(dpy->Extensions.KHR_no_config_context); 662 663 /* The extension doesn't permit binding draw and read buffers with 664 * differing contexts */ 665 if (draw && read && draw->Config != read->Config) 666 return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); 667 } 668 669 return EGL_TRUE; 670} 671 672 673/** 674 * Bind the context to the current thread and given surfaces. Return the 675 * previous bound context and surfaces. The caller should unreference the 676 * returned context and surfaces. 677 * 678 * Making a second call with the resources returned by the first call 679 * unsurprisingly undoes the first call, except for the resouce reference 680 * counts. 681 */ 682EGLBoolean 683_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read, 684 _EGLContext **old_ctx, 685 _EGLSurface **old_draw, _EGLSurface **old_read) 686{ 687 _EGLThreadInfo *t = _eglGetCurrentThread(); 688 _EGLContext *prev_ctx; 689 _EGLSurface *prev_draw, *prev_read; 690 691 if (!_eglCheckMakeCurrent(ctx, draw, read)) 692 return EGL_FALSE; 693 694 /* increment refcounts before binding */ 695 _eglGetContext(ctx); 696 _eglGetSurface(draw); 697 _eglGetSurface(read); 698 699 /* bind the new context */ 700 prev_ctx = _eglBindContextToThread(ctx, t); 701 702 /* break previous bindings */ 703 if (prev_ctx) { 704 prev_draw = prev_ctx->DrawSurface; 705 prev_read = prev_ctx->ReadSurface; 706 707 if (prev_draw) 708 prev_draw->CurrentContext = NULL; 709 if (prev_read) 710 prev_read->CurrentContext = NULL; 711 712 prev_ctx->DrawSurface = NULL; 713 prev_ctx->ReadSurface = NULL; 714 } 715 else { 716 prev_draw = prev_read = NULL; 717 } 718 719 /* establish new bindings */ 720 if (ctx) { 721 if (draw) 722 draw->CurrentContext = ctx; 723 if (read) 724 read->CurrentContext = ctx; 725 726 ctx->DrawSurface = draw; 727 ctx->ReadSurface = read; 728 } 729 730 assert(old_ctx && old_draw && old_read); 731 *old_ctx = prev_ctx; 732 *old_draw = prev_draw; 733 *old_read = prev_read; 734 735 return EGL_TRUE; 736} 737