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
34namespace gl
35{
36Context::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
159Context::~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
224void 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.
320void 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
341void 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
349void Context::setClearDepth(float depth)
350{
351    mState.depthClearValue = depth;
352}
353
354void Context::setClearStencil(int stencil)
355{
356    mState.stencilClearValue = stencil;
357}
358
359void Context::setCullFace(bool enabled)
360{
361    if (mState.cullFace != enabled)
362    {
363        mState.cullFace = enabled;
364        mCullStateDirty = true;
365    }
366}
367
368bool Context::isCullFaceEnabled() const
369{
370    return mState.cullFace;
371}
372
373void Context::setCullMode(GLenum mode)
374{
375    if (mState.cullMode != mode)
376    {
377        mState.cullMode = mode;
378        mCullStateDirty = true;
379    }
380}
381
382void Context::setFrontFace(GLenum front)
383{
384    if (mState.frontFace != front)
385    {
386        mState.frontFace = front;
387        mFrontFaceDirty = true;
388    }
389}
390
391void Context::setDepthTest(bool enabled)
392{
393    if (mState.depthTest != enabled)
394    {
395        mState.depthTest = enabled;
396        mDepthStateDirty = true;
397    }
398}
399
400bool Context::isDepthTestEnabled() const
401{
402    return mState.depthTest;
403}
404
405void Context::setDepthFunc(GLenum depthFunc)
406{
407    if (mState.depthFunc != depthFunc)
408    {
409        mState.depthFunc = depthFunc;
410        mDepthStateDirty = true;
411    }
412}
413
414void Context::setDepthRange(float zNear, float zFar)
415{
416    mState.zNear = zNear;
417    mState.zFar = zFar;
418}
419
420void Context::setBlend(bool enabled)
421{
422    if (mState.blend != enabled)
423    {
424        mState.blend = enabled;
425        mBlendStateDirty = true;
426    }
427}
428
429bool Context::isBlendEnabled() const
430{
431    return mState.blend;
432}
433
434void 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
449void 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
464void 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
475void Context::setStencilTest(bool enabled)
476{
477    if (mState.stencilTest != enabled)
478    {
479        mState.stencilTest = enabled;
480        mStencilStateDirty = true;
481    }
482}
483
484bool Context::isStencilTestEnabled() const
485{
486    return mState.stencilTest;
487}
488
489void 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
502void 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
515void Context::setStencilWritemask(GLuint stencilWritemask)
516{
517    if (mState.stencilWritemask != stencilWritemask)
518    {
519        mState.stencilWritemask = stencilWritemask;
520        mStencilStateDirty = true;
521    }
522}
523
524void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
525{
526    if (mState.stencilBackWritemask != stencilBackWritemask)
527    {
528        mState.stencilBackWritemask = stencilBackWritemask;
529        mStencilStateDirty = true;
530    }
531}
532
533void 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
546void 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
559void Context::setPolygonOffsetFill(bool enabled)
560{
561    if (mState.polygonOffsetFill != enabled)
562    {
563        mState.polygonOffsetFill = enabled;
564        mPolygonOffsetStateDirty = true;
565    }
566}
567
568bool Context::isPolygonOffsetFillEnabled() const
569{
570    return mState.polygonOffsetFill;
571
572}
573
574void 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
585void Context::setSampleAlphaToCoverage(bool enabled)
586{
587    if (mState.sampleAlphaToCoverage != enabled)
588    {
589        mState.sampleAlphaToCoverage = enabled;
590        mSampleStateDirty = true;
591    }
592}
593
594bool Context::isSampleAlphaToCoverageEnabled() const
595{
596    return mState.sampleAlphaToCoverage;
597}
598
599void Context::setSampleCoverage(bool enabled)
600{
601    if (mState.sampleCoverage != enabled)
602    {
603        mState.sampleCoverage = enabled;
604        mSampleStateDirty = true;
605    }
606}
607
608bool Context::isSampleCoverageEnabled() const
609{
610    return mState.sampleCoverage;
611}
612
613void 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
624void Context::setScissorTest(bool enabled)
625{
626    if (mState.scissorTest != enabled)
627    {
628        mState.scissorTest = enabled;
629        mScissorStateDirty = true;
630    }
631}
632
633bool Context::isScissorTestEnabled() const
634{
635    return mState.scissorTest;
636}
637
638void Context::setDither(bool enabled)
639{
640    if (mState.dither != enabled)
641    {
642        mState.dither = enabled;
643        mDitherStateDirty = true;
644    }
645}
646
647bool Context::isDitherEnabled() const
648{
649    return mState.dither;
650}
651
652void Context::setLineWidth(GLfloat width)
653{
654    mState.lineWidth = width;
655}
656
657void Context::setGenerateMipmapHint(GLenum hint)
658{
659    mState.generateMipmapHint = hint;
660}
661
662void 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
670void 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
678void 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
691void 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
704void Context::setDepthMask(bool mask)
705{
706    if (mState.depthMask != mask)
707    {
708        mState.depthMask = mask;
709        mMaskStateDirty = true;
710    }
711}
712
713void Context::setActiveSampler(int active)
714{
715    mState.activeSampler = active;
716}
717
718GLuint Context::getReadFramebufferHandle() const
719{
720    return mState.readFramebuffer;
721}
722
723GLuint Context::getDrawFramebufferHandle() const
724{
725    return mState.drawFramebuffer;
726}
727
728GLuint Context::getRenderbufferHandle() const
729{
730    return mState.renderbuffer.id();
731}
732
733GLuint Context::getArrayBufferHandle() const
734{
735    return mState.arrayBuffer.id();
736}
737
738void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
739{
740    mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
741}
742
743const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
744{
745    return mState.vertexAttribute[attribNum];
746}
747
748void 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
759const void *Context::getVertexAttribPointer(unsigned int attribNum) const
760{
761    return mState.vertexAttribute[attribNum].mPointer;
762}
763
764const VertexAttributeArray &Context::getVertexAttributes()
765{
766    return mState.vertexAttribute;
767}
768
769void Context::setPackAlignment(GLint alignment)
770{
771    mState.packAlignment = alignment;
772}
773
774GLint Context::getPackAlignment() const
775{
776    return mState.packAlignment;
777}
778
779void Context::setUnpackAlignment(GLint alignment)
780{
781    mState.unpackAlignment = alignment;
782}
783
784GLint Context::getUnpackAlignment() const
785{
786    return mState.unpackAlignment;
787}
788
789GLuint Context::createBuffer()
790{
791    return mResourceManager->createBuffer();
792}
793
794GLuint Context::createProgram()
795{
796    return mResourceManager->createProgram();
797}
798
799GLuint Context::createShader(GLenum type)
800{
801    return mResourceManager->createShader(type);
802}
803
804GLuint Context::createTexture()
805{
806    return mResourceManager->createTexture();
807}
808
809GLuint Context::createRenderbuffer()
810{
811    return mResourceManager->createRenderbuffer();
812}
813
814// Returns an unused framebuffer name
815GLuint 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
829GLuint 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
843void Context::deleteBuffer(GLuint buffer)
844{
845    if (mResourceManager->getBuffer(buffer))
846    {
847        detachBuffer(buffer);
848    }
849
850    mResourceManager->deleteBuffer(buffer);
851}
852
853void Context::deleteShader(GLuint shader)
854{
855    mResourceManager->deleteShader(shader);
856}
857
858void Context::deleteProgram(GLuint program)
859{
860    mResourceManager->deleteProgram(program);
861}
862
863void Context::deleteTexture(GLuint texture)
864{
865    if (mResourceManager->getTexture(texture))
866    {
867        detachTexture(texture);
868    }
869
870    mResourceManager->deleteTexture(texture);
871}
872
873void Context::deleteRenderbuffer(GLuint renderbuffer)
874{
875    if (mResourceManager->getRenderbuffer(renderbuffer))
876    {
877        detachRenderbuffer(renderbuffer);
878    }
879
880    mResourceManager->deleteRenderbuffer(renderbuffer);
881}
882
883void 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
896void 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
907Buffer *Context::getBuffer(GLuint handle)
908{
909    return mResourceManager->getBuffer(handle);
910}
911
912Shader *Context::getShader(GLuint handle)
913{
914    return mResourceManager->getShader(handle);
915}
916
917Program *Context::getProgram(GLuint handle)
918{
919    return mResourceManager->getProgram(handle);
920}
921
922Texture *Context::getTexture(GLuint handle)
923{
924    return mResourceManager->getTexture(handle);
925}
926
927Renderbuffer *Context::getRenderbuffer(GLuint handle)
928{
929    return mResourceManager->getRenderbuffer(handle);
930}
931
932Framebuffer *Context::getReadFramebuffer()
933{
934    return getFramebuffer(mState.readFramebuffer);
935}
936
937Framebuffer *Context::getDrawFramebuffer()
938{
939    return getFramebuffer(mState.drawFramebuffer);
940}
941
942void Context::bindArrayBuffer(unsigned int buffer)
943{
944    mResourceManager->checkBufferAllocation(buffer);
945
946    mState.arrayBuffer.set(getBuffer(buffer));
947}
948
949void Context::bindElementArrayBuffer(unsigned int buffer)
950{
951    mResourceManager->checkBufferAllocation(buffer);
952
953    mState.elementArrayBuffer.set(getBuffer(buffer));
954}
955
956void Context::bindTexture2D(GLuint texture)
957{
958    mResourceManager->checkTextureAllocation(texture, SAMPLER_2D);
959
960    mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(getTexture(texture));
961}
962
963void Context::bindTextureCubeMap(GLuint texture)
964{
965    mResourceManager->checkTextureAllocation(texture, SAMPLER_CUBE);
966
967    mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(getTexture(texture));
968}
969
970void Context::bindReadFramebuffer(GLuint framebuffer)
971{
972    if (!getFramebuffer(framebuffer))
973    {
974        mFramebufferMap[framebuffer] = new Framebuffer();
975    }
976
977    mState.readFramebuffer = framebuffer;
978}
979
980void Context::bindDrawFramebuffer(GLuint framebuffer)
981{
982    if (!getFramebuffer(framebuffer))
983    {
984        mFramebufferMap[framebuffer] = new Framebuffer();
985    }
986
987    mState.drawFramebuffer = framebuffer;
988}
989
990void Context::bindRenderbuffer(GLuint renderbuffer)
991{
992    mResourceManager->checkRenderbufferAllocation(renderbuffer);
993
994    mState.renderbuffer.set(getRenderbuffer(renderbuffer));
995}
996
997void 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
1019void Context::setFramebufferZero(Framebuffer *buffer)
1020{
1021    delete mFramebufferMap[0];
1022    mFramebufferMap[0] = buffer;
1023}
1024
1025void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
1026{
1027    Renderbuffer *renderbufferObject = mState.renderbuffer.get();
1028    renderbufferObject->setStorage(renderbuffer);
1029}
1030
1031Framebuffer *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
1045Fence *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
1059Buffer *Context::getArrayBuffer()
1060{
1061    return mState.arrayBuffer.get();
1062}
1063
1064Buffer *Context::getElementArrayBuffer()
1065{
1066    return mState.elementArrayBuffer.get();
1067}
1068
1069Program *Context::getCurrentProgram()
1070{
1071    return mResourceManager->getProgram(mState.currentProgram);
1072}
1073
1074Texture2D *Context::getTexture2D()
1075{
1076    return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, SAMPLER_2D));
1077}
1078
1079TextureCubeMap *Context::getTextureCubeMap()
1080{
1081    return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, SAMPLER_CUBE));
1082}
1083
1084Texture *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
1101bool 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
1130bool 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
1174bool 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
1402bool 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
1567bool 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
1713void 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.
1953void 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
1964GLenum 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
1982GLenum 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
1996void 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
2017void 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
2070void 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
2327void 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
2556void 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
2610void 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
2677void 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
2727void 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
2756void 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
2811void 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
2843void Context::recordInvalidEnum()
2844{
2845    mInvalidEnum = true;
2846}
2847
2848void Context::recordInvalidValue()
2849{
2850    mInvalidValue = true;
2851}
2852
2853void Context::recordInvalidOperation()
2854{
2855    mInvalidOperation = true;
2856}
2857
2858void Context::recordOutOfMemory()
2859{
2860    mOutOfMemory = true;
2861}
2862
2863void 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.
2870GLenum 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
2910bool Context::supportsShaderModel3() const
2911{
2912    return mSupportsShaderModel3;
2913}
2914
2915int Context::getMaximumVaryingVectors() const
2916{
2917    return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
2918}
2919
2920int Context::getMaximumFragmentUniformVectors() const
2921{
2922    return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2;
2923}
2924
2925int Context::getMaxSupportedSamples() const
2926{
2927    return mMaxSupportedSamples;
2928}
2929
2930int 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
2954bool Context::supportsEventQueries() const
2955{
2956    return mSupportsEventQueries;
2957}
2958
2959bool Context::supportsCompressedTextures() const
2960{
2961    return mSupportsCompressedTextures;
2962}
2963
2964bool Context::supportsFloatTextures() const
2965{
2966    return mSupportsFloatTextures;
2967}
2968
2969bool Context::supportsFloatLinearFilter() const
2970{
2971    return mSupportsFloatLinearFilter;
2972}
2973
2974bool Context::supportsFloatRenderableTextures() const
2975{
2976    return mSupportsFloatRenderableTextures;
2977}
2978
2979bool Context::supportsHalfFloatTextures() const
2980{
2981    return mSupportsHalfFloatTextures;
2982}
2983
2984bool Context::supportsHalfFloatLinearFilter() const
2985{
2986    return mSupportsHalfFloatLinearFilter;
2987}
2988
2989bool Context::supportsHalfFloatRenderableTextures() const
2990{
2991    return mSupportsHalfFloatRenderableTextures;
2992}
2993
2994int Context::getMaximumRenderbufferDimension() const
2995{
2996    return mMaxRenderbufferDimension;
2997}
2998
2999int Context::getMaximumTextureDimension() const
3000{
3001    return mMaxTextureDimension;
3002}
3003
3004int Context::getMaximumCubeTextureDimension() const
3005{
3006    return mMaxCubeTextureDimension;
3007}
3008
3009int Context::getMaximumTextureLevel() const
3010{
3011    return mMaxTextureLevel;
3012}
3013
3014bool Context::supportsLuminanceTextures() const
3015{
3016    return mSupportsLuminanceTextures;
3017}
3018
3019bool Context::supportsLuminanceAlphaTextures() const
3020{
3021    return mSupportsLuminanceAlphaTextures;
3022}
3023
3024bool Context::supports32bitIndices() const
3025{
3026    return mSupports32bitIndices;
3027}
3028
3029void 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
3054void 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
3090void 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
3107void 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
3137Texture *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
3181bool Context::cullSkipsDraw(GLenum drawMode)
3182{
3183    return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
3184}
3185
3186bool 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
3205void 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
3217void 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
3273const char *Context::getExtensionString() const
3274{
3275    return mExtensionString.c_str();
3276}
3277
3278void 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
3556extern "C"
3557{
3558gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
3559{
3560    return new gl::Context(config, shareContext);
3561}
3562
3563void glDestroyContext(gl::Context *context)
3564{
3565    delete context;
3566
3567    if (context == gl::getContext())
3568    {
3569        gl::makeCurrent(NULL, NULL, NULL);
3570    }
3571}
3572
3573void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
3574{
3575    gl::makeCurrent(context, display, surface);
3576}
3577
3578gl::Context *glGetCurrentContext()
3579{
3580    return gl::getContext();
3581}
3582}
3583