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