blob: c619ec6c176344b182370a09d287645052047b53 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
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
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/Context.h"
daniel@transgaming.com16973022010-03-11 19:22:19 +000011
12#include <algorithm>
13
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000014#include "libEGL/Display.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000015
16#include "libGLESv2/main.h"
17#include "libGLESv2/mathutil.h"
18#include "libGLESv2/utilities.h"
19#include "libGLESv2/Blit.h"
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000020#include "libGLESv2/ResourceManager.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000021#include "libGLESv2/Buffer.h"
22#include "libGLESv2/FrameBuffer.h"
23#include "libGLESv2/Program.h"
24#include "libGLESv2/RenderBuffer.h"
25#include "libGLESv2/Shader.h"
26#include "libGLESv2/Texture.h"
27#include "libGLESv2/geometry/backend.h"
28#include "libGLESv2/geometry/VertexDataManager.h"
29#include "libGLESv2/geometry/IndexDataManager.h"
30#include "libGLESv2/geometry/dx9.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031
daniel@transgaming.com86487c22010-03-11 19:41:43 +000032#undef near
33#undef far
34
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000035namespace gl
36{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000037Context::Context(const egl::Config *config)
38 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000039{
40 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
daniel@transgaming.com092bd482010-05-12 03:39:36 +000041
daniel@transgaming.com428d1582010-05-04 03:35:25 +000042 mState.depthClearValue = 1.0f;
43 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000044
daniel@transgaming.com428d1582010-05-04 03:35:25 +000045 mState.cullFace = false;
46 mState.cullMode = GL_BACK;
47 mState.frontFace = GL_CCW;
48 mState.depthTest = false;
49 mState.depthFunc = GL_LESS;
50 mState.blend = false;
51 mState.sourceBlendRGB = GL_ONE;
52 mState.sourceBlendAlpha = GL_ONE;
53 mState.destBlendRGB = GL_ZERO;
54 mState.destBlendAlpha = GL_ZERO;
55 mState.blendEquationRGB = GL_FUNC_ADD;
56 mState.blendEquationAlpha = GL_FUNC_ADD;
57 mState.blendColor.red = 0;
58 mState.blendColor.green = 0;
59 mState.blendColor.blue = 0;
60 mState.blendColor.alpha = 0;
61 mState.stencilTest = false;
62 mState.stencilFunc = GL_ALWAYS;
63 mState.stencilRef = 0;
64 mState.stencilMask = -1;
65 mState.stencilWritemask = -1;
66 mState.stencilBackFunc = GL_ALWAYS;
67 mState.stencilBackRef = 0;
68 mState.stencilBackMask = - 1;
69 mState.stencilBackWritemask = -1;
70 mState.stencilFail = GL_KEEP;
71 mState.stencilPassDepthFail = GL_KEEP;
72 mState.stencilPassDepthPass = GL_KEEP;
73 mState.stencilBackFail = GL_KEEP;
74 mState.stencilBackPassDepthFail = GL_KEEP;
75 mState.stencilBackPassDepthPass = GL_KEEP;
76 mState.polygonOffsetFill = false;
77 mState.polygonOffsetFactor = 0.0f;
78 mState.polygonOffsetUnits = 0.0f;
79 mState.sampleAlphaToCoverage = false;
80 mState.sampleCoverage = false;
81 mState.sampleCoverageValue = 1.0f;
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +000082 mState.sampleCoverageInvert = false;
daniel@transgaming.com428d1582010-05-04 03:35:25 +000083 mState.scissorTest = false;
84 mState.dither = true;
85 mState.generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000086
daniel@transgaming.com428d1582010-05-04 03:35:25 +000087 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000088
daniel@transgaming.com428d1582010-05-04 03:35:25 +000089 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;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095
daniel@transgaming.com428d1582010-05-04 03:35:25 +000096 mState.scissorX = 0;
97 mState.scissorY = 0;
98 mState.scissorWidth = config->mDisplayMode.Width;
99 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000101 mState.colorMaskRed = true;
102 mState.colorMaskGreen = true;
103 mState.colorMaskBlue = true;
104 mState.colorMaskAlpha = true;
105 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000107 // FIXME: Resource managers should get managed with context sharing
108 mResourceManager = new ResourceManager();
109
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110 // [OpenGL ES 2.0.24] section 3.7 page 83:
111 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
112 // and cube map texture state vectors respectively associated with them.
113 // In order that access to these initial textures not be lost, they are treated as texture
114 // objects all of whose names are 0.
115
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000116 mTexture2DZero = new Texture2D();
117 mTextureCubeMapZero = new TextureCubeMap();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000118
119 mColorbufferZero = NULL;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000120 mDepthStencilbufferZero = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000122 mState.activeSampler = 0;
123 mState.arrayBuffer = 0;
124 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125 bindTextureCubeMap(0);
126 bindTexture2D(0);
127 bindFramebuffer(0);
128 bindRenderbuffer(0);
129
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000130 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000132 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
133 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000134 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000135 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136 }
137
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000138 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
139 {
140 mIncompleteTextures[type] = NULL;
141 }
142
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000143 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000145 mState.packAlignment = 4;
146 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000147
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000148 mBufferBackEnd = NULL;
149 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000150 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000151 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000152
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000153 mInvalidEnum = false;
154 mInvalidValue = false;
155 mInvalidOperation = false;
156 mOutOfMemory = false;
157 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000158
159 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000160
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000161 mMaskedClearSavedState = NULL;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000162 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000163}
164
165Context::~Context()
166{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000167 if (mState.currentProgram != 0)
168 {
169 Program *programObject = mResourceManager->getProgram(mState.currentProgram);
170 if (programObject)
171 {
172 programObject->release();
173 }
174 mState.currentProgram = 0;
175 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000176
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000177 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
178 {
179 delete mIncompleteTextures[type];
180 }
181
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182 delete mTexture2DZero;
183 delete mTextureCubeMapZero;
184
185 delete mColorbufferZero;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000186 delete mDepthStencilbufferZero;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000188 delete mBufferBackEnd;
189 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000190 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000191 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000192
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000193 while (!mFramebufferMap.empty())
194 {
195 deleteFramebuffer(mFramebufferMap.begin()->first);
196 }
197
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000198 if (mMaskedClearSavedState)
199 {
200 mMaskedClearSavedState->Release();
201 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000202
203 // FIXME: Context should not be responsible for resource manager deallocation
204 delete mResourceManager;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000205}
206
207void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
208{
209 IDirect3DDevice9 *device = display->getDevice();
210
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000211 if (!mHasBeenCurrent)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000212 {
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000213 mDeviceCaps = display->getDeviceCaps();
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000214
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000215 mBufferBackEnd = new Dx9BackEnd(this, device);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000216 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000217 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000218 mBlit = new Blit(this);
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000219
220 initExtensionString();
221
222 mState.viewportX = 0;
223 mState.viewportY = 0;
224 mState.viewportWidth = surface->getWidth();
225 mState.viewportHeight = surface->getHeight();
226
227 mState.scissorX = 0;
228 mState.scissorY = 0;
229 mState.scissorWidth = surface->getWidth();
230 mState.scissorHeight = surface->getHeight();
231
232 mHasBeenCurrent = true;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000233 }
234
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
236 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000237 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238
daniel@transgaming.com0190f842010-07-28 19:21:02 +0000239 Framebuffer *framebufferZero = new Framebuffer(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000240 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000241 DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242
243 setFramebufferZero(framebufferZero);
244 setColorbufferZero(colorbufferZero);
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000245 setDepthStencilbufferZero(depthStencilbufferZero);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000246
247 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
248 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
249 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
250
251 defaultRenderTarget->Release();
252
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000253 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000254 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000255 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000257
daniel@transgaming.combe5a0862010-07-28 19:20:37 +0000258 mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000259
260 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261}
262
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000263// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000264void Context::markAllStateDirty()
265{
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000266 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000267 mAppliedDepthbufferSerial = 0;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000268 mAppliedProgram = 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000269
270 mClearStateDirty = true;
271 mCullStateDirty = true;
272 mDepthStateDirty = true;
273 mMaskStateDirty = true;
274 mBlendStateDirty = true;
275 mStencilStateDirty = true;
276 mPolygonOffsetStateDirty = true;
277 mScissorStateDirty = true;
278 mSampleStateDirty = true;
279 mDitherStateDirty = true;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000280}
281
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282void Context::setClearColor(float red, float green, float blue, float alpha)
283{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000284 mState.colorClearValue.red = red;
285 mState.colorClearValue.green = green;
286 mState.colorClearValue.blue = blue;
287 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288}
289
290void Context::setClearDepth(float depth)
291{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000292 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000293}
294
295void Context::setClearStencil(int stencil)
296{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000297 mState.stencilClearValue = stencil;
298}
299
300void Context::setCullFace(bool enabled)
301{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000302 if (mState.cullFace != enabled)
303 {
304 mState.cullFace = enabled;
305 mCullStateDirty = true;
306 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000307}
308
309bool Context::isCullFaceEnabled() const
310{
311 return mState.cullFace;
312}
313
314void Context::setCullMode(GLenum mode)
315{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000316 if (mState.cullMode != mode)
317 {
318 mState.cullMode = mode;
319 mCullStateDirty = true;
320 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000321}
322
323void Context::setFrontFace(GLenum front)
324{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000325 if (mState.frontFace != front)
326 {
327 mState.frontFace = front;
328 mFrontFaceDirty = true;
329 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000330}
331
332void Context::setDepthTest(bool enabled)
333{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000334 if (mState.depthTest != enabled)
335 {
336 mState.depthTest = enabled;
337 mDepthStateDirty = true;
338 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000339}
340
341bool Context::isDepthTestEnabled() const
342{
343 return mState.depthTest;
344}
345
346void Context::setDepthFunc(GLenum depthFunc)
347{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000348 if (mState.depthFunc != depthFunc)
349 {
350 mState.depthFunc = depthFunc;
351 mDepthStateDirty = true;
352 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000353}
354
355void Context::setDepthRange(float zNear, float zFar)
356{
357 mState.zNear = zNear;
358 mState.zFar = zFar;
359}
360
361void Context::setBlend(bool enabled)
362{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000363 if (mState.blend != enabled)
364 {
365 mState.blend = enabled;
366 mBlendStateDirty = true;
367 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000368}
369
370bool Context::isBlendEnabled() const
371{
372 return mState.blend;
373}
374
375void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
376{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000377 if (mState.sourceBlendRGB != sourceRGB ||
378 mState.sourceBlendAlpha != sourceAlpha ||
379 mState.destBlendRGB != destRGB ||
380 mState.destBlendAlpha != destAlpha)
381 {
382 mState.sourceBlendRGB = sourceRGB;
383 mState.destBlendRGB = destRGB;
384 mState.sourceBlendAlpha = sourceAlpha;
385 mState.destBlendAlpha = destAlpha;
386 mBlendStateDirty = true;
387 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000388}
389
390void Context::setBlendColor(float red, float green, float blue, float alpha)
391{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000392 if (mState.blendColor.red != red ||
393 mState.blendColor.green != green ||
394 mState.blendColor.blue != blue ||
395 mState.blendColor.alpha != alpha)
396 {
397 mState.blendColor.red = red;
398 mState.blendColor.green = green;
399 mState.blendColor.blue = blue;
400 mState.blendColor.alpha = alpha;
401 mBlendStateDirty = true;
402 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000403}
404
405void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
406{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000407 if (mState.blendEquationRGB != rgbEquation ||
408 mState.blendEquationAlpha != alphaEquation)
409 {
410 mState.blendEquationRGB = rgbEquation;
411 mState.blendEquationAlpha = alphaEquation;
412 mBlendStateDirty = true;
413 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000414}
415
416void Context::setStencilTest(bool enabled)
417{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000418 if (mState.stencilTest != enabled)
419 {
420 mState.stencilTest = enabled;
421 mStencilStateDirty = true;
422 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000423}
424
425bool Context::isStencilTestEnabled() const
426{
427 return mState.stencilTest;
428}
429
430void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
431{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000432 if (mState.stencilFunc != stencilFunc ||
433 mState.stencilRef != stencilRef ||
434 mState.stencilMask != stencilMask)
435 {
436 mState.stencilFunc = stencilFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000437 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000438 mState.stencilMask = stencilMask;
439 mStencilStateDirty = true;
440 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000441}
442
443void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
444{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000445 if (mState.stencilBackFunc != stencilBackFunc ||
446 mState.stencilBackRef != stencilBackRef ||
447 mState.stencilBackMask != stencilBackMask)
448 {
449 mState.stencilBackFunc = stencilBackFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000450 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000451 mState.stencilBackMask = stencilBackMask;
452 mStencilStateDirty = true;
453 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000454}
455
456void Context::setStencilWritemask(GLuint stencilWritemask)
457{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000458 if (mState.stencilWritemask != stencilWritemask)
459 {
460 mState.stencilWritemask = stencilWritemask;
461 mStencilStateDirty = true;
462 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000463}
464
465void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
466{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000467 if (mState.stencilBackWritemask != stencilBackWritemask)
468 {
469 mState.stencilBackWritemask = stencilBackWritemask;
470 mStencilStateDirty = true;
471 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000472}
473
474void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
475{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000476 if (mState.stencilFail != stencilFail ||
477 mState.stencilPassDepthFail != stencilPassDepthFail ||
478 mState.stencilPassDepthPass != stencilPassDepthPass)
479 {
480 mState.stencilFail = stencilFail;
481 mState.stencilPassDepthFail = stencilPassDepthFail;
482 mState.stencilPassDepthPass = stencilPassDepthPass;
483 mStencilStateDirty = true;
484 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000485}
486
487void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
488{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000489 if (mState.stencilBackFail != stencilBackFail ||
490 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
491 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
492 {
493 mState.stencilBackFail = stencilBackFail;
494 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
495 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
496 mStencilStateDirty = true;
497 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000498}
499
500void Context::setPolygonOffsetFill(bool enabled)
501{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000502 if (mState.polygonOffsetFill != enabled)
503 {
504 mState.polygonOffsetFill = enabled;
505 mPolygonOffsetStateDirty = true;
506 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000507}
508
509bool Context::isPolygonOffsetFillEnabled() const
510{
511 return mState.polygonOffsetFill;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000512
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000513}
514
515void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
516{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000517 if (mState.polygonOffsetFactor != factor ||
518 mState.polygonOffsetUnits != units)
519 {
520 mState.polygonOffsetFactor = factor;
521 mState.polygonOffsetUnits = units;
522 mPolygonOffsetStateDirty = true;
523 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000524}
525
526void Context::setSampleAlphaToCoverage(bool enabled)
527{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000528 if (mState.sampleAlphaToCoverage != enabled)
529 {
530 mState.sampleAlphaToCoverage = enabled;
531 mSampleStateDirty = true;
532 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000533}
534
535bool Context::isSampleAlphaToCoverageEnabled() const
536{
537 return mState.sampleAlphaToCoverage;
538}
539
540void Context::setSampleCoverage(bool enabled)
541{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000542 if (mState.sampleCoverage != enabled)
543 {
544 mState.sampleCoverage = enabled;
545 mSampleStateDirty = true;
546 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000547}
548
549bool Context::isSampleCoverageEnabled() const
550{
551 return mState.sampleCoverage;
552}
553
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +0000554void Context::setSampleCoverageParams(GLclampf value, bool invert)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000555{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000556 if (mState.sampleCoverageValue != value ||
557 mState.sampleCoverageInvert != invert)
558 {
559 mState.sampleCoverageValue = value;
560 mState.sampleCoverageInvert = invert;
561 mSampleStateDirty = true;
562 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000563}
564
565void Context::setScissorTest(bool enabled)
566{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000567 if (mState.scissorTest != enabled)
568 {
569 mState.scissorTest = enabled;
570 mScissorStateDirty = true;
571 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000572}
573
574bool Context::isScissorTestEnabled() const
575{
576 return mState.scissorTest;
577}
578
579void Context::setDither(bool enabled)
580{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000581 if (mState.dither != enabled)
582 {
583 mState.dither = enabled;
584 mDitherStateDirty = true;
585 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000586}
587
588bool Context::isDitherEnabled() const
589{
590 return mState.dither;
591}
592
593void Context::setLineWidth(GLfloat width)
594{
595 mState.lineWidth = width;
596}
597
598void Context::setGenerateMipmapHint(GLenum hint)
599{
600 mState.generateMipmapHint = hint;
601}
602
603void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
604{
605 mState.viewportX = x;
606 mState.viewportY = y;
607 mState.viewportWidth = width;
608 mState.viewportHeight = height;
609}
610
611void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
612{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000613 if (mState.scissorX != x || mState.scissorY != y ||
614 mState.scissorWidth != width || mState.scissorHeight != height)
615 {
616 mState.scissorX = x;
617 mState.scissorY = y;
618 mState.scissorWidth = width;
619 mState.scissorHeight = height;
620 mScissorStateDirty = true;
621 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000622}
623
624void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
625{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000626 if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
627 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
628 {
629 mState.colorMaskRed = red;
630 mState.colorMaskGreen = green;
631 mState.colorMaskBlue = blue;
632 mState.colorMaskAlpha = alpha;
633 mMaskStateDirty = true;
634 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000635}
636
637void Context::setDepthMask(bool mask)
638{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000639 if (mState.depthMask != mask)
640 {
641 mState.depthMask = mask;
642 mMaskStateDirty = true;
643 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000644}
645
646void Context::setActiveSampler(int active)
647{
648 mState.activeSampler = active;
649}
650
651GLuint Context::getFramebufferHandle() const
652{
653 return mState.framebuffer;
654}
655
656GLuint Context::getRenderbufferHandle() const
657{
658 return mState.renderbuffer;
659}
660
661GLuint Context::getArrayBufferHandle() const
662{
663 return mState.arrayBuffer;
664}
665
666void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
667{
668 mState.vertexAttribute[attribNum].mEnabled = enabled;
669}
670
671const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
672{
673 return mState.vertexAttribute[attribNum];
674}
675
676void Context::setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type, bool normalized,
677 GLsizei stride, const void *pointer)
678{
679 mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer;
680 mState.vertexAttribute[attribNum].mSize = size;
681 mState.vertexAttribute[attribNum].mType = type;
682 mState.vertexAttribute[attribNum].mNormalized = normalized;
683 mState.vertexAttribute[attribNum].mStride = stride;
684 mState.vertexAttribute[attribNum].mPointer = pointer;
685}
686
687const void *Context::getVertexAttribPointer(unsigned int attribNum) const
688{
689 return mState.vertexAttribute[attribNum].mPointer;
690}
691
692// returns entire set of attributes as a block
693const AttributeState *Context::getVertexAttribBlock()
694{
695 return mState.vertexAttribute;
696}
697
698void Context::setPackAlignment(GLint alignment)
699{
700 mState.packAlignment = alignment;
701}
702
703GLint Context::getPackAlignment() const
704{
705 return mState.packAlignment;
706}
707
708void Context::setUnpackAlignment(GLint alignment)
709{
710 mState.unpackAlignment = alignment;
711}
712
713GLint Context::getUnpackAlignment() const
714{
715 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000716}
717
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000718GLuint Context::createBuffer()
719{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000720 return mResourceManager->createBuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000721}
722
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000723GLuint Context::createProgram()
724{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000725 return mResourceManager->createProgram();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726}
727
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000728GLuint Context::createShader(GLenum type)
729{
730 return mResourceManager->createShader(type);
731}
732
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000733GLuint Context::createTexture()
734{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000735 return mResourceManager->createTexture();
736}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000737
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000738GLuint Context::createRenderbuffer()
739{
740 return mResourceManager->createRenderbuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000741}
742
743// Returns an unused framebuffer name
744GLuint Context::createFramebuffer()
745{
746 unsigned int handle = 1;
747
748 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
749 {
750 handle++;
751 }
752
753 mFramebufferMap[handle] = NULL;
754
755 return handle;
756}
757
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000758void Context::deleteBuffer(GLuint buffer)
759{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000760 if (mResourceManager->getBuffer(buffer))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000761 {
762 detachBuffer(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000763 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000764
765 mResourceManager->deleteBuffer(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000766}
767
768void Context::deleteShader(GLuint shader)
769{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000770 mResourceManager->deleteShader(shader);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000771}
772
773void Context::deleteProgram(GLuint program)
774{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000775 mResourceManager->deleteProgram(program);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000776}
777
778void Context::deleteTexture(GLuint texture)
779{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000780 if (mResourceManager->getTexture(texture))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000781 {
782 detachTexture(texture);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000783 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000784
785 mResourceManager->deleteTexture(texture);
786}
787
788void Context::deleteRenderbuffer(GLuint renderbuffer)
789{
790 if (mResourceManager->getRenderbuffer(renderbuffer))
791 {
792 detachRenderbuffer(renderbuffer);
793 }
794
795 mResourceManager->deleteRenderbuffer(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000796}
797
798void Context::deleteFramebuffer(GLuint framebuffer)
799{
800 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
801
802 if (framebufferObject != mFramebufferMap.end())
803 {
804 detachFramebuffer(framebuffer);
805
806 delete framebufferObject->second;
807 mFramebufferMap.erase(framebufferObject);
808 }
809}
810
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000811Buffer *Context::getBuffer(GLuint handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000812{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000813 return mResourceManager->getBuffer(handle);
814}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000815
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000816Shader *Context::getShader(GLuint handle)
817{
818 return mResourceManager->getShader(handle);
819}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000820
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000821Program *Context::getProgram(GLuint handle)
822{
823 return mResourceManager->getProgram(handle);
824}
825
826Texture *Context::getTexture(GLuint handle)
827{
828 return mResourceManager->getTexture(handle);
829}
830
831Renderbuffer *Context::getRenderbuffer(GLuint handle)
832{
833 return mResourceManager->getRenderbuffer(handle);
834}
835
836Framebuffer *Context::getFramebuffer()
837{
838 return getFramebuffer(mState.framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000839}
840
841void Context::bindArrayBuffer(unsigned int buffer)
842{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000843 mResourceManager->checkBufferAllocation(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000844
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000845 mState.arrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000846}
847
848void Context::bindElementArrayBuffer(unsigned int buffer)
849{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000850 mResourceManager->checkBufferAllocation(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000851
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000852 mState.elementArrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000853}
854
855void Context::bindTexture2D(GLuint texture)
856{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000857 mResourceManager->checkTextureAllocation(texture, SAMPLER_2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000858
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000859 mState.texture2D = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000860
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000861 mState.samplerTexture[SAMPLER_2D][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000862}
863
864void Context::bindTextureCubeMap(GLuint texture)
865{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000866 mResourceManager->checkTextureAllocation(texture, SAMPLER_CUBE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000867
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000868 mState.textureCubeMap = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000869
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000870 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000871}
872
873void Context::bindFramebuffer(GLuint framebuffer)
874{
875 if (!getFramebuffer(framebuffer))
876 {
daniel@transgaming.com0190f842010-07-28 19:21:02 +0000877 mFramebufferMap[framebuffer] = new Framebuffer(framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000878 }
879
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000880 mState.framebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000881}
882
883void Context::bindRenderbuffer(GLuint renderbuffer)
884{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000885 mState.renderbuffer = renderbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000886}
887
888void Context::useProgram(GLuint program)
889{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000890 GLuint priorProgram = mState.currentProgram;
891 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000892
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000893 if (priorProgram != program)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000894 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000895 Program *newProgram = mResourceManager->getProgram(program);
896 Program *oldProgram = mResourceManager->getProgram(priorProgram);
897
898 if (newProgram)
899 {
900 newProgram->addRef();
901 }
902
903 if (oldProgram)
904 {
905 oldProgram->release();
906 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000907 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000908}
909
910void Context::setFramebufferZero(Framebuffer *buffer)
911{
912 delete mFramebufferMap[0];
913 mFramebufferMap[0] = buffer;
914}
915
916void Context::setColorbufferZero(Colorbuffer *buffer)
917{
918 delete mColorbufferZero;
919 mColorbufferZero = buffer;
920}
921
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000922void Context::setDepthStencilbufferZero(DepthStencilbuffer *buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000923{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000924 delete mDepthStencilbufferZero;
925 mDepthStencilbufferZero = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000926}
927
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000928void Context::setRenderbuffer(Renderbuffer *renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000929{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000930 mResourceManager->deleteRenderbuffer(mState.renderbuffer);
931 mResourceManager->setRenderbuffer(mState.renderbuffer, renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000932}
933
934Framebuffer *Context::getFramebuffer(unsigned int handle)
935{
936 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000937
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000938 if (framebuffer == mFramebufferMap.end())
939 {
940 return NULL;
941 }
942 else
943 {
944 return framebuffer->second;
945 }
946}
947
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000948Colorbuffer *Context::getColorbuffer(GLuint handle)
949{
950 if (handle != 0)
951 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000952 Renderbuffer *renderbuffer = mResourceManager->getRenderbuffer(handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000953
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000954 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000955 {
956 return static_cast<Colorbuffer*>(renderbuffer);
957 }
958 }
959 else // Special case: 0 refers to different initial render targets based on the attachment type
960 {
961 return mColorbufferZero;
962 }
963
964 return NULL;
965}
966
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000967DepthStencilbuffer *Context::getDepthbuffer(GLuint handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968{
969 if (handle != 0)
970 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000971 Renderbuffer *renderbuffer = mResourceManager->getRenderbuffer(handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000972
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000973 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000974 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000975 return static_cast<DepthStencilbuffer*>(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000976 }
977 }
978 else // Special case: 0 refers to different initial render targets based on the attachment type
979 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000980 return mDepthStencilbufferZero;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000981 }
982
983 return NULL;
984}
985
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000986DepthStencilbuffer *Context::getStencilbuffer(GLuint handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000987{
988 if (handle != 0)
989 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000990 Renderbuffer *renderbuffer = mResourceManager->getRenderbuffer(handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000991
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000992 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000993 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000994 return static_cast<DepthStencilbuffer*>(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000995 }
996 }
997 else
998 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000999 return mDepthStencilbufferZero;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001000 }
1001
1002 return NULL;
1003}
1004
1005Buffer *Context::getArrayBuffer()
1006{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001007 return mResourceManager->getBuffer(mState.arrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001008}
1009
1010Buffer *Context::getElementArrayBuffer()
1011{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001012 return mResourceManager->getBuffer(mState.elementArrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001013}
1014
1015Program *Context::getCurrentProgram()
1016{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001017 return mResourceManager->getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001018}
1019
1020Texture2D *Context::getTexture2D()
1021{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001022 if (mState.texture2D == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001023 {
1024 return mTexture2DZero;
1025 }
1026
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001027 return (Texture2D*)mResourceManager->getTexture(mState.texture2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001028}
1029
1030TextureCubeMap *Context::getTextureCubeMap()
1031{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001032 if (mState.textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001033 {
1034 return mTextureCubeMapZero;
1035 }
1036
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001037 return (TextureCubeMap*)mResourceManager->getTexture(mState.textureCubeMap);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001038}
1039
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001040Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001041{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001042 GLuint texid = mState.samplerTexture[type][sampler];
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001043
1044 if (texid == 0)
1045 {
1046 switch (type)
1047 {
1048 default: UNREACHABLE();
1049 case SAMPLER_2D: return mTexture2DZero;
1050 case SAMPLER_CUBE: return mTextureCubeMapZero;
1051 }
1052 }
1053
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001054 return mResourceManager->getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001055}
1056
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001057bool Context::getBooleanv(GLenum pname, GLboolean *params)
1058{
1059 switch (pname)
1060 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001061 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1062 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1063 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001064 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001065 params[0] = mState.colorMaskRed;
1066 params[1] = mState.colorMaskGreen;
1067 params[2] = mState.colorMaskBlue;
1068 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001069 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001070 case GL_CULL_FACE: *params = mState.cullFace;
1071 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
1072 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
1073 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
1074 case GL_SCISSOR_TEST: *params = mState.scissorTest;
1075 case GL_STENCIL_TEST: *params = mState.stencilTest;
1076 case GL_DEPTH_TEST: *params = mState.depthTest;
1077 case GL_BLEND: *params = mState.blend;
1078 case GL_DITHER: *params = mState.dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001079 default:
1080 return false;
1081 }
1082
1083 return true;
1084}
1085
1086bool Context::getFloatv(GLenum pname, GLfloat *params)
1087{
1088 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1089 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1090 // GetIntegerv as its native query function. As it would require conversion in any
1091 // case, this should make no difference to the calling application.
1092 switch (pname)
1093 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001094 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1095 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1096 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1097 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1098 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001099 case GL_ALIASED_LINE_WIDTH_RANGE:
1100 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1101 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1102 break;
1103 case GL_ALIASED_POINT_SIZE_RANGE:
1104 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001105 params[1] = supportsShaderModel3() ? gl::ALIASED_POINT_SIZE_RANGE_MAX_SM3 : gl::ALIASED_POINT_SIZE_RANGE_MAX_SM2;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001106 break;
1107 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001108 params[0] = mState.zNear;
1109 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001110 break;
1111 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001112 params[0] = mState.colorClearValue.red;
1113 params[1] = mState.colorClearValue.green;
1114 params[2] = mState.colorClearValue.blue;
1115 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001116 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001117 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001118 params[0] = mState.blendColor.red;
1119 params[1] = mState.blendColor.green;
1120 params[2] = mState.blendColor.blue;
1121 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001122 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001123 default:
1124 return false;
1125 }
1126
1127 return true;
1128}
1129
1130bool Context::getIntegerv(GLenum pname, GLint *params)
1131{
1132 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv 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. You may find it in
1136 // Context::getFloatv.
1137 switch (pname)
1138 {
1139 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1140 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1141 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
1142 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1143 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1144 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1145 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
1146 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001147 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1148 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
1149 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
1150 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
1151 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer; break;
1152 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer; break;
1153 case GL_FRAMEBUFFER_BINDING: *params = mState.framebuffer; break;
1154 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer; break;
1155 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1156 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1157 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1158 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1159 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
1160 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1161 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1162 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1163 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1164 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1165 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1166 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1167 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1168 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1169 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1170 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1171 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1172 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1173 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1174 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1175 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1176 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1177 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1178 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1179 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1180 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1181 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
1182 case GL_SUBPIXEL_BITS: *params = 4; break;
1183 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
1184 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
1185 case GL_SAMPLE_BUFFERS: *params = 0; break;
1186 case GL_SAMPLES: *params = 0; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001187 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1188 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1189 case GL_MAX_VIEWPORT_DIMS:
1190 {
1191 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
1192 params[0] = maxDimension;
1193 params[1] = maxDimension;
1194 }
1195 break;
1196 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001197 params[0] = mState.viewportX;
1198 params[1] = mState.viewportY;
1199 params[2] = mState.viewportWidth;
1200 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001201 break;
1202 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001203 params[0] = mState.scissorX;
1204 params[1] = mState.scissorY;
1205 params[2] = mState.scissorWidth;
1206 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001207 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001208 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1209 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001210 case GL_RED_BITS:
1211 case GL_GREEN_BITS:
1212 case GL_BLUE_BITS:
1213 case GL_ALPHA_BITS:
1214 {
1215 gl::Framebuffer *framebuffer = getFramebuffer();
1216 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1217
1218 if (colorbuffer)
1219 {
1220 switch (pname)
1221 {
1222 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1223 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1224 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1225 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1226 }
1227 }
1228 else
1229 {
1230 *params = 0;
1231 }
1232 }
1233 break;
1234 case GL_DEPTH_BITS:
1235 {
1236 gl::Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001237 gl::DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001238
1239 if (depthbuffer)
1240 {
1241 *params = depthbuffer->getDepthSize();
1242 }
1243 else
1244 {
1245 *params = 0;
1246 }
1247 }
1248 break;
1249 case GL_STENCIL_BITS:
1250 {
1251 gl::Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001252 gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001253
1254 if (stencilbuffer)
1255 {
1256 *params = stencilbuffer->getStencilSize();
1257 }
1258 else
1259 {
1260 *params = 0;
1261 }
1262 }
1263 break;
1264 case GL_TEXTURE_BINDING_2D:
1265 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001266 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001267 {
1268 error(GL_INVALID_OPERATION);
1269 return false;
1270 }
1271
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001272 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001273 }
1274 break;
1275 case GL_TEXTURE_BINDING_CUBE_MAP:
1276 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001277 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001278 {
1279 error(GL_INVALID_OPERATION);
1280 return false;
1281 }
1282
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001283 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001284 }
1285 break;
1286 default:
1287 return false;
1288 }
1289
1290 return true;
1291}
1292
1293bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1294{
1295 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1296 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1297 // to the fact that it is stored internally as a float, and so would require conversion
1298 // if returned from Context::getIntegerv. Since this conversion is already implemented
1299 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1300 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1301 // application.
1302 switch (pname)
1303 {
1304 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1305 case GL_SHADER_BINARY_FORMATS:
1306 {
1307 *type = GL_INT;
1308 *numParams = 0;
1309 }
1310 break;
1311 case GL_MAX_VERTEX_ATTRIBS:
1312 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1313 case GL_MAX_VARYING_VECTORS:
1314 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1315 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1316 case GL_MAX_TEXTURE_IMAGE_UNITS:
1317 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1318 case GL_MAX_RENDERBUFFER_SIZE:
1319 case GL_NUM_SHADER_BINARY_FORMATS:
1320 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1321 case GL_ARRAY_BUFFER_BINDING:
1322 case GL_FRAMEBUFFER_BINDING:
1323 case GL_RENDERBUFFER_BINDING:
1324 case GL_CURRENT_PROGRAM:
1325 case GL_PACK_ALIGNMENT:
1326 case GL_UNPACK_ALIGNMENT:
1327 case GL_GENERATE_MIPMAP_HINT:
1328 case GL_RED_BITS:
1329 case GL_GREEN_BITS:
1330 case GL_BLUE_BITS:
1331 case GL_ALPHA_BITS:
1332 case GL_DEPTH_BITS:
1333 case GL_STENCIL_BITS:
1334 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1335 case GL_CULL_FACE_MODE:
1336 case GL_FRONT_FACE:
1337 case GL_ACTIVE_TEXTURE:
1338 case GL_STENCIL_FUNC:
1339 case GL_STENCIL_VALUE_MASK:
1340 case GL_STENCIL_REF:
1341 case GL_STENCIL_FAIL:
1342 case GL_STENCIL_PASS_DEPTH_FAIL:
1343 case GL_STENCIL_PASS_DEPTH_PASS:
1344 case GL_STENCIL_BACK_FUNC:
1345 case GL_STENCIL_BACK_VALUE_MASK:
1346 case GL_STENCIL_BACK_REF:
1347 case GL_STENCIL_BACK_FAIL:
1348 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1349 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1350 case GL_DEPTH_FUNC:
1351 case GL_BLEND_SRC_RGB:
1352 case GL_BLEND_SRC_ALPHA:
1353 case GL_BLEND_DST_RGB:
1354 case GL_BLEND_DST_ALPHA:
1355 case GL_BLEND_EQUATION_RGB:
1356 case GL_BLEND_EQUATION_ALPHA:
1357 case GL_STENCIL_WRITEMASK:
1358 case GL_STENCIL_BACK_WRITEMASK:
1359 case GL_STENCIL_CLEAR_VALUE:
1360 case GL_SUBPIXEL_BITS:
1361 case GL_MAX_TEXTURE_SIZE:
1362 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1363 case GL_SAMPLE_BUFFERS:
1364 case GL_SAMPLES:
1365 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1366 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1367 case GL_TEXTURE_BINDING_2D:
1368 case GL_TEXTURE_BINDING_CUBE_MAP:
1369 {
1370 *type = GL_INT;
1371 *numParams = 1;
1372 }
1373 break;
1374 case GL_MAX_VIEWPORT_DIMS:
1375 {
1376 *type = GL_INT;
1377 *numParams = 2;
1378 }
1379 break;
1380 case GL_VIEWPORT:
1381 case GL_SCISSOR_BOX:
1382 {
1383 *type = GL_INT;
1384 *numParams = 4;
1385 }
1386 break;
1387 case GL_SHADER_COMPILER:
1388 case GL_SAMPLE_COVERAGE_INVERT:
1389 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001390 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1391 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1392 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1393 case GL_SAMPLE_COVERAGE:
1394 case GL_SCISSOR_TEST:
1395 case GL_STENCIL_TEST:
1396 case GL_DEPTH_TEST:
1397 case GL_BLEND:
1398 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001399 {
1400 *type = GL_BOOL;
1401 *numParams = 1;
1402 }
1403 break;
1404 case GL_COLOR_WRITEMASK:
1405 {
1406 *type = GL_BOOL;
1407 *numParams = 4;
1408 }
1409 break;
1410 case GL_POLYGON_OFFSET_FACTOR:
1411 case GL_POLYGON_OFFSET_UNITS:
1412 case GL_SAMPLE_COVERAGE_VALUE:
1413 case GL_DEPTH_CLEAR_VALUE:
1414 case GL_LINE_WIDTH:
1415 {
1416 *type = GL_FLOAT;
1417 *numParams = 1;
1418 }
1419 break;
1420 case GL_ALIASED_LINE_WIDTH_RANGE:
1421 case GL_ALIASED_POINT_SIZE_RANGE:
1422 case GL_DEPTH_RANGE:
1423 {
1424 *type = GL_FLOAT;
1425 *numParams = 2;
1426 }
1427 break;
1428 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001429 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001430 {
1431 *type = GL_FLOAT;
1432 *numParams = 4;
1433 }
1434 break;
1435 default:
1436 return false;
1437 }
1438
1439 return true;
1440}
1441
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001442// Applies the render target surface, depth stencil surface, viewport rectangle and
1443// scissor rectangle to the Direct3D 9 device
1444bool Context::applyRenderTarget(bool ignoreViewport)
1445{
1446 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001447
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001448 Framebuffer *framebufferObject = getFramebuffer();
1449
1450 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1451 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001452 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1453
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001454 return false;
1455 }
1456
1457 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001458 IDirect3DSurface9 *depthStencil = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001459
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001460 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
1461 if (renderTargetSerial != mAppliedRenderTargetSerial)
1462 {
1463 device->SetRenderTarget(0, renderTarget);
1464 mAppliedRenderTargetSerial = renderTargetSerial;
1465 }
1466
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001467 unsigned int depthbufferSerial = 0;
1468 unsigned int stencilbufferSerial = 0;
1469 if (framebufferObject->getDepthbufferType() != GL_NONE)
1470 {
1471 depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil();
1472 depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial();
1473 }
1474 else if (framebufferObject->getStencilbufferType() != GL_NONE)
1475 {
1476 depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
1477 stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial();
1478 }
1479
1480 if (depthbufferSerial != mAppliedDepthbufferSerial ||
1481 stencilbufferSerial != mAppliedStencilbufferSerial)
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001482 {
1483 device->SetDepthStencilSurface(depthStencil);
1484 mAppliedDepthbufferSerial = depthbufferSerial;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001485 mAppliedStencilbufferSerial = stencilbufferSerial;
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001486 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001487
1488 D3DVIEWPORT9 viewport;
1489 D3DSURFACE_DESC desc;
1490 renderTarget->GetDesc(&desc);
1491
1492 if (ignoreViewport)
1493 {
1494 viewport.X = 0;
1495 viewport.Y = 0;
1496 viewport.Width = desc.Width;
1497 viewport.Height = desc.Height;
1498 viewport.MinZ = 0.0f;
1499 viewport.MaxZ = 1.0f;
1500 }
1501 else
1502 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001503 viewport.X = std::max(mState.viewportX, 0);
1504 viewport.Y = std::max(mState.viewportY, 0);
1505 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1506 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1507 viewport.MinZ = clamp01(mState.zNear);
1508 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001509 }
1510
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001511 if (viewport.Width <= 0 || viewport.Height <= 0)
1512 {
1513 return false; // Nothing to render
1514 }
1515
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001516 device->SetViewport(&viewport);
1517
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001518 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001519 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001520 if (mState.scissorTest)
1521 {
1522 RECT rect = {mState.scissorX,
1523 mState.scissorY,
1524 mState.scissorX + mState.scissorWidth,
1525 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001526
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001527 device->SetScissorRect(&rect);
1528 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1529 }
1530 else
1531 {
1532 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1533 }
1534
1535 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001536 }
1537
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001538 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001539 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001540 Program *programObject = getCurrentProgram();
1541
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001542 GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001543 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001544 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001545
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00001546 GLint window = programObject->getDxViewportLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001547 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1548 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1549 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001550 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1551
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001552 GLint depth = programObject->getDxDepthLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001553 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001554 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1555
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001556 GLint near = programObject->getDepthRangeNearLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001557 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001558
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001559 GLint far = programObject->getDepthRangeFarLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001560 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001561
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001562 GLint diff = programObject->getDepthRangeDiffLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001563 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001564 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001565 }
1566
1567 return true;
1568}
1569
1570// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001571void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001572{
1573 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001574 Program *programObject = getCurrentProgram();
1575
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001576 GLint frontCCW = programObject->getDxFrontCCWLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001577 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001578 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001579
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001580 GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001581 GLint alwaysFront = !isTriangleMode(drawMode);
1582 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1583
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001584 Framebuffer *framebufferObject = getFramebuffer();
1585
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001586 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001587 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001588 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001589 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001590 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001591 }
1592 else
1593 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001594 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001595 }
1596
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001597 mCullStateDirty = false;
1598 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001599
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001600 if (mDepthStateDirty)
1601 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001602 if (mState.depthTest && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001603 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001604 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1605 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001606 }
1607 else
1608 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001609 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001610 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001611
1612 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001613 }
1614
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001615 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001616 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001617 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001618 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001619 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1620
1621 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1622 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1623 {
1624 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1625 }
1626 else
1627 {
1628 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1629 unorm<8>(mState.blendColor.alpha),
1630 unorm<8>(mState.blendColor.alpha),
1631 unorm<8>(mState.blendColor.alpha)));
1632 }
1633
1634 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1635 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1636 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1637
1638 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1639 mState.destBlendRGB != mState.destBlendAlpha ||
1640 mState.blendEquationRGB != mState.blendEquationAlpha)
1641 {
1642 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1643
1644 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1645 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1646 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
1647
1648 }
1649 else
1650 {
1651 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1652 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001653 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001654 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001655 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001656 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001657 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001658
1659 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001660 }
1661
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001662 if (mStencilStateDirty || mFrontFaceDirty)
1663 {
1664 if (mState.stencilTest && hasStencil())
1665 {
1666 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1667 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1668
1669 // FIXME: Unsupported by D3D9
1670 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1671 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1672 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1673 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1674 mState.stencilRef != mState.stencilBackRef ||
1675 mState.stencilMask != mState.stencilBackMask)
1676 {
1677 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1678 return error(GL_INVALID_OPERATION);
1679 }
1680
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001681 // get the maximum size of the stencil ref
1682 gl::Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001683 gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001684 GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
1685
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001686 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1687 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1688 es2dx::ConvertComparison(mState.stencilFunc));
1689
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001690 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001691 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
1692
1693 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1694 es2dx::ConvertStencilOp(mState.stencilFail));
1695 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1696 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1697 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1698 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1699
1700 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1701 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1702 es2dx::ConvertComparison(mState.stencilBackFunc));
1703
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001704 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001705 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
1706
1707 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1708 es2dx::ConvertStencilOp(mState.stencilBackFail));
1709 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1710 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1711 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1712 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1713 }
1714 else
1715 {
1716 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1717 }
1718
1719 mStencilStateDirty = false;
1720 }
1721
1722 if (mMaskStateDirty)
1723 {
1724 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1725 mState.colorMaskBlue, mState.colorMaskAlpha));
1726 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1727
1728 mMaskStateDirty = false;
1729 }
1730
1731 if (mPolygonOffsetStateDirty)
1732 {
1733 if (mState.polygonOffsetFill)
1734 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001735 gl::DepthStencilbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001736 if (depthbuffer)
1737 {
1738 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1739 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1740 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1741 }
1742 }
1743 else
1744 {
1745 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1746 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1747 }
1748
1749 mPolygonOffsetStateDirty = false;
1750 }
1751
1752 if (mConfig->mMultiSample != 0 && mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001753 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001754 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001755 {
1756 FIXME("Sample alpha to coverage is unimplemented.");
1757 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001758
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001759 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001760 {
1761 FIXME("Sample coverage is unimplemented.");
1762 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001763
1764 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001765 }
1766
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001767 if (mDitherStateDirty)
1768 {
1769 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
1770
1771 mDitherStateDirty = false;
1772 }
1773
1774 mFrontFaceDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001775}
1776
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001777// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001778void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001779{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001780 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001781 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001782 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001783 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001784 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001785 }
1786 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001787}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001788
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001789GLenum Context::applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool *useIndexing, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001790{
1791 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1792
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001793 GLenum err = mVertexDataManager->preRenderValidate(first, count, translated);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001794 if (err != GL_NO_ERROR)
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001795 {
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001796 return err;
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001797 }
1798
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001799 lookupAttributeMapping(translated);
1800
1801 mBufferBackEnd->setupAttributesPreDraw(translated);
1802
1803 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
1804 {
1805 if (translated[i].enabled && translated[i].nonArray)
1806 {
1807 err = mIndexDataManager->preRenderValidateUnindexed(mode, count, indexInfo);
1808 if (err != GL_NO_ERROR)
1809 {
1810 return err;
1811 }
1812
1813 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
1814
1815 *useIndexing = true;
1816 return GL_NO_ERROR;
1817 }
1818 }
1819
1820 *useIndexing = false;
1821 return GL_NO_ERROR;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001822}
1823
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001824GLenum Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001825{
1826 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1827
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001828 GLenum err = mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001829
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001830 if (err == GL_NO_ERROR)
1831 {
1832 lookupAttributeMapping(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001833
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001834 mBufferBackEnd->setupAttributesPreDraw(translated);
1835 }
1836
1837 return err;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001838}
1839
1840// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001841GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001842{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001843 GLenum err = mIndexDataManager->preRenderValidate(mode, type, count, mResourceManager->getBuffer(mState.elementArrayBuffer), indices, indexInfo);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001844
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001845 if (err == GL_NO_ERROR)
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001846 {
1847 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
1848 }
1849
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001850 return err;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001851}
1852
1853// Applies the shaders and shader constants to the Direct3D 9 device
1854void Context::applyShaders()
1855{
1856 IDirect3DDevice9 *device = getDevice();
1857 Program *programObject = getCurrentProgram();
1858 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1859 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1860
1861 device->SetVertexShader(vertexShader);
1862 device->SetPixelShader(pixelShader);
1863
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001864 if (programObject->getSerial() != mAppliedProgram)
1865 {
1866 programObject->dirtyAllUniforms();
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001867 programObject->dirtyAllSamplers();
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001868 mAppliedProgram = programObject->getSerial();
1869 }
1870
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001871 programObject->applyUniforms();
1872}
1873
1874// Applies the textures and sampler states to the Direct3D 9 device
1875void Context::applyTextures()
1876{
1877 IDirect3DDevice9 *device = getDevice();
1878 Program *programObject = getCurrentProgram();
1879
1880 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1881 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001882 int textureUnit = programObject->getSamplerMapping(sampler);
1883 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001884 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001885 SamplerType textureType = programObject->getSamplerType(sampler);
1886
1887 Texture *texture = getSamplerTexture(textureUnit, textureType);
1888
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001889 if (programObject->isSamplerDirty(sampler) || texture->isDirty())
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001890 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001891 if (texture->isComplete())
1892 {
1893 GLenum wrapS = texture->getWrapS();
1894 GLenum wrapT = texture->getWrapT();
1895 GLenum minFilter = texture->getMinFilter();
1896 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001897
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001898 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1899 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001900
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001901 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1902 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1903 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1904 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1905 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001906
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001907 device->SetTexture(sampler, texture->getTexture());
1908 }
1909 else
1910 {
1911 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1912 }
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001913 }
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001914
1915 programObject->setSamplerDirty(sampler, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001916 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001917 else
1918 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001919 if (programObject->isSamplerDirty(sampler))
1920 {
1921 device->SetTexture(sampler, NULL);
1922 programObject->setSamplerDirty(sampler, false);
1923 }
1924 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001925 }
1926}
1927
1928void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1929{
1930 Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.combbc57792010-07-28 19:21:05 +00001931
1932 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1933 {
1934 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1935 }
1936
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001937 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1938 IDirect3DDevice9 *device = getDevice();
1939
1940 D3DSURFACE_DESC desc;
1941 renderTarget->GetDesc(&desc);
1942
1943 IDirect3DSurface9 *systemSurface;
1944 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1945
1946 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1947 {
1948 return error(GL_OUT_OF_MEMORY);
1949 }
1950
1951 ASSERT(SUCCEEDED(result));
1952
1953 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1954 {
1955 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1956 }
1957
1958 result = device->GetRenderTargetData(renderTarget, systemSurface);
1959
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001960 if (FAILED(result))
1961 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001962 systemSurface->Release();
1963
apatrick@chromium.org6db8cab2010-07-22 20:39:50 +00001964 switch (result)
1965 {
1966 case D3DERR_DRIVERINTERNALERROR:
1967 case D3DERR_DEVICELOST:
1968 return error(GL_OUT_OF_MEMORY);
1969 default:
1970 UNREACHABLE();
1971 return; // No sensible error to generate
1972 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001973 }
1974
1975 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001976 RECT rect = {std::max(x, 0),
1977 std::max(y, 0),
1978 std::min(x + width, (int)desc.Width),
1979 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001980
1981 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1982
1983 if (FAILED(result))
1984 {
1985 UNREACHABLE();
1986 systemSurface->Release();
1987
1988 return; // No sensible error to generate
1989 }
1990
1991 unsigned char *source = (unsigned char*)lock.pBits;
1992 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001993 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001994
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001995 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001996
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001997 for (int j = 0; j < rect.bottom - rect.top; j++)
1998 {
1999 for (int i = 0; i < rect.right - rect.left; i++)
2000 {
2001 float r;
2002 float g;
2003 float b;
2004 float a;
2005
2006 switch (desc.Format)
2007 {
2008 case D3DFMT_R5G6B5:
2009 {
2010 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2011
2012 a = 1.0f;
2013 b = (rgb & 0x001F) * (1.0f / 0x001F);
2014 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2015 r = (rgb & 0xF800) * (1.0f / 0xF800);
2016 }
2017 break;
2018 case D3DFMT_X1R5G5B5:
2019 {
2020 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2021
2022 a = 1.0f;
2023 b = (xrgb & 0x001F) * (1.0f / 0x001F);
2024 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
2025 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
2026 }
2027 break;
2028 case D3DFMT_A1R5G5B5:
2029 {
2030 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2031
2032 a = (argb & 0x8000) ? 1.0f : 0.0f;
2033 b = (argb & 0x001F) * (1.0f / 0x001F);
2034 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2035 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2036 }
2037 break;
2038 case D3DFMT_A8R8G8B8:
2039 {
2040 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2041
2042 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2043 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2044 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2045 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2046 }
2047 break;
2048 case D3DFMT_X8R8G8B8:
2049 {
2050 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2051
2052 a = 1.0f;
2053 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2054 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2055 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2056 }
2057 break;
2058 case D3DFMT_A2R10G10B10:
2059 {
2060 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2061
2062 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2063 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2064 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2065 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2066 }
2067 break;
2068 default:
2069 UNIMPLEMENTED(); // FIXME
2070 UNREACHABLE();
2071 }
2072
2073 switch (format)
2074 {
2075 case GL_RGBA:
2076 switch (type)
2077 {
2078 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002079 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2080 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2081 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2082 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002083 break;
2084 default: UNREACHABLE();
2085 }
2086 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002087 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002088 switch (type)
2089 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002090 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002091 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2092 ((unsigned short)(31 * b + 0.5f) << 0) |
2093 ((unsigned short)(63 * g + 0.5f) << 5) |
2094 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002095 break;
2096 default: UNREACHABLE();
2097 }
2098 break;
2099 default: UNREACHABLE();
2100 }
2101 }
2102 }
2103
2104 systemSurface->UnlockRect();
2105
2106 systemSurface->Release();
2107}
2108
2109void Context::clear(GLbitfield mask)
2110{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002111 Framebuffer *framebufferObject = getFramebuffer();
2112
2113 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2114 {
2115 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2116
2117 return;
2118 }
2119
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002120 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002121 IDirect3DDevice9 *device = getDevice();
2122 DWORD flags = 0;
2123
2124 if (mask & GL_COLOR_BUFFER_BIT)
2125 {
2126 mask &= ~GL_COLOR_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002127
2128 if (framebufferObject->getColorbufferType() != GL_NONE)
2129 {
2130 flags |= D3DCLEAR_TARGET;
2131 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002132 }
2133
2134 if (mask & GL_DEPTH_BUFFER_BIT)
2135 {
2136 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002137 if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002138 {
2139 flags |= D3DCLEAR_ZBUFFER;
2140 }
2141 }
2142
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002143 GLuint stencilUnmasked = 0x0;
2144
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002145 if (mask & GL_STENCIL_BUFFER_BIT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002146 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002147 mask &= ~GL_STENCIL_BUFFER_BIT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002148 if (framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002149 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002150 IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
2151 D3DSURFACE_DESC desc;
2152 depthStencil->GetDesc(&desc);
2153
2154 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2155 stencilUnmasked = (0x1 << stencilSize) - 1;
2156
2157 if (stencilUnmasked != 0x0)
2158 {
2159 flags |= D3DCLEAR_STENCIL;
2160 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002161 }
2162 }
2163
2164 if (mask != 0)
2165 {
2166 return error(GL_INVALID_VALUE);
2167 }
2168
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002169 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2170 {
2171 return;
2172 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002173
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002174 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2175 unorm<8>(mState.colorClearValue.red),
2176 unorm<8>(mState.colorClearValue.green),
2177 unorm<8>(mState.colorClearValue.blue));
2178 float depth = clamp01(mState.depthClearValue);
2179 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002180
2181 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2182
2183 D3DSURFACE_DESC desc;
2184 renderTarget->GetDesc(&desc);
2185
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002186 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002187
2188 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002189 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002190 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002191 !(mState.colorMaskRed && mState.colorMaskGreen &&
2192 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002193
2194 if (needMaskedColorClear || needMaskedStencilClear)
2195 {
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002196 // State which is altered in all paths from this point to the clear call is saved.
2197 // State which is altered in only some paths will be flagged dirty in the case that
2198 // that path is taken.
2199 HRESULT hr;
2200 if (mMaskedClearSavedState == NULL)
2201 {
2202 hr = device->BeginStateBlock();
2203 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2204
2205 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2206 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2207 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2208 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2209 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2210 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2211 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2212 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2213 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2214 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2215 device->SetPixelShader(NULL);
2216 device->SetVertexShader(NULL);
2217 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2218 device->SetStreamSourceFreq(0, 1);
2219
2220 hr = device->EndStateBlock(&mMaskedClearSavedState);
2221 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2222 }
2223
2224 ASSERT(mMaskedClearSavedState != NULL);
2225
2226 if (mMaskedClearSavedState != NULL)
2227 {
2228 hr = mMaskedClearSavedState->Capture();
2229 ASSERT(SUCCEEDED(hr));
2230 }
2231
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002232 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2233 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2234 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2235 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2236 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2237 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2238 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2239 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2240
2241 if (flags & D3DCLEAR_TARGET)
2242 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002243 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2244 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2245 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2246 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002247 }
2248 else
2249 {
2250 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2251 }
2252
2253 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2254 {
2255 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2256 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2257 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2258 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002259 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002260 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002261 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2262 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002263 mStencilStateDirty = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002264 }
2265 else
2266 {
2267 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2268 }
2269
2270 device->SetPixelShader(NULL);
2271 device->SetVertexShader(NULL);
2272 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002273 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002274
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002275 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002276 {
2277 float x, y, z, w;
2278 D3DCOLOR diffuse;
2279 };
2280
2281 Vertex quad[4];
2282 quad[0].x = 0.0f;
2283 quad[0].y = (float)desc.Height;
2284 quad[0].z = 0.0f;
2285 quad[0].w = 1.0f;
2286 quad[0].diffuse = color;
2287
2288 quad[1].x = (float)desc.Width;
2289 quad[1].y = (float)desc.Height;
2290 quad[1].z = 0.0f;
2291 quad[1].w = 1.0f;
2292 quad[1].diffuse = color;
2293
2294 quad[2].x = 0.0f;
2295 quad[2].y = 0.0f;
2296 quad[2].z = 0.0f;
2297 quad[2].w = 1.0f;
2298 quad[2].diffuse = color;
2299
2300 quad[3].x = (float)desc.Width;
2301 quad[3].y = 0.0f;
2302 quad[3].z = 0.0f;
2303 quad[3].w = 1.0f;
2304 quad[3].diffuse = color;
2305
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002306 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002307 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002308
2309 if (flags & D3DCLEAR_ZBUFFER)
2310 {
2311 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2312 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2313 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2314 }
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002315
2316 if (mMaskedClearSavedState != NULL)
2317 {
2318 mMaskedClearSavedState->Apply();
2319 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002320 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002321 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002322 {
2323 device->Clear(0, NULL, flags, color, depth, stencil);
2324 }
2325}
2326
2327void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2328{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002329 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002330 {
2331 return error(GL_INVALID_OPERATION);
2332 }
2333
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002334 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002335 IDirect3DDevice9 *device = getDevice();
2336 D3DPRIMITIVETYPE primitiveType;
2337 int primitiveCount;
2338
2339 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2340 return error(GL_INVALID_ENUM);
2341
2342 if (primitiveCount <= 0)
2343 {
2344 return;
2345 }
2346
2347 if (!applyRenderTarget(false))
2348 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002349 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002350 }
2351
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002352 applyState(mode);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002353
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002354 TranslatedIndexData indexInfo;
2355 bool useIndexing;
2356 GLenum err = applyVertexBuffer(mode, first, count, &useIndexing, &indexInfo);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002357 if (err != GL_NO_ERROR)
2358 {
2359 return error(err);
2360 }
2361
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002362 applyShaders();
2363 applyTextures();
2364
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002365 if (!getCurrentProgram()->validateSamplers())
2366 {
2367 return error(GL_INVALID_OPERATION);
2368 }
2369
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002370 if (!cullSkipsDraw(mode))
2371 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002372 display->startScene();
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002373 if (useIndexing)
2374 {
2375 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
2376 }
2377 else
2378 {
2379 device->DrawPrimitive(primitiveType, 0, primitiveCount);
2380 }
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002381 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002382}
2383
2384void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2385{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002386 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002387 {
2388 return error(GL_INVALID_OPERATION);
2389 }
2390
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002391 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002392 {
2393 return error(GL_INVALID_OPERATION);
2394 }
2395
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002396 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002397 IDirect3DDevice9 *device = getDevice();
2398 D3DPRIMITIVETYPE primitiveType;
2399 int primitiveCount;
2400
2401 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2402 return error(GL_INVALID_ENUM);
2403
2404 if (primitiveCount <= 0)
2405 {
2406 return;
2407 }
2408
2409 if (!applyRenderTarget(false))
2410 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002411 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002412 }
2413
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002414 applyState(mode);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002415
2416 TranslatedIndexData indexInfo;
2417 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2418 if (err != GL_NO_ERROR)
2419 {
2420 return error(err);
2421 }
2422
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002423 err = applyVertexBuffer(indexInfo);
2424 if (err != GL_NO_ERROR)
2425 {
2426 return error(err);
2427 }
2428
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002429 applyShaders();
2430 applyTextures();
2431
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002432 if (!getCurrentProgram()->validateSamplers())
2433 {
2434 return error(GL_INVALID_OPERATION);
2435 }
2436
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002437 if (!cullSkipsDraw(mode))
2438 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002439 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002440 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002441 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002442}
2443
2444void Context::finish()
2445{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002446 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002447 IDirect3DDevice9 *device = getDevice();
2448 IDirect3DQuery9 *occlusionQuery = NULL;
2449
2450 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2451
2452 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2453 {
2454 return error(GL_OUT_OF_MEMORY);
2455 }
2456
2457 ASSERT(SUCCEEDED(result));
2458
2459 if (occlusionQuery)
2460 {
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002461 IDirect3DStateBlock9 *savedState = NULL;
2462 device->CreateStateBlock(D3DSBT_ALL, &savedState);
2463
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002464 occlusionQuery->Issue(D3DISSUE_BEGIN);
2465
2466 // Render something outside the render target
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002467 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002468 device->SetPixelShader(NULL);
2469 device->SetVertexShader(NULL);
2470 device->SetFVF(D3DFVF_XYZRHW);
2471 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002472 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002473 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002474
2475 occlusionQuery->Issue(D3DISSUE_END);
2476
2477 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2478 {
2479 // Keep polling, but allow other threads to do something useful first
2480 Sleep(0);
2481 }
2482
2483 occlusionQuery->Release();
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002484
2485 if (savedState)
2486 {
2487 savedState->Apply();
2488 savedState->Release();
2489 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002490 }
2491}
2492
2493void Context::flush()
2494{
2495 IDirect3DDevice9 *device = getDevice();
2496 IDirect3DQuery9 *eventQuery = NULL;
2497
2498 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2499
2500 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2501 {
2502 return error(GL_OUT_OF_MEMORY);
2503 }
2504
2505 ASSERT(SUCCEEDED(result));
2506
2507 if (eventQuery)
2508 {
2509 eventQuery->Issue(D3DISSUE_END);
2510
2511 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2512 {
2513 // Keep polling, but allow other threads to do something useful first
2514 Sleep(0);
2515 }
2516
2517 eventQuery->Release();
2518 }
2519}
2520
2521void Context::recordInvalidEnum()
2522{
2523 mInvalidEnum = true;
2524}
2525
2526void Context::recordInvalidValue()
2527{
2528 mInvalidValue = true;
2529}
2530
2531void Context::recordInvalidOperation()
2532{
2533 mInvalidOperation = true;
2534}
2535
2536void Context::recordOutOfMemory()
2537{
2538 mOutOfMemory = true;
2539}
2540
2541void Context::recordInvalidFramebufferOperation()
2542{
2543 mInvalidFramebufferOperation = true;
2544}
2545
2546// Get one of the recorded errors and clear its flag, if any.
2547// [OpenGL ES 2.0.24] section 2.5 page 13.
2548GLenum Context::getError()
2549{
2550 if (mInvalidEnum)
2551 {
2552 mInvalidEnum = false;
2553
2554 return GL_INVALID_ENUM;
2555 }
2556
2557 if (mInvalidValue)
2558 {
2559 mInvalidValue = false;
2560
2561 return GL_INVALID_VALUE;
2562 }
2563
2564 if (mInvalidOperation)
2565 {
2566 mInvalidOperation = false;
2567
2568 return GL_INVALID_OPERATION;
2569 }
2570
2571 if (mOutOfMemory)
2572 {
2573 mOutOfMemory = false;
2574
2575 return GL_OUT_OF_MEMORY;
2576 }
2577
2578 if (mInvalidFramebufferOperation)
2579 {
2580 mInvalidFramebufferOperation = false;
2581
2582 return GL_INVALID_FRAMEBUFFER_OPERATION;
2583 }
2584
2585 return GL_NO_ERROR;
2586}
2587
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002588bool Context::supportsShaderModel3() const
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002589{
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002590 return mSupportsShaderModel3;
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002591}
2592
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002593void Context::detachBuffer(GLuint buffer)
2594{
2595 // [OpenGL ES 2.0.24] section 2.9 page 22:
2596 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2597 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2598
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002599 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002600 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002601 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002602 }
2603
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002604 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002605 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002606 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002607 }
2608
2609 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2610 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002611 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002612 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002613 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002614 }
2615 }
2616}
2617
2618void Context::detachTexture(GLuint texture)
2619{
2620 // [OpenGL ES 2.0.24] section 3.8 page 84:
2621 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2622 // rebound to texture object zero
2623
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002624 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002625 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002626 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002627 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002628 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002629 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002630 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002631 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002632 }
2633 }
2634
2635 // [OpenGL ES 2.0.24] section 4.4 page 112:
2636 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2637 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2638 // image was attached in the currently bound framebuffer.
2639
2640 Framebuffer *framebuffer = getFramebuffer();
2641
2642 if (framebuffer)
2643 {
2644 framebuffer->detachTexture(texture);
2645 }
2646}
2647
2648void Context::detachFramebuffer(GLuint framebuffer)
2649{
2650 // [OpenGL ES 2.0.24] section 4.4 page 107:
2651 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2652 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2653
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002654 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002655 {
2656 bindFramebuffer(0);
2657 }
2658}
2659
2660void Context::detachRenderbuffer(GLuint renderbuffer)
2661{
2662 // [OpenGL ES 2.0.24] section 4.4 page 109:
2663 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2664 // had been executed with the target RENDERBUFFER and name of zero.
2665
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002666 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002667 {
2668 bindRenderbuffer(0);
2669 }
2670
2671 // [OpenGL ES 2.0.24] section 4.4 page 111:
2672 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2673 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2674 // point to which this image was attached in the currently bound framebuffer.
2675
2676 Framebuffer *framebuffer = getFramebuffer();
2677
2678 if (framebuffer)
2679 {
2680 framebuffer->detachRenderbuffer(renderbuffer);
2681 }
2682}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002683
2684Texture *Context::getIncompleteTexture(SamplerType type)
2685{
2686 Texture *t = mIncompleteTextures[type];
2687
2688 if (t == NULL)
2689 {
2690 static const GLubyte color[] = { 0, 0, 0, 255 };
2691
2692 switch (type)
2693 {
2694 default:
2695 UNREACHABLE();
2696 // default falls through to SAMPLER_2D
2697
2698 case SAMPLER_2D:
2699 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002700 Texture2D *incomplete2d = new Texture2D();
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002701 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002702 t = incomplete2d;
2703 }
2704 break;
2705
2706 case SAMPLER_CUBE:
2707 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002708 TextureCubeMap *incompleteCube = new TextureCubeMap();
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002709
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002710 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2711 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2712 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2713 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2714 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2715 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002716
2717 t = incompleteCube;
2718 }
2719 break;
2720 }
2721
2722 mIncompleteTextures[type] = t;
2723 }
2724
2725 return t;
2726}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002727
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002728bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002729{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002730 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002731}
2732
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002733bool Context::isTriangleMode(GLenum drawMode)
2734{
2735 switch (drawMode)
2736 {
2737 case GL_TRIANGLES:
2738 case GL_TRIANGLE_FAN:
2739 case GL_TRIANGLE_STRIP:
2740 return true;
2741 case GL_POINTS:
2742 case GL_LINES:
2743 case GL_LINE_LOOP:
2744 case GL_LINE_STRIP:
2745 return false;
2746 default: UNREACHABLE();
2747 }
2748
2749 return false;
2750}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002751
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002752bool Context::hasStencil()
2753{
2754 Framebuffer *framebufferObject = getFramebuffer();
2755
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002756 if (framebufferObject && framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002757 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002758 DepthStencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002759
2760 if (stencilbufferObject)
2761 {
2762 return stencilbufferObject->getStencilSize() > 0;
2763 }
2764 }
2765
2766 return false;
2767}
2768
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002769void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2770{
2771 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2772
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002773 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2774 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2775 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2776 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002777
2778 mVertexDataManager->dirtyCurrentValues();
2779}
2780
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002781void Context::initExtensionString()
2782{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002783 mExtensionString += "GL_OES_packed_depth_stencil ";
2784
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002785 if (mBufferBackEnd->supportIntIndices())
2786 {
2787 mExtensionString += "GL_OES_element_index_uint ";
2788 }
2789
2790 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2791 if (end != std::string::npos)
2792 {
2793 mExtensionString.resize(end+1);
2794 }
2795}
2796
2797const char *Context::getExtensionString() const
2798{
2799 return mExtensionString.c_str();
2800}
2801
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002802}
2803
2804extern "C"
2805{
2806gl::Context *glCreateContext(const egl::Config *config)
2807{
2808 return new gl::Context(config);
2809}
2810
2811void glDestroyContext(gl::Context *context)
2812{
2813 delete context;
2814
2815 if (context == gl::getContext())
2816 {
2817 gl::makeCurrent(NULL, NULL, NULL);
2818 }
2819}
2820
2821void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2822{
2823 gl::makeCurrent(context, display, surface);
2824}
2825
2826gl::Context *glGetCurrentContext()
2827{
2828 return gl::getContext();
2829}
2830}