blob: 4334d833b9b0647cf1717734263c18c60311524d [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
239 Framebuffer *framebufferZero = new Framebuffer();
240 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 {
877 mFramebufferMap[framebuffer] = new Framebuffer();
878 }
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();
1931 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1932 IDirect3DDevice9 *device = getDevice();
1933
1934 D3DSURFACE_DESC desc;
1935 renderTarget->GetDesc(&desc);
1936
1937 IDirect3DSurface9 *systemSurface;
1938 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1939
1940 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1941 {
1942 return error(GL_OUT_OF_MEMORY);
1943 }
1944
1945 ASSERT(SUCCEEDED(result));
1946
1947 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1948 {
1949 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1950 }
1951
1952 result = device->GetRenderTargetData(renderTarget, systemSurface);
1953
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001954 if (FAILED(result))
1955 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001956 systemSurface->Release();
1957
apatrick@chromium.org6db8cab2010-07-22 20:39:50 +00001958 switch (result)
1959 {
1960 case D3DERR_DRIVERINTERNALERROR:
1961 case D3DERR_DEVICELOST:
1962 return error(GL_OUT_OF_MEMORY);
1963 default:
1964 UNREACHABLE();
1965 return; // No sensible error to generate
1966 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001967 }
1968
1969 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001970 RECT rect = {std::max(x, 0),
1971 std::max(y, 0),
1972 std::min(x + width, (int)desc.Width),
1973 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001974
1975 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1976
1977 if (FAILED(result))
1978 {
1979 UNREACHABLE();
1980 systemSurface->Release();
1981
1982 return; // No sensible error to generate
1983 }
1984
1985 unsigned char *source = (unsigned char*)lock.pBits;
1986 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001987 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001988
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001989 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001990
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001991 for (int j = 0; j < rect.bottom - rect.top; j++)
1992 {
1993 for (int i = 0; i < rect.right - rect.left; i++)
1994 {
1995 float r;
1996 float g;
1997 float b;
1998 float a;
1999
2000 switch (desc.Format)
2001 {
2002 case D3DFMT_R5G6B5:
2003 {
2004 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2005
2006 a = 1.0f;
2007 b = (rgb & 0x001F) * (1.0f / 0x001F);
2008 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2009 r = (rgb & 0xF800) * (1.0f / 0xF800);
2010 }
2011 break;
2012 case D3DFMT_X1R5G5B5:
2013 {
2014 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2015
2016 a = 1.0f;
2017 b = (xrgb & 0x001F) * (1.0f / 0x001F);
2018 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
2019 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
2020 }
2021 break;
2022 case D3DFMT_A1R5G5B5:
2023 {
2024 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2025
2026 a = (argb & 0x8000) ? 1.0f : 0.0f;
2027 b = (argb & 0x001F) * (1.0f / 0x001F);
2028 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2029 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2030 }
2031 break;
2032 case D3DFMT_A8R8G8B8:
2033 {
2034 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2035
2036 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2037 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2038 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2039 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2040 }
2041 break;
2042 case D3DFMT_X8R8G8B8:
2043 {
2044 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2045
2046 a = 1.0f;
2047 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2048 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2049 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2050 }
2051 break;
2052 case D3DFMT_A2R10G10B10:
2053 {
2054 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2055
2056 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2057 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2058 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2059 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2060 }
2061 break;
2062 default:
2063 UNIMPLEMENTED(); // FIXME
2064 UNREACHABLE();
2065 }
2066
2067 switch (format)
2068 {
2069 case GL_RGBA:
2070 switch (type)
2071 {
2072 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002073 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2074 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2075 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2076 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002077 break;
2078 default: UNREACHABLE();
2079 }
2080 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002081 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002082 switch (type)
2083 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002084 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002085 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2086 ((unsigned short)(31 * b + 0.5f) << 0) |
2087 ((unsigned short)(63 * g + 0.5f) << 5) |
2088 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002089 break;
2090 default: UNREACHABLE();
2091 }
2092 break;
2093 default: UNREACHABLE();
2094 }
2095 }
2096 }
2097
2098 systemSurface->UnlockRect();
2099
2100 systemSurface->Release();
2101}
2102
2103void Context::clear(GLbitfield mask)
2104{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002105 Framebuffer *framebufferObject = getFramebuffer();
2106
2107 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2108 {
2109 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2110
2111 return;
2112 }
2113
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002114 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002115 IDirect3DDevice9 *device = getDevice();
2116 DWORD flags = 0;
2117
2118 if (mask & GL_COLOR_BUFFER_BIT)
2119 {
2120 mask &= ~GL_COLOR_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002121
2122 if (framebufferObject->getColorbufferType() != GL_NONE)
2123 {
2124 flags |= D3DCLEAR_TARGET;
2125 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002126 }
2127
2128 if (mask & GL_DEPTH_BUFFER_BIT)
2129 {
2130 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002131 if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002132 {
2133 flags |= D3DCLEAR_ZBUFFER;
2134 }
2135 }
2136
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002137 GLuint stencilUnmasked = 0x0;
2138
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002139 if (mask & GL_STENCIL_BUFFER_BIT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002140 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002141 mask &= ~GL_STENCIL_BUFFER_BIT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002142 if (framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002143 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002144 IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
2145 D3DSURFACE_DESC desc;
2146 depthStencil->GetDesc(&desc);
2147
2148 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2149 stencilUnmasked = (0x1 << stencilSize) - 1;
2150
2151 if (stencilUnmasked != 0x0)
2152 {
2153 flags |= D3DCLEAR_STENCIL;
2154 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002155 }
2156 }
2157
2158 if (mask != 0)
2159 {
2160 return error(GL_INVALID_VALUE);
2161 }
2162
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002163 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2164 {
2165 return;
2166 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002167
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002168 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2169 unorm<8>(mState.colorClearValue.red),
2170 unorm<8>(mState.colorClearValue.green),
2171 unorm<8>(mState.colorClearValue.blue));
2172 float depth = clamp01(mState.depthClearValue);
2173 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002174
2175 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2176
2177 D3DSURFACE_DESC desc;
2178 renderTarget->GetDesc(&desc);
2179
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002180 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002181
2182 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002183 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002184 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002185 !(mState.colorMaskRed && mState.colorMaskGreen &&
2186 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002187
2188 if (needMaskedColorClear || needMaskedStencilClear)
2189 {
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002190 // State which is altered in all paths from this point to the clear call is saved.
2191 // State which is altered in only some paths will be flagged dirty in the case that
2192 // that path is taken.
2193 HRESULT hr;
2194 if (mMaskedClearSavedState == NULL)
2195 {
2196 hr = device->BeginStateBlock();
2197 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2198
2199 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2200 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2201 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2202 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2203 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2204 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2205 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2206 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2207 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2208 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2209 device->SetPixelShader(NULL);
2210 device->SetVertexShader(NULL);
2211 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2212 device->SetStreamSourceFreq(0, 1);
2213
2214 hr = device->EndStateBlock(&mMaskedClearSavedState);
2215 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2216 }
2217
2218 ASSERT(mMaskedClearSavedState != NULL);
2219
2220 if (mMaskedClearSavedState != NULL)
2221 {
2222 hr = mMaskedClearSavedState->Capture();
2223 ASSERT(SUCCEEDED(hr));
2224 }
2225
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002226 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2227 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2228 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2229 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2230 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2231 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2232 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2233 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2234
2235 if (flags & D3DCLEAR_TARGET)
2236 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002237 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2238 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2239 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2240 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002241 }
2242 else
2243 {
2244 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2245 }
2246
2247 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2248 {
2249 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2250 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2251 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2252 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002253 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002254 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002255 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2256 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002257 mStencilStateDirty = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002258 }
2259 else
2260 {
2261 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2262 }
2263
2264 device->SetPixelShader(NULL);
2265 device->SetVertexShader(NULL);
2266 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002267 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002268
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002269 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002270 {
2271 float x, y, z, w;
2272 D3DCOLOR diffuse;
2273 };
2274
2275 Vertex quad[4];
2276 quad[0].x = 0.0f;
2277 quad[0].y = (float)desc.Height;
2278 quad[0].z = 0.0f;
2279 quad[0].w = 1.0f;
2280 quad[0].diffuse = color;
2281
2282 quad[1].x = (float)desc.Width;
2283 quad[1].y = (float)desc.Height;
2284 quad[1].z = 0.0f;
2285 quad[1].w = 1.0f;
2286 quad[1].diffuse = color;
2287
2288 quad[2].x = 0.0f;
2289 quad[2].y = 0.0f;
2290 quad[2].z = 0.0f;
2291 quad[2].w = 1.0f;
2292 quad[2].diffuse = color;
2293
2294 quad[3].x = (float)desc.Width;
2295 quad[3].y = 0.0f;
2296 quad[3].z = 0.0f;
2297 quad[3].w = 1.0f;
2298 quad[3].diffuse = color;
2299
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002300 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002301 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002302
2303 if (flags & D3DCLEAR_ZBUFFER)
2304 {
2305 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2306 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2307 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2308 }
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002309
2310 if (mMaskedClearSavedState != NULL)
2311 {
2312 mMaskedClearSavedState->Apply();
2313 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002314 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002315 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002316 {
2317 device->Clear(0, NULL, flags, color, depth, stencil);
2318 }
2319}
2320
2321void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2322{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002323 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002324 {
2325 return error(GL_INVALID_OPERATION);
2326 }
2327
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002328 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002329 IDirect3DDevice9 *device = getDevice();
2330 D3DPRIMITIVETYPE primitiveType;
2331 int primitiveCount;
2332
2333 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2334 return error(GL_INVALID_ENUM);
2335
2336 if (primitiveCount <= 0)
2337 {
2338 return;
2339 }
2340
2341 if (!applyRenderTarget(false))
2342 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002343 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002344 }
2345
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002346 applyState(mode);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002347
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002348 TranslatedIndexData indexInfo;
2349 bool useIndexing;
2350 GLenum err = applyVertexBuffer(mode, first, count, &useIndexing, &indexInfo);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002351 if (err != GL_NO_ERROR)
2352 {
2353 return error(err);
2354 }
2355
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002356 applyShaders();
2357 applyTextures();
2358
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002359 if (!getCurrentProgram()->validateSamplers())
2360 {
2361 return error(GL_INVALID_OPERATION);
2362 }
2363
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002364 if (!cullSkipsDraw(mode))
2365 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002366 display->startScene();
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002367 if (useIndexing)
2368 {
2369 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
2370 }
2371 else
2372 {
2373 device->DrawPrimitive(primitiveType, 0, primitiveCount);
2374 }
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002375 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002376}
2377
2378void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2379{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002380 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002381 {
2382 return error(GL_INVALID_OPERATION);
2383 }
2384
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002385 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002386 {
2387 return error(GL_INVALID_OPERATION);
2388 }
2389
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002390 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002391 IDirect3DDevice9 *device = getDevice();
2392 D3DPRIMITIVETYPE primitiveType;
2393 int primitiveCount;
2394
2395 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2396 return error(GL_INVALID_ENUM);
2397
2398 if (primitiveCount <= 0)
2399 {
2400 return;
2401 }
2402
2403 if (!applyRenderTarget(false))
2404 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002405 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002406 }
2407
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002408 applyState(mode);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002409
2410 TranslatedIndexData indexInfo;
2411 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2412 if (err != GL_NO_ERROR)
2413 {
2414 return error(err);
2415 }
2416
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002417 err = applyVertexBuffer(indexInfo);
2418 if (err != GL_NO_ERROR)
2419 {
2420 return error(err);
2421 }
2422
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002423 applyShaders();
2424 applyTextures();
2425
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002426 if (!getCurrentProgram()->validateSamplers())
2427 {
2428 return error(GL_INVALID_OPERATION);
2429 }
2430
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002431 if (!cullSkipsDraw(mode))
2432 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002433 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002434 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 +00002435 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002436}
2437
2438void Context::finish()
2439{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002440 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002441 IDirect3DDevice9 *device = getDevice();
2442 IDirect3DQuery9 *occlusionQuery = NULL;
2443
2444 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2445
2446 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2447 {
2448 return error(GL_OUT_OF_MEMORY);
2449 }
2450
2451 ASSERT(SUCCEEDED(result));
2452
2453 if (occlusionQuery)
2454 {
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002455 IDirect3DStateBlock9 *savedState = NULL;
2456 device->CreateStateBlock(D3DSBT_ALL, &savedState);
2457
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002458 occlusionQuery->Issue(D3DISSUE_BEGIN);
2459
2460 // Render something outside the render target
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002461 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002462 device->SetPixelShader(NULL);
2463 device->SetVertexShader(NULL);
2464 device->SetFVF(D3DFVF_XYZRHW);
2465 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002466 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002467 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002468
2469 occlusionQuery->Issue(D3DISSUE_END);
2470
2471 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2472 {
2473 // Keep polling, but allow other threads to do something useful first
2474 Sleep(0);
2475 }
2476
2477 occlusionQuery->Release();
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002478
2479 if (savedState)
2480 {
2481 savedState->Apply();
2482 savedState->Release();
2483 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002484 }
2485}
2486
2487void Context::flush()
2488{
2489 IDirect3DDevice9 *device = getDevice();
2490 IDirect3DQuery9 *eventQuery = NULL;
2491
2492 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2493
2494 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2495 {
2496 return error(GL_OUT_OF_MEMORY);
2497 }
2498
2499 ASSERT(SUCCEEDED(result));
2500
2501 if (eventQuery)
2502 {
2503 eventQuery->Issue(D3DISSUE_END);
2504
2505 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2506 {
2507 // Keep polling, but allow other threads to do something useful first
2508 Sleep(0);
2509 }
2510
2511 eventQuery->Release();
2512 }
2513}
2514
2515void Context::recordInvalidEnum()
2516{
2517 mInvalidEnum = true;
2518}
2519
2520void Context::recordInvalidValue()
2521{
2522 mInvalidValue = true;
2523}
2524
2525void Context::recordInvalidOperation()
2526{
2527 mInvalidOperation = true;
2528}
2529
2530void Context::recordOutOfMemory()
2531{
2532 mOutOfMemory = true;
2533}
2534
2535void Context::recordInvalidFramebufferOperation()
2536{
2537 mInvalidFramebufferOperation = true;
2538}
2539
2540// Get one of the recorded errors and clear its flag, if any.
2541// [OpenGL ES 2.0.24] section 2.5 page 13.
2542GLenum Context::getError()
2543{
2544 if (mInvalidEnum)
2545 {
2546 mInvalidEnum = false;
2547
2548 return GL_INVALID_ENUM;
2549 }
2550
2551 if (mInvalidValue)
2552 {
2553 mInvalidValue = false;
2554
2555 return GL_INVALID_VALUE;
2556 }
2557
2558 if (mInvalidOperation)
2559 {
2560 mInvalidOperation = false;
2561
2562 return GL_INVALID_OPERATION;
2563 }
2564
2565 if (mOutOfMemory)
2566 {
2567 mOutOfMemory = false;
2568
2569 return GL_OUT_OF_MEMORY;
2570 }
2571
2572 if (mInvalidFramebufferOperation)
2573 {
2574 mInvalidFramebufferOperation = false;
2575
2576 return GL_INVALID_FRAMEBUFFER_OPERATION;
2577 }
2578
2579 return GL_NO_ERROR;
2580}
2581
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002582bool Context::supportsShaderModel3() const
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002583{
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002584 return mSupportsShaderModel3;
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002585}
2586
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002587void Context::detachBuffer(GLuint buffer)
2588{
2589 // [OpenGL ES 2.0.24] section 2.9 page 22:
2590 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2591 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2592
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002593 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002594 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002595 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002596 }
2597
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002598 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002599 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002600 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002601 }
2602
2603 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2604 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002605 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002606 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002607 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002608 }
2609 }
2610}
2611
2612void Context::detachTexture(GLuint texture)
2613{
2614 // [OpenGL ES 2.0.24] section 3.8 page 84:
2615 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2616 // rebound to texture object zero
2617
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002618 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002619 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002620 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002621 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002622 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002623 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002624 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002625 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002626 }
2627 }
2628
2629 // [OpenGL ES 2.0.24] section 4.4 page 112:
2630 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2631 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2632 // image was attached in the currently bound framebuffer.
2633
2634 Framebuffer *framebuffer = getFramebuffer();
2635
2636 if (framebuffer)
2637 {
2638 framebuffer->detachTexture(texture);
2639 }
2640}
2641
2642void Context::detachFramebuffer(GLuint framebuffer)
2643{
2644 // [OpenGL ES 2.0.24] section 4.4 page 107:
2645 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2646 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2647
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002648 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002649 {
2650 bindFramebuffer(0);
2651 }
2652}
2653
2654void Context::detachRenderbuffer(GLuint renderbuffer)
2655{
2656 // [OpenGL ES 2.0.24] section 4.4 page 109:
2657 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2658 // had been executed with the target RENDERBUFFER and name of zero.
2659
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002660 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002661 {
2662 bindRenderbuffer(0);
2663 }
2664
2665 // [OpenGL ES 2.0.24] section 4.4 page 111:
2666 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2667 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2668 // point to which this image was attached in the currently bound framebuffer.
2669
2670 Framebuffer *framebuffer = getFramebuffer();
2671
2672 if (framebuffer)
2673 {
2674 framebuffer->detachRenderbuffer(renderbuffer);
2675 }
2676}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002677
2678Texture *Context::getIncompleteTexture(SamplerType type)
2679{
2680 Texture *t = mIncompleteTextures[type];
2681
2682 if (t == NULL)
2683 {
2684 static const GLubyte color[] = { 0, 0, 0, 255 };
2685
2686 switch (type)
2687 {
2688 default:
2689 UNREACHABLE();
2690 // default falls through to SAMPLER_2D
2691
2692 case SAMPLER_2D:
2693 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002694 Texture2D *incomplete2d = new Texture2D();
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002695 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002696 t = incomplete2d;
2697 }
2698 break;
2699
2700 case SAMPLER_CUBE:
2701 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00002702 TextureCubeMap *incompleteCube = new TextureCubeMap();
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002703
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002704 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2705 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2706 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2707 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2708 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2709 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002710
2711 t = incompleteCube;
2712 }
2713 break;
2714 }
2715
2716 mIncompleteTextures[type] = t;
2717 }
2718
2719 return t;
2720}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002721
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002722bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002723{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002724 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002725}
2726
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002727bool Context::isTriangleMode(GLenum drawMode)
2728{
2729 switch (drawMode)
2730 {
2731 case GL_TRIANGLES:
2732 case GL_TRIANGLE_FAN:
2733 case GL_TRIANGLE_STRIP:
2734 return true;
2735 case GL_POINTS:
2736 case GL_LINES:
2737 case GL_LINE_LOOP:
2738 case GL_LINE_STRIP:
2739 return false;
2740 default: UNREACHABLE();
2741 }
2742
2743 return false;
2744}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002745
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002746bool Context::hasStencil()
2747{
2748 Framebuffer *framebufferObject = getFramebuffer();
2749
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002750 if (framebufferObject && framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002751 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002752 DepthStencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002753
2754 if (stencilbufferObject)
2755 {
2756 return stencilbufferObject->getStencilSize() > 0;
2757 }
2758 }
2759
2760 return false;
2761}
2762
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002763void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2764{
2765 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2766
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002767 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2768 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2769 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2770 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002771
2772 mVertexDataManager->dirtyCurrentValues();
2773}
2774
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002775void Context::initExtensionString()
2776{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002777 mExtensionString += "GL_OES_packed_depth_stencil ";
2778
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002779 if (mBufferBackEnd->supportIntIndices())
2780 {
2781 mExtensionString += "GL_OES_element_index_uint ";
2782 }
2783
2784 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2785 if (end != std::string::npos)
2786 {
2787 mExtensionString.resize(end+1);
2788 }
2789}
2790
2791const char *Context::getExtensionString() const
2792{
2793 return mExtensionString.c_str();
2794}
2795
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002796}
2797
2798extern "C"
2799{
2800gl::Context *glCreateContext(const egl::Config *config)
2801{
2802 return new gl::Context(config);
2803}
2804
2805void glDestroyContext(gl::Context *context)
2806{
2807 delete context;
2808
2809 if (context == gl::getContext())
2810 {
2811 gl::makeCurrent(NULL, NULL, NULL);
2812 }
2813}
2814
2815void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2816{
2817 gl::makeCurrent(context, display, surface);
2818}
2819
2820gl::Context *glGetCurrentContext()
2821{
2822 return gl::getContext();
2823}
2824}