Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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.  */
  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.          ctx->ClientMajorVersion = val;
  105.          break;
  106.  
  107.       case EGL_CONTEXT_MINOR_VERSION_KHR:
  108.          if (!dpy->Extensions.KHR_create_context) {
  109.             err = EGL_BAD_ATTRIBUTE;
  110.             break;
  111.          }
  112.  
  113.          ctx->ClientMinorVersion = val;
  114.          break;
  115.  
  116.       case EGL_CONTEXT_FLAGS_KHR:
  117.          if (!dpy->Extensions.KHR_create_context) {
  118.             err = EGL_BAD_ATTRIBUTE;
  119.             break;
  120.          }
  121.  
  122.          /* The EGL_KHR_create_context spec says:
  123.           *
  124.           *     "Flags are only defined for OpenGL context creation, and
  125.           *     specifying a flags value other than zero for other types of
  126.           *     contexts, including OpenGL ES contexts, will generate an
  127.           *     error."
  128.           */
  129.          if (api != EGL_OPENGL_API && val != 0) {
  130.             err = EGL_BAD_ATTRIBUTE;
  131.             break;
  132.          }
  133.  
  134.          ctx->Flags = val;
  135.          break;
  136.  
  137.       case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
  138.          if (!dpy->Extensions.KHR_create_context) {
  139.             err = EGL_BAD_ATTRIBUTE;
  140.             break;
  141.          }
  142.  
  143.          /* The EGL_KHR_create_context spec says:
  144.           *
  145.           *     "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for
  146.           *     OpenGL contexts, and specifying it for other types of
  147.           *     contexts, including OpenGL ES contexts, will generate an
  148.           *     error."
  149.           */
  150.          if (api != EGL_OPENGL_API) {
  151.             err = EGL_BAD_ATTRIBUTE;
  152.             break;
  153.          }
  154.  
  155.          ctx->Profile = val;
  156.          break;
  157.  
  158.       case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
  159.          /* The EGL_KHR_create_context spec says:
  160.           *
  161.           *     "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only
  162.           *     meaningful for OpenGL contexts, and specifying it for other
  163.           *     types of contexts, including OpenGL ES contexts, will generate
  164.           *     an error."
  165.           */
  166.            if (!dpy->Extensions.KHR_create_context
  167.                || api != EGL_OPENGL_API) {
  168.             err = EGL_BAD_ATTRIBUTE;
  169.             break;
  170.          }
  171.  
  172.          ctx->ResetNotificationStrategy = val;
  173.          break;
  174.  
  175.       case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
  176.          /* The EGL_EXT_create_context_robustness spec says:
  177.           *
  178.           *     "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only
  179.           *     meaningful for OpenGL ES contexts, and specifying it for other
  180.           *     types of contexts will generate an EGL_BAD_ATTRIBUTE error."
  181.           */
  182.          if (!dpy->Extensions.EXT_create_context_robustness
  183.              || api != EGL_OPENGL_ES_API) {
  184.             err = EGL_BAD_ATTRIBUTE;
  185.             break;
  186.          }
  187.  
  188.          ctx->ResetNotificationStrategy = val;
  189.          break;
  190.  
  191.       case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
  192.          if (!dpy->Extensions.EXT_create_context_robustness) {
  193.             err = EGL_BAD_ATTRIBUTE;
  194.             break;
  195.          }
  196.  
  197.          ctx->Flags = EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR;
  198.          break;
  199.  
  200.       default:
  201.          err = EGL_BAD_ATTRIBUTE;
  202.          break;
  203.       }
  204.  
  205.       if (err != EGL_SUCCESS) {
  206.          _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attr);
  207.          break;
  208.       }
  209.    }
  210.  
  211.    if (api == EGL_OPENGL_API) {
  212.       /* The EGL_KHR_create_context spec says:
  213.        *
  214.        *     "If the requested OpenGL version is less than 3.2,
  215.        *     EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the
  216.        *     functionality of the context is determined solely by the
  217.        *     requested version."
  218.        *
  219.        * Since the value is ignored, only validate the setting if the version
  220.        * is >= 3.2.
  221.        */
  222.       if (ctx->ClientMajorVersion >= 4
  223.           || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) {
  224.          switch (ctx->Profile) {
  225.          case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR:
  226.          case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR:
  227.             break;
  228.  
  229.          default:
  230.             /* The EGL_KHR_create_context spec says:
  231.              *
  232.              *     "* If an OpenGL context is requested, the requested version
  233.              *        is greater than 3.2, and the value for attribute
  234.              *        EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has
  235.              *        any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR
  236.              *        and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has
  237.              *        more than one of these bits set; or if the implementation does
  238.              *        not support the requested profile, then an EGL_BAD_MATCH error
  239.              *        is generated."
  240.              */
  241.             err = EGL_BAD_MATCH;
  242.             break;
  243.          }
  244.       }
  245.  
  246.       /* The EGL_KHR_create_context spec says:
  247.        *
  248.        *     "* If an OpenGL context is requested and the values for
  249.        *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
  250.        *        EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with
  251.        *        the value for attribute
  252.        *        EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL
  253.        *        version and feature set that are not defined, than an
  254.        *        EGL_BAD_MATCH error is generated.
  255.        *
  256.        *        ... Thus, examples of invalid combinations of attributes
  257.        *        include:
  258.        *
  259.        *          - Major version < 1 or > 4
  260.        *          - Major version == 1 and minor version < 0 or > 5
  261.        *          - Major version == 2 and minor version < 0 or > 1
  262.        *          - Major version == 3 and minor version < 0 or > 2
  263.        *          - Major version == 4 and minor version < 0 or > 2
  264.        *          - Forward-compatible flag set and major version < 3"
  265.        */
  266.       if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
  267.          err = EGL_BAD_MATCH;
  268.  
  269.       switch (ctx->ClientMajorVersion) {
  270.       case 1:
  271.          if (ctx->ClientMinorVersion > 5
  272.              || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
  273.             err = EGL_BAD_MATCH;
  274.          break;
  275.  
  276.       case 2:
  277.          if (ctx->ClientMinorVersion > 1
  278.              || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0)
  279.             err = EGL_BAD_MATCH;
  280.          break;
  281.  
  282.       case 3:
  283.          /* Note: The text above is incorrect.  There *is* an OpenGL 3.3!
  284.           */
  285.          if (ctx->ClientMinorVersion > 3)
  286.             err = EGL_BAD_MATCH;
  287.          break;
  288.  
  289.       case 4:
  290.       default:
  291.          /* Don't put additional version checks here.  We don't know that
  292.           * there won't be versions > 4.2.
  293.           */
  294.          break;
  295.       }
  296.    } else if (api == EGL_OPENGL_ES_API) {
  297.       /* The EGL_KHR_create_context spec says:
  298.        *
  299.        *     "* If an OpenGL ES context is requested and the values for
  300.        *        attributes EGL_CONTEXT_MAJOR_VERSION_KHR and
  301.        *        EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that
  302.        *        is not defined, than an EGL_BAD_MATCH error is generated.
  303.        *
  304.        *        ... Examples of invalid combinations of attributes include:
  305.        *
  306.        *          - Major version < 1 or > 2
  307.        *          - Major version == 1 and minor version < 0 or > 1
  308.        *          - Major version == 2 and minor version != 0
  309.        */
  310.       if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0)
  311.          err = EGL_BAD_MATCH;
  312.  
  313.       switch (ctx->ClientMajorVersion) {
  314.       case 1:
  315.          if (ctx->ClientMinorVersion > 1)
  316.             err = EGL_BAD_MATCH;
  317.          break;
  318.  
  319.       case 2:
  320.          if (ctx->ClientMinorVersion > 0)
  321.             err = EGL_BAD_MATCH;
  322.          break;
  323.  
  324.       case 3:
  325.          /* Don't put additional version checks here.  We don't know that
  326.           * there won't be versions > 3.0.
  327.           */
  328.          break;
  329.  
  330.       default:
  331.          err = EGL_BAD_MATCH;
  332.          break;
  333.       }
  334.    }
  335.  
  336.    switch (ctx->ResetNotificationStrategy) {
  337.    case EGL_NO_RESET_NOTIFICATION_KHR:
  338.    case EGL_LOSE_CONTEXT_ON_RESET_KHR:
  339.       break;
  340.  
  341.    default:
  342.       err = EGL_BAD_ATTRIBUTE;
  343.       break;
  344.    }
  345.  
  346.    if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
  347.                       | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
  348.                       | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
  349.       err = EGL_BAD_ATTRIBUTE;
  350.    }
  351.  
  352.    return err;
  353. }
  354.  
  355.  
  356. /**
  357.  * Initialize the given _EGLContext object to defaults and/or the values
  358.  * in the attrib_list.
  359.  */
  360. EGLBoolean
  361. _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
  362.                 const EGLint *attrib_list)
  363. {
  364.    const EGLenum api = eglQueryAPI();
  365.    EGLint err;
  366.  
  367.    if (api == EGL_NONE) {
  368.       _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
  369.       return EGL_FALSE;
  370.    }
  371.  
  372.    _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
  373.    ctx->ClientAPI = api;
  374.    ctx->Config = conf;
  375.    ctx->WindowRenderBuffer = EGL_NONE;
  376.    ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
  377.  
  378.    ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
  379.    ctx->ClientMinorVersion = 0;
  380.    ctx->Flags = 0;
  381.    ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
  382.    ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
  383.  
  384.    err = _eglParseContextAttribList(ctx, dpy, attrib_list);
  385.    if (err == EGL_SUCCESS && ctx->Config) {
  386.       EGLint api_bit;
  387.  
  388.       api_bit = _eglGetContextAPIBit(ctx);
  389.       if (!(ctx->Config->RenderableType & api_bit)) {
  390.          _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
  391.                api_bit, ctx->Config->RenderableType);
  392.          err = EGL_BAD_CONFIG;
  393.       }
  394.    }
  395.    if (err != EGL_SUCCESS)
  396.       return _eglError(err, "eglCreateContext");
  397.  
  398.    return EGL_TRUE;
  399. }
  400.  
  401.  
  402. static EGLint
  403. _eglQueryContextRenderBuffer(_EGLContext *ctx)
  404. {
  405.    _EGLSurface *surf = ctx->DrawSurface;
  406.    EGLint rb;
  407.  
  408.    if (!surf)
  409.       return EGL_NONE;
  410.    if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
  411.       rb = ctx->WindowRenderBuffer;
  412.    else
  413.       rb = surf->RenderBuffer;
  414.    return rb;
  415. }
  416.  
  417.  
  418. EGLBoolean
  419. _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
  420.                  EGLint attribute, EGLint *value)
  421. {
  422.    (void) drv;
  423.    (void) dpy;
  424.  
  425.    if (!value)
  426.       return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
  427.  
  428.    switch (attribute) {
  429.    case EGL_CONFIG_ID:
  430.       if (!c->Config)
  431.          return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
  432.       *value = c->Config->ConfigID;
  433.       break;
  434.    case EGL_CONTEXT_CLIENT_VERSION:
  435.       *value = c->ClientMajorVersion;
  436.       break;
  437.    case EGL_CONTEXT_CLIENT_TYPE:
  438.       *value = c->ClientAPI;
  439.       break;
  440.    case EGL_RENDER_BUFFER:
  441.       *value = _eglQueryContextRenderBuffer(c);
  442.       break;
  443.    default:
  444.       return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
  445.    }
  446.  
  447.    return EGL_TRUE;
  448. }
  449.  
  450.  
  451. /**
  452.  * Bind the context to the thread and return the previous context.
  453.  *
  454.  * Note that the context may be NULL.
  455.  */
  456. static _EGLContext *
  457. _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
  458. {
  459.    EGLint apiIndex;
  460.    _EGLContext *oldCtx;
  461.  
  462.    apiIndex = (ctx) ?
  463.       _eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex;
  464.  
  465.    oldCtx = t->CurrentContexts[apiIndex];
  466.    if (ctx != oldCtx) {
  467.       if (oldCtx)
  468.          oldCtx->Binding = NULL;
  469.       if (ctx)
  470.          ctx->Binding = t;
  471.  
  472.       t->CurrentContexts[apiIndex] = ctx;
  473.    }
  474.  
  475.    return oldCtx;
  476. }
  477.  
  478.  
  479. /**
  480.  * Return true if the given context and surfaces can be made current.
  481.  */
  482. static EGLBoolean
  483. _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
  484. {
  485.    _EGLThreadInfo *t = _eglGetCurrentThread();
  486.    _EGLDisplay *dpy;
  487.    EGLint conflict_api;
  488.  
  489.    if (_eglIsCurrentThreadDummy())
  490.       return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
  491.  
  492.    /* this is easy */
  493.    if (!ctx) {
  494.       if (draw || read)
  495.          return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
  496.       return EGL_TRUE;
  497.    }
  498.  
  499.    dpy = ctx->Resource.Display;
  500.    if (!dpy->Extensions.KHR_surfaceless_context
  501.        && (draw == NULL || read == NULL))
  502.       return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
  503.  
  504.    /*
  505.     * The spec says
  506.     *
  507.     * "If ctx is current to some other thread, or if either draw or read are
  508.     * bound to contexts in another thread, an EGL_BAD_ACCESS error is
  509.     * generated."
  510.     *
  511.     * and
  512.     *
  513.     * "at most one context may be bound to a particular surface at a given
  514.     * time"
  515.     */
  516.    if (ctx->Binding && ctx->Binding != t)
  517.       return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
  518.    if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
  519.       if (draw->CurrentContext->Binding != t ||
  520.           draw->CurrentContext->ClientAPI != ctx->ClientAPI)
  521.          return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
  522.    }
  523.    if (read && read->CurrentContext && read->CurrentContext != ctx) {
  524.       if (read->CurrentContext->Binding != t ||
  525.           read->CurrentContext->ClientAPI != ctx->ClientAPI)
  526.          return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
  527.    }
  528.  
  529.    /* If the context has a config then it must match that of the two
  530.     * surfaces */
  531.    if (ctx->Config) {
  532.       if ((draw && draw->Config != ctx->Config) ||
  533.           (read && read->Config != ctx->Config))
  534.          return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
  535.    } else {
  536.       /* Otherwise we must be using the EGL_MESA_configless_context
  537.        * extension */
  538.       assert(dpy->Extensions.MESA_configless_context);
  539.  
  540.       /* The extension doesn't permit binding draw and read buffers with
  541.        * differing contexts */
  542.       if (draw && read && draw->Config != read->Config)
  543.          return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
  544.    }
  545.  
  546.    switch (ctx->ClientAPI) {
  547.    /* OpenGL and OpenGL ES are conflicting */
  548.    case EGL_OPENGL_ES_API:
  549.       conflict_api = EGL_OPENGL_API;
  550.       break;
  551.    case EGL_OPENGL_API:
  552.       conflict_api = EGL_OPENGL_ES_API;
  553.       break;
  554.    default:
  555.       conflict_api = -1;
  556.       break;
  557.    }
  558.  
  559.    if (conflict_api >= 0 && _eglGetAPIContext(conflict_api))
  560.       return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
  561.  
  562.    return EGL_TRUE;
  563. }
  564.  
  565.  
  566. /**
  567.  * Bind the context to the current thread and given surfaces.  Return the
  568.  * previous bound context and surfaces.  The caller should unreference the
  569.  * returned context and surfaces.
  570.  *
  571.  * Making a second call with the resources returned by the first call
  572.  * unsurprisingly undoes the first call, except for the resouce reference
  573.  * counts.
  574.  */
  575. EGLBoolean
  576. _eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
  577.                 _EGLContext **old_ctx,
  578.                 _EGLSurface **old_draw, _EGLSurface **old_read)
  579. {
  580.    _EGLThreadInfo *t = _eglGetCurrentThread();
  581.    _EGLContext *prev_ctx;
  582.    _EGLSurface *prev_draw, *prev_read;
  583.  
  584.    if (!_eglCheckMakeCurrent(ctx, draw, read))
  585.       return EGL_FALSE;
  586.  
  587.    /* increment refcounts before binding */
  588.    _eglGetContext(ctx);
  589.    _eglGetSurface(draw);
  590.    _eglGetSurface(read);
  591.  
  592.    /* bind the new context */
  593.    prev_ctx = _eglBindContextToThread(ctx, t);
  594.  
  595.    /* break previous bindings */
  596.    if (prev_ctx) {
  597.       prev_draw = prev_ctx->DrawSurface;
  598.       prev_read = prev_ctx->ReadSurface;
  599.  
  600.       if (prev_draw)
  601.          prev_draw->CurrentContext = NULL;
  602.       if (prev_read)
  603.          prev_read->CurrentContext = NULL;
  604.  
  605.       prev_ctx->DrawSurface = NULL;
  606.       prev_ctx->ReadSurface = NULL;
  607.    }
  608.    else {
  609.       prev_draw = prev_read = NULL;
  610.    }
  611.  
  612.    /* establish new bindings */
  613.    if (ctx) {
  614.       if (draw)
  615.          draw->CurrentContext = ctx;
  616.       if (read)
  617.          read->CurrentContext = ctx;
  618.  
  619.       ctx->DrawSurface = draw;
  620.       ctx->ReadSurface = read;
  621.    }
  622.  
  623.    assert(old_ctx && old_draw && old_read);
  624.    *old_ctx = prev_ctx;
  625.    *old_draw = prev_draw;
  626.    *old_read = prev_read;
  627.  
  628.    return EGL_TRUE;
  629. }
  630.