Home | History | Annotate | Download | only in main
      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       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  */
    485 EGLBoolean
    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 
    527 static 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 
    543 EGLBoolean
    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  */
    586 static _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  */
    608 static 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  */
    682 EGLBoolean
    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