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       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