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