Home | History | Annotate | Download | only in libGLESv2
      1 //
      2 // Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
      3 // Use of this source code is governed by a BSD-style license that can be
      4 // found in the LICENSE file.
      5 //
      6 
      7 // Context.cpp: Implements the gl::Context class, managing all GL state and performing
      8 // rendering operations. It is the GLES2 specific implementation of EGLContext.
      9 
     10 #include "libGLESv2/Context.h"
     11 
     12 #include <algorithm>
     13 
     14 #include "libEGL/Display.h"
     15 
     16 #include "libGLESv2/main.h"
     17 #include "libGLESv2/mathutil.h"
     18 #include "libGLESv2/utilities.h"
     19 #include "libGLESv2/Blit.h"
     20 #include "libGLESv2/ResourceManager.h"
     21 #include "libGLESv2/Buffer.h"
     22 #include "libGLESv2/Fence.h"
     23 #include "libGLESv2/FrameBuffer.h"
     24 #include "libGLESv2/Program.h"
     25 #include "libGLESv2/RenderBuffer.h"
     26 #include "libGLESv2/Shader.h"
     27 #include "libGLESv2/Texture.h"
     28 #include "libGLESv2/geometry/VertexDataManager.h"
     29 #include "libGLESv2/geometry/IndexDataManager.h"
     30 
     31 #undef near
     32 #undef far
     33 
     34 namespace gl
     35 {
     36 Context::Context(const egl::Config *config, const gl::Context *shareContext)
     37     : mConfig(config)
     38 {
     39     setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
     40 
     41     mState.depthClearValue = 1.0f;
     42     mState.stencilClearValue = 0;
     43 
     44     mState.cullFace = false;
     45     mState.cullMode = GL_BACK;
     46     mState.frontFace = GL_CCW;
     47     mState.depthTest = false;
     48     mState.depthFunc = GL_LESS;
     49     mState.blend = false;
     50     mState.sourceBlendRGB = GL_ONE;
     51     mState.sourceBlendAlpha = GL_ONE;
     52     mState.destBlendRGB = GL_ZERO;
     53     mState.destBlendAlpha = GL_ZERO;
     54     mState.blendEquationRGB = GL_FUNC_ADD;
     55     mState.blendEquationAlpha = GL_FUNC_ADD;
     56     mState.blendColor.red = 0;
     57     mState.blendColor.green = 0;
     58     mState.blendColor.blue = 0;
     59     mState.blendColor.alpha = 0;
     60     mState.stencilTest = false;
     61     mState.stencilFunc = GL_ALWAYS;
     62     mState.stencilRef = 0;
     63     mState.stencilMask = -1;
     64     mState.stencilWritemask = -1;
     65     mState.stencilBackFunc = GL_ALWAYS;
     66     mState.stencilBackRef = 0;
     67     mState.stencilBackMask = - 1;
     68     mState.stencilBackWritemask = -1;
     69     mState.stencilFail = GL_KEEP;
     70     mState.stencilPassDepthFail = GL_KEEP;
     71     mState.stencilPassDepthPass = GL_KEEP;
     72     mState.stencilBackFail = GL_KEEP;
     73     mState.stencilBackPassDepthFail = GL_KEEP;
     74     mState.stencilBackPassDepthPass = GL_KEEP;
     75     mState.polygonOffsetFill = false;
     76     mState.polygonOffsetFactor = 0.0f;
     77     mState.polygonOffsetUnits = 0.0f;
     78     mState.sampleAlphaToCoverage = false;
     79     mState.sampleCoverage = false;
     80     mState.sampleCoverageValue = 1.0f;
     81     mState.sampleCoverageInvert = false;
     82     mState.scissorTest = false;
     83     mState.dither = true;
     84     mState.generateMipmapHint = GL_DONT_CARE;
     85     mState.fragmentShaderDerivativeHint = GL_DONT_CARE;
     86 
     87     mState.lineWidth = 1.0f;
     88 
     89     mState.viewportX = 0;
     90     mState.viewportY = 0;
     91     mState.viewportWidth = config->mDisplayMode.Width;
     92     mState.viewportHeight = config->mDisplayMode.Height;
     93     mState.zNear = 0.0f;
     94     mState.zFar = 1.0f;
     95 
     96     mState.scissorX = 0;
     97     mState.scissorY = 0;
     98     mState.scissorWidth = config->mDisplayMode.Width;
     99     mState.scissorHeight = config->mDisplayMode.Height;
    100 
    101     mState.colorMaskRed = true;
    102     mState.colorMaskGreen = true;
    103     mState.colorMaskBlue = true;
    104     mState.colorMaskAlpha = true;
    105     mState.depthMask = true;
    106 
    107     if (shareContext != NULL)
    108     {
    109         mResourceManager = shareContext->mResourceManager;
    110         mResourceManager->addRef();
    111     }
    112     else
    113     {
    114         mResourceManager = new ResourceManager();
    115     }
    116 
    117     // [OpenGL ES 2.0.24] section 3.7 page 83:
    118     // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
    119     // and cube map texture state vectors respectively associated with them.
    120     // In order that access to these initial textures not be lost, they are treated as texture
    121     // objects all of whose names are 0.
    122 
    123     mTexture2DZero.set(new Texture2D(0));
    124     mTextureCubeMapZero.set(new TextureCubeMap(0));
    125 
    126     mState.activeSampler = 0;
    127     bindArrayBuffer(0);
    128     bindElementArrayBuffer(0);
    129     bindTextureCubeMap(0);
    130     bindTexture2D(0);
    131     bindReadFramebuffer(0);
    132     bindDrawFramebuffer(0);
    133     bindRenderbuffer(0);
    134 
    135     mState.currentProgram = 0;
    136 
    137     mState.packAlignment = 4;
    138     mState.unpackAlignment = 4;
    139 
    140     mVertexDataManager = NULL;
    141     mIndexDataManager = NULL;
    142     mBlit = NULL;
    143 
    144     mInvalidEnum = false;
    145     mInvalidValue = false;
    146     mInvalidOperation = false;
    147     mOutOfMemory = false;
    148     mInvalidFramebufferOperation = false;
    149 
    150     mHasBeenCurrent = false;
    151 
    152     mSupportsCompressedTextures = false;
    153     mSupportsEventQueries = false;
    154     mMaxSupportedSamples = 0;
    155     mMaskedClearSavedState = NULL;
    156     markAllStateDirty();
    157 }
    158 
    159 Context::~Context()
    160 {
    161     if (mState.currentProgram != 0)
    162     {
    163         Program *programObject = mResourceManager->getProgram(mState.currentProgram);
    164         if (programObject)
    165         {
    166             programObject->release();
    167         }
    168         mState.currentProgram = 0;
    169     }
    170 
    171     while (!mFramebufferMap.empty())
    172     {
    173         deleteFramebuffer(mFramebufferMap.begin()->first);
    174     }
    175 
    176     while (!mFenceMap.empty())
    177     {
    178         deleteFence(mFenceMap.begin()->first);
    179     }
    180 
    181     while (!mMultiSampleSupport.empty())
    182     {
    183         delete [] mMultiSampleSupport.begin()->second;
    184         mMultiSampleSupport.erase(mMultiSampleSupport.begin());
    185     }
    186 
    187     for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
    188     {
    189         for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
    190         {
    191             mState.samplerTexture[type][sampler].set(NULL);
    192         }
    193     }
    194 
    195     for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
    196     {
    197         mIncompleteTextures[type].set(NULL);
    198     }
    199 
    200     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
    201     {
    202         mState.vertexAttribute[i].mBoundBuffer.set(NULL);
    203     }
    204 
    205     mState.arrayBuffer.set(NULL);
    206     mState.elementArrayBuffer.set(NULL);
    207     mState.renderbuffer.set(NULL);
    208 
    209     mTexture2DZero.set(NULL);
    210     mTextureCubeMapZero.set(NULL);
    211 
    212     delete mVertexDataManager;
    213     delete mIndexDataManager;
    214     delete mBlit;
    215 
    216     if (mMaskedClearSavedState)
    217     {
    218         mMaskedClearSavedState->Release();
    219     }
    220 
    221     mResourceManager->release();
    222 }
    223 
    224 void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
    225 {
    226     IDirect3DDevice9 *device = display->getDevice();
    227 
    228     if (!mHasBeenCurrent)
    229     {
    230         mDeviceCaps = display->getDeviceCaps();
    231 
    232         mVertexDataManager = new VertexDataManager(this, device);
    233         mIndexDataManager = new IndexDataManager(this, device);
    234         mBlit = new Blit(this);
    235 
    236         mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
    237 
    238         mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight),
    239                                         (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
    240         mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
    241         mMaxRenderbufferDimension = mMaxTextureDimension;
    242         mMaxTextureLevel = log2(mMaxTextureDimension) + 1;
    243         TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d",
    244               mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel);
    245 
    246         const D3DFORMAT renderBufferFormats[] =
    247         {
    248             D3DFMT_A8R8G8B8,
    249             D3DFMT_X8R8G8B8,
    250             D3DFMT_R5G6B5,
    251             D3DFMT_D24S8
    252         };
    253 
    254         int max = 0;
    255         for (int i = 0; i < sizeof(renderBufferFormats) / sizeof(D3DFORMAT); ++i)
    256         {
    257             bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
    258             display->getMultiSampleSupport(renderBufferFormats[i], multisampleArray);
    259             mMultiSampleSupport[renderBufferFormats[i]] = multisampleArray;
    260 
    261             for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
    262             {
    263                 if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
    264                 {
    265                     max = j;
    266                 }
    267             }
    268         }
    269 
    270         mMaxSupportedSamples = max;
    271 
    272         mSupportsEventQueries = display->getEventQuerySupport();
    273         mSupportsCompressedTextures = display->getCompressedTextureSupport();
    274         mSupportsFloatTextures = display->getFloatTextureSupport(&mSupportsFloatLinearFilter, &mSupportsFloatRenderableTextures);
    275         mSupportsHalfFloatTextures = display->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter, &mSupportsHalfFloatRenderableTextures);
    276         mSupportsLuminanceTextures = display->getLuminanceTextureSupport();
    277         mSupportsLuminanceAlphaTextures = display->getLuminanceAlphaTextureSupport();
    278 
    279         mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16);
    280 
    281         initExtensionString();
    282 
    283         mState.viewportX = 0;
    284         mState.viewportY = 0;
    285         mState.viewportWidth = surface->getWidth();
    286         mState.viewportHeight = surface->getHeight();
    287 
    288         mState.scissorX = 0;
    289         mState.scissorY = 0;
    290         mState.scissorWidth = surface->getWidth();
    291         mState.scissorHeight = surface->getHeight();
    292 
    293         mHasBeenCurrent = true;
    294     }
    295 
    296     // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
    297     IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
    298     IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
    299 
    300     Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
    301     DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
    302     Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);
    303 
    304     setFramebufferZero(framebufferZero);
    305 
    306     if (defaultRenderTarget)
    307     {
    308         defaultRenderTarget->Release();
    309     }
    310 
    311     if (depthStencil)
    312     {
    313         depthStencil->Release();
    314     }
    315 
    316     markAllStateDirty();
    317 }
    318 
    319 // This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
    320 void Context::markAllStateDirty()
    321 {
    322     mAppliedRenderTargetSerial = 0;
    323     mAppliedDepthbufferSerial = 0;
    324     mAppliedStencilbufferSerial = 0;
    325     mDepthStencilInitialized = false;
    326     mAppliedProgram = 0;
    327 
    328     mClearStateDirty = true;
    329     mCullStateDirty = true;
    330     mDepthStateDirty = true;
    331     mMaskStateDirty = true;
    332     mBlendStateDirty = true;
    333     mStencilStateDirty = true;
    334     mPolygonOffsetStateDirty = true;
    335     mScissorStateDirty = true;
    336     mSampleStateDirty = true;
    337     mDitherStateDirty = true;
    338     mFrontFaceDirty = true;
    339 }
    340 
    341 void Context::setClearColor(float red, float green, float blue, float alpha)
    342 {
    343     mState.colorClearValue.red = red;
    344     mState.colorClearValue.green = green;
    345     mState.colorClearValue.blue = blue;
    346     mState.colorClearValue.alpha = alpha;
    347 }
    348 
    349 void Context::setClearDepth(float depth)
    350 {
    351     mState.depthClearValue = depth;
    352 }
    353 
    354 void Context::setClearStencil(int stencil)
    355 {
    356     mState.stencilClearValue = stencil;
    357 }
    358 
    359 void Context::setCullFace(bool enabled)
    360 {
    361     if (mState.cullFace != enabled)
    362     {
    363         mState.cullFace = enabled;
    364         mCullStateDirty = true;
    365     }
    366 }
    367 
    368 bool Context::isCullFaceEnabled() const
    369 {
    370     return mState.cullFace;
    371 }
    372 
    373 void Context::setCullMode(GLenum mode)
    374 {
    375     if (mState.cullMode != mode)
    376     {
    377         mState.cullMode = mode;
    378         mCullStateDirty = true;
    379     }
    380 }
    381 
    382 void Context::setFrontFace(GLenum front)
    383 {
    384     if (mState.frontFace != front)
    385     {
    386         mState.frontFace = front;
    387         mFrontFaceDirty = true;
    388     }
    389 }
    390 
    391 void Context::setDepthTest(bool enabled)
    392 {
    393     if (mState.depthTest != enabled)
    394     {
    395         mState.depthTest = enabled;
    396         mDepthStateDirty = true;
    397     }
    398 }
    399 
    400 bool Context::isDepthTestEnabled() const
    401 {
    402     return mState.depthTest;
    403 }
    404 
    405 void Context::setDepthFunc(GLenum depthFunc)
    406 {
    407     if (mState.depthFunc != depthFunc)
    408     {
    409         mState.depthFunc = depthFunc;
    410         mDepthStateDirty = true;
    411     }
    412 }
    413 
    414 void Context::setDepthRange(float zNear, float zFar)
    415 {
    416     mState.zNear = zNear;
    417     mState.zFar = zFar;
    418 }
    419 
    420 void Context::setBlend(bool enabled)
    421 {
    422     if (mState.blend != enabled)
    423     {
    424         mState.blend = enabled;
    425         mBlendStateDirty = true;
    426     }
    427 }
    428 
    429 bool Context::isBlendEnabled() const
    430 {
    431     return mState.blend;
    432 }
    433 
    434 void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
    435 {
    436     if (mState.sourceBlendRGB != sourceRGB ||
    437         mState.sourceBlendAlpha != sourceAlpha ||
    438         mState.destBlendRGB != destRGB ||
    439         mState.destBlendAlpha != destAlpha)
    440     {
    441         mState.sourceBlendRGB = sourceRGB;
    442         mState.destBlendRGB = destRGB;
    443         mState.sourceBlendAlpha = sourceAlpha;
    444         mState.destBlendAlpha = destAlpha;
    445         mBlendStateDirty = true;
    446     }
    447 }
    448 
    449 void Context::setBlendColor(float red, float green, float blue, float alpha)
    450 {
    451     if (mState.blendColor.red != red ||
    452         mState.blendColor.green != green ||
    453         mState.blendColor.blue != blue ||
    454         mState.blendColor.alpha != alpha)
    455     {
    456         mState.blendColor.red = red;
    457         mState.blendColor.green = green;
    458         mState.blendColor.blue = blue;
    459         mState.blendColor.alpha = alpha;
    460         mBlendStateDirty = true;
    461     }
    462 }
    463 
    464 void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
    465 {
    466     if (mState.blendEquationRGB != rgbEquation ||
    467         mState.blendEquationAlpha != alphaEquation)
    468     {
    469         mState.blendEquationRGB = rgbEquation;
    470         mState.blendEquationAlpha = alphaEquation;
    471         mBlendStateDirty = true;
    472     }
    473 }
    474 
    475 void Context::setStencilTest(bool enabled)
    476 {
    477     if (mState.stencilTest != enabled)
    478     {
    479         mState.stencilTest = enabled;
    480         mStencilStateDirty = true;
    481     }
    482 }
    483 
    484 bool Context::isStencilTestEnabled() const
    485 {
    486     return mState.stencilTest;
    487 }
    488 
    489 void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
    490 {
    491     if (mState.stencilFunc != stencilFunc ||
    492         mState.stencilRef != stencilRef ||
    493         mState.stencilMask != stencilMask)
    494     {
    495         mState.stencilFunc = stencilFunc;
    496         mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
    497         mState.stencilMask = stencilMask;
    498         mStencilStateDirty = true;
    499     }
    500 }
    501 
    502 void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
    503 {
    504     if (mState.stencilBackFunc != stencilBackFunc ||
    505         mState.stencilBackRef != stencilBackRef ||
    506         mState.stencilBackMask != stencilBackMask)
    507     {
    508         mState.stencilBackFunc = stencilBackFunc;
    509         mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
    510         mState.stencilBackMask = stencilBackMask;
    511         mStencilStateDirty = true;
    512     }
    513 }
    514 
    515 void Context::setStencilWritemask(GLuint stencilWritemask)
    516 {
    517     if (mState.stencilWritemask != stencilWritemask)
    518     {
    519         mState.stencilWritemask = stencilWritemask;
    520         mStencilStateDirty = true;
    521     }
    522 }
    523 
    524 void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
    525 {
    526     if (mState.stencilBackWritemask != stencilBackWritemask)
    527     {
    528         mState.stencilBackWritemask = stencilBackWritemask;
    529         mStencilStateDirty = true;
    530     }
    531 }
    532 
    533 void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
    534 {
    535     if (mState.stencilFail != stencilFail ||
    536         mState.stencilPassDepthFail != stencilPassDepthFail ||
    537         mState.stencilPassDepthPass != stencilPassDepthPass)
    538     {
    539         mState.stencilFail = stencilFail;
    540         mState.stencilPassDepthFail = stencilPassDepthFail;
    541         mState.stencilPassDepthPass = stencilPassDepthPass;
    542         mStencilStateDirty = true;
    543     }
    544 }
    545 
    546 void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
    547 {
    548     if (mState.stencilBackFail != stencilBackFail ||
    549         mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
    550         mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
    551     {
    552         mState.stencilBackFail = stencilBackFail;
    553         mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
    554         mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
    555         mStencilStateDirty = true;
    556     }
    557 }
    558 
    559 void Context::setPolygonOffsetFill(bool enabled)
    560 {
    561     if (mState.polygonOffsetFill != enabled)
    562     {
    563         mState.polygonOffsetFill = enabled;
    564         mPolygonOffsetStateDirty = true;
    565     }
    566 }
    567 
    568 bool Context::isPolygonOffsetFillEnabled() const
    569 {
    570     return mState.polygonOffsetFill;
    571 
    572 }
    573 
    574 void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
    575 {
    576     if (mState.polygonOffsetFactor != factor ||
    577         mState.polygonOffsetUnits != units)
    578     {
    579         mState.polygonOffsetFactor = factor;
    580         mState.polygonOffsetUnits = units;
    581         mPolygonOffsetStateDirty = true;
    582     }
    583 }
    584 
    585 void Context::setSampleAlphaToCoverage(bool enabled)
    586 {
    587     if (mState.sampleAlphaToCoverage != enabled)
    588     {
    589         mState.sampleAlphaToCoverage = enabled;
    590         mSampleStateDirty = true;
    591     }
    592 }
    593 
    594 bool Context::isSampleAlphaToCoverageEnabled() const
    595 {
    596     return mState.sampleAlphaToCoverage;
    597 }
    598 
    599 void Context::setSampleCoverage(bool enabled)
    600 {
    601     if (mState.sampleCoverage != enabled)
    602     {
    603         mState.sampleCoverage = enabled;
    604         mSampleStateDirty = true;
    605     }
    606 }
    607 
    608 bool Context::isSampleCoverageEnabled() const
    609 {
    610     return mState.sampleCoverage;
    611 }
    612 
    613 void Context::setSampleCoverageParams(GLclampf value, bool invert)
    614 {
    615     if (mState.sampleCoverageValue != value ||
    616         mState.sampleCoverageInvert != invert)
    617     {
    618         mState.sampleCoverageValue = value;
    619         mState.sampleCoverageInvert = invert;
    620         mSampleStateDirty = true;
    621     }
    622 }
    623 
    624 void Context::setScissorTest(bool enabled)
    625 {
    626     if (mState.scissorTest != enabled)
    627     {
    628         mState.scissorTest = enabled;
    629         mScissorStateDirty = true;
    630     }
    631 }
    632 
    633 bool Context::isScissorTestEnabled() const
    634 {
    635     return mState.scissorTest;
    636 }
    637 
    638 void Context::setDither(bool enabled)
    639 {
    640     if (mState.dither != enabled)
    641     {
    642         mState.dither = enabled;
    643         mDitherStateDirty = true;
    644     }
    645 }
    646 
    647 bool Context::isDitherEnabled() const
    648 {
    649     return mState.dither;
    650 }
    651 
    652 void Context::setLineWidth(GLfloat width)
    653 {
    654     mState.lineWidth = width;
    655 }
    656 
    657 void Context::setGenerateMipmapHint(GLenum hint)
    658 {
    659     mState.generateMipmapHint = hint;
    660 }
    661 
    662 void Context::setFragmentShaderDerivativeHint(GLenum hint)
    663 {
    664     mState.fragmentShaderDerivativeHint = hint;
    665     // TODO: Propagate the hint to shader translator so we can write
    666     // ddx, ddx_coarse, or ddx_fine depending on the hint.
    667     // Ignore for now. It is valid for implementations to ignore hint.
    668 }
    669 
    670 void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
    671 {
    672     mState.viewportX = x;
    673     mState.viewportY = y;
    674     mState.viewportWidth = width;
    675     mState.viewportHeight = height;
    676 }
    677 
    678 void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
    679 {
    680     if (mState.scissorX != x || mState.scissorY != y ||
    681         mState.scissorWidth != width || mState.scissorHeight != height)
    682     {
    683         mState.scissorX = x;
    684         mState.scissorY = y;
    685         mState.scissorWidth = width;
    686         mState.scissorHeight = height;
    687         mScissorStateDirty = true;
    688     }
    689 }
    690 
    691 void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
    692 {
    693     if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
    694         mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
    695     {
    696         mState.colorMaskRed = red;
    697         mState.colorMaskGreen = green;
    698         mState.colorMaskBlue = blue;
    699         mState.colorMaskAlpha = alpha;
    700         mMaskStateDirty = true;
    701     }
    702 }
    703 
    704 void Context::setDepthMask(bool mask)
    705 {
    706     if (mState.depthMask != mask)
    707     {
    708         mState.depthMask = mask;
    709         mMaskStateDirty = true;
    710     }
    711 }
    712 
    713 void Context::setActiveSampler(int active)
    714 {
    715     mState.activeSampler = active;
    716 }
    717 
    718 GLuint Context::getReadFramebufferHandle() const
    719 {
    720     return mState.readFramebuffer;
    721 }
    722 
    723 GLuint Context::getDrawFramebufferHandle() const
    724 {
    725     return mState.drawFramebuffer;
    726 }
    727 
    728 GLuint Context::getRenderbufferHandle() const
    729 {
    730     return mState.renderbuffer.id();
    731 }
    732 
    733 GLuint Context::getArrayBufferHandle() const
    734 {
    735     return mState.arrayBuffer.id();
    736 }
    737 
    738 void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
    739 {
    740     mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
    741 }
    742 
    743 const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
    744 {
    745     return mState.vertexAttribute[attribNum];
    746 }
    747 
    748 void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
    749                                    GLsizei stride, const void *pointer)
    750 {
    751     mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
    752     mState.vertexAttribute[attribNum].mSize = size;
    753     mState.vertexAttribute[attribNum].mType = type;
    754     mState.vertexAttribute[attribNum].mNormalized = normalized;
    755     mState.vertexAttribute[attribNum].mStride = stride;
    756     mState.vertexAttribute[attribNum].mPointer = pointer;
    757 }
    758 
    759 const void *Context::getVertexAttribPointer(unsigned int attribNum) const
    760 {
    761     return mState.vertexAttribute[attribNum].mPointer;
    762 }
    763 
    764 const VertexAttributeArray &Context::getVertexAttributes()
    765 {
    766     return mState.vertexAttribute;
    767 }
    768 
    769 void Context::setPackAlignment(GLint alignment)
    770 {
    771     mState.packAlignment = alignment;
    772 }
    773 
    774 GLint Context::getPackAlignment() const
    775 {
    776     return mState.packAlignment;
    777 }
    778 
    779 void Context::setUnpackAlignment(GLint alignment)
    780 {
    781     mState.unpackAlignment = alignment;
    782 }
    783 
    784 GLint Context::getUnpackAlignment() const
    785 {
    786     return mState.unpackAlignment;
    787 }
    788 
    789 GLuint Context::createBuffer()
    790 {
    791     return mResourceManager->createBuffer();
    792 }
    793 
    794 GLuint Context::createProgram()
    795 {
    796     return mResourceManager->createProgram();
    797 }
    798 
    799 GLuint Context::createShader(GLenum type)
    800 {
    801     return mResourceManager->createShader(type);
    802 }
    803 
    804 GLuint Context::createTexture()
    805 {
    806     return mResourceManager->createTexture();
    807 }
    808 
    809 GLuint Context::createRenderbuffer()
    810 {
    811     return mResourceManager->createRenderbuffer();
    812 }
    813 
    814 // Returns an unused framebuffer name
    815 GLuint Context::createFramebuffer()
    816 {
    817     unsigned int handle = 1;
    818 
    819     while (mFramebufferMap.find(handle) != mFramebufferMap.end())
    820     {
    821         handle++;
    822     }
    823 
    824     mFramebufferMap[handle] = NULL;
    825 
    826     return handle;
    827 }
    828 
    829 GLuint Context::createFence()
    830 {
    831     unsigned int handle = 0;
    832 
    833     while (mFenceMap.find(handle) != mFenceMap.end())
    834     {
    835         handle++;
    836     }
    837 
    838     mFenceMap[handle] = new Fence;
    839 
    840     return handle;
    841 }
    842 
    843 void Context::deleteBuffer(GLuint buffer)
    844 {
    845     if (mResourceManager->getBuffer(buffer))
    846     {
    847         detachBuffer(buffer);
    848     }
    849 
    850     mResourceManager->deleteBuffer(buffer);
    851 }
    852 
    853 void Context::deleteShader(GLuint shader)
    854 {
    855     mResourceManager->deleteShader(shader);
    856 }
    857 
    858 void Context::deleteProgram(GLuint program)
    859 {
    860     mResourceManager->deleteProgram(program);
    861 }
    862 
    863 void Context::deleteTexture(GLuint texture)
    864 {
    865     if (mResourceManager->getTexture(texture))
    866     {
    867         detachTexture(texture);
    868     }
    869 
    870     mResourceManager->deleteTexture(texture);
    871 }
    872 
    873 void Context::deleteRenderbuffer(GLuint renderbuffer)
    874 {
    875     if (mResourceManager->getRenderbuffer(renderbuffer))
    876     {
    877         detachRenderbuffer(renderbuffer);
    878     }
    879 
    880     mResourceManager->deleteRenderbuffer(renderbuffer);
    881 }
    882 
    883 void Context::deleteFramebuffer(GLuint framebuffer)
    884 {
    885     FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
    886 
    887     if (framebufferObject != mFramebufferMap.end())
    888     {
    889         detachFramebuffer(framebuffer);
    890 
    891         delete framebufferObject->second;
    892         mFramebufferMap.erase(framebufferObject);
    893     }
    894 }
    895 
    896 void Context::deleteFence(GLuint fence)
    897 {
    898     FenceMap::iterator fenceObject = mFenceMap.find(fence);
    899 
    900     if (fenceObject != mFenceMap.end())
    901     {
    902         delete fenceObject->second;
    903         mFenceMap.erase(fenceObject);
    904     }
    905 }
    906 
    907 Buffer *Context::getBuffer(GLuint handle)
    908 {
    909     return mResourceManager->getBuffer(handle);
    910 }
    911 
    912 Shader *Context::getShader(GLuint handle)
    913 {
    914     return mResourceManager->getShader(handle);
    915 }
    916 
    917 Program *Context::getProgram(GLuint handle)
    918 {
    919     return mResourceManager->getProgram(handle);
    920 }
    921 
    922 Texture *Context::getTexture(GLuint handle)
    923 {
    924     return mResourceManager->getTexture(handle);
    925 }
    926 
    927 Renderbuffer *Context::getRenderbuffer(GLuint handle)
    928 {
    929     return mResourceManager->getRenderbuffer(handle);
    930 }
    931 
    932 Framebuffer *Context::getReadFramebuffer()
    933 {
    934     return getFramebuffer(mState.readFramebuffer);
    935 }
    936 
    937 Framebuffer *Context::getDrawFramebuffer()
    938 {
    939     return getFramebuffer(mState.drawFramebuffer);
    940 }
    941 
    942 void Context::bindArrayBuffer(unsigned int buffer)
    943 {
    944     mResourceManager->checkBufferAllocation(buffer);
    945 
    946     mState.arrayBuffer.set(getBuffer(buffer));
    947 }
    948 
    949 void Context::bindElementArrayBuffer(unsigned int buffer)
    950 {
    951     mResourceManager->checkBufferAllocation(buffer);
    952 
    953     mState.elementArrayBuffer.set(getBuffer(buffer));
    954 }
    955 
    956 void Context::bindTexture2D(GLuint texture)
    957 {
    958     mResourceManager->checkTextureAllocation(texture, SAMPLER_2D);
    959 
    960     mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(getTexture(texture));
    961 }
    962 
    963 void Context::bindTextureCubeMap(GLuint texture)
    964 {
    965     mResourceManager->checkTextureAllocation(texture, SAMPLER_CUBE);
    966 
    967     mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(getTexture(texture));
    968 }
    969 
    970 void Context::bindReadFramebuffer(GLuint framebuffer)
    971 {
    972     if (!getFramebuffer(framebuffer))
    973     {
    974         mFramebufferMap[framebuffer] = new Framebuffer();
    975     }
    976 
    977     mState.readFramebuffer = framebuffer;
    978 }
    979 
    980 void Context::bindDrawFramebuffer(GLuint framebuffer)
    981 {
    982     if (!getFramebuffer(framebuffer))
    983     {
    984         mFramebufferMap[framebuffer] = new Framebuffer();
    985     }
    986 
    987     mState.drawFramebuffer = framebuffer;
    988 }
    989 
    990 void Context::bindRenderbuffer(GLuint renderbuffer)
    991 {
    992     mResourceManager->checkRenderbufferAllocation(renderbuffer);
    993 
    994     mState.renderbuffer.set(getRenderbuffer(renderbuffer));
    995 }
    996 
    997 void Context::useProgram(GLuint program)
    998 {
    999     GLuint priorProgram = mState.currentProgram;
   1000     mState.currentProgram = program;               // Must switch before trying to delete, otherwise it only gets flagged.
   1001 
   1002     if (priorProgram != program)
   1003     {
   1004         Program *newProgram = mResourceManager->getProgram(program);
   1005         Program *oldProgram = mResourceManager->getProgram(priorProgram);
   1006 
   1007         if (newProgram)
   1008         {
   1009             newProgram->addRef();
   1010         }
   1011 
   1012         if (oldProgram)
   1013         {
   1014             oldProgram->release();
   1015         }
   1016     }
   1017 }
   1018 
   1019 void Context::setFramebufferZero(Framebuffer *buffer)
   1020 {
   1021     delete mFramebufferMap[0];
   1022     mFramebufferMap[0] = buffer;
   1023 }
   1024 
   1025 void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
   1026 {
   1027     Renderbuffer *renderbufferObject = mState.renderbuffer.get();
   1028     renderbufferObject->setStorage(renderbuffer);
   1029 }
   1030 
   1031 Framebuffer *Context::getFramebuffer(unsigned int handle)
   1032 {
   1033     FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
   1034 
   1035     if (framebuffer == mFramebufferMap.end())
   1036     {
   1037         return NULL;
   1038     }
   1039     else
   1040     {
   1041         return framebuffer->second;
   1042     }
   1043 }
   1044 
   1045 Fence *Context::getFence(unsigned int handle)
   1046 {
   1047     FenceMap::iterator fence = mFenceMap.find(handle);
   1048 
   1049     if (fence == mFenceMap.end())
   1050     {
   1051         return NULL;
   1052     }
   1053     else
   1054     {
   1055         return fence->second;
   1056     }
   1057 }
   1058 
   1059 Buffer *Context::getArrayBuffer()
   1060 {
   1061     return mState.arrayBuffer.get();
   1062 }
   1063 
   1064 Buffer *Context::getElementArrayBuffer()
   1065 {
   1066     return mState.elementArrayBuffer.get();
   1067 }
   1068 
   1069 Program *Context::getCurrentProgram()
   1070 {
   1071     return mResourceManager->getProgram(mState.currentProgram);
   1072 }
   1073 
   1074 Texture2D *Context::getTexture2D()
   1075 {
   1076     return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, SAMPLER_2D));
   1077 }
   1078 
   1079 TextureCubeMap *Context::getTextureCubeMap()
   1080 {
   1081     return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, SAMPLER_CUBE));
   1082 }
   1083 
   1084 Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
   1085 {
   1086     GLuint texid = mState.samplerTexture[type][sampler].id();
   1087 
   1088     if (texid == 0)   // Special case: 0 refers to different initial textures based on the target
   1089     {
   1090         switch (type)
   1091         {
   1092           default: UNREACHABLE();
   1093           case SAMPLER_2D: return mTexture2DZero.get();
   1094           case SAMPLER_CUBE: return mTextureCubeMapZero.get();
   1095         }
   1096     }
   1097 
   1098     return mState.samplerTexture[type][sampler].get();
   1099 }
   1100 
   1101 bool Context::getBooleanv(GLenum pname, GLboolean *params)
   1102 {
   1103     switch (pname)
   1104     {
   1105       case GL_SHADER_COMPILER:          *params = GL_TRUE;                          break;
   1106       case GL_SAMPLE_COVERAGE_INVERT:   *params = mState.sampleCoverageInvert;      break;
   1107       case GL_DEPTH_WRITEMASK:          *params = mState.depthMask;                 break;
   1108       case GL_COLOR_WRITEMASK:
   1109         params[0] = mState.colorMaskRed;
   1110         params[1] = mState.colorMaskGreen;
   1111         params[2] = mState.colorMaskBlue;
   1112         params[3] = mState.colorMaskAlpha;
   1113         break;
   1114       case GL_CULL_FACE:                *params = mState.cullFace;                  break;
   1115       case GL_POLYGON_OFFSET_FILL:      *params = mState.polygonOffsetFill;         break;
   1116       case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;     break;
   1117       case GL_SAMPLE_COVERAGE:          *params = mState.sampleCoverage;            break;
   1118       case GL_SCISSOR_TEST:             *params = mState.scissorTest;               break;
   1119       case GL_STENCIL_TEST:             *params = mState.stencilTest;               break;
   1120       case GL_DEPTH_TEST:               *params = mState.depthTest;                 break;
   1121       case GL_BLEND:                    *params = mState.blend;                     break;
   1122       case GL_DITHER:                   *params = mState.dither;                    break;
   1123       default:
   1124         return false;
   1125     }
   1126 
   1127     return true;
   1128 }
   1129 
   1130 bool Context::getFloatv(GLenum pname, GLfloat *params)
   1131 {
   1132     // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
   1133     // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
   1134     // GetIntegerv as its native query function. As it would require conversion in any
   1135     // case, this should make no difference to the calling application.
   1136     switch (pname)
   1137     {
   1138       case GL_LINE_WIDTH:               *params = mState.lineWidth;            break;
   1139       case GL_SAMPLE_COVERAGE_VALUE:    *params = mState.sampleCoverageValue;  break;
   1140       case GL_DEPTH_CLEAR_VALUE:        *params = mState.depthClearValue;      break;
   1141       case GL_POLYGON_OFFSET_FACTOR:    *params = mState.polygonOffsetFactor;  break;
   1142       case GL_POLYGON_OFFSET_UNITS:     *params = mState.polygonOffsetUnits;   break;
   1143       case GL_ALIASED_LINE_WIDTH_RANGE:
   1144         params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
   1145         params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
   1146         break;
   1147       case GL_ALIASED_POINT_SIZE_RANGE:
   1148         params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
   1149         params[1] = supportsShaderModel3() ? gl::ALIASED_POINT_SIZE_RANGE_MAX_SM3 : gl::ALIASED_POINT_SIZE_RANGE_MAX_SM2;
   1150         break;
   1151       case GL_DEPTH_RANGE:
   1152         params[0] = mState.zNear;
   1153         params[1] = mState.zFar;
   1154         break;
   1155       case GL_COLOR_CLEAR_VALUE:
   1156         params[0] = mState.colorClearValue.red;
   1157         params[1] = mState.colorClearValue.green;
   1158         params[2] = mState.colorClearValue.blue;
   1159         params[3] = mState.colorClearValue.alpha;
   1160         break;
   1161       case GL_BLEND_COLOR:
   1162         params[0] = mState.blendColor.red;
   1163         params[1] = mState.blendColor.green;
   1164         params[2] = mState.blendColor.blue;
   1165         params[3] = mState.blendColor.alpha;
   1166         break;
   1167       default:
   1168         return false;
   1169     }
   1170 
   1171     return true;
   1172 }
   1173 
   1174 bool Context::getIntegerv(GLenum pname, GLint *params)
   1175 {
   1176     // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
   1177     // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
   1178     // GetIntegerv as its native query function. As it would require conversion in any
   1179     // case, this should make no difference to the calling application. You may find it in
   1180     // Context::getFloatv.
   1181     switch (pname)
   1182     {
   1183       case GL_MAX_VERTEX_ATTRIBS:               *params = gl::MAX_VERTEX_ATTRIBS;               break;
   1184       case GL_MAX_VERTEX_UNIFORM_VECTORS:       *params = gl::MAX_VERTEX_UNIFORM_VECTORS;       break;
   1185       case GL_MAX_VARYING_VECTORS:              *params = getMaximumVaryingVectors();           break;
   1186       case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
   1187       case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:   *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS;   break;
   1188       case GL_MAX_TEXTURE_IMAGE_UNITS:          *params = gl::MAX_TEXTURE_IMAGE_UNITS;          break;
   1189       case GL_MAX_FRAGMENT_UNIFORM_VECTORS:     *params = getMaximumFragmentUniformVectors();   break;
   1190       case GL_MAX_RENDERBUFFER_SIZE:            *params = getMaximumRenderbufferDimension();    break;
   1191       case GL_NUM_SHADER_BINARY_FORMATS:        *params = 0;                                    break;
   1192       case GL_SHADER_BINARY_FORMATS:      /* no shader binary formats are supported */          break;
   1193       case GL_ARRAY_BUFFER_BINDING:             *params = mState.arrayBuffer.id();              break;
   1194       case GL_ELEMENT_ARRAY_BUFFER_BINDING:     *params = mState.elementArrayBuffer.id();       break;
   1195       //case GL_FRAMEBUFFER_BINDING:            // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
   1196       case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE:   *params = mState.drawFramebuffer;               break;
   1197       case GL_READ_FRAMEBUFFER_BINDING_ANGLE:   *params = mState.readFramebuffer;               break;
   1198       case GL_RENDERBUFFER_BINDING:             *params = mState.renderbuffer.id();             break;
   1199       case GL_CURRENT_PROGRAM:                  *params = mState.currentProgram;                break;
   1200       case GL_PACK_ALIGNMENT:                   *params = mState.packAlignment;                 break;
   1201       case GL_UNPACK_ALIGNMENT:                 *params = mState.unpackAlignment;               break;
   1202       case GL_GENERATE_MIPMAP_HINT:             *params = mState.generateMipmapHint;            break;
   1203       case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;
   1204       case GL_ACTIVE_TEXTURE:                   *params = (mState.activeSampler + GL_TEXTURE0); break;
   1205       case GL_STENCIL_FUNC:                     *params = mState.stencilFunc;                   break;
   1206       case GL_STENCIL_REF:                      *params = mState.stencilRef;                    break;
   1207       case GL_STENCIL_VALUE_MASK:               *params = mState.stencilMask;                   break;
   1208       case GL_STENCIL_BACK_FUNC:                *params = mState.stencilBackFunc;               break;
   1209       case GL_STENCIL_BACK_REF:                 *params = mState.stencilBackRef;                break;
   1210       case GL_STENCIL_BACK_VALUE_MASK:          *params = mState.stencilBackMask;               break;
   1211       case GL_STENCIL_FAIL:                     *params = mState.stencilFail;                   break;
   1212       case GL_STENCIL_PASS_DEPTH_FAIL:          *params = mState.stencilPassDepthFail;          break;
   1213       case GL_STENCIL_PASS_DEPTH_PASS:          *params = mState.stencilPassDepthPass;          break;
   1214       case GL_STENCIL_BACK_FAIL:                *params = mState.stencilBackFail;               break;
   1215       case GL_STENCIL_BACK_PASS_DEPTH_FAIL:     *params = mState.stencilBackPassDepthFail;      break;
   1216       case GL_STENCIL_BACK_PASS_DEPTH_PASS:     *params = mState.stencilBackPassDepthPass;      break;
   1217       case GL_DEPTH_FUNC:                       *params = mState.depthFunc;                     break;
   1218       case GL_BLEND_SRC_RGB:                    *params = mState.sourceBlendRGB;                break;
   1219       case GL_BLEND_SRC_ALPHA:                  *params = mState.sourceBlendAlpha;              break;
   1220       case GL_BLEND_DST_RGB:                    *params = mState.destBlendRGB;                  break;
   1221       case GL_BLEND_DST_ALPHA:                  *params = mState.destBlendAlpha;                break;
   1222       case GL_BLEND_EQUATION_RGB:               *params = mState.blendEquationRGB;              break;
   1223       case GL_BLEND_EQUATION_ALPHA:             *params = mState.blendEquationAlpha;            break;
   1224       case GL_STENCIL_WRITEMASK:                *params = mState.stencilWritemask;              break;
   1225       case GL_STENCIL_BACK_WRITEMASK:           *params = mState.stencilBackWritemask;          break;
   1226       case GL_STENCIL_CLEAR_VALUE:              *params = mState.stencilClearValue;             break;
   1227       case GL_SUBPIXEL_BITS:                    *params = 4;                                    break;
   1228       case GL_MAX_TEXTURE_SIZE:                 *params = getMaximumTextureDimension();         break;
   1229       case GL_MAX_CUBE_MAP_TEXTURE_SIZE:        *params = getMaximumCubeTextureDimension();     break;
   1230       case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
   1231         {
   1232             if (supportsCompressedTextures())
   1233             {
   1234                 // at current, only GL_COMPRESSED_RGB_S3TC_DXT1_EXT and
   1235                 // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT are supported
   1236                 *params = 2;
   1237             }
   1238             else
   1239             {
   1240                 *params = 0;
   1241             }
   1242         }
   1243         break;
   1244       case GL_MAX_SAMPLES_ANGLE:
   1245         {
   1246             GLsizei maxSamples = getMaxSupportedSamples();
   1247             if (maxSamples != 0)
   1248             {
   1249                 *params = maxSamples;
   1250             }
   1251             else
   1252             {
   1253                 return false;
   1254             }
   1255 
   1256             break;
   1257         }
   1258       case GL_SAMPLE_BUFFERS:
   1259       case GL_SAMPLES:
   1260         {
   1261             gl::Framebuffer *framebuffer = getDrawFramebuffer();
   1262             if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
   1263             {
   1264                 switch (pname)
   1265                 {
   1266                   case GL_SAMPLE_BUFFERS:
   1267                     if (framebuffer->getSamples() != 0)
   1268                     {
   1269                         *params = 1;
   1270                     }
   1271                     else
   1272                     {
   1273                         *params = 0;
   1274                     }
   1275                     break;
   1276                   case GL_SAMPLES:
   1277                     *params = framebuffer->getSamples();
   1278                     break;
   1279                 }
   1280             }
   1281             else
   1282             {
   1283                 *params = 0;
   1284             }
   1285         }
   1286         break;
   1287       case GL_IMPLEMENTATION_COLOR_READ_TYPE:   *params = gl::IMPLEMENTATION_COLOR_READ_TYPE;   break;
   1288       case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
   1289       case GL_MAX_VIEWPORT_DIMS:
   1290         {
   1291             int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension());
   1292             params[0] = maxDimension;
   1293             params[1] = maxDimension;
   1294         }
   1295         break;
   1296       case GL_COMPRESSED_TEXTURE_FORMATS:
   1297         {
   1298             if (supportsCompressedTextures())
   1299             {
   1300                 params[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
   1301                 params[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
   1302             }
   1303         }
   1304         break;
   1305       case GL_VIEWPORT:
   1306         params[0] = mState.viewportX;
   1307         params[1] = mState.viewportY;
   1308         params[2] = mState.viewportWidth;
   1309         params[3] = mState.viewportHeight;
   1310         break;
   1311       case GL_SCISSOR_BOX:
   1312         params[0] = mState.scissorX;
   1313         params[1] = mState.scissorY;
   1314         params[2] = mState.scissorWidth;
   1315         params[3] = mState.scissorHeight;
   1316         break;
   1317       case GL_CULL_FACE_MODE:                   *params = mState.cullMode;                 break;
   1318       case GL_FRONT_FACE:                       *params = mState.frontFace;                break;
   1319       case GL_RED_BITS:
   1320       case GL_GREEN_BITS:
   1321       case GL_BLUE_BITS:
   1322       case GL_ALPHA_BITS:
   1323         {
   1324             gl::Framebuffer *framebuffer = getDrawFramebuffer();
   1325             gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
   1326 
   1327             if (colorbuffer)
   1328             {
   1329                 switch (pname)
   1330                 {
   1331                   case GL_RED_BITS:   *params = colorbuffer->getRedSize();   break;
   1332                   case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
   1333                   case GL_BLUE_BITS:  *params = colorbuffer->getBlueSize();  break;
   1334                   case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
   1335                 }
   1336             }
   1337             else
   1338             {
   1339                 *params = 0;
   1340             }
   1341         }
   1342         break;
   1343       case GL_DEPTH_BITS:
   1344         {
   1345             gl::Framebuffer *framebuffer = getDrawFramebuffer();
   1346             gl::DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer();
   1347 
   1348             if (depthbuffer)
   1349             {
   1350                 *params = depthbuffer->getDepthSize();
   1351             }
   1352             else
   1353             {
   1354                 *params = 0;
   1355             }
   1356         }
   1357         break;
   1358       case GL_STENCIL_BITS:
   1359         {
   1360             gl::Framebuffer *framebuffer = getDrawFramebuffer();
   1361             gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
   1362 
   1363             if (stencilbuffer)
   1364             {
   1365                 *params = stencilbuffer->getStencilSize();
   1366             }
   1367             else
   1368             {
   1369                 *params = 0;
   1370             }
   1371         }
   1372         break;
   1373       case GL_TEXTURE_BINDING_2D:
   1374         {
   1375             if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
   1376             {
   1377                 error(GL_INVALID_OPERATION);
   1378                 return false;
   1379             }
   1380 
   1381             *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler].id();
   1382         }
   1383         break;
   1384       case GL_TEXTURE_BINDING_CUBE_MAP:
   1385         {
   1386             if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
   1387             {
   1388                 error(GL_INVALID_OPERATION);
   1389                 return false;
   1390             }
   1391 
   1392             *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].id();
   1393         }
   1394         break;
   1395       default:
   1396         return false;
   1397     }
   1398 
   1399     return true;
   1400 }
   1401 
   1402 bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
   1403 {
   1404     // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
   1405     // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
   1406     // to the fact that it is stored internally as a float, and so would require conversion
   1407     // if returned from Context::getIntegerv. Since this conversion is already implemented
   1408     // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
   1409     // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
   1410     // application.
   1411     switch (pname)
   1412     {
   1413       case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
   1414       case GL_SHADER_BINARY_FORMATS:
   1415         {
   1416             *type = GL_INT;
   1417             *numParams = 0;
   1418         }
   1419         break;
   1420       case GL_MAX_VERTEX_ATTRIBS:
   1421       case GL_MAX_VERTEX_UNIFORM_VECTORS:
   1422       case GL_MAX_VARYING_VECTORS:
   1423       case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
   1424       case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
   1425       case GL_MAX_TEXTURE_IMAGE_UNITS:
   1426       case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
   1427       case GL_MAX_RENDERBUFFER_SIZE:
   1428       case GL_NUM_SHADER_BINARY_FORMATS:
   1429       case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
   1430       case GL_ARRAY_BUFFER_BINDING:
   1431       case GL_FRAMEBUFFER_BINDING:
   1432       case GL_RENDERBUFFER_BINDING:
   1433       case GL_CURRENT_PROGRAM:
   1434       case GL_PACK_ALIGNMENT:
   1435       case GL_UNPACK_ALIGNMENT:
   1436       case GL_GENERATE_MIPMAP_HINT:
   1437       case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
   1438       case GL_RED_BITS:
   1439       case GL_GREEN_BITS:
   1440       case GL_BLUE_BITS:
   1441       case GL_ALPHA_BITS:
   1442       case GL_DEPTH_BITS:
   1443       case GL_STENCIL_BITS:
   1444       case GL_ELEMENT_ARRAY_BUFFER_BINDING:
   1445       case GL_CULL_FACE_MODE:
   1446       case GL_FRONT_FACE:
   1447       case GL_ACTIVE_TEXTURE:
   1448       case GL_STENCIL_FUNC:
   1449       case GL_STENCIL_VALUE_MASK:
   1450       case GL_STENCIL_REF:
   1451       case GL_STENCIL_FAIL:
   1452       case GL_STENCIL_PASS_DEPTH_FAIL:
   1453       case GL_STENCIL_PASS_DEPTH_PASS:
   1454       case GL_STENCIL_BACK_FUNC:
   1455       case GL_STENCIL_BACK_VALUE_MASK:
   1456       case GL_STENCIL_BACK_REF:
   1457       case GL_STENCIL_BACK_FAIL:
   1458       case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
   1459       case GL_STENCIL_BACK_PASS_DEPTH_PASS:
   1460       case GL_DEPTH_FUNC:
   1461       case GL_BLEND_SRC_RGB:
   1462       case GL_BLEND_SRC_ALPHA:
   1463       case GL_BLEND_DST_RGB:
   1464       case GL_BLEND_DST_ALPHA:
   1465       case GL_BLEND_EQUATION_RGB:
   1466       case GL_BLEND_EQUATION_ALPHA:
   1467       case GL_STENCIL_WRITEMASK:
   1468       case GL_STENCIL_BACK_WRITEMASK:
   1469       case GL_STENCIL_CLEAR_VALUE:
   1470       case GL_SUBPIXEL_BITS:
   1471       case GL_MAX_TEXTURE_SIZE:
   1472       case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
   1473       case GL_SAMPLE_BUFFERS:
   1474       case GL_SAMPLES:
   1475       case GL_IMPLEMENTATION_COLOR_READ_TYPE:
   1476       case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
   1477       case GL_TEXTURE_BINDING_2D:
   1478       case GL_TEXTURE_BINDING_CUBE_MAP:
   1479         {
   1480             *type = GL_INT;
   1481             *numParams = 1;
   1482         }
   1483         break;
   1484       case GL_MAX_SAMPLES_ANGLE:
   1485         {
   1486             if (getMaxSupportedSamples() != 0)
   1487             {
   1488                 *type = GL_INT;
   1489                 *numParams = 1;
   1490             }
   1491             else
   1492             {
   1493                 return false;
   1494             }
   1495         }
   1496         break;
   1497       case GL_MAX_VIEWPORT_DIMS:
   1498         {
   1499             *type = GL_INT;
   1500             *numParams = 2;
   1501         }
   1502         break;
   1503       case GL_VIEWPORT:
   1504       case GL_SCISSOR_BOX:
   1505         {
   1506             *type = GL_INT;
   1507             *numParams = 4;
   1508         }
   1509         break;
   1510       case GL_SHADER_COMPILER:
   1511       case GL_SAMPLE_COVERAGE_INVERT:
   1512       case GL_DEPTH_WRITEMASK:
   1513       case GL_CULL_FACE:                // CULL_FACE through DITHER are natural to IsEnabled,
   1514       case GL_POLYGON_OFFSET_FILL:      // but can be retrieved through the Get{Type}v queries.
   1515       case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
   1516       case GL_SAMPLE_COVERAGE:
   1517       case GL_SCISSOR_TEST:
   1518       case GL_STENCIL_TEST:
   1519       case GL_DEPTH_TEST:
   1520       case GL_BLEND:
   1521       case GL_DITHER:
   1522         {
   1523             *type = GL_BOOL;
   1524             *numParams = 1;
   1525         }
   1526         break;
   1527       case GL_COLOR_WRITEMASK:
   1528         {
   1529             *type = GL_BOOL;
   1530             *numParams = 4;
   1531         }
   1532         break;
   1533       case GL_POLYGON_OFFSET_FACTOR:
   1534       case GL_POLYGON_OFFSET_UNITS:
   1535       case GL_SAMPLE_COVERAGE_VALUE:
   1536       case GL_DEPTH_CLEAR_VALUE:
   1537       case GL_LINE_WIDTH:
   1538         {
   1539             *type = GL_FLOAT;
   1540             *numParams = 1;
   1541         }
   1542         break;
   1543       case GL_ALIASED_LINE_WIDTH_RANGE:
   1544       case GL_ALIASED_POINT_SIZE_RANGE:
   1545       case GL_DEPTH_RANGE:
   1546         {
   1547             *type = GL_FLOAT;
   1548             *numParams = 2;
   1549         }
   1550         break;
   1551       case GL_COLOR_CLEAR_VALUE:
   1552       case GL_BLEND_COLOR:
   1553         {
   1554             *type = GL_FLOAT;
   1555             *numParams = 4;
   1556         }
   1557         break;
   1558       default:
   1559         return false;
   1560     }
   1561 
   1562     return true;
   1563 }
   1564 
   1565 // Applies the render target surface, depth stencil surface, viewport rectangle and
   1566 // scissor rectangle to the Direct3D 9 device
   1567 bool Context::applyRenderTarget(bool ignoreViewport)
   1568 {
   1569     IDirect3DDevice9 *device = getDevice();
   1570 
   1571     Framebuffer *framebufferObject = getDrawFramebuffer();
   1572 
   1573     if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
   1574     {
   1575         error(GL_INVALID_FRAMEBUFFER_OPERATION);
   1576 
   1577         return false;
   1578     }
   1579 
   1580     IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
   1581 
   1582     if (!renderTarget)
   1583     {
   1584         return false;   // Context must be lost
   1585     }
   1586 
   1587     IDirect3DSurface9 *depthStencil = NULL;
   1588 
   1589     unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
   1590     if (renderTargetSerial != mAppliedRenderTargetSerial)
   1591     {
   1592         device->SetRenderTarget(0, renderTarget);
   1593         mAppliedRenderTargetSerial = renderTargetSerial;
   1594         mScissorStateDirty = true; // Scissor area must be clamped to render target's size-- this is different for different render targets.
   1595     }
   1596 
   1597     unsigned int depthbufferSerial = 0;
   1598     unsigned int stencilbufferSerial = 0;
   1599     if (framebufferObject->getDepthbufferType() != GL_NONE)
   1600     {
   1601         depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil();
   1602         if (!depthStencil)
   1603         {
   1604             ERR("Depth stencil pointer unexpectedly null.");
   1605             return false;
   1606         }
   1607 
   1608         depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial();
   1609     }
   1610     else if (framebufferObject->getStencilbufferType() != GL_NONE)
   1611     {
   1612         depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
   1613         if (!depthStencil)
   1614         {
   1615             ERR("Depth stencil pointer unexpectedly null.");
   1616             return false;
   1617         }
   1618 
   1619         stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial();
   1620     }
   1621 
   1622     if (depthbufferSerial != mAppliedDepthbufferSerial ||
   1623         stencilbufferSerial != mAppliedStencilbufferSerial ||
   1624         !mDepthStencilInitialized)
   1625     {
   1626         device->SetDepthStencilSurface(depthStencil);
   1627         mAppliedDepthbufferSerial = depthbufferSerial;
   1628         mAppliedStencilbufferSerial = stencilbufferSerial;
   1629         mDepthStencilInitialized = true;
   1630     }
   1631 
   1632     D3DVIEWPORT9 viewport;
   1633     D3DSURFACE_DESC desc;
   1634     renderTarget->GetDesc(&desc);
   1635 
   1636     float zNear = clamp01(mState.zNear);
   1637     float zFar = clamp01(mState.zFar);
   1638 
   1639     if (ignoreViewport)
   1640     {
   1641         viewport.X = 0;
   1642         viewport.Y = 0;
   1643         viewport.Width = desc.Width;
   1644         viewport.Height = desc.Height;
   1645         viewport.MinZ = 0.0f;
   1646         viewport.MaxZ = 1.0f;
   1647     }
   1648     else
   1649     {
   1650         viewport.X = std::max(mState.viewportX, 0);
   1651         viewport.Y = std::max(mState.viewportY, 0);
   1652         viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
   1653         viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
   1654         viewport.MinZ = zNear;
   1655         viewport.MaxZ = zFar;
   1656     }
   1657 
   1658     if (viewport.Width <= 0 || viewport.Height <= 0)
   1659     {
   1660         return false;   // Nothing to render
   1661     }
   1662 
   1663     device->SetViewport(&viewport);
   1664 
   1665     if (mScissorStateDirty)
   1666     {
   1667         if (mState.scissorTest)
   1668         {
   1669             RECT rect = {mState.scissorX,
   1670                          mState.scissorY,
   1671                          mState.scissorX + mState.scissorWidth,
   1672                          mState.scissorY + mState.scissorHeight};
   1673             rect.right = std::min(static_cast<UINT>(rect.right), desc.Width);
   1674             rect.bottom = std::min(static_cast<UINT>(rect.bottom), desc.Height);
   1675             device->SetScissorRect(&rect);
   1676             device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
   1677         }
   1678         else
   1679         {
   1680             device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
   1681         }
   1682 
   1683         mScissorStateDirty = false;
   1684     }
   1685 
   1686     if (mState.currentProgram)
   1687     {
   1688         Program *programObject = getCurrentProgram();
   1689 
   1690         GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
   1691         GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
   1692         programObject->setUniform2fv(halfPixelSize, 1, xy);
   1693 
   1694         GLint viewport = programObject->getDxViewportLocation();
   1695         GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
   1696                           (float)mState.viewportX + mState.viewportWidth / 2.0f,
   1697                           (float)mState.viewportY + mState.viewportHeight / 2.0f};
   1698         programObject->setUniform4fv(viewport, 1, whxy);
   1699 
   1700         GLint depth = programObject->getDxDepthLocation();
   1701         GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
   1702         programObject->setUniform2fv(depth, 1, dz);
   1703 
   1704         GLint depthRange = programObject->getDxDepthRangeLocation();
   1705         GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear};
   1706         programObject->setUniform3fv(depthRange, 1, nearFarDiff);
   1707     }
   1708 
   1709     return true;
   1710 }
   1711 
   1712 // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
   1713 void Context::applyState(GLenum drawMode)
   1714 {
   1715     IDirect3DDevice9 *device = getDevice();
   1716     Program *programObject = getCurrentProgram();
   1717 
   1718     GLint frontCCW = programObject->getDxFrontCCWLocation();
   1719     GLint ccw = (mState.frontFace == GL_CCW);
   1720     programObject->setUniform1iv(frontCCW, 1, &ccw);
   1721 
   1722     GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
   1723     GLint alwaysFront = !isTriangleMode(drawMode);
   1724     programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
   1725 
   1726     Framebuffer *framebufferObject = getDrawFramebuffer();
   1727 
   1728     if (mCullStateDirty || mFrontFaceDirty)
   1729     {
   1730         if (mState.cullFace)
   1731         {
   1732             device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
   1733         }
   1734         else
   1735         {
   1736             device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
   1737         }
   1738 
   1739         mCullStateDirty = false;
   1740     }
   1741 
   1742     if (mDepthStateDirty)
   1743     {
   1744         if (mState.depthTest && framebufferObject->getDepthbufferType() != GL_NONE)
   1745         {
   1746             device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
   1747             device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
   1748         }
   1749         else
   1750         {
   1751             device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
   1752         }
   1753 
   1754         mDepthStateDirty = false;
   1755     }
   1756 
   1757     if (mBlendStateDirty)
   1758     {
   1759         if (mState.blend)
   1760         {
   1761             device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
   1762 
   1763             if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
   1764                 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
   1765             {
   1766                 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
   1767             }
   1768             else
   1769             {
   1770                 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
   1771                                                                         unorm<8>(mState.blendColor.alpha),
   1772                                                                         unorm<8>(mState.blendColor.alpha),
   1773                                                                         unorm<8>(mState.blendColor.alpha)));
   1774             }
   1775 
   1776             device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
   1777             device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
   1778             device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
   1779 
   1780             if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
   1781                 mState.destBlendRGB != mState.destBlendAlpha ||
   1782                 mState.blendEquationRGB != mState.blendEquationAlpha)
   1783             {
   1784                 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
   1785 
   1786                 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
   1787                 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
   1788                 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
   1789 
   1790             }
   1791             else
   1792             {
   1793                 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
   1794             }
   1795         }
   1796         else
   1797         {
   1798             device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
   1799         }
   1800 
   1801         mBlendStateDirty = false;
   1802     }
   1803 
   1804     if (mStencilStateDirty || mFrontFaceDirty)
   1805     {
   1806         if (mState.stencilTest && framebufferObject->hasStencil())
   1807         {
   1808             device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
   1809             device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
   1810 
   1811             // FIXME: Unsupported by D3D9
   1812             const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
   1813             const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
   1814             const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
   1815             if (mState.stencilWritemask != mState.stencilBackWritemask ||
   1816                 mState.stencilRef != mState.stencilBackRef ||
   1817                 mState.stencilMask != mState.stencilBackMask)
   1818             {
   1819                 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
   1820                 return error(GL_INVALID_OPERATION);
   1821             }
   1822 
   1823             // get the maximum size of the stencil ref
   1824             gl::DepthStencilbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
   1825             GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
   1826 
   1827             device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
   1828             device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
   1829                                    es2dx::ConvertComparison(mState.stencilFunc));
   1830 
   1831             device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
   1832             device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
   1833 
   1834             device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
   1835                                    es2dx::ConvertStencilOp(mState.stencilFail));
   1836             device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
   1837                                    es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
   1838             device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
   1839                                    es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
   1840 
   1841             device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
   1842             device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
   1843                                    es2dx::ConvertComparison(mState.stencilBackFunc));
   1844 
   1845             device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
   1846             device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
   1847 
   1848             device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
   1849                                    es2dx::ConvertStencilOp(mState.stencilBackFail));
   1850             device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
   1851                                    es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
   1852             device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
   1853                                    es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
   1854         }
   1855         else
   1856         {
   1857             device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
   1858         }
   1859 
   1860         mStencilStateDirty = false;
   1861     }
   1862 
   1863     if (mMaskStateDirty)
   1864     {
   1865         device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
   1866                                                                                mState.colorMaskBlue, mState.colorMaskAlpha));
   1867         device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
   1868 
   1869         mMaskStateDirty = false;
   1870     }
   1871 
   1872     if (mPolygonOffsetStateDirty)
   1873     {
   1874         if (mState.polygonOffsetFill)
   1875         {
   1876             gl::DepthStencilbuffer *depthbuffer = framebufferObject->getDepthbuffer();
   1877             if (depthbuffer)
   1878             {
   1879                 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
   1880                 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
   1881                 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
   1882             }
   1883         }
   1884         else
   1885         {
   1886             device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
   1887             device->SetRenderState(D3DRS_DEPTHBIAS, 0);
   1888         }
   1889 
   1890         mPolygonOffsetStateDirty = false;
   1891     }
   1892 
   1893     if (mSampleStateDirty)
   1894     {
   1895         if (framebufferObject->isMultisample())
   1896         {
   1897             if (mState.sampleAlphaToCoverage)
   1898             {
   1899                 FIXME("Sample alpha to coverage is unimplemented.");
   1900             }
   1901 
   1902             device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
   1903             if (mState.sampleCoverage)
   1904             {
   1905                 unsigned int mask = 0;
   1906                 if (mState.sampleCoverageValue != 0)
   1907                 {
   1908                     float threshold = 0.5f;
   1909 
   1910                     for (int i = 0; i < framebufferObject->getSamples(); ++i)
   1911                     {
   1912                         mask <<= 1;
   1913 
   1914                         if ((i + 1) * mState.sampleCoverageValue >= threshold)
   1915                         {
   1916                             threshold += 1.0f;
   1917                             mask |= 1;
   1918                         }
   1919                     }
   1920                 }
   1921 
   1922                 if (mState.sampleCoverageInvert)
   1923                 {
   1924                     mask = ~mask;
   1925                 }
   1926 
   1927                 device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask);
   1928             }
   1929             else
   1930             {
   1931                 device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
   1932             }
   1933         }
   1934         else
   1935         {
   1936             device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);
   1937         }
   1938 
   1939         mSampleStateDirty = false;
   1940     }
   1941 
   1942     if (mDitherStateDirty)
   1943     {
   1944         device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
   1945 
   1946         mDitherStateDirty = false;
   1947     }
   1948 
   1949     mFrontFaceDirty = false;
   1950 }
   1951 
   1952 // Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
   1953 void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
   1954 {
   1955     for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
   1956     {
   1957         if (attributes[i].active)
   1958         {
   1959             attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
   1960         }
   1961     }
   1962 }
   1963 
   1964 GLenum Context::applyVertexBuffer(GLint first, GLsizei count)
   1965 {
   1966     TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
   1967 
   1968     GLenum err = mVertexDataManager->prepareVertexData(first, count, translated);
   1969     if (err != GL_NO_ERROR)
   1970     {
   1971         return err;
   1972     }
   1973 
   1974     lookupAttributeMapping(translated);
   1975 
   1976     mVertexDataManager->setupAttributes(translated);
   1977 
   1978     return GL_NO_ERROR;
   1979 }
   1980 
   1981 // Applies the indices and element array bindings to the Direct3D 9 device
   1982 GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
   1983 {
   1984     IDirect3DDevice9 *device = getDevice();
   1985     GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
   1986 
   1987     if (err == GL_NO_ERROR)
   1988     {
   1989         device->SetIndices(indexInfo->indexBuffer);
   1990     }
   1991 
   1992     return err;
   1993 }
   1994 
   1995 // Applies the shaders and shader constants to the Direct3D 9 device
   1996 void Context::applyShaders()
   1997 {
   1998     IDirect3DDevice9 *device = getDevice();
   1999     Program *programObject = getCurrentProgram();
   2000     IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
   2001     IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
   2002 
   2003     device->SetVertexShader(vertexShader);
   2004     device->SetPixelShader(pixelShader);
   2005 
   2006     if (programObject->getSerial() != mAppliedProgram)
   2007     {
   2008         programObject->dirtyAllUniforms();
   2009         programObject->dirtyAllSamplers();
   2010         mAppliedProgram = programObject->getSerial();
   2011     }
   2012 
   2013     programObject->applyUniforms();
   2014 }
   2015 
   2016 // Applies the textures and sampler states to the Direct3D 9 device
   2017 void Context::applyTextures()
   2018 {
   2019     IDirect3DDevice9 *device = getDevice();
   2020     Program *programObject = getCurrentProgram();
   2021 
   2022     for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
   2023     {
   2024         int textureUnit = programObject->getSamplerMapping(sampler);
   2025         if (textureUnit != -1)
   2026         {
   2027             SamplerType textureType = programObject->getSamplerType(sampler);
   2028 
   2029             Texture *texture = getSamplerTexture(textureUnit, textureType);
   2030 
   2031             if (programObject->isSamplerDirty(sampler) || texture->isDirty())
   2032             {
   2033                 if (texture->isComplete())
   2034                 {
   2035                     GLenum wrapS = texture->getWrapS();
   2036                     GLenum wrapT = texture->getWrapT();
   2037                     GLenum minFilter = texture->getMinFilter();
   2038                     GLenum magFilter = texture->getMagFilter();
   2039 
   2040                     device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
   2041                     device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
   2042 
   2043                     device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
   2044                     D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
   2045                     es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
   2046                     device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
   2047                     device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
   2048 
   2049                     device->SetTexture(sampler, texture->getTexture());
   2050                 }
   2051                 else
   2052                 {
   2053                     device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
   2054                 }
   2055             }
   2056 
   2057             programObject->setSamplerDirty(sampler, false);
   2058         }
   2059         else
   2060         {
   2061             if (programObject->isSamplerDirty(sampler))
   2062             {
   2063                 device->SetTexture(sampler, NULL);
   2064                 programObject->setSamplerDirty(sampler, false);
   2065             }
   2066         }
   2067     }
   2068 }
   2069 
   2070 void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
   2071 {
   2072     Framebuffer *framebuffer = getReadFramebuffer();
   2073 
   2074     if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
   2075     {
   2076         return error(GL_INVALID_FRAMEBUFFER_OPERATION);
   2077     }
   2078 
   2079     if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
   2080     {
   2081         return error(GL_INVALID_OPERATION);
   2082     }
   2083 
   2084     IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
   2085 
   2086     if (!renderTarget)
   2087     {
   2088         return;   // Context must be lost, return silently
   2089     }
   2090 
   2091     IDirect3DDevice9 *device = getDevice();
   2092 
   2093     D3DSURFACE_DESC desc;
   2094     renderTarget->GetDesc(&desc);
   2095 
   2096     IDirect3DSurface9 *systemSurface;
   2097     HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
   2098 
   2099     if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
   2100     {
   2101         return error(GL_OUT_OF_MEMORY);
   2102     }
   2103 
   2104     ASSERT(SUCCEEDED(result));
   2105 
   2106     if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
   2107     {
   2108         UNIMPLEMENTED();   // FIXME: Requires resolve using StretchRect into non-multisampled render target
   2109     }
   2110 
   2111     result = device->GetRenderTargetData(renderTarget, systemSurface);
   2112 
   2113     if (FAILED(result))
   2114     {
   2115         systemSurface->Release();
   2116 
   2117         switch (result)
   2118         {
   2119             case D3DERR_DRIVERINTERNALERROR:
   2120             case D3DERR_DEVICELOST:
   2121                 return error(GL_OUT_OF_MEMORY);
   2122             default:
   2123                 UNREACHABLE();
   2124                 return;   // No sensible error to generate
   2125         }
   2126     }
   2127 
   2128     D3DLOCKED_RECT lock;
   2129     RECT rect = {std::max(x, 0),
   2130                  std::max(y, 0),
   2131                  std::min(x + width, (int)desc.Width),
   2132                  std::min(y + height, (int)desc.Height)};
   2133 
   2134     result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
   2135 
   2136     if (FAILED(result))
   2137     {
   2138         UNREACHABLE();
   2139         systemSurface->Release();
   2140 
   2141         return;   // No sensible error to generate
   2142     }
   2143 
   2144     unsigned char *source = (unsigned char*)lock.pBits;
   2145     unsigned char *dest = (unsigned char*)pixels;
   2146     unsigned short *dest16 = (unsigned short*)pixels;
   2147 
   2148     GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
   2149 
   2150     for (int j = 0; j < rect.bottom - rect.top; j++)
   2151     {
   2152         if (desc.Format == D3DFMT_A8R8G8B8 &&
   2153             format == GL_BGRA_EXT &&
   2154             type == GL_UNSIGNED_BYTE)
   2155         {
   2156             // Fast path for EXT_read_format_bgra, given
   2157             // an RGBA source buffer.  Note that buffers with no
   2158             // alpha go through the slow path below.
   2159             memcpy(dest + j * outputPitch,
   2160                    source + j * lock.Pitch,
   2161                    (rect.right - rect.left) * 4);
   2162             continue;
   2163         }
   2164 
   2165         for (int i = 0; i < rect.right - rect.left; i++)
   2166         {
   2167             float r;
   2168             float g;
   2169             float b;
   2170             float a;
   2171 
   2172             switch (desc.Format)
   2173             {
   2174               case D3DFMT_R5G6B5:
   2175                 {
   2176                     unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
   2177 
   2178                     a = 1.0f;
   2179                     b = (rgb & 0x001F) * (1.0f / 0x001F);
   2180                     g = (rgb & 0x07E0) * (1.0f / 0x07E0);
   2181                     r = (rgb & 0xF800) * (1.0f / 0xF800);
   2182                 }
   2183                 break;
   2184               case D3DFMT_A1R5G5B5:
   2185                 {
   2186                     unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
   2187 
   2188                     a = (argb & 0x8000) ? 1.0f : 0.0f;
   2189                     b = (argb & 0x001F) * (1.0f / 0x001F);
   2190                     g = (argb & 0x03E0) * (1.0f / 0x03E0);
   2191                     r = (argb & 0x7C00) * (1.0f / 0x7C00);
   2192                 }
   2193                 break;
   2194               case D3DFMT_A8R8G8B8:
   2195                 {
   2196                     unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
   2197 
   2198                     a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
   2199                     b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
   2200                     g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
   2201                     r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
   2202                 }
   2203                 break;
   2204               case D3DFMT_X8R8G8B8:
   2205                 {
   2206                     unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
   2207 
   2208                     a = 1.0f;
   2209                     b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
   2210                     g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
   2211                     r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
   2212                 }
   2213                 break;
   2214               case D3DFMT_A2R10G10B10:
   2215                 {
   2216                     unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
   2217 
   2218                     a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
   2219                     b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
   2220                     g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
   2221                     r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
   2222                 }
   2223                 break;
   2224               case D3DFMT_A32B32G32R32F:
   2225                 {
   2226                     // float formats in D3D are stored rgba, rather than the other way round
   2227                     r = *((float*)(source + 16 * i + j * lock.Pitch) + 0);
   2228                     g = *((float*)(source + 16 * i + j * lock.Pitch) + 1);
   2229                     b = *((float*)(source + 16 * i + j * lock.Pitch) + 2);
   2230                     a = *((float*)(source + 16 * i + j * lock.Pitch) + 3);
   2231                 }
   2232                 break;
   2233               case D3DFMT_A16B16G16R16F:
   2234                 {
   2235                     // float formats in D3D are stored rgba, rather than the other way round
   2236                     float abgr[4];
   2237 
   2238                     D3DXFloat16To32Array(abgr, (D3DXFLOAT16*)(source + 8 * i + j * lock.Pitch), 4);
   2239 
   2240                     a = abgr[3];
   2241                     b = abgr[2];
   2242                     g = abgr[1];
   2243                     r = abgr[0];
   2244                 }
   2245                 break;
   2246               default:
   2247                 UNIMPLEMENTED();   // FIXME
   2248                 UNREACHABLE();
   2249             }
   2250 
   2251             switch (format)
   2252             {
   2253               case GL_RGBA:
   2254                 switch (type)
   2255                 {
   2256                   case GL_UNSIGNED_BYTE:
   2257                     dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
   2258                     dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
   2259                     dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
   2260                     dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
   2261                     break;
   2262                   default: UNREACHABLE();
   2263                 }
   2264                 break;
   2265               case GL_BGRA_EXT:
   2266                 switch (type)
   2267                 {
   2268                   case GL_UNSIGNED_BYTE:
   2269                     dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
   2270                     dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
   2271                     dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
   2272                     dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
   2273                     break;
   2274                   case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
   2275                     // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
   2276                     // this type is packed as follows:
   2277                     //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
   2278                     //  --------------------------------------------------------------------------------
   2279                     // |       4th         |        3rd         |        2nd        |   1st component   |
   2280                     //  --------------------------------------------------------------------------------
   2281                     // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
   2282                     dest16[i + j * outputPitch / sizeof(unsigned short)] =
   2283                         ((unsigned short)(15 * a + 0.5f) << 12)|
   2284                         ((unsigned short)(15 * r + 0.5f) << 8) |
   2285                         ((unsigned short)(15 * g + 0.5f) << 4) |
   2286                         ((unsigned short)(15 * b + 0.5f) << 0);
   2287                     break;
   2288                   case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
   2289                     // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
   2290                     // this type is packed as follows:
   2291                     //   15   14   13   12   11   10    9    8    7    6    5    4    3    2    1    0
   2292                     //  --------------------------------------------------------------------------------
   2293                     // | 4th |          3rd           |           2nd          |      1st component     |
   2294                     //  --------------------------------------------------------------------------------
   2295                     // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
   2296                     dest16[i + j * outputPitch / sizeof(unsigned short)] =
   2297                         ((unsigned short)(     a + 0.5f) << 15) |
   2298                         ((unsigned short)(31 * r + 0.5f) << 10) |
   2299                         ((unsigned short)(31 * g + 0.5f) << 5) |
   2300                         ((unsigned short)(31 * b + 0.5f) << 0);
   2301                     break;
   2302                   default: UNREACHABLE();
   2303                 }
   2304                 break;
   2305               case GL_RGB:   // IMPLEMENTATION_COLOR_READ_FORMAT
   2306                 switch (type)
   2307                 {
   2308                   case GL_UNSIGNED_SHORT_5_6_5:   // IMPLEMENTATION_COLOR_READ_TYPE
   2309                     dest16[i + j * outputPitch / sizeof(unsigned short)] =
   2310                         ((unsigned short)(31 * b + 0.5f) << 0) |
   2311                         ((unsigned short)(63 * g + 0.5f) << 5) |
   2312                         ((unsigned short)(31 * r + 0.5f) << 11);
   2313                     break;
   2314                   default: UNREACHABLE();
   2315                 }
   2316                 break;
   2317               default: UNREACHABLE();
   2318             }
   2319         }
   2320     }
   2321 
   2322     systemSurface->UnlockRect();
   2323 
   2324     systemSurface->Release();
   2325 }
   2326 
   2327 void Context::clear(GLbitfield mask)
   2328 {
   2329     Framebuffer *framebufferObject = getDrawFramebuffer();
   2330 
   2331     if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
   2332     {
   2333         error(GL_INVALID_FRAMEBUFFER_OPERATION);
   2334 
   2335         return;
   2336     }
   2337 
   2338     egl::Display *display = getDisplay();
   2339     IDirect3DDevice9 *device = getDevice();
   2340     DWORD flags = 0;
   2341 
   2342     if (mask & GL_COLOR_BUFFER_BIT)
   2343     {
   2344         mask &= ~GL_COLOR_BUFFER_BIT;
   2345 
   2346         if (framebufferObject->getColorbufferType() != GL_NONE)
   2347         {
   2348             flags |= D3DCLEAR_TARGET;
   2349         }
   2350     }
   2351 
   2352     if (mask & GL_DEPTH_BUFFER_BIT)
   2353     {
   2354         mask &= ~GL_DEPTH_BUFFER_BIT;
   2355         if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
   2356         {
   2357             flags |= D3DCLEAR_ZBUFFER;
   2358         }
   2359     }
   2360 
   2361     GLuint stencilUnmasked = 0x0;
   2362 
   2363     if (mask & GL_STENCIL_BUFFER_BIT)
   2364     {
   2365         mask &= ~GL_STENCIL_BUFFER_BIT;
   2366         if (framebufferObject->getStencilbufferType() != GL_NONE)
   2367         {
   2368             IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
   2369             if (!depthStencil)
   2370             {
   2371                 ERR("Depth stencil pointer unexpectedly null.");
   2372                 return;
   2373             }
   2374 
   2375             D3DSURFACE_DESC desc;
   2376             depthStencil->GetDesc(&desc);
   2377 
   2378             unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
   2379             stencilUnmasked = (0x1 << stencilSize) - 1;
   2380 
   2381             if (stencilUnmasked != 0x0)
   2382             {
   2383                 flags |= D3DCLEAR_STENCIL;
   2384             }
   2385         }
   2386     }
   2387 
   2388     if (mask != 0)
   2389     {
   2390         return error(GL_INVALID_VALUE);
   2391     }
   2392 
   2393     if (!applyRenderTarget(true))   // Clips the clear to the scissor rectangle but not the viewport
   2394     {
   2395         return;
   2396     }
   2397 
   2398     D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
   2399                                             unorm<8>(mState.colorClearValue.red),
   2400                                             unorm<8>(mState.colorClearValue.green),
   2401                                             unorm<8>(mState.colorClearValue.blue));
   2402     float depth = clamp01(mState.depthClearValue);
   2403     int stencil = mState.stencilClearValue & 0x000000FF;
   2404 
   2405     IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
   2406 
   2407     if (!renderTarget)
   2408     {
   2409         return;   // Context must be lost, return silently
   2410     }
   2411 
   2412     D3DSURFACE_DESC desc;
   2413     renderTarget->GetDesc(&desc);
   2414 
   2415     bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
   2416 
   2417     const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
   2418                                         (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
   2419     const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
   2420                                       !(mState.colorMaskRed && mState.colorMaskGreen &&
   2421                                         mState.colorMaskBlue && alphaUnmasked);
   2422 
   2423     if (needMaskedColorClear || needMaskedStencilClear)
   2424     {
   2425         // State which is altered in all paths from this point to the clear call is saved.
   2426         // State which is altered in only some paths will be flagged dirty in the case that
   2427         //  that path is taken.
   2428         HRESULT hr;
   2429         if (mMaskedClearSavedState == NULL)
   2430         {
   2431             hr = device->BeginStateBlock();
   2432             ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
   2433 
   2434             device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
   2435             device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
   2436             device->SetRenderState(D3DRS_ZENABLE, FALSE);
   2437             device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
   2438             device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
   2439             device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
   2440             device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
   2441             device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
   2442             device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
   2443             device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
   2444             device->SetPixelShader(NULL);
   2445             device->SetVertexShader(NULL);
   2446             device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
   2447             device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
   2448 
   2449             hr = device->EndStateBlock(&mMaskedClearSavedState);
   2450             ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
   2451         }
   2452 
   2453         ASSERT(mMaskedClearSavedState != NULL);
   2454 
   2455         if (mMaskedClearSavedState != NULL)
   2456         {
   2457             hr = mMaskedClearSavedState->Capture();
   2458             ASSERT(SUCCEEDED(hr));
   2459         }
   2460 
   2461         device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
   2462         device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
   2463         device->SetRenderState(D3DRS_ZENABLE, FALSE);
   2464         device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
   2465         device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
   2466         device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
   2467         device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
   2468         device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
   2469 
   2470         if (flags & D3DCLEAR_TARGET)
   2471         {
   2472             device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed   ? D3DCOLORWRITEENABLE_RED   : 0) |
   2473                                                            (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
   2474                                                            (mState.colorMaskBlue  ? D3DCOLORWRITEENABLE_BLUE  : 0) |
   2475                                                            (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
   2476         }
   2477         else
   2478         {
   2479             device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
   2480         }
   2481 
   2482         if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
   2483         {
   2484             device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
   2485             device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
   2486             device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
   2487             device->SetRenderState(D3DRS_STENCILREF, stencil);
   2488             device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
   2489             device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
   2490             device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
   2491             device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
   2492             mStencilStateDirty = true;
   2493         }
   2494         else
   2495         {
   2496             device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
   2497         }
   2498 
   2499         device->SetPixelShader(NULL);
   2500         device->SetVertexShader(NULL);
   2501         device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
   2502         device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
   2503 
   2504         struct Vertex
   2505         {
   2506             float x, y, z, w;
   2507             D3DCOLOR diffuse;
   2508         };
   2509 
   2510         Vertex quad[4];
   2511         quad[0].x = 0.0f;
   2512         quad[0].y = (float)desc.Height;
   2513         quad[0].z = 0.0f;
   2514         quad[0].w = 1.0f;
   2515         quad[0].diffuse = color;
   2516 
   2517         quad[1].x = (float)desc.Width;
   2518         quad[1].y = (float)desc.Height;
   2519         quad[1].z = 0.0f;
   2520         quad[1].w = 1.0f;
   2521         quad[1].diffuse = color;
   2522 
   2523         quad[2].x = 0.0f;
   2524         quad[2].y = 0.0f;
   2525         quad[2].z = 0.0f;
   2526         quad[2].w = 1.0f;
   2527         quad[2].diffuse = color;
   2528 
   2529         quad[3].x = (float)desc.Width;
   2530         quad[3].y = 0.0f;
   2531         quad[3].z = 0.0f;
   2532         quad[3].w = 1.0f;
   2533         quad[3].diffuse = color;
   2534 
   2535         display->startScene();
   2536         device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
   2537 
   2538         if (flags & D3DCLEAR_ZBUFFER)
   2539         {
   2540             device->SetRenderState(D3DRS_ZENABLE, TRUE);
   2541             device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
   2542             device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
   2543         }
   2544 
   2545         if (mMaskedClearSavedState != NULL)
   2546         {
   2547             mMaskedClearSavedState->Apply();
   2548         }
   2549     }
   2550     else if (flags)
   2551     {
   2552         device->Clear(0, NULL, flags, color, depth, stencil);
   2553     }
   2554 }
   2555 
   2556 void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
   2557 {
   2558     if (!mState.currentProgram)
   2559     {
   2560         return error(GL_INVALID_OPERATION);
   2561     }
   2562 
   2563     egl::Display *display = getDisplay();
   2564     IDirect3DDevice9 *device = getDevice();
   2565     D3DPRIMITIVETYPE primitiveType;
   2566     int primitiveCount;
   2567 
   2568     if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
   2569         return error(GL_INVALID_ENUM);
   2570 
   2571     if (primitiveCount <= 0)
   2572     {
   2573         return;
   2574     }
   2575 
   2576     if (!applyRenderTarget(false))
   2577     {
   2578         return;
   2579     }
   2580 
   2581     applyState(mode);
   2582 
   2583     GLenum err = applyVertexBuffer(first, count);
   2584     if (err != GL_NO_ERROR)
   2585     {
   2586         return error(err);
   2587     }
   2588 
   2589     applyShaders();
   2590     applyTextures();
   2591 
   2592     if (!getCurrentProgram()->validateSamplers())
   2593     {
   2594         return error(GL_INVALID_OPERATION);
   2595     }
   2596 
   2597     if (!cullSkipsDraw(mode))
   2598     {
   2599         display->startScene();
   2600 
   2601         device->DrawPrimitive(primitiveType, 0, primitiveCount);
   2602 
   2603         if (mode == GL_LINE_LOOP)   // Draw the last segment separately
   2604         {
   2605             drawClosingLine(first, first + count - 1);
   2606         }
   2607     }
   2608 }
   2609 
   2610 void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
   2611 {
   2612     if (!mState.currentProgram)
   2613     {
   2614         return error(GL_INVALID_OPERATION);
   2615     }
   2616 
   2617     if (!indices && !mState.elementArrayBuffer)
   2618     {
   2619         return error(GL_INVALID_OPERATION);
   2620     }
   2621 
   2622     egl::Display *display = getDisplay();
   2623     IDirect3DDevice9 *device = getDevice();
   2624     D3DPRIMITIVETYPE primitiveType;
   2625     int primitiveCount;
   2626 
   2627     if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
   2628         return error(GL_INVALID_ENUM);
   2629 
   2630     if (primitiveCount <= 0)
   2631     {
   2632         return;
   2633     }
   2634 
   2635     if (!applyRenderTarget(false))
   2636     {
   2637         return;
   2638     }
   2639 
   2640     applyState(mode);
   2641 
   2642     TranslatedIndexData indexInfo;
   2643     GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
   2644     if (err != GL_NO_ERROR)
   2645     {
   2646         return error(err);
   2647     }
   2648 
   2649     GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
   2650     err = applyVertexBuffer(indexInfo.minIndex, vertexCount);
   2651     if (err != GL_NO_ERROR)
   2652     {
   2653         return error(err);
   2654     }
   2655 
   2656     applyShaders();
   2657     applyTextures();
   2658 
   2659     if (!getCurrentProgram()->validateSamplers())
   2660     {
   2661         return error(GL_INVALID_OPERATION);
   2662     }
   2663 
   2664     if (!cullSkipsDraw(mode))
   2665     {
   2666         display->startScene();
   2667 
   2668         device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount);
   2669 
   2670         if (mode == GL_LINE_LOOP)   // Draw the last segment separately
   2671         {
   2672             drawClosingLine(count, type, indices);
   2673         }
   2674     }
   2675 }
   2676 
   2677 void Context::finish()
   2678 {
   2679     egl::Display *display = getDisplay();
   2680     IDirect3DDevice9 *device = getDevice();
   2681     IDirect3DQuery9 *occlusionQuery = NULL;
   2682 
   2683     HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
   2684 
   2685     if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
   2686     {
   2687         return error(GL_OUT_OF_MEMORY);
   2688     }
   2689 
   2690     ASSERT(SUCCEEDED(result));
   2691 
   2692     if (occlusionQuery)
   2693     {
   2694         IDirect3DStateBlock9 *savedState = NULL;
   2695         device->CreateStateBlock(D3DSBT_ALL, &savedState);
   2696 
   2697         HRESULT result = occlusionQuery->Issue(D3DISSUE_BEGIN);
   2698         ASSERT(SUCCEEDED(result));
   2699 
   2700         // Render something outside the render target
   2701         device->SetPixelShader(NULL);
   2702         device->SetVertexShader(NULL);
   2703         device->SetFVF(D3DFVF_XYZRHW);
   2704         float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
   2705         display->startScene();
   2706         device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
   2707 
   2708         result = occlusionQuery->Issue(D3DISSUE_END);
   2709         ASSERT(SUCCEEDED(result));
   2710 
   2711         while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
   2712         {
   2713             // Keep polling, but allow other threads to do something useful first
   2714             Sleep(0);
   2715         }
   2716 
   2717         occlusionQuery->Release();
   2718 
   2719         if (savedState)
   2720         {
   2721             savedState->Apply();
   2722             savedState->Release();
   2723         }
   2724     }
   2725 }
   2726 
   2727 void Context::flush()
   2728 {
   2729     IDirect3DDevice9 *device = getDevice();
   2730     IDirect3DQuery9 *eventQuery = NULL;
   2731 
   2732     HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
   2733 
   2734     if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
   2735     {
   2736         return error(GL_OUT_OF_MEMORY);
   2737     }
   2738 
   2739     ASSERT(SUCCEEDED(result));
   2740 
   2741     if (eventQuery)
   2742     {
   2743         HRESULT result = eventQuery->Issue(D3DISSUE_END);
   2744         ASSERT(SUCCEEDED(result));
   2745 
   2746         result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
   2747         eventQuery->Release();
   2748 
   2749         if (result == D3DERR_DEVICELOST)
   2750         {
   2751             error(GL_OUT_OF_MEMORY);
   2752         }
   2753     }
   2754 }
   2755 
   2756 void Context::drawClosingLine(unsigned int first, unsigned int last)
   2757 {
   2758     IDirect3DDevice9 *device = getDevice();
   2759     IDirect3DIndexBuffer9 *indexBuffer = NULL;
   2760     HRESULT result = D3DERR_INVALIDCALL;
   2761 
   2762     if (supports32bitIndices())
   2763     {
   2764         result = device->CreateIndexBuffer(8, D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &indexBuffer, 0);
   2765 
   2766         if (SUCCEEDED(result))
   2767         {
   2768             unsigned int *data;
   2769             result = indexBuffer->Lock(0, 0, (void**)&data, 0);
   2770 
   2771             if (SUCCEEDED(result))
   2772             {
   2773                 data[0] = last;
   2774                 data[1] = first;
   2775             }
   2776         }
   2777     }
   2778     else
   2779     {
   2780         result = device->CreateIndexBuffer(4, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &indexBuffer, 0);
   2781 
   2782         if (SUCCEEDED(result))
   2783         {
   2784             unsigned short *data;
   2785             result = indexBuffer->Lock(0, 0, (void**)&data, 0);
   2786 
   2787             if (SUCCEEDED(result))
   2788             {
   2789                 data[0] = last;
   2790                 data[1] = first;
   2791             }
   2792         }
   2793     }
   2794 
   2795     if (SUCCEEDED(result))
   2796     {
   2797         indexBuffer->Unlock();
   2798         device->SetIndices(indexBuffer);
   2799 
   2800         device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, 2, 0, 1);
   2801 
   2802         indexBuffer->Release();
   2803     }
   2804     else
   2805     {
   2806         ERR("Could not create an index buffer for closing a line loop.");
   2807         error(GL_OUT_OF_MEMORY);
   2808     }
   2809 }
   2810 
   2811 void Context::drawClosingLine(GLsizei count, GLenum type, const void *indices)
   2812 {
   2813     unsigned int first = 0;
   2814     unsigned int last = 0;
   2815 
   2816     if (mState.elementArrayBuffer.get())
   2817     {
   2818         Buffer *indexBuffer = mState.elementArrayBuffer.get();
   2819         intptr_t offset = reinterpret_cast<intptr_t>(indices);
   2820         indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset;
   2821     }
   2822 
   2823     switch (type)
   2824     {
   2825       case GL_UNSIGNED_BYTE:
   2826         first = static_cast<const GLubyte*>(indices)[0];
   2827         last = static_cast<const GLubyte*>(indices)[count - 1];
   2828         break;
   2829       case GL_UNSIGNED_SHORT:
   2830         first = static_cast<const GLushort*>(indices)[0];
   2831         last = static_cast<const GLushort*>(indices)[count - 1];
   2832         break;
   2833       case GL_UNSIGNED_INT:
   2834         first = static_cast<const GLuint*>(indices)[0];
   2835         last = static_cast<const GLuint*>(indices)[count - 1];
   2836         break;
   2837       default: UNREACHABLE();
   2838     }
   2839 
   2840     drawClosingLine(first, last);
   2841 }
   2842 
   2843 void Context::recordInvalidEnum()
   2844 {
   2845     mInvalidEnum = true;
   2846 }
   2847 
   2848 void Context::recordInvalidValue()
   2849 {
   2850     mInvalidValue = true;
   2851 }
   2852 
   2853 void Context::recordInvalidOperation()
   2854 {
   2855     mInvalidOperation = true;
   2856 }
   2857 
   2858 void Context::recordOutOfMemory()
   2859 {
   2860     mOutOfMemory = true;
   2861 }
   2862 
   2863 void Context::recordInvalidFramebufferOperation()
   2864 {
   2865     mInvalidFramebufferOperation = true;
   2866 }
   2867 
   2868 // Get one of the recorded errors and clear its flag, if any.
   2869 // [OpenGL ES 2.0.24] section 2.5 page 13.
   2870 GLenum Context::getError()
   2871 {
   2872     if (mInvalidEnum)
   2873     {
   2874         mInvalidEnum = false;
   2875 
   2876         return GL_INVALID_ENUM;
   2877     }
   2878 
   2879     if (mInvalidValue)
   2880     {
   2881         mInvalidValue = false;
   2882 
   2883         return GL_INVALID_VALUE;
   2884     }
   2885 
   2886     if (mInvalidOperation)
   2887     {
   2888         mInvalidOperation = false;
   2889 
   2890         return GL_INVALID_OPERATION;
   2891     }
   2892 
   2893     if (mOutOfMemory)
   2894     {
   2895         mOutOfMemory = false;
   2896 
   2897         return GL_OUT_OF_MEMORY;
   2898     }
   2899 
   2900     if (mInvalidFramebufferOperation)
   2901     {
   2902         mInvalidFramebufferOperation = false;
   2903 
   2904         return GL_INVALID_FRAMEBUFFER_OPERATION;
   2905     }
   2906 
   2907     return GL_NO_ERROR;
   2908 }
   2909 
   2910 bool Context::supportsShaderModel3() const
   2911 {
   2912     return mSupportsShaderModel3;
   2913 }
   2914 
   2915 int Context::getMaximumVaryingVectors() const
   2916 {
   2917     return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
   2918 }
   2919 
   2920 int Context::getMaximumFragmentUniformVectors() const
   2921 {
   2922     return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2;
   2923 }
   2924 
   2925 int Context::getMaxSupportedSamples() const
   2926 {
   2927     return mMaxSupportedSamples;
   2928 }
   2929 
   2930 int Context::getNearestSupportedSamples(D3DFORMAT format, int requested) const
   2931 {
   2932     if (requested == 0)
   2933     {
   2934         return requested;
   2935     }
   2936 
   2937     std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
   2938     if (itr == mMultiSampleSupport.end())
   2939     {
   2940         return -1;
   2941     }
   2942 
   2943     for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
   2944     {
   2945         if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
   2946         {
   2947             return i;
   2948         }
   2949     }
   2950 
   2951     return -1;
   2952 }
   2953 
   2954 bool Context::supportsEventQueries() const
   2955 {
   2956     return mSupportsEventQueries;
   2957 }
   2958 
   2959 bool Context::supportsCompressedTextures() const
   2960 {
   2961     return mSupportsCompressedTextures;
   2962 }
   2963 
   2964 bool Context::supportsFloatTextures() const
   2965 {
   2966     return mSupportsFloatTextures;
   2967 }
   2968 
   2969 bool Context::supportsFloatLinearFilter() const
   2970 {
   2971     return mSupportsFloatLinearFilter;
   2972 }
   2973 
   2974 bool Context::supportsFloatRenderableTextures() const
   2975 {
   2976     return mSupportsFloatRenderableTextures;
   2977 }
   2978 
   2979 bool Context::supportsHalfFloatTextures() const
   2980 {
   2981     return mSupportsHalfFloatTextures;
   2982 }
   2983 
   2984 bool Context::supportsHalfFloatLinearFilter() const
   2985 {
   2986     return mSupportsHalfFloatLinearFilter;
   2987 }
   2988 
   2989 bool Context::supportsHalfFloatRenderableTextures() const
   2990 {
   2991     return mSupportsHalfFloatRenderableTextures;
   2992 }
   2993 
   2994 int Context::getMaximumRenderbufferDimension() const
   2995 {
   2996     return mMaxRenderbufferDimension;
   2997 }
   2998 
   2999 int Context::getMaximumTextureDimension() const
   3000 {
   3001     return mMaxTextureDimension;
   3002 }
   3003 
   3004 int Context::getMaximumCubeTextureDimension() const
   3005 {
   3006     return mMaxCubeTextureDimension;
   3007 }
   3008 
   3009 int Context::getMaximumTextureLevel() const
   3010 {
   3011     return mMaxTextureLevel;
   3012 }
   3013 
   3014 bool Context::supportsLuminanceTextures() const
   3015 {
   3016     return mSupportsLuminanceTextures;
   3017 }
   3018 
   3019 bool Context::supportsLuminanceAlphaTextures() const
   3020 {
   3021     return mSupportsLuminanceAlphaTextures;
   3022 }
   3023 
   3024 bool Context::supports32bitIndices() const
   3025 {
   3026     return mSupports32bitIndices;
   3027 }
   3028 
   3029 void Context::detachBuffer(GLuint buffer)
   3030 {
   3031     // [OpenGL ES 2.0.24] section 2.9 page 22:
   3032     // If a buffer object is deleted while it is bound, all bindings to that object in the current context
   3033     // (i.e. in the thread that called Delete-Buffers) are reset to zero.
   3034 
   3035     if (mState.arrayBuffer.id() == buffer)
   3036     {
   3037         mState.arrayBuffer.set(NULL);
   3038     }
   3039 
   3040     if (mState.elementArrayBuffer.id() == buffer)
   3041     {
   3042         mState.elementArrayBuffer.set(NULL);
   3043     }
   3044 
   3045     for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
   3046     {
   3047         if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
   3048         {
   3049             mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
   3050         }
   3051     }
   3052 }
   3053 
   3054 void Context::detachTexture(GLuint texture)
   3055 {
   3056     // [OpenGL ES 2.0.24] section 3.8 page 84:
   3057     // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
   3058     // rebound to texture object zero
   3059 
   3060     for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
   3061     {
   3062         for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
   3063         {
   3064             if (mState.samplerTexture[type][sampler].id() == texture)
   3065             {
   3066                 mState.samplerTexture[type][sampler].set(NULL);
   3067             }
   3068         }
   3069     }
   3070 
   3071     // [OpenGL ES 2.0.24] section 4.4 page 112:
   3072     // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
   3073     // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
   3074     // image was attached in the currently bound framebuffer.
   3075 
   3076     Framebuffer *readFramebuffer = getReadFramebuffer();
   3077     Framebuffer *drawFramebuffer = getDrawFramebuffer();
   3078 
   3079     if (readFramebuffer)
   3080     {
   3081         readFramebuffer->detachTexture(texture);
   3082     }
   3083 
   3084     if (drawFramebuffer && drawFramebuffer != readFramebuffer)
   3085     {
   3086         drawFramebuffer->detachTexture(texture);
   3087     }
   3088 }
   3089 
   3090 void Context::detachFramebuffer(GLuint framebuffer)
   3091 {
   3092     // [OpenGL ES 2.0.24] section 4.4 page 107:
   3093     // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
   3094     // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
   3095 
   3096     if (mState.readFramebuffer == framebuffer)
   3097     {
   3098         bindReadFramebuffer(0);
   3099     }
   3100 
   3101     if (mState.drawFramebuffer == framebuffer)
   3102     {
   3103         bindDrawFramebuffer(0);
   3104     }
   3105 }
   3106 
   3107 void Context::detachRenderbuffer(GLuint renderbuffer)
   3108 {
   3109     // [OpenGL ES 2.0.24] section 4.4 page 109:
   3110     // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
   3111     // had been executed with the target RENDERBUFFER and name of zero.
   3112 
   3113     if (mState.renderbuffer.id() == renderbuffer)
   3114     {
   3115         bindRenderbuffer(0);
   3116     }
   3117 
   3118     // [OpenGL ES 2.0.24] section 4.4 page 111:
   3119     // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
   3120     // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
   3121     // point to which this image was attached in the currently bound framebuffer.
   3122 
   3123     Framebuffer *readFramebuffer = getReadFramebuffer();
   3124     Framebuffer *drawFramebuffer = getDrawFramebuffer();
   3125 
   3126     if (readFramebuffer)
   3127     {
   3128         readFramebuffer->detachRenderbuffer(renderbuffer);
   3129     }
   3130 
   3131     if (drawFramebuffer && drawFramebuffer != readFramebuffer)
   3132     {
   3133         drawFramebuffer->detachRenderbuffer(renderbuffer);
   3134     }
   3135 }
   3136 
   3137 Texture *Context::getIncompleteTexture(SamplerType type)
   3138 {
   3139     Texture *t = mIncompleteTextures[type].get();
   3140 
   3141     if (t == NULL)
   3142     {
   3143         static const GLubyte color[] = { 0, 0, 0, 255 };
   3144 
   3145         switch (type)
   3146         {
   3147           default:
   3148             UNREACHABLE();
   3149             // default falls through to SAMPLER_2D
   3150 
   3151           case SAMPLER_2D:
   3152             {
   3153                 Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID);
   3154                 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
   3155                 t = incomplete2d;
   3156             }
   3157             break;
   3158 
   3159           case SAMPLER_CUBE:
   3160             {
   3161               TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID);
   3162 
   3163               incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
   3164               incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
   3165               incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
   3166               incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
   3167               incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
   3168               incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
   3169 
   3170               t = incompleteCube;
   3171             }
   3172             break;
   3173         }
   3174 
   3175         mIncompleteTextures[type].set(t);
   3176     }
   3177 
   3178     return t;
   3179 }
   3180 
   3181 bool Context::cullSkipsDraw(GLenum drawMode)
   3182 {
   3183     return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
   3184 }
   3185 
   3186 bool Context::isTriangleMode(GLenum drawMode)
   3187 {
   3188     switch (drawMode)
   3189     {
   3190       case GL_TRIANGLES:
   3191       case GL_TRIANGLE_FAN:
   3192       case GL_TRIANGLE_STRIP:
   3193         return true;
   3194       case GL_POINTS:
   3195       case GL_LINES:
   3196       case GL_LINE_LOOP:
   3197       case GL_LINE_STRIP:
   3198         return false;
   3199       default: UNREACHABLE();
   3200     }
   3201 
   3202     return false;
   3203 }
   3204 
   3205 void Context::setVertexAttrib(GLuint index, const GLfloat *values)
   3206 {
   3207     ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
   3208 
   3209     mState.vertexAttribute[index].mCurrentValue[0] = values[0];
   3210     mState.vertexAttribute[index].mCurrentValue[1] = values[1];
   3211     mState.vertexAttribute[index].mCurrentValue[2] = values[2];
   3212     mState.vertexAttribute[index].mCurrentValue[3] = values[3];
   3213 
   3214     mVertexDataManager->dirtyCurrentValue(index);
   3215 }
   3216 
   3217 void Context::initExtensionString()
   3218 {
   3219     mExtensionString += "GL_OES_packed_depth_stencil ";
   3220     mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
   3221     mExtensionString += "GL_EXT_read_format_bgra ";
   3222     mExtensionString += "GL_ANGLE_framebuffer_blit ";
   3223     mExtensionString += "GL_OES_rgb8_rgba8 ";
   3224     mExtensionString += "GL_OES_standard_derivatives ";
   3225 
   3226     if (supportsEventQueries())
   3227     {
   3228         mExtensionString += "GL_NV_fence ";
   3229     }
   3230 
   3231     if (supportsCompressedTextures())
   3232     {
   3233         mExtensionString += "GL_EXT_texture_compression_dxt1 ";
   3234     }
   3235 
   3236     if (supportsFloatTextures())
   3237     {
   3238         mExtensionString += "GL_OES_texture_float ";
   3239     }
   3240 
   3241     if (supportsHalfFloatTextures())
   3242     {
   3243         mExtensionString += "GL_OES_texture_half_float ";
   3244     }
   3245 
   3246     if (supportsFloatLinearFilter())
   3247     {
   3248         mExtensionString += "GL_OES_texture_float_linear ";
   3249     }
   3250 
   3251     if (supportsHalfFloatLinearFilter())
   3252     {
   3253         mExtensionString += "GL_OES_texture_half_float_linear ";
   3254     }
   3255 
   3256     if (getMaxSupportedSamples() != 0)
   3257     {
   3258         mExtensionString += "GL_ANGLE_framebuffer_multisample ";
   3259     }
   3260 
   3261     if (supports32bitIndices())
   3262     {
   3263         mExtensionString += "GL_OES_element_index_uint ";
   3264     }
   3265 
   3266     std::string::size_type end = mExtensionString.find_last_not_of(' ');
   3267     if (end != std::string::npos)
   3268     {
   3269         mExtensionString.resize(end+1);
   3270     }
   3271 }
   3272 
   3273 const char *Context::getExtensionString() const
   3274 {
   3275     return mExtensionString.c_str();
   3276 }
   3277 
   3278 void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
   3279                               GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
   3280                               GLbitfield mask)
   3281 {
   3282     IDirect3DDevice9 *device = getDevice();
   3283 
   3284     Framebuffer *readFramebuffer = getReadFramebuffer();
   3285     Framebuffer *drawFramebuffer = getDrawFramebuffer();
   3286 
   3287     if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
   3288         !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
   3289     {
   3290         return error(GL_INVALID_FRAMEBUFFER_OPERATION);
   3291     }
   3292 
   3293     if (drawFramebuffer->getSamples() != 0)
   3294     {
   3295         return error(GL_INVALID_OPERATION);
   3296     }
   3297 
   3298     RECT sourceRect;
   3299     RECT destRect;
   3300 
   3301     if (srcX0 < srcX1)
   3302     {
   3303         sourceRect.left = srcX0;
   3304         sourceRect.right = srcX1;
   3305         destRect.left = dstX0;
   3306         destRect.right = dstX1;
   3307     }
   3308     else
   3309     {
   3310         sourceRect.left = srcX1;
   3311         destRect.left = dstX1;
   3312         sourceRect.right = srcX0;
   3313         destRect.right = dstX0;
   3314     }
   3315 
   3316     // Arguments to StretchRect must be in D3D-style (0-top) coordinates, so we must
   3317     // flip our Y-values here
   3318     if (srcY0 < srcY1)
   3319     {
   3320         sourceRect.bottom = srcY1;
   3321         destRect.bottom = dstY1;
   3322         sourceRect.top = srcY0;
   3323         destRect.top = dstY0;
   3324     }
   3325     else
   3326     {
   3327         sourceRect.bottom = srcY0;
   3328         destRect.bottom = dstY0;
   3329         sourceRect.top = srcY1;
   3330         destRect.top = dstY1;
   3331     }
   3332 
   3333     RECT sourceScissoredRect = sourceRect;
   3334     RECT destScissoredRect = destRect;
   3335 
   3336     if (mState.scissorTest)
   3337     {
   3338         // Only write to parts of the destination framebuffer which pass the scissor test
   3339         // Please note: the destRect is now in D3D-style coordinates, so the *top* of the
   3340         // rect will be checked against scissorY, rather than the bottom.
   3341         if (destRect.left < mState.scissorX)
   3342         {
   3343             int xDiff = mState.scissorX - destRect.left;
   3344             destScissoredRect.left = mState.scissorX;
   3345             sourceScissoredRect.left += xDiff;
   3346         }
   3347 
   3348         if (destRect.right > mState.scissorX + mState.scissorWidth)
   3349         {
   3350             int xDiff = destRect.right - (mState.scissorX + mState.scissorWidth);
   3351             destScissoredRect.right = mState.scissorX + mState.scissorWidth;
   3352             sourceScissoredRect.right -= xDiff;
   3353         }
   3354 
   3355         if (destRect.top < mState.scissorY)
   3356         {
   3357             int yDiff = mState.scissorY - destRect.top;
   3358             destScissoredRect.top = mState.scissorY;
   3359             sourceScissoredRect.top += yDiff;
   3360         }
   3361 
   3362         if (destRect.bottom > mState.scissorY + mState.scissorHeight)
   3363         {
   3364             int yDiff = destRect.bottom - (mState.scissorY + mState.scissorHeight);
   3365             destScissoredRect.bottom = mState.scissorY + mState.scissorHeight;
   3366             sourceScissoredRect.bottom -= yDiff;
   3367         }
   3368     }
   3369 
   3370     bool blitRenderTarget = false;
   3371     bool blitDepthStencil = false;
   3372 
   3373     RECT sourceTrimmedRect = sourceScissoredRect;
   3374     RECT destTrimmedRect = destScissoredRect;
   3375 
   3376     // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of
   3377     // the actual draw and read surfaces.
   3378     if (sourceTrimmedRect.left < 0)
   3379     {
   3380         int xDiff = 0 - sourceTrimmedRect.left;
   3381         sourceTrimmedRect.left = 0;
   3382         destTrimmedRect.left += xDiff;
   3383     }
   3384 
   3385     int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth();
   3386     int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight();
   3387     int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth();
   3388     int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight();
   3389 
   3390     if (sourceTrimmedRect.right > readBufferWidth)
   3391     {
   3392         int xDiff = sourceTrimmedRect.right - readBufferWidth;
   3393         sourceTrimmedRect.right = readBufferWidth;
   3394         destTrimmedRect.right -= xDiff;
   3395     }
   3396 
   3397     if (sourceTrimmedRect.top < 0)
   3398     {
   3399         int yDiff = 0 - sourceTrimmedRect.top;
   3400         sourceTrimmedRect.top = 0;
   3401         destTrimmedRect.top += yDiff;
   3402     }
   3403 
   3404     if (sourceTrimmedRect.bottom > readBufferHeight)
   3405     {
   3406         int yDiff = sourceTrimmedRect.bottom - readBufferHeight;
   3407         sourceTrimmedRect.bottom = readBufferHeight;
   3408         destTrimmedRect.bottom -= yDiff;
   3409     }
   3410 
   3411     if (destTrimmedRect.left < 0)
   3412     {
   3413         int xDiff = 0 - destTrimmedRect.left;
   3414         destTrimmedRect.left = 0;
   3415         sourceTrimmedRect.left += xDiff;
   3416     }
   3417 
   3418     if (destTrimmedRect.right > drawBufferWidth)
   3419     {
   3420         int xDiff = destTrimmedRect.right - drawBufferWidth;
   3421         destTrimmedRect.right = drawBufferWidth;
   3422         sourceTrimmedRect.right -= xDiff;
   3423     }
   3424 
   3425     if (destTrimmedRect.top < 0)
   3426     {
   3427         int yDiff = 0 - destTrimmedRect.top;
   3428         destTrimmedRect.top = 0;
   3429         sourceTrimmedRect.top += yDiff;
   3430     }
   3431 
   3432     if (destTrimmedRect.bottom > drawBufferHeight)
   3433     {
   3434         int yDiff = destTrimmedRect.bottom - drawBufferHeight;
   3435         destTrimmedRect.bottom = drawBufferHeight;
   3436         sourceTrimmedRect.bottom -= yDiff;
   3437     }
   3438 
   3439     bool partialBufferCopy = false;
   3440     if (sourceTrimmedRect.bottom - sourceTrimmedRect.top < readBufferHeight ||
   3441         sourceTrimmedRect.right - sourceTrimmedRect.left < readBufferWidth ||
   3442         destTrimmedRect.bottom - destTrimmedRect.top < drawBufferHeight ||
   3443         destTrimmedRect.right - destTrimmedRect.left < drawBufferWidth ||
   3444         sourceTrimmedRect.top != 0 || destTrimmedRect.top != 0 || sourceTrimmedRect.left != 0 || destTrimmedRect.left != 0)
   3445     {
   3446         partialBufferCopy = true;
   3447     }
   3448 
   3449     if (mask & GL_COLOR_BUFFER_BIT)
   3450     {
   3451         const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
   3452             readFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
   3453         const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
   3454             drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
   3455         if (!validReadType || !validDrawType ||
   3456             readFramebuffer->getColorbuffer()->getD3DFormat() != drawFramebuffer->getColorbuffer()->getD3DFormat())
   3457         {
   3458             ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
   3459             return error(GL_INVALID_OPERATION);
   3460         }
   3461 
   3462         if (partialBufferCopy && readFramebuffer->getSamples() != 0)
   3463         {
   3464             return error(GL_INVALID_OPERATION);
   3465         }
   3466 
   3467         blitRenderTarget = true;
   3468 
   3469     }
   3470 
   3471     if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
   3472     {
   3473         DepthStencilbuffer *readDSBuffer = NULL;
   3474         DepthStencilbuffer *drawDSBuffer = NULL;
   3475 
   3476         // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
   3477         // both a depth and stencil buffer, it will be the same buffer.
   3478 
   3479         if (mask & GL_DEPTH_BUFFER_BIT)
   3480         {
   3481             if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
   3482             {
   3483                 if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
   3484                     readFramebuffer->getDepthbuffer()->getD3DFormat() != drawFramebuffer->getDepthbuffer()->getD3DFormat())
   3485                 {
   3486                     return error(GL_INVALID_OPERATION);
   3487                 }
   3488 
   3489                 blitDepthStencil = true;
   3490                 readDSBuffer = readFramebuffer->getDepthbuffer();
   3491                 drawDSBuffer = drawFramebuffer->getDepthbuffer();
   3492             }
   3493         }
   3494 
   3495         if (mask & GL_STENCIL_BUFFER_BIT)
   3496         {
   3497             if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
   3498             {
   3499                 if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
   3500                     readFramebuffer->getStencilbuffer()->getD3DFormat() != drawFramebuffer->getStencilbuffer()->getD3DFormat())
   3501                 {
   3502                     return error(GL_INVALID_OPERATION);
   3503                 }
   3504 
   3505                 blitDepthStencil = true;
   3506                 readDSBuffer = readFramebuffer->getStencilbuffer();
   3507                 drawDSBuffer = drawFramebuffer->getStencilbuffer();
   3508             }
   3509         }
   3510 
   3511         if (partialBufferCopy)
   3512         {
   3513             ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
   3514             return error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted
   3515         }
   3516 
   3517         if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) ||
   3518             (readDSBuffer && readDSBuffer->getSamples() != 0))
   3519         {
   3520             return error(GL_INVALID_OPERATION);
   3521         }
   3522     }
   3523 
   3524     if (blitRenderTarget || blitDepthStencil)
   3525     {
   3526         egl::Display *display = getDisplay();
   3527         display->endScene();
   3528 
   3529         if (blitRenderTarget)
   3530         {
   3531             HRESULT result = device->StretchRect(readFramebuffer->getRenderTarget(), &sourceTrimmedRect,
   3532                                                  drawFramebuffer->getRenderTarget(), &destTrimmedRect, D3DTEXF_NONE);
   3533 
   3534             if (FAILED(result))
   3535             {
   3536                 ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
   3537                 return;
   3538             }
   3539         }
   3540 
   3541         if (blitDepthStencil)
   3542         {
   3543             HRESULT result = device->StretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, D3DTEXF_NONE);
   3544 
   3545             if (FAILED(result))
   3546             {
   3547                 ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
   3548                 return;
   3549             }
   3550         }
   3551     }
   3552 }
   3553 
   3554 }
   3555 
   3556 extern "C"
   3557 {
   3558 gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
   3559 {
   3560     return new gl::Context(config, shareContext);
   3561 }
   3562 
   3563 void glDestroyContext(gl::Context *context)
   3564 {
   3565     delete context;
   3566 
   3567     if (context == gl::getContext())
   3568     {
   3569         gl::makeCurrent(NULL, NULL, NULL);
   3570     }
   3571 }
   3572 
   3573 void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
   3574 {
   3575     gl::makeCurrent(context, display, surface);
   3576 }
   3577 
   3578 gl::Context *glGetCurrentContext()
   3579 {
   3580     return gl::getContext();
   3581 }
   3582 }
   3583