Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /**************************************************************************
  2.  *
  3.  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
  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.       default:
  326.          /* Don't put additional version checks here.  We don't know that
  327.           * there won't be versions > 3.0.
  328.           */
  329.          break;
  330.       }
  331.    }
  332.  
  333.    switch (ctx->ResetNotificationStrategy) {
  334.    case EGL_NO_RESET_NOTIFICATION_KHR:
  335.    case EGL_LOSE_CONTEXT_ON_RESET_KHR:
  336.       break;
  337.  
  338.    default:
  339.       err = EGL_BAD_ATTRIBUTE;
  340.       break;
  341.    }
  342.  
  343.    if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR
  344.                       | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR
  345.                       | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) {
  346.       err = EGL_BAD_ATTRIBUTE;
  347.    }
  348.  
  349.    return err;
  350. }
  351.  
  352.  
  353. /**
  354.  * Initialize the given _EGLContext object to defaults and/or the values
  355.  * in the attrib_list.
  356.  */
  357. EGLBoolean
  358. _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf,
  359.                 const EGLint *attrib_list)
  360. {
  361.    const EGLenum api = eglQueryAPI();
  362.    EGLint err;
  363.  
  364.    if (api == EGL_NONE) {
  365.       _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
  366.       return EGL_FALSE;
  367.    }
  368.  
  369.    _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy);
  370.    ctx->ClientAPI = api;
  371.    ctx->Config = conf;
  372.    ctx->WindowRenderBuffer = EGL_NONE;
  373.    ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
  374.  
  375.    ctx->ClientMajorVersion = 1; /* the default, per EGL spec */
  376.    ctx->ClientMinorVersion = 0;
  377.    ctx->Flags = 0;
  378.    ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR;
  379.    ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR;
  380.  
  381.    err = _eglParseContextAttribList(ctx, dpy, attrib_list);
  382.    if (err == EGL_SUCCESS && ctx->Config) {
  383.       EGLint api_bit;
  384.  
  385.       api_bit = _eglGetContextAPIBit(ctx);
  386.       if (!(ctx->Config->RenderableType & api_bit)) {
  387.          _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x",
  388.                api_bit, ctx->Config->RenderableType);
  389.          err = EGL_BAD_CONFIG;
  390.       }
  391.    }
  392.    if (err != EGL_SUCCESS)
  393.       return _eglError(err, "eglCreateContext");
  394.  
  395.    return EGL_TRUE;
  396. }
  397.  
  398.  
  399. static EGLint
  400. _eglQueryContextRenderBuffer(_EGLContext *ctx)
  401. {
  402.    _EGLSurface *surf = ctx->DrawSurface;
  403.    EGLint rb;
  404.  
  405.    if (!surf)
  406.       return EGL_NONE;
  407.    if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
  408.       rb = ctx->WindowRenderBuffer;
  409.    else
  410.       rb = surf->RenderBuffer;
  411.    return rb;
  412. }
  413.  
  414.  
  415. EGLBoolean
  416. _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
  417.                  EGLint attribute, EGLint *value)
  418. {
  419.    (void) drv;
  420.    (void) dpy;
  421.  
  422.    if (!value)
  423.       return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
  424.  
  425.    switch (attribute) {
  426.    case EGL_CONFIG_ID:
  427.       if (!c->Config)
  428.          return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
  429.       *value = c->Config->ConfigID;
  430.       break;
  431.    case EGL_CONTEXT_CLIENT_VERSION:
  432.       *value = c->ClientMajorVersion;
  433.       break;
  434.    case EGL_CONTEXT_CLIENT_TYPE:
  435.       *value = c->ClientAPI;
  436.       break;
  437.    case EGL_RENDER_BUFFER:
  438.       *value = _eglQueryContextRenderBuffer(c);
  439.       break;
  440.    default:
  441.       return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
  442.    }
  443.  
  444.    return EGL_TRUE;
  445. }
  446.  
  447.  
  448. /**
  449.  * Bind the context to the thread and return the previous context.
  450.  *
  451.  * Note that the context may be NULL.
  452.  */
  453. static _EGLContext *
  454. _eglBindContextToThread(_EGLContext *ctx, _EGLThreadInfo *t)
  455. {
  456.    EGLint apiIndex;
  457.    _EGLContext *oldCtx;
  458.  
  459.     apiIndex = (ctx) ?
  460.       _eglConvertApiToIndex(ctx->ClientAPI) : t->CurrentAPIIndex;
  461.  
  462.    oldCtx = t->CurrentContexts[apiIndex];
  463.    if (ctx != oldCtx) {
  464.       if (oldCtx)
  465.          oldCtx->Binding = NULL;
  466.       if (ctx)
  467.          ctx->Binding = t;
  468.  
  469.       t->CurrentContexts[apiIndex] = ctx;
  470.    }
  471.  
  472.    return oldCtx;
  473. }
  474.  
  475.  
  476. /**
  477.  * Return true if the given context and surfaces can be made current.
  478.  */
  479. static EGLBoolean
  480. _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
  481. {
  482.    _EGLThreadInfo *t = _eglGetCurrentThread();
  483.    _EGLDisplay *dpy;
  484.    EGLint conflict_api;
  485.  
  486.    if (_eglIsCurrentThreadDummy())
  487.       return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent");
  488.  
  489.    /* this is easy */
  490.    if (!ctx) {
  491.       if (draw || read)
  492.          return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
  493.       return EGL_TRUE;
  494.    }
  495.  
  496.    dpy = ctx->Resource.Display;
  497.    if (!dpy->Extensions.KHR_surfaceless_context
  498.        && (draw == NULL || read == NULL))
  499.       return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
  500.  
  501.    /*
  502.     * The spec says
  503.     *
  504.     * "If ctx is current to some other thread, or if either draw or read are
  505.     * bound to contexts in another thread, an EGL_BAD_ACCESS error is
  506.     * generated."
  507.     *
  508.     * and
  509.     *
  510.     * "at most one context may be bound to a particular surface at a given
  511.     * time"
  512.     */
  513.    if (ctx->Binding && ctx->Binding != t)
  514.       return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
  515.    if (draw && draw->CurrentContext && draw->CurrentContext != ctx) {
  516.       if (draw->CurrentContext->Binding != t ||
  517.           draw->CurrentContext->ClientAPI != ctx->ClientAPI)
  518.          return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
  519.    }
  520.    if (read && read->CurrentContext && read->CurrentContext != ctx) {
  521.       if (read->CurrentContext->Binding != t ||
  522.           read->CurrentContext->ClientAPI != ctx->ClientAPI)
  523.          return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
  524.    }
  525.  
  526.    /* simply require the configs to be equal */
  527.    if ((draw && draw->Config != ctx->Config) ||
  528.        (read && read->Config != ctx->Config))
  529.       return _eglError(EGL_BAD_MATCH, "eglMakeCurrent");
  530.  
  531.    switch (ctx->ClientAPI) {
  532.    /* OpenGL and OpenGL ES are conflicting */
  533.    case EGL_OPENGL_ES_API:
  534.       conflict_api = EGL_OPENGL_API;
  535.       break;
  536.    case EGL_OPENGL_API:
  537.       conflict_api = EGL_OPENGL_ES_API;
  538.       break;
  539.    default:
  540.       conflict_api = -1;
  541.       break;
  542.    }
  543.  
  544.    if (conflict_api >= 0 && _eglGetAPIContext(conflict_api))
  545.       return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent");
  546.  
  547.    return EGL_TRUE;
  548. }
  549.  
  550.  
  551. /**
  552.  * Bind the context to the current thread and given surfaces.  Return the
  553.  * previous bound context and surfaces.  The caller should unreference the
  554.  * returned context and surfaces.
  555.  *
  556.  * Making a second call with the resources returned by the first call
  557.  * unsurprisingly undoes the first call, except for the resouce reference
  558.  * counts.
  559.  */
  560. EGLBoolean
  561. _eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
  562.                 _EGLContext **old_ctx,
  563.                 _EGLSurface **old_draw, _EGLSurface **old_read)
  564. {
  565.    _EGLThreadInfo *t = _eglGetCurrentThread();
  566.    _EGLContext *prev_ctx;
  567.    _EGLSurface *prev_draw, *prev_read;
  568.  
  569.    if (!_eglCheckMakeCurrent(ctx, draw, read))
  570.       return EGL_FALSE;
  571.  
  572.    /* increment refcounts before binding */
  573.    _eglGetContext(ctx);
  574.    _eglGetSurface(draw);
  575.    _eglGetSurface(read);
  576.  
  577.    /* bind the new context */
  578.    prev_ctx = _eglBindContextToThread(ctx, t);
  579.  
  580.    /* break previous bindings */
  581.    if (prev_ctx) {
  582.       prev_draw = prev_ctx->DrawSurface;
  583.       prev_read = prev_ctx->ReadSurface;
  584.  
  585.       if (prev_draw)
  586.          prev_draw->CurrentContext = NULL;
  587.       if (prev_read)
  588.          prev_read->CurrentContext = NULL;
  589.  
  590.       prev_ctx->DrawSurface = NULL;
  591.       prev_ctx->ReadSurface = NULL;
  592.    }
  593.    else {
  594.       prev_draw = prev_read = NULL;
  595.    }
  596.  
  597.    /* establish new bindings */
  598.    if (ctx) {
  599.       if (draw)
  600.          draw->CurrentContext = ctx;
  601.       if (read)
  602.          read->CurrentContext = ctx;
  603.  
  604.       ctx->DrawSurface = draw;
  605.       ctx->ReadSurface = read;
  606.    }
  607.  
  608.    assert(old_ctx && old_draw && old_read);
  609.    *old_ctx = prev_ctx;
  610.    *old_draw = prev_draw;
  611.    *old_read = prev_read;
  612.  
  613.    return EGL_TRUE;
  614. }
  615.