blob: 81ded612a9d79a736e241e6741c4822aeacc9f87 [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"
20#include "libGLESv2/Buffer.h"
21#include "libGLESv2/FrameBuffer.h"
22#include "libGLESv2/Program.h"
23#include "libGLESv2/RenderBuffer.h"
24#include "libGLESv2/Shader.h"
25#include "libGLESv2/Texture.h"
26#include "libGLESv2/geometry/backend.h"
27#include "libGLESv2/geometry/VertexDataManager.h"
28#include "libGLESv2/geometry/IndexDataManager.h"
29#include "libGLESv2/geometry/dx9.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030
daniel@transgaming.com86487c22010-03-11 19:41:43 +000031#undef near
32#undef far
33
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034namespace gl
35{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000036Context::Context(const egl::Config *config)
37 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038{
39 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
daniel@transgaming.com092bd482010-05-12 03:39:36 +000040
daniel@transgaming.com428d1582010-05-04 03:35:25 +000041 mState.depthClearValue = 1.0f;
42 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043
daniel@transgaming.com428d1582010-05-04 03:35:25 +000044 mState.cullFace = false;
45 mState.cullMode = GL_BACK;
46 mState.frontFace = GL_CCW;
47 mState.depthTest = false;
48 mState.depthFunc = GL_LESS;
49 mState.blend = false;
50 mState.sourceBlendRGB = GL_ONE;
51 mState.sourceBlendAlpha = GL_ONE;
52 mState.destBlendRGB = GL_ZERO;
53 mState.destBlendAlpha = GL_ZERO;
54 mState.blendEquationRGB = GL_FUNC_ADD;
55 mState.blendEquationAlpha = GL_FUNC_ADD;
56 mState.blendColor.red = 0;
57 mState.blendColor.green = 0;
58 mState.blendColor.blue = 0;
59 mState.blendColor.alpha = 0;
60 mState.stencilTest = false;
61 mState.stencilFunc = GL_ALWAYS;
62 mState.stencilRef = 0;
63 mState.stencilMask = -1;
64 mState.stencilWritemask = -1;
65 mState.stencilBackFunc = GL_ALWAYS;
66 mState.stencilBackRef = 0;
67 mState.stencilBackMask = - 1;
68 mState.stencilBackWritemask = -1;
69 mState.stencilFail = GL_KEEP;
70 mState.stencilPassDepthFail = GL_KEEP;
71 mState.stencilPassDepthPass = GL_KEEP;
72 mState.stencilBackFail = GL_KEEP;
73 mState.stencilBackPassDepthFail = GL_KEEP;
74 mState.stencilBackPassDepthPass = GL_KEEP;
75 mState.polygonOffsetFill = false;
76 mState.polygonOffsetFactor = 0.0f;
77 mState.polygonOffsetUnits = 0.0f;
78 mState.sampleAlphaToCoverage = false;
79 mState.sampleCoverage = false;
80 mState.sampleCoverageValue = 1.0f;
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +000081 mState.sampleCoverageInvert = false;
daniel@transgaming.com428d1582010-05-04 03:35:25 +000082 mState.scissorTest = false;
83 mState.dither = true;
84 mState.generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085
daniel@transgaming.com428d1582010-05-04 03:35:25 +000086 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000087
daniel@transgaming.com428d1582010-05-04 03:35:25 +000088 mState.viewportX = 0;
89 mState.viewportY = 0;
90 mState.viewportWidth = config->mDisplayMode.Width;
91 mState.viewportHeight = config->mDisplayMode.Height;
92 mState.zNear = 0.0f;
93 mState.zFar = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000094
daniel@transgaming.com428d1582010-05-04 03:35:25 +000095 mState.scissorX = 0;
96 mState.scissorY = 0;
97 mState.scissorWidth = config->mDisplayMode.Width;
98 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000100 mState.colorMaskRed = true;
101 mState.colorMaskGreen = true;
102 mState.colorMaskBlue = true;
103 mState.colorMaskAlpha = true;
104 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105
106 // [OpenGL ES 2.0.24] section 3.7 page 83:
107 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
108 // and cube map texture state vectors respectively associated with them.
109 // In order that access to these initial textures not be lost, they are treated as texture
110 // objects all of whose names are 0.
111
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000112 mTexture2DZero = new Texture2D(this);
113 mTextureCubeMapZero = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114
115 mColorbufferZero = NULL;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000116 mDepthStencilbufferZero = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000117
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000118 mState.activeSampler = 0;
119 mState.arrayBuffer = 0;
120 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000121 bindTextureCubeMap(0);
122 bindTexture2D(0);
123 bindFramebuffer(0);
124 bindRenderbuffer(0);
125
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000126 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000127 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000128 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
129 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000130 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000131 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132 }
133
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000134 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
135 {
136 mIncompleteTextures[type] = NULL;
137 }
138
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000139 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000140
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000141 mState.packAlignment = 4;
142 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000143
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000144 mBufferBackEnd = NULL;
145 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000146 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000147 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000148
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149 mInvalidEnum = false;
150 mInvalidValue = false;
151 mInvalidOperation = false;
152 mOutOfMemory = false;
153 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000154
155 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000156
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000157 mMaskedClearSavedState = NULL;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000158 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159}
160
161Context::~Context()
162{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000163 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000165 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
166 {
167 delete mIncompleteTextures[type];
168 }
169
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170 delete mTexture2DZero;
171 delete mTextureCubeMapZero;
172
173 delete mColorbufferZero;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000174 delete mDepthStencilbufferZero;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000176 delete mBufferBackEnd;
177 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000178 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000179 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000180
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000181 while (!mBufferMap.empty())
182 {
183 deleteBuffer(mBufferMap.begin()->first);
184 }
185
186 while (!mProgramMap.empty())
187 {
188 deleteProgram(mProgramMap.begin()->first);
189 }
190
191 while (!mShaderMap.empty())
192 {
193 deleteShader(mShaderMap.begin()->first);
194 }
195
196 while (!mFramebufferMap.empty())
197 {
198 deleteFramebuffer(mFramebufferMap.begin()->first);
199 }
200
201 while (!mRenderbufferMap.empty())
202 {
203 deleteRenderbuffer(mRenderbufferMap.begin()->first);
204 }
205
206 while (!mTextureMap.empty())
207 {
208 deleteTexture(mTextureMap.begin()->first);
209 }
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000210
211 if (mMaskedClearSavedState)
212 {
213 mMaskedClearSavedState->Release();
214 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215}
216
217void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
218{
219 IDirect3DDevice9 *device = display->getDevice();
220
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000221 if (!mHasBeenCurrent)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000222 {
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000223 mDeviceCaps = display->getDeviceCaps();
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000224
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000225 mBufferBackEnd = new Dx9BackEnd(this, device);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000226 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000227 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000228 mBlit = new Blit(this);
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000229
230 initExtensionString();
231
232 mState.viewportX = 0;
233 mState.viewportY = 0;
234 mState.viewportWidth = surface->getWidth();
235 mState.viewportHeight = surface->getHeight();
236
237 mState.scissorX = 0;
238 mState.scissorY = 0;
239 mState.scissorWidth = surface->getWidth();
240 mState.scissorHeight = surface->getHeight();
241
242 mHasBeenCurrent = true;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000243 }
244
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
246 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000247 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248
249 Framebuffer *framebufferZero = new Framebuffer();
250 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000251 DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252
253 setFramebufferZero(framebufferZero);
254 setColorbufferZero(colorbufferZero);
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000255 setDepthStencilbufferZero(depthStencilbufferZero);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256
257 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
258 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
259 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
260
261 defaultRenderTarget->Release();
262
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000263 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000265 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000267
daniel@transgaming.combe5a0862010-07-28 19:20:37 +0000268 mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000269
270 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271}
272
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000273// 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 +0000274void Context::markAllStateDirty()
275{
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000276 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000277 mAppliedDepthbufferSerial = 0;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000278 mAppliedProgram = 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000279
280 mClearStateDirty = true;
281 mCullStateDirty = true;
282 mDepthStateDirty = true;
283 mMaskStateDirty = true;
284 mBlendStateDirty = true;
285 mStencilStateDirty = true;
286 mPolygonOffsetStateDirty = true;
287 mScissorStateDirty = true;
288 mSampleStateDirty = true;
289 mDitherStateDirty = true;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000290}
291
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292void Context::setClearColor(float red, float green, float blue, float alpha)
293{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000294 mState.colorClearValue.red = red;
295 mState.colorClearValue.green = green;
296 mState.colorClearValue.blue = blue;
297 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000298}
299
300void Context::setClearDepth(float depth)
301{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000302 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303}
304
305void Context::setClearStencil(int stencil)
306{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000307 mState.stencilClearValue = stencil;
308}
309
310void Context::setCullFace(bool enabled)
311{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000312 if (mState.cullFace != enabled)
313 {
314 mState.cullFace = enabled;
315 mCullStateDirty = true;
316 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000317}
318
319bool Context::isCullFaceEnabled() const
320{
321 return mState.cullFace;
322}
323
324void Context::setCullMode(GLenum mode)
325{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000326 if (mState.cullMode != mode)
327 {
328 mState.cullMode = mode;
329 mCullStateDirty = true;
330 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000331}
332
333void Context::setFrontFace(GLenum front)
334{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000335 if (mState.frontFace != front)
336 {
337 mState.frontFace = front;
338 mFrontFaceDirty = true;
339 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000340}
341
342void Context::setDepthTest(bool enabled)
343{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000344 if (mState.depthTest != enabled)
345 {
346 mState.depthTest = enabled;
347 mDepthStateDirty = true;
348 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000349}
350
351bool Context::isDepthTestEnabled() const
352{
353 return mState.depthTest;
354}
355
356void Context::setDepthFunc(GLenum depthFunc)
357{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000358 if (mState.depthFunc != depthFunc)
359 {
360 mState.depthFunc = depthFunc;
361 mDepthStateDirty = true;
362 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000363}
364
365void Context::setDepthRange(float zNear, float zFar)
366{
367 mState.zNear = zNear;
368 mState.zFar = zFar;
369}
370
371void Context::setBlend(bool enabled)
372{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000373 if (mState.blend != enabled)
374 {
375 mState.blend = enabled;
376 mBlendStateDirty = true;
377 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000378}
379
380bool Context::isBlendEnabled() const
381{
382 return mState.blend;
383}
384
385void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
386{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000387 if (mState.sourceBlendRGB != sourceRGB ||
388 mState.sourceBlendAlpha != sourceAlpha ||
389 mState.destBlendRGB != destRGB ||
390 mState.destBlendAlpha != destAlpha)
391 {
392 mState.sourceBlendRGB = sourceRGB;
393 mState.destBlendRGB = destRGB;
394 mState.sourceBlendAlpha = sourceAlpha;
395 mState.destBlendAlpha = destAlpha;
396 mBlendStateDirty = true;
397 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000398}
399
400void Context::setBlendColor(float red, float green, float blue, float alpha)
401{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000402 if (mState.blendColor.red != red ||
403 mState.blendColor.green != green ||
404 mState.blendColor.blue != blue ||
405 mState.blendColor.alpha != alpha)
406 {
407 mState.blendColor.red = red;
408 mState.blendColor.green = green;
409 mState.blendColor.blue = blue;
410 mState.blendColor.alpha = alpha;
411 mBlendStateDirty = true;
412 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000413}
414
415void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
416{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000417 if (mState.blendEquationRGB != rgbEquation ||
418 mState.blendEquationAlpha != alphaEquation)
419 {
420 mState.blendEquationRGB = rgbEquation;
421 mState.blendEquationAlpha = alphaEquation;
422 mBlendStateDirty = true;
423 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000424}
425
426void Context::setStencilTest(bool enabled)
427{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000428 if (mState.stencilTest != enabled)
429 {
430 mState.stencilTest = enabled;
431 mStencilStateDirty = true;
432 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000433}
434
435bool Context::isStencilTestEnabled() const
436{
437 return mState.stencilTest;
438}
439
440void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
441{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000442 if (mState.stencilFunc != stencilFunc ||
443 mState.stencilRef != stencilRef ||
444 mState.stencilMask != stencilMask)
445 {
446 mState.stencilFunc = stencilFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000447 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000448 mState.stencilMask = stencilMask;
449 mStencilStateDirty = true;
450 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000451}
452
453void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
454{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000455 if (mState.stencilBackFunc != stencilBackFunc ||
456 mState.stencilBackRef != stencilBackRef ||
457 mState.stencilBackMask != stencilBackMask)
458 {
459 mState.stencilBackFunc = stencilBackFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000460 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000461 mState.stencilBackMask = stencilBackMask;
462 mStencilStateDirty = true;
463 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000464}
465
466void Context::setStencilWritemask(GLuint stencilWritemask)
467{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000468 if (mState.stencilWritemask != stencilWritemask)
469 {
470 mState.stencilWritemask = stencilWritemask;
471 mStencilStateDirty = true;
472 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000473}
474
475void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
476{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000477 if (mState.stencilBackWritemask != stencilBackWritemask)
478 {
479 mState.stencilBackWritemask = stencilBackWritemask;
480 mStencilStateDirty = true;
481 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000482}
483
484void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
485{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000486 if (mState.stencilFail != stencilFail ||
487 mState.stencilPassDepthFail != stencilPassDepthFail ||
488 mState.stencilPassDepthPass != stencilPassDepthPass)
489 {
490 mState.stencilFail = stencilFail;
491 mState.stencilPassDepthFail = stencilPassDepthFail;
492 mState.stencilPassDepthPass = stencilPassDepthPass;
493 mStencilStateDirty = true;
494 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000495}
496
497void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
498{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000499 if (mState.stencilBackFail != stencilBackFail ||
500 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
501 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
502 {
503 mState.stencilBackFail = stencilBackFail;
504 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
505 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
506 mStencilStateDirty = true;
507 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000508}
509
510void Context::setPolygonOffsetFill(bool enabled)
511{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000512 if (mState.polygonOffsetFill != enabled)
513 {
514 mState.polygonOffsetFill = enabled;
515 mPolygonOffsetStateDirty = true;
516 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000517}
518
519bool Context::isPolygonOffsetFillEnabled() const
520{
521 return mState.polygonOffsetFill;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000522
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000523}
524
525void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
526{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000527 if (mState.polygonOffsetFactor != factor ||
528 mState.polygonOffsetUnits != units)
529 {
530 mState.polygonOffsetFactor = factor;
531 mState.polygonOffsetUnits = units;
532 mPolygonOffsetStateDirty = true;
533 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000534}
535
536void Context::setSampleAlphaToCoverage(bool enabled)
537{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000538 if (mState.sampleAlphaToCoverage != enabled)
539 {
540 mState.sampleAlphaToCoverage = enabled;
541 mSampleStateDirty = true;
542 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000543}
544
545bool Context::isSampleAlphaToCoverageEnabled() const
546{
547 return mState.sampleAlphaToCoverage;
548}
549
550void Context::setSampleCoverage(bool enabled)
551{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000552 if (mState.sampleCoverage != enabled)
553 {
554 mState.sampleCoverage = enabled;
555 mSampleStateDirty = true;
556 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000557}
558
559bool Context::isSampleCoverageEnabled() const
560{
561 return mState.sampleCoverage;
562}
563
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +0000564void Context::setSampleCoverageParams(GLclampf value, bool invert)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000565{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000566 if (mState.sampleCoverageValue != value ||
567 mState.sampleCoverageInvert != invert)
568 {
569 mState.sampleCoverageValue = value;
570 mState.sampleCoverageInvert = invert;
571 mSampleStateDirty = true;
572 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000573}
574
575void Context::setScissorTest(bool enabled)
576{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000577 if (mState.scissorTest != enabled)
578 {
579 mState.scissorTest = enabled;
580 mScissorStateDirty = true;
581 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000582}
583
584bool Context::isScissorTestEnabled() const
585{
586 return mState.scissorTest;
587}
588
589void Context::setDither(bool enabled)
590{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000591 if (mState.dither != enabled)
592 {
593 mState.dither = enabled;
594 mDitherStateDirty = true;
595 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000596}
597
598bool Context::isDitherEnabled() const
599{
600 return mState.dither;
601}
602
603void Context::setLineWidth(GLfloat width)
604{
605 mState.lineWidth = width;
606}
607
608void Context::setGenerateMipmapHint(GLenum hint)
609{
610 mState.generateMipmapHint = hint;
611}
612
613void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
614{
615 mState.viewportX = x;
616 mState.viewportY = y;
617 mState.viewportWidth = width;
618 mState.viewportHeight = height;
619}
620
621void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
622{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000623 if (mState.scissorX != x || mState.scissorY != y ||
624 mState.scissorWidth != width || mState.scissorHeight != height)
625 {
626 mState.scissorX = x;
627 mState.scissorY = y;
628 mState.scissorWidth = width;
629 mState.scissorHeight = height;
630 mScissorStateDirty = true;
631 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000632}
633
634void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
635{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000636 if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
637 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
638 {
639 mState.colorMaskRed = red;
640 mState.colorMaskGreen = green;
641 mState.colorMaskBlue = blue;
642 mState.colorMaskAlpha = alpha;
643 mMaskStateDirty = true;
644 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000645}
646
647void Context::setDepthMask(bool mask)
648{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000649 if (mState.depthMask != mask)
650 {
651 mState.depthMask = mask;
652 mMaskStateDirty = true;
653 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000654}
655
656void Context::setActiveSampler(int active)
657{
658 mState.activeSampler = active;
659}
660
661GLuint Context::getFramebufferHandle() const
662{
663 return mState.framebuffer;
664}
665
666GLuint Context::getRenderbufferHandle() const
667{
668 return mState.renderbuffer;
669}
670
671GLuint Context::getArrayBufferHandle() const
672{
673 return mState.arrayBuffer;
674}
675
676void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
677{
678 mState.vertexAttribute[attribNum].mEnabled = enabled;
679}
680
681const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
682{
683 return mState.vertexAttribute[attribNum];
684}
685
686void Context::setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type, bool normalized,
687 GLsizei stride, const void *pointer)
688{
689 mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer;
690 mState.vertexAttribute[attribNum].mSize = size;
691 mState.vertexAttribute[attribNum].mType = type;
692 mState.vertexAttribute[attribNum].mNormalized = normalized;
693 mState.vertexAttribute[attribNum].mStride = stride;
694 mState.vertexAttribute[attribNum].mPointer = pointer;
695}
696
697const void *Context::getVertexAttribPointer(unsigned int attribNum) const
698{
699 return mState.vertexAttribute[attribNum].mPointer;
700}
701
702// returns entire set of attributes as a block
703const AttributeState *Context::getVertexAttribBlock()
704{
705 return mState.vertexAttribute;
706}
707
708void Context::setPackAlignment(GLint alignment)
709{
710 mState.packAlignment = alignment;
711}
712
713GLint Context::getPackAlignment() const
714{
715 return mState.packAlignment;
716}
717
718void Context::setUnpackAlignment(GLint alignment)
719{
720 mState.unpackAlignment = alignment;
721}
722
723GLint Context::getUnpackAlignment() const
724{
725 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726}
727
728// Returns an unused buffer name
729GLuint Context::createBuffer()
730{
731 unsigned int handle = 1;
732
733 while (mBufferMap.find(handle) != mBufferMap.end())
734 {
735 handle++;
736 }
737
738 mBufferMap[handle] = NULL;
739
740 return handle;
741}
742
743// Returns an unused shader/program name
744GLuint Context::createShader(GLenum type)
745{
746 unsigned int handle = 1;
747
748 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
749 {
750 handle++;
751 }
752
753 if (type == GL_VERTEX_SHADER)
754 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000755 mShaderMap[handle] = new VertexShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000756 }
757 else if (type == GL_FRAGMENT_SHADER)
758 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000759 mShaderMap[handle] = new FragmentShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000760 }
761 else UNREACHABLE();
762
763 return handle;
764}
765
766// Returns an unused program/shader name
767GLuint Context::createProgram()
768{
769 unsigned int handle = 1;
770
771 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
772 {
773 handle++;
774 }
775
776 mProgramMap[handle] = new Program();
777
778 return handle;
779}
780
781// Returns an unused texture name
782GLuint Context::createTexture()
783{
784 unsigned int handle = 1;
785
786 while (mTextureMap.find(handle) != mTextureMap.end())
787 {
788 handle++;
789 }
790
791 mTextureMap[handle] = NULL;
792
793 return handle;
794}
795
796// Returns an unused framebuffer name
797GLuint Context::createFramebuffer()
798{
799 unsigned int handle = 1;
800
801 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
802 {
803 handle++;
804 }
805
806 mFramebufferMap[handle] = NULL;
807
808 return handle;
809}
810
811// Returns an unused renderbuffer name
812GLuint Context::createRenderbuffer()
813{
814 unsigned int handle = 1;
815
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000816 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000817 {
818 handle++;
819 }
820
821 mRenderbufferMap[handle] = NULL;
822
823 return handle;
824}
825
826void Context::deleteBuffer(GLuint buffer)
827{
828 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
829
830 if (bufferObject != mBufferMap.end())
831 {
832 detachBuffer(buffer);
833
834 delete bufferObject->second;
835 mBufferMap.erase(bufferObject);
836 }
837}
838
839void Context::deleteShader(GLuint shader)
840{
841 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
842
843 if (shaderObject != mShaderMap.end())
844 {
845 if (!shaderObject->second->isAttached())
846 {
847 delete shaderObject->second;
848 mShaderMap.erase(shaderObject);
849 }
850 else
851 {
852 shaderObject->second->flagForDeletion();
853 }
854 }
855}
856
857void Context::deleteProgram(GLuint program)
858{
859 ProgramMap::iterator programObject = mProgramMap.find(program);
860
861 if (programObject != mProgramMap.end())
862 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000863 if (program != mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000864 {
865 delete programObject->second;
866 mProgramMap.erase(programObject);
867 }
868 else
869 {
870 programObject->second->flagForDeletion();
871 }
872 }
873}
874
875void Context::deleteTexture(GLuint texture)
876{
877 TextureMap::iterator textureObject = mTextureMap.find(texture);
878
879 if (textureObject != mTextureMap.end())
880 {
881 detachTexture(texture);
882
883 if (texture != 0)
884 {
885 delete textureObject->second;
886 }
887
888 mTextureMap.erase(textureObject);
889 }
890}
891
892void Context::deleteFramebuffer(GLuint framebuffer)
893{
894 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
895
896 if (framebufferObject != mFramebufferMap.end())
897 {
898 detachFramebuffer(framebuffer);
899
900 delete framebufferObject->second;
901 mFramebufferMap.erase(framebufferObject);
902 }
903}
904
905void Context::deleteRenderbuffer(GLuint renderbuffer)
906{
907 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
908
909 if (renderbufferObject != mRenderbufferMap.end())
910 {
911 detachRenderbuffer(renderbuffer);
912
913 delete renderbufferObject->second;
914 mRenderbufferMap.erase(renderbufferObject);
915 }
916}
917
918void Context::bindArrayBuffer(unsigned int buffer)
919{
920 if (buffer != 0 && !getBuffer(buffer))
921 {
daniel@transgaming.comdefa1c32010-05-18 18:51:45 +0000922 mBufferMap[buffer] = new Buffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000923 }
924
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000925 mState.arrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000926}
927
928void Context::bindElementArrayBuffer(unsigned int buffer)
929{
930 if (buffer != 0 && !getBuffer(buffer))
931 {
daniel@transgaming.comdefa1c32010-05-18 18:51:45 +0000932 mBufferMap[buffer] = new Buffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000933 }
934
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000935 mState.elementArrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000936}
937
938void Context::bindTexture2D(GLuint texture)
939{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000940 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000941 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000942 mTextureMap[texture] = new Texture2D(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000943 }
944
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000945 mState.texture2D = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000946
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000947 mState.samplerTexture[SAMPLER_2D][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000948}
949
950void Context::bindTextureCubeMap(GLuint texture)
951{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000952 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000953 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000954 mTextureMap[texture] = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000955 }
956
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000957 mState.textureCubeMap = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000958
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000959 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000960}
961
962void Context::bindFramebuffer(GLuint framebuffer)
963{
964 if (!getFramebuffer(framebuffer))
965 {
966 mFramebufferMap[framebuffer] = new Framebuffer();
967 }
968
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000969 mState.framebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000970}
971
972void Context::bindRenderbuffer(GLuint renderbuffer)
973{
974 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
975 {
976 mRenderbufferMap[renderbuffer] = new Renderbuffer();
977 }
978
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000979 mState.renderbuffer = renderbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000980}
981
982void Context::useProgram(GLuint program)
983{
984 Program *programObject = getCurrentProgram();
985
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000986 GLuint priorProgram = mState.currentProgram;
987 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000988
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000989 if (programObject && programObject->isFlaggedForDeletion())
990 {
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000991 deleteProgram(priorProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000992 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000993}
994
995void Context::setFramebufferZero(Framebuffer *buffer)
996{
997 delete mFramebufferMap[0];
998 mFramebufferMap[0] = buffer;
999}
1000
1001void Context::setColorbufferZero(Colorbuffer *buffer)
1002{
1003 delete mColorbufferZero;
1004 mColorbufferZero = buffer;
1005}
1006
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001007void Context::setDepthStencilbufferZero(DepthStencilbuffer *buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001008{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001009 delete mDepthStencilbufferZero;
1010 mDepthStencilbufferZero = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001011}
1012
1013void Context::setRenderbuffer(Renderbuffer *buffer)
1014{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001015 delete mRenderbufferMap[mState.renderbuffer];
1016 mRenderbufferMap[mState.renderbuffer] = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001017}
1018
1019Buffer *Context::getBuffer(unsigned int handle)
1020{
1021 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001022
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001023 if (buffer == mBufferMap.end())
1024 {
1025 return NULL;
1026 }
1027 else
1028 {
1029 return buffer->second;
1030 }
1031}
1032
1033Shader *Context::getShader(unsigned int handle)
1034{
1035 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001036
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001037 if (shader == mShaderMap.end())
1038 {
1039 return NULL;
1040 }
1041 else
1042 {
1043 return shader->second;
1044 }
1045}
1046
1047Program *Context::getProgram(unsigned int handle)
1048{
1049 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001050
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001051 if (program == mProgramMap.end())
1052 {
1053 return NULL;
1054 }
1055 else
1056 {
1057 return program->second;
1058 }
1059}
1060
1061Texture *Context::getTexture(unsigned int handle)
1062{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001063 if (handle == 0) return NULL;
1064
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001065 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001066
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001067 if (texture == mTextureMap.end())
1068 {
1069 return NULL;
1070 }
1071 else
1072 {
1073 return texture->second;
1074 }
1075}
1076
1077Framebuffer *Context::getFramebuffer(unsigned int handle)
1078{
1079 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001080
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001081 if (framebuffer == mFramebufferMap.end())
1082 {
1083 return NULL;
1084 }
1085 else
1086 {
1087 return framebuffer->second;
1088 }
1089}
1090
1091Renderbuffer *Context::getRenderbuffer(unsigned int handle)
1092{
1093 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001094
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001095 if (renderbuffer == mRenderbufferMap.end())
1096 {
1097 return NULL;
1098 }
1099 else
1100 {
1101 return renderbuffer->second;
1102 }
1103}
1104
1105Colorbuffer *Context::getColorbuffer(GLuint handle)
1106{
1107 if (handle != 0)
1108 {
1109 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1110
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001111 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001112 {
1113 return static_cast<Colorbuffer*>(renderbuffer);
1114 }
1115 }
1116 else // Special case: 0 refers to different initial render targets based on the attachment type
1117 {
1118 return mColorbufferZero;
1119 }
1120
1121 return NULL;
1122}
1123
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001124DepthStencilbuffer *Context::getDepthbuffer(GLuint handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001125{
1126 if (handle != 0)
1127 {
1128 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1129
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001130 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001131 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001132 return static_cast<DepthStencilbuffer*>(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001133 }
1134 }
1135 else // Special case: 0 refers to different initial render targets based on the attachment type
1136 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001137 return mDepthStencilbufferZero;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001138 }
1139
1140 return NULL;
1141}
1142
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001143DepthStencilbuffer *Context::getStencilbuffer(GLuint handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001144{
1145 if (handle != 0)
1146 {
1147 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1148
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001149 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001150 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001151 return static_cast<DepthStencilbuffer*>(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001152 }
1153 }
1154 else
1155 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001156 return mDepthStencilbufferZero;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001157 }
1158
1159 return NULL;
1160}
1161
1162Buffer *Context::getArrayBuffer()
1163{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001164 return getBuffer(mState.arrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001165}
1166
1167Buffer *Context::getElementArrayBuffer()
1168{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001169 return getBuffer(mState.elementArrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001170}
1171
1172Program *Context::getCurrentProgram()
1173{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001174 return getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001175}
1176
1177Texture2D *Context::getTexture2D()
1178{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001179 if (mState.texture2D == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001180 {
1181 return mTexture2DZero;
1182 }
1183
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001184 return (Texture2D*)getTexture(mState.texture2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001185}
1186
1187TextureCubeMap *Context::getTextureCubeMap()
1188{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001189 if (mState.textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001190 {
1191 return mTextureCubeMapZero;
1192 }
1193
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001194 return (TextureCubeMap*)getTexture(mState.textureCubeMap);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001195}
1196
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001197Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001198{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001199 GLuint texid = mState.samplerTexture[type][sampler];
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001200
1201 if (texid == 0)
1202 {
1203 switch (type)
1204 {
1205 default: UNREACHABLE();
1206 case SAMPLER_2D: return mTexture2DZero;
1207 case SAMPLER_CUBE: return mTextureCubeMapZero;
1208 }
1209 }
1210
1211 return getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001212}
1213
1214Framebuffer *Context::getFramebuffer()
1215{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001216 return getFramebuffer(mState.framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001217}
1218
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001219bool Context::getBooleanv(GLenum pname, GLboolean *params)
1220{
1221 switch (pname)
1222 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001223 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1224 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1225 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001226 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001227 params[0] = mState.colorMaskRed;
1228 params[1] = mState.colorMaskGreen;
1229 params[2] = mState.colorMaskBlue;
1230 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001231 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001232 case GL_CULL_FACE: *params = mState.cullFace;
1233 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
1234 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
1235 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
1236 case GL_SCISSOR_TEST: *params = mState.scissorTest;
1237 case GL_STENCIL_TEST: *params = mState.stencilTest;
1238 case GL_DEPTH_TEST: *params = mState.depthTest;
1239 case GL_BLEND: *params = mState.blend;
1240 case GL_DITHER: *params = mState.dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001241 default:
1242 return false;
1243 }
1244
1245 return true;
1246}
1247
1248bool Context::getFloatv(GLenum pname, GLfloat *params)
1249{
1250 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1251 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1252 // GetIntegerv as its native query function. As it would require conversion in any
1253 // case, this should make no difference to the calling application.
1254 switch (pname)
1255 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001256 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1257 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1258 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1259 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1260 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001261 case GL_ALIASED_LINE_WIDTH_RANGE:
1262 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1263 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1264 break;
1265 case GL_ALIASED_POINT_SIZE_RANGE:
1266 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001267 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 +00001268 break;
1269 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001270 params[0] = mState.zNear;
1271 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001272 break;
1273 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001274 params[0] = mState.colorClearValue.red;
1275 params[1] = mState.colorClearValue.green;
1276 params[2] = mState.colorClearValue.blue;
1277 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001278 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001279 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001280 params[0] = mState.blendColor.red;
1281 params[1] = mState.blendColor.green;
1282 params[2] = mState.blendColor.blue;
1283 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001284 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001285 default:
1286 return false;
1287 }
1288
1289 return true;
1290}
1291
1292bool Context::getIntegerv(GLenum pname, GLint *params)
1293{
1294 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1295 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1296 // GetIntegerv as its native query function. As it would require conversion in any
1297 // case, this should make no difference to the calling application. You may find it in
1298 // Context::getFloatv.
1299 switch (pname)
1300 {
1301 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1302 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1303 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
1304 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1305 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1306 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1307 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
1308 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001309 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1310 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
1311 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
1312 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
1313 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer; break;
1314 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer; break;
1315 case GL_FRAMEBUFFER_BINDING: *params = mState.framebuffer; break;
1316 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer; break;
1317 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1318 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1319 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1320 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1321 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
1322 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1323 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1324 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1325 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1326 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1327 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1328 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1329 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1330 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1331 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1332 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1333 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1334 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1335 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1336 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1337 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1338 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1339 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1340 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1341 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1342 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1343 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
1344 case GL_SUBPIXEL_BITS: *params = 4; break;
1345 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
1346 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
1347 case GL_SAMPLE_BUFFERS: *params = 0; break;
1348 case GL_SAMPLES: *params = 0; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001349 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1350 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1351 case GL_MAX_VIEWPORT_DIMS:
1352 {
1353 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
1354 params[0] = maxDimension;
1355 params[1] = maxDimension;
1356 }
1357 break;
1358 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001359 params[0] = mState.viewportX;
1360 params[1] = mState.viewportY;
1361 params[2] = mState.viewportWidth;
1362 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001363 break;
1364 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001365 params[0] = mState.scissorX;
1366 params[1] = mState.scissorY;
1367 params[2] = mState.scissorWidth;
1368 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001369 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001370 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1371 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001372 case GL_RED_BITS:
1373 case GL_GREEN_BITS:
1374 case GL_BLUE_BITS:
1375 case GL_ALPHA_BITS:
1376 {
1377 gl::Framebuffer *framebuffer = getFramebuffer();
1378 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1379
1380 if (colorbuffer)
1381 {
1382 switch (pname)
1383 {
1384 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1385 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1386 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1387 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1388 }
1389 }
1390 else
1391 {
1392 *params = 0;
1393 }
1394 }
1395 break;
1396 case GL_DEPTH_BITS:
1397 {
1398 gl::Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001399 gl::DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001400
1401 if (depthbuffer)
1402 {
1403 *params = depthbuffer->getDepthSize();
1404 }
1405 else
1406 {
1407 *params = 0;
1408 }
1409 }
1410 break;
1411 case GL_STENCIL_BITS:
1412 {
1413 gl::Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001414 gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001415
1416 if (stencilbuffer)
1417 {
1418 *params = stencilbuffer->getStencilSize();
1419 }
1420 else
1421 {
1422 *params = 0;
1423 }
1424 }
1425 break;
1426 case GL_TEXTURE_BINDING_2D:
1427 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001428 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001429 {
1430 error(GL_INVALID_OPERATION);
1431 return false;
1432 }
1433
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001434 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001435 }
1436 break;
1437 case GL_TEXTURE_BINDING_CUBE_MAP:
1438 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001439 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001440 {
1441 error(GL_INVALID_OPERATION);
1442 return false;
1443 }
1444
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001445 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001446 }
1447 break;
1448 default:
1449 return false;
1450 }
1451
1452 return true;
1453}
1454
1455bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1456{
1457 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1458 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1459 // to the fact that it is stored internally as a float, and so would require conversion
1460 // if returned from Context::getIntegerv. Since this conversion is already implemented
1461 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1462 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1463 // application.
1464 switch (pname)
1465 {
1466 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1467 case GL_SHADER_BINARY_FORMATS:
1468 {
1469 *type = GL_INT;
1470 *numParams = 0;
1471 }
1472 break;
1473 case GL_MAX_VERTEX_ATTRIBS:
1474 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1475 case GL_MAX_VARYING_VECTORS:
1476 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1477 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1478 case GL_MAX_TEXTURE_IMAGE_UNITS:
1479 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1480 case GL_MAX_RENDERBUFFER_SIZE:
1481 case GL_NUM_SHADER_BINARY_FORMATS:
1482 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1483 case GL_ARRAY_BUFFER_BINDING:
1484 case GL_FRAMEBUFFER_BINDING:
1485 case GL_RENDERBUFFER_BINDING:
1486 case GL_CURRENT_PROGRAM:
1487 case GL_PACK_ALIGNMENT:
1488 case GL_UNPACK_ALIGNMENT:
1489 case GL_GENERATE_MIPMAP_HINT:
1490 case GL_RED_BITS:
1491 case GL_GREEN_BITS:
1492 case GL_BLUE_BITS:
1493 case GL_ALPHA_BITS:
1494 case GL_DEPTH_BITS:
1495 case GL_STENCIL_BITS:
1496 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1497 case GL_CULL_FACE_MODE:
1498 case GL_FRONT_FACE:
1499 case GL_ACTIVE_TEXTURE:
1500 case GL_STENCIL_FUNC:
1501 case GL_STENCIL_VALUE_MASK:
1502 case GL_STENCIL_REF:
1503 case GL_STENCIL_FAIL:
1504 case GL_STENCIL_PASS_DEPTH_FAIL:
1505 case GL_STENCIL_PASS_DEPTH_PASS:
1506 case GL_STENCIL_BACK_FUNC:
1507 case GL_STENCIL_BACK_VALUE_MASK:
1508 case GL_STENCIL_BACK_REF:
1509 case GL_STENCIL_BACK_FAIL:
1510 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1511 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1512 case GL_DEPTH_FUNC:
1513 case GL_BLEND_SRC_RGB:
1514 case GL_BLEND_SRC_ALPHA:
1515 case GL_BLEND_DST_RGB:
1516 case GL_BLEND_DST_ALPHA:
1517 case GL_BLEND_EQUATION_RGB:
1518 case GL_BLEND_EQUATION_ALPHA:
1519 case GL_STENCIL_WRITEMASK:
1520 case GL_STENCIL_BACK_WRITEMASK:
1521 case GL_STENCIL_CLEAR_VALUE:
1522 case GL_SUBPIXEL_BITS:
1523 case GL_MAX_TEXTURE_SIZE:
1524 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1525 case GL_SAMPLE_BUFFERS:
1526 case GL_SAMPLES:
1527 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1528 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1529 case GL_TEXTURE_BINDING_2D:
1530 case GL_TEXTURE_BINDING_CUBE_MAP:
1531 {
1532 *type = GL_INT;
1533 *numParams = 1;
1534 }
1535 break;
1536 case GL_MAX_VIEWPORT_DIMS:
1537 {
1538 *type = GL_INT;
1539 *numParams = 2;
1540 }
1541 break;
1542 case GL_VIEWPORT:
1543 case GL_SCISSOR_BOX:
1544 {
1545 *type = GL_INT;
1546 *numParams = 4;
1547 }
1548 break;
1549 case GL_SHADER_COMPILER:
1550 case GL_SAMPLE_COVERAGE_INVERT:
1551 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001552 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1553 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1554 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1555 case GL_SAMPLE_COVERAGE:
1556 case GL_SCISSOR_TEST:
1557 case GL_STENCIL_TEST:
1558 case GL_DEPTH_TEST:
1559 case GL_BLEND:
1560 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001561 {
1562 *type = GL_BOOL;
1563 *numParams = 1;
1564 }
1565 break;
1566 case GL_COLOR_WRITEMASK:
1567 {
1568 *type = GL_BOOL;
1569 *numParams = 4;
1570 }
1571 break;
1572 case GL_POLYGON_OFFSET_FACTOR:
1573 case GL_POLYGON_OFFSET_UNITS:
1574 case GL_SAMPLE_COVERAGE_VALUE:
1575 case GL_DEPTH_CLEAR_VALUE:
1576 case GL_LINE_WIDTH:
1577 {
1578 *type = GL_FLOAT;
1579 *numParams = 1;
1580 }
1581 break;
1582 case GL_ALIASED_LINE_WIDTH_RANGE:
1583 case GL_ALIASED_POINT_SIZE_RANGE:
1584 case GL_DEPTH_RANGE:
1585 {
1586 *type = GL_FLOAT;
1587 *numParams = 2;
1588 }
1589 break;
1590 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001591 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001592 {
1593 *type = GL_FLOAT;
1594 *numParams = 4;
1595 }
1596 break;
1597 default:
1598 return false;
1599 }
1600
1601 return true;
1602}
1603
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001604// Applies the render target surface, depth stencil surface, viewport rectangle and
1605// scissor rectangle to the Direct3D 9 device
1606bool Context::applyRenderTarget(bool ignoreViewport)
1607{
1608 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001609
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001610 Framebuffer *framebufferObject = getFramebuffer();
1611
1612 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1613 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001614 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1615
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001616 return false;
1617 }
1618
1619 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001620 IDirect3DSurface9 *depthStencil = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001621
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001622 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
1623 if (renderTargetSerial != mAppliedRenderTargetSerial)
1624 {
1625 device->SetRenderTarget(0, renderTarget);
1626 mAppliedRenderTargetSerial = renderTargetSerial;
1627 }
1628
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001629 unsigned int depthbufferSerial = 0;
1630 unsigned int stencilbufferSerial = 0;
1631 if (framebufferObject->getDepthbufferType() != GL_NONE)
1632 {
1633 depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil();
1634 depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial();
1635 }
1636 else if (framebufferObject->getStencilbufferType() != GL_NONE)
1637 {
1638 depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
1639 stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial();
1640 }
1641
1642 if (depthbufferSerial != mAppliedDepthbufferSerial ||
1643 stencilbufferSerial != mAppliedStencilbufferSerial)
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001644 {
1645 device->SetDepthStencilSurface(depthStencil);
1646 mAppliedDepthbufferSerial = depthbufferSerial;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001647 mAppliedStencilbufferSerial = stencilbufferSerial;
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001648 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001649
1650 D3DVIEWPORT9 viewport;
1651 D3DSURFACE_DESC desc;
1652 renderTarget->GetDesc(&desc);
1653
1654 if (ignoreViewport)
1655 {
1656 viewport.X = 0;
1657 viewport.Y = 0;
1658 viewport.Width = desc.Width;
1659 viewport.Height = desc.Height;
1660 viewport.MinZ = 0.0f;
1661 viewport.MaxZ = 1.0f;
1662 }
1663 else
1664 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001665 viewport.X = std::max(mState.viewportX, 0);
1666 viewport.Y = std::max(mState.viewportY, 0);
1667 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1668 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1669 viewport.MinZ = clamp01(mState.zNear);
1670 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001671 }
1672
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001673 if (viewport.Width <= 0 || viewport.Height <= 0)
1674 {
1675 return false; // Nothing to render
1676 }
1677
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001678 device->SetViewport(&viewport);
1679
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001680 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001681 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001682 if (mState.scissorTest)
1683 {
1684 RECT rect = {mState.scissorX,
1685 mState.scissorY,
1686 mState.scissorX + mState.scissorWidth,
1687 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001688
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001689 device->SetScissorRect(&rect);
1690 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1691 }
1692 else
1693 {
1694 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1695 }
1696
1697 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001698 }
1699
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001700 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001701 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001702 Program *programObject = getCurrentProgram();
1703
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001704 GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001705 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001706 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001707
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00001708 GLint window = programObject->getDxViewportLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001709 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1710 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1711 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001712 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1713
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001714 GLint depth = programObject->getDxDepthLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001715 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001716 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1717
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001718 GLint near = programObject->getDepthRangeNearLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001719 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001720
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001721 GLint far = programObject->getDepthRangeFarLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001722 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001723
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001724 GLint diff = programObject->getDepthRangeDiffLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001725 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001726 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001727 }
1728
1729 return true;
1730}
1731
1732// 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 +00001733void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001734{
1735 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001736 Program *programObject = getCurrentProgram();
1737
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001738 GLint frontCCW = programObject->getDxFrontCCWLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001739 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001740 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001741
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001742 GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001743 GLint alwaysFront = !isTriangleMode(drawMode);
1744 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1745
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001746 Framebuffer *framebufferObject = getFramebuffer();
1747
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001748 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001749 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001750 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001751 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001752 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001753 }
1754 else
1755 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001756 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001757 }
1758
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001759 mCullStateDirty = false;
1760 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001761
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001762 if (mDepthStateDirty)
1763 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001764 if (mState.depthTest && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001765 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001766 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1767 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001768 }
1769 else
1770 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001771 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001772 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001773
1774 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001775 }
1776
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001777 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001778 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001779 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001780 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001781 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1782
1783 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1784 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1785 {
1786 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1787 }
1788 else
1789 {
1790 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1791 unorm<8>(mState.blendColor.alpha),
1792 unorm<8>(mState.blendColor.alpha),
1793 unorm<8>(mState.blendColor.alpha)));
1794 }
1795
1796 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1797 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1798 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1799
1800 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1801 mState.destBlendRGB != mState.destBlendAlpha ||
1802 mState.blendEquationRGB != mState.blendEquationAlpha)
1803 {
1804 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1805
1806 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1807 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1808 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
1809
1810 }
1811 else
1812 {
1813 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1814 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001815 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001816 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001817 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001818 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001819 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001820
1821 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001822 }
1823
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001824 if (mStencilStateDirty || mFrontFaceDirty)
1825 {
1826 if (mState.stencilTest && hasStencil())
1827 {
1828 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1829 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1830
1831 // FIXME: Unsupported by D3D9
1832 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1833 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1834 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1835 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1836 mState.stencilRef != mState.stencilBackRef ||
1837 mState.stencilMask != mState.stencilBackMask)
1838 {
1839 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1840 return error(GL_INVALID_OPERATION);
1841 }
1842
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001843 // get the maximum size of the stencil ref
1844 gl::Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001845 gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001846 GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
1847
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001848 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1849 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1850 es2dx::ConvertComparison(mState.stencilFunc));
1851
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001852 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 +00001853 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
1854
1855 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1856 es2dx::ConvertStencilOp(mState.stencilFail));
1857 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1858 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1859 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1860 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1861
1862 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1863 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1864 es2dx::ConvertComparison(mState.stencilBackFunc));
1865
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001866 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 +00001867 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
1868
1869 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1870 es2dx::ConvertStencilOp(mState.stencilBackFail));
1871 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1872 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1873 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1874 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1875 }
1876 else
1877 {
1878 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1879 }
1880
1881 mStencilStateDirty = false;
1882 }
1883
1884 if (mMaskStateDirty)
1885 {
1886 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1887 mState.colorMaskBlue, mState.colorMaskAlpha));
1888 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1889
1890 mMaskStateDirty = false;
1891 }
1892
1893 if (mPolygonOffsetStateDirty)
1894 {
1895 if (mState.polygonOffsetFill)
1896 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001897 gl::DepthStencilbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001898 if (depthbuffer)
1899 {
1900 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1901 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1902 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1903 }
1904 }
1905 else
1906 {
1907 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1908 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1909 }
1910
1911 mPolygonOffsetStateDirty = false;
1912 }
1913
1914 if (mConfig->mMultiSample != 0 && mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001915 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001916 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001917 {
1918 FIXME("Sample alpha to coverage is unimplemented.");
1919 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001920
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001921 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001922 {
1923 FIXME("Sample coverage is unimplemented.");
1924 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001925
1926 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001927 }
1928
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001929 if (mDitherStateDirty)
1930 {
1931 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
1932
1933 mDitherStateDirty = false;
1934 }
1935
1936 mFrontFaceDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001937}
1938
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001939// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001940void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001941{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001942 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001943 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001944 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001945 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001946 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001947 }
1948 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001949}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001950
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001951GLenum Context::applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool *useIndexing, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001952{
1953 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1954
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001955 GLenum err = mVertexDataManager->preRenderValidate(first, count, translated);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001956 if (err != GL_NO_ERROR)
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001957 {
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001958 return err;
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001959 }
1960
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001961 lookupAttributeMapping(translated);
1962
1963 mBufferBackEnd->setupAttributesPreDraw(translated);
1964
1965 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
1966 {
1967 if (translated[i].enabled && translated[i].nonArray)
1968 {
1969 err = mIndexDataManager->preRenderValidateUnindexed(mode, count, indexInfo);
1970 if (err != GL_NO_ERROR)
1971 {
1972 return err;
1973 }
1974
1975 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
1976
1977 *useIndexing = true;
1978 return GL_NO_ERROR;
1979 }
1980 }
1981
1982 *useIndexing = false;
1983 return GL_NO_ERROR;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001984}
1985
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001986GLenum Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001987{
1988 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1989
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001990 GLenum err = mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001991
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001992 if (err == GL_NO_ERROR)
1993 {
1994 lookupAttributeMapping(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001995
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001996 mBufferBackEnd->setupAttributesPreDraw(translated);
1997 }
1998
1999 return err;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002000}
2001
2002// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002003GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002004{
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002005 GLenum err = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices, indexInfo);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002006
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002007 if (err == GL_NO_ERROR)
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002008 {
2009 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
2010 }
2011
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002012 return err;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002013}
2014
2015// Applies the shaders and shader constants to the Direct3D 9 device
2016void Context::applyShaders()
2017{
2018 IDirect3DDevice9 *device = getDevice();
2019 Program *programObject = getCurrentProgram();
2020 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
2021 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
2022
2023 device->SetVertexShader(vertexShader);
2024 device->SetPixelShader(pixelShader);
2025
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002026 if (programObject->getSerial() != mAppliedProgram)
2027 {
2028 programObject->dirtyAllUniforms();
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002029 programObject->dirtyAllSamplers();
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002030 mAppliedProgram = programObject->getSerial();
2031 }
2032
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002033 programObject->applyUniforms();
2034}
2035
2036// Applies the textures and sampler states to the Direct3D 9 device
2037void Context::applyTextures()
2038{
2039 IDirect3DDevice9 *device = getDevice();
2040 Program *programObject = getCurrentProgram();
2041
2042 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
2043 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002044 int textureUnit = programObject->getSamplerMapping(sampler);
2045 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002046 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002047 SamplerType textureType = programObject->getSamplerType(sampler);
2048
2049 Texture *texture = getSamplerTexture(textureUnit, textureType);
2050
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002051 if (programObject->isSamplerDirty(sampler) || texture->isDirty())
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002052 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002053 if (texture->isComplete())
2054 {
2055 GLenum wrapS = texture->getWrapS();
2056 GLenum wrapT = texture->getWrapT();
2057 GLenum minFilter = texture->getMinFilter();
2058 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002059
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002060 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
2061 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002062
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002063 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
2064 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
2065 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
2066 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
2067 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002068
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002069 device->SetTexture(sampler, texture->getTexture());
2070 }
2071 else
2072 {
2073 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
2074 }
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002075 }
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002076
2077 programObject->setSamplerDirty(sampler, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002078 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002079 else
2080 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002081 if (programObject->isSamplerDirty(sampler))
2082 {
2083 device->SetTexture(sampler, NULL);
2084 programObject->setSamplerDirty(sampler, false);
2085 }
2086 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002087 }
2088}
2089
2090void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
2091{
2092 Framebuffer *framebuffer = getFramebuffer();
2093 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
2094 IDirect3DDevice9 *device = getDevice();
2095
2096 D3DSURFACE_DESC desc;
2097 renderTarget->GetDesc(&desc);
2098
2099 IDirect3DSurface9 *systemSurface;
2100 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
2101
2102 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2103 {
2104 return error(GL_OUT_OF_MEMORY);
2105 }
2106
2107 ASSERT(SUCCEEDED(result));
2108
2109 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
2110 {
2111 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
2112 }
2113
2114 result = device->GetRenderTargetData(renderTarget, systemSurface);
2115
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002116 if (FAILED(result))
2117 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002118 systemSurface->Release();
2119
apatrick@chromium.org6db8cab2010-07-22 20:39:50 +00002120 switch (result)
2121 {
2122 case D3DERR_DRIVERINTERNALERROR:
2123 case D3DERR_DEVICELOST:
2124 return error(GL_OUT_OF_MEMORY);
2125 default:
2126 UNREACHABLE();
2127 return; // No sensible error to generate
2128 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002129 }
2130
2131 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00002132 RECT rect = {std::max(x, 0),
2133 std::max(y, 0),
2134 std::min(x + width, (int)desc.Width),
2135 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002136
2137 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
2138
2139 if (FAILED(result))
2140 {
2141 UNREACHABLE();
2142 systemSurface->Release();
2143
2144 return; // No sensible error to generate
2145 }
2146
2147 unsigned char *source = (unsigned char*)lock.pBits;
2148 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002149 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002150
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002151 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002152
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002153 for (int j = 0; j < rect.bottom - rect.top; j++)
2154 {
2155 for (int i = 0; i < rect.right - rect.left; i++)
2156 {
2157 float r;
2158 float g;
2159 float b;
2160 float a;
2161
2162 switch (desc.Format)
2163 {
2164 case D3DFMT_R5G6B5:
2165 {
2166 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2167
2168 a = 1.0f;
2169 b = (rgb & 0x001F) * (1.0f / 0x001F);
2170 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2171 r = (rgb & 0xF800) * (1.0f / 0xF800);
2172 }
2173 break;
2174 case D3DFMT_X1R5G5B5:
2175 {
2176 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2177
2178 a = 1.0f;
2179 b = (xrgb & 0x001F) * (1.0f / 0x001F);
2180 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
2181 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
2182 }
2183 break;
2184 case D3DFMT_A1R5G5B5:
2185 {
2186 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2187
2188 a = (argb & 0x8000) ? 1.0f : 0.0f;
2189 b = (argb & 0x001F) * (1.0f / 0x001F);
2190 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2191 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2192 }
2193 break;
2194 case D3DFMT_A8R8G8B8:
2195 {
2196 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2197
2198 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2199 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2200 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2201 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2202 }
2203 break;
2204 case D3DFMT_X8R8G8B8:
2205 {
2206 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2207
2208 a = 1.0f;
2209 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2210 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2211 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2212 }
2213 break;
2214 case D3DFMT_A2R10G10B10:
2215 {
2216 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2217
2218 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2219 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2220 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2221 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2222 }
2223 break;
2224 default:
2225 UNIMPLEMENTED(); // FIXME
2226 UNREACHABLE();
2227 }
2228
2229 switch (format)
2230 {
2231 case GL_RGBA:
2232 switch (type)
2233 {
2234 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002235 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2236 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2237 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2238 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002239 break;
2240 default: UNREACHABLE();
2241 }
2242 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002243 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002244 switch (type)
2245 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002246 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002247 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2248 ((unsigned short)(31 * b + 0.5f) << 0) |
2249 ((unsigned short)(63 * g + 0.5f) << 5) |
2250 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002251 break;
2252 default: UNREACHABLE();
2253 }
2254 break;
2255 default: UNREACHABLE();
2256 }
2257 }
2258 }
2259
2260 systemSurface->UnlockRect();
2261
2262 systemSurface->Release();
2263}
2264
2265void Context::clear(GLbitfield mask)
2266{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002267 Framebuffer *framebufferObject = getFramebuffer();
2268
2269 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2270 {
2271 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2272
2273 return;
2274 }
2275
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002276 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002277 IDirect3DDevice9 *device = getDevice();
2278 DWORD flags = 0;
2279
2280 if (mask & GL_COLOR_BUFFER_BIT)
2281 {
2282 mask &= ~GL_COLOR_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002283
2284 if (framebufferObject->getColorbufferType() != GL_NONE)
2285 {
2286 flags |= D3DCLEAR_TARGET;
2287 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002288 }
2289
2290 if (mask & GL_DEPTH_BUFFER_BIT)
2291 {
2292 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002293 if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002294 {
2295 flags |= D3DCLEAR_ZBUFFER;
2296 }
2297 }
2298
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002299 GLuint stencilUnmasked = 0x0;
2300
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002301 if (mask & GL_STENCIL_BUFFER_BIT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002302 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002303 mask &= ~GL_STENCIL_BUFFER_BIT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002304 if (framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002305 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002306 IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
2307 D3DSURFACE_DESC desc;
2308 depthStencil->GetDesc(&desc);
2309
2310 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2311 stencilUnmasked = (0x1 << stencilSize) - 1;
2312
2313 if (stencilUnmasked != 0x0)
2314 {
2315 flags |= D3DCLEAR_STENCIL;
2316 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002317 }
2318 }
2319
2320 if (mask != 0)
2321 {
2322 return error(GL_INVALID_VALUE);
2323 }
2324
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002325 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2326 {
2327 return;
2328 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002329
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002330 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2331 unorm<8>(mState.colorClearValue.red),
2332 unorm<8>(mState.colorClearValue.green),
2333 unorm<8>(mState.colorClearValue.blue));
2334 float depth = clamp01(mState.depthClearValue);
2335 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002336
2337 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2338
2339 D3DSURFACE_DESC desc;
2340 renderTarget->GetDesc(&desc);
2341
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002342 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002343
2344 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002345 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002346 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002347 !(mState.colorMaskRed && mState.colorMaskGreen &&
2348 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002349
2350 if (needMaskedColorClear || needMaskedStencilClear)
2351 {
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002352 // State which is altered in all paths from this point to the clear call is saved.
2353 // State which is altered in only some paths will be flagged dirty in the case that
2354 // that path is taken.
2355 HRESULT hr;
2356 if (mMaskedClearSavedState == NULL)
2357 {
2358 hr = device->BeginStateBlock();
2359 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2360
2361 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2362 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2363 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2364 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2365 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2366 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2367 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2368 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2369 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2370 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2371 device->SetPixelShader(NULL);
2372 device->SetVertexShader(NULL);
2373 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2374 device->SetStreamSourceFreq(0, 1);
2375
2376 hr = device->EndStateBlock(&mMaskedClearSavedState);
2377 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2378 }
2379
2380 ASSERT(mMaskedClearSavedState != NULL);
2381
2382 if (mMaskedClearSavedState != NULL)
2383 {
2384 hr = mMaskedClearSavedState->Capture();
2385 ASSERT(SUCCEEDED(hr));
2386 }
2387
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002388 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2389 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2390 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2391 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2392 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2393 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2394 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2395 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2396
2397 if (flags & D3DCLEAR_TARGET)
2398 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002399 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2400 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2401 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2402 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002403 }
2404 else
2405 {
2406 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2407 }
2408
2409 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2410 {
2411 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2412 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2413 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2414 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002415 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002416 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002417 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2418 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002419 mStencilStateDirty = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002420 }
2421 else
2422 {
2423 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2424 }
2425
2426 device->SetPixelShader(NULL);
2427 device->SetVertexShader(NULL);
2428 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002429 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002430
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002431 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002432 {
2433 float x, y, z, w;
2434 D3DCOLOR diffuse;
2435 };
2436
2437 Vertex quad[4];
2438 quad[0].x = 0.0f;
2439 quad[0].y = (float)desc.Height;
2440 quad[0].z = 0.0f;
2441 quad[0].w = 1.0f;
2442 quad[0].diffuse = color;
2443
2444 quad[1].x = (float)desc.Width;
2445 quad[1].y = (float)desc.Height;
2446 quad[1].z = 0.0f;
2447 quad[1].w = 1.0f;
2448 quad[1].diffuse = color;
2449
2450 quad[2].x = 0.0f;
2451 quad[2].y = 0.0f;
2452 quad[2].z = 0.0f;
2453 quad[2].w = 1.0f;
2454 quad[2].diffuse = color;
2455
2456 quad[3].x = (float)desc.Width;
2457 quad[3].y = 0.0f;
2458 quad[3].z = 0.0f;
2459 quad[3].w = 1.0f;
2460 quad[3].diffuse = color;
2461
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002462 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002463 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002464
2465 if (flags & D3DCLEAR_ZBUFFER)
2466 {
2467 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2468 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2469 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2470 }
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002471
2472 if (mMaskedClearSavedState != NULL)
2473 {
2474 mMaskedClearSavedState->Apply();
2475 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002476 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002477 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002478 {
2479 device->Clear(0, NULL, flags, color, depth, stencil);
2480 }
2481}
2482
2483void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2484{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002485 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002486 {
2487 return error(GL_INVALID_OPERATION);
2488 }
2489
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002490 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002491 IDirect3DDevice9 *device = getDevice();
2492 D3DPRIMITIVETYPE primitiveType;
2493 int primitiveCount;
2494
2495 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2496 return error(GL_INVALID_ENUM);
2497
2498 if (primitiveCount <= 0)
2499 {
2500 return;
2501 }
2502
2503 if (!applyRenderTarget(false))
2504 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002505 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002506 }
2507
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002508 applyState(mode);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002509
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002510 TranslatedIndexData indexInfo;
2511 bool useIndexing;
2512 GLenum err = applyVertexBuffer(mode, first, count, &useIndexing, &indexInfo);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002513 if (err != GL_NO_ERROR)
2514 {
2515 return error(err);
2516 }
2517
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002518 applyShaders();
2519 applyTextures();
2520
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002521 if (!getCurrentProgram()->validateSamplers())
2522 {
2523 return error(GL_INVALID_OPERATION);
2524 }
2525
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002526 if (!cullSkipsDraw(mode))
2527 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002528 display->startScene();
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002529 if (useIndexing)
2530 {
2531 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
2532 }
2533 else
2534 {
2535 device->DrawPrimitive(primitiveType, 0, primitiveCount);
2536 }
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002537 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002538}
2539
2540void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2541{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002542 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002543 {
2544 return error(GL_INVALID_OPERATION);
2545 }
2546
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002547 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002548 {
2549 return error(GL_INVALID_OPERATION);
2550 }
2551
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002552 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002553 IDirect3DDevice9 *device = getDevice();
2554 D3DPRIMITIVETYPE primitiveType;
2555 int primitiveCount;
2556
2557 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2558 return error(GL_INVALID_ENUM);
2559
2560 if (primitiveCount <= 0)
2561 {
2562 return;
2563 }
2564
2565 if (!applyRenderTarget(false))
2566 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002567 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002568 }
2569
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002570 applyState(mode);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002571
2572 TranslatedIndexData indexInfo;
2573 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2574 if (err != GL_NO_ERROR)
2575 {
2576 return error(err);
2577 }
2578
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002579 err = applyVertexBuffer(indexInfo);
2580 if (err != GL_NO_ERROR)
2581 {
2582 return error(err);
2583 }
2584
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002585 applyShaders();
2586 applyTextures();
2587
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002588 if (!getCurrentProgram()->validateSamplers())
2589 {
2590 return error(GL_INVALID_OPERATION);
2591 }
2592
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002593 if (!cullSkipsDraw(mode))
2594 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002595 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002596 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 +00002597 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002598}
2599
2600void Context::finish()
2601{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002602 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002603 IDirect3DDevice9 *device = getDevice();
2604 IDirect3DQuery9 *occlusionQuery = NULL;
2605
2606 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2607
2608 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2609 {
2610 return error(GL_OUT_OF_MEMORY);
2611 }
2612
2613 ASSERT(SUCCEEDED(result));
2614
2615 if (occlusionQuery)
2616 {
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002617 IDirect3DStateBlock9 *savedState = NULL;
2618 device->CreateStateBlock(D3DSBT_ALL, &savedState);
2619
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002620 occlusionQuery->Issue(D3DISSUE_BEGIN);
2621
2622 // Render something outside the render target
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002623 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002624 device->SetPixelShader(NULL);
2625 device->SetVertexShader(NULL);
2626 device->SetFVF(D3DFVF_XYZRHW);
2627 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002628 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002629 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002630
2631 occlusionQuery->Issue(D3DISSUE_END);
2632
2633 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2634 {
2635 // Keep polling, but allow other threads to do something useful first
2636 Sleep(0);
2637 }
2638
2639 occlusionQuery->Release();
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002640
2641 if (savedState)
2642 {
2643 savedState->Apply();
2644 savedState->Release();
2645 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002646 }
2647}
2648
2649void Context::flush()
2650{
2651 IDirect3DDevice9 *device = getDevice();
2652 IDirect3DQuery9 *eventQuery = NULL;
2653
2654 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2655
2656 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2657 {
2658 return error(GL_OUT_OF_MEMORY);
2659 }
2660
2661 ASSERT(SUCCEEDED(result));
2662
2663 if (eventQuery)
2664 {
2665 eventQuery->Issue(D3DISSUE_END);
2666
2667 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2668 {
2669 // Keep polling, but allow other threads to do something useful first
2670 Sleep(0);
2671 }
2672
2673 eventQuery->Release();
2674 }
2675}
2676
2677void Context::recordInvalidEnum()
2678{
2679 mInvalidEnum = true;
2680}
2681
2682void Context::recordInvalidValue()
2683{
2684 mInvalidValue = true;
2685}
2686
2687void Context::recordInvalidOperation()
2688{
2689 mInvalidOperation = true;
2690}
2691
2692void Context::recordOutOfMemory()
2693{
2694 mOutOfMemory = true;
2695}
2696
2697void Context::recordInvalidFramebufferOperation()
2698{
2699 mInvalidFramebufferOperation = true;
2700}
2701
2702// Get one of the recorded errors and clear its flag, if any.
2703// [OpenGL ES 2.0.24] section 2.5 page 13.
2704GLenum Context::getError()
2705{
2706 if (mInvalidEnum)
2707 {
2708 mInvalidEnum = false;
2709
2710 return GL_INVALID_ENUM;
2711 }
2712
2713 if (mInvalidValue)
2714 {
2715 mInvalidValue = false;
2716
2717 return GL_INVALID_VALUE;
2718 }
2719
2720 if (mInvalidOperation)
2721 {
2722 mInvalidOperation = false;
2723
2724 return GL_INVALID_OPERATION;
2725 }
2726
2727 if (mOutOfMemory)
2728 {
2729 mOutOfMemory = false;
2730
2731 return GL_OUT_OF_MEMORY;
2732 }
2733
2734 if (mInvalidFramebufferOperation)
2735 {
2736 mInvalidFramebufferOperation = false;
2737
2738 return GL_INVALID_FRAMEBUFFER_OPERATION;
2739 }
2740
2741 return GL_NO_ERROR;
2742}
2743
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002744bool Context::supportsShaderModel3() const
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002745{
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002746 return mSupportsShaderModel3;
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002747}
2748
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002749void Context::detachBuffer(GLuint buffer)
2750{
2751 // [OpenGL ES 2.0.24] section 2.9 page 22:
2752 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2753 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2754
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002755 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002756 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002757 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002758 }
2759
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002760 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002761 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002762 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002763 }
2764
2765 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2766 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002767 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002768 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002769 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002770 }
2771 }
2772}
2773
2774void Context::detachTexture(GLuint texture)
2775{
2776 // [OpenGL ES 2.0.24] section 3.8 page 84:
2777 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2778 // rebound to texture object zero
2779
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002780 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002781 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002782 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002783 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002784 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002785 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002786 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002787 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002788 }
2789 }
2790
2791 // [OpenGL ES 2.0.24] section 4.4 page 112:
2792 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2793 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2794 // image was attached in the currently bound framebuffer.
2795
2796 Framebuffer *framebuffer = getFramebuffer();
2797
2798 if (framebuffer)
2799 {
2800 framebuffer->detachTexture(texture);
2801 }
2802}
2803
2804void Context::detachFramebuffer(GLuint framebuffer)
2805{
2806 // [OpenGL ES 2.0.24] section 4.4 page 107:
2807 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2808 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2809
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002810 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002811 {
2812 bindFramebuffer(0);
2813 }
2814}
2815
2816void Context::detachRenderbuffer(GLuint renderbuffer)
2817{
2818 // [OpenGL ES 2.0.24] section 4.4 page 109:
2819 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2820 // had been executed with the target RENDERBUFFER and name of zero.
2821
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002822 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002823 {
2824 bindRenderbuffer(0);
2825 }
2826
2827 // [OpenGL ES 2.0.24] section 4.4 page 111:
2828 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2829 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2830 // point to which this image was attached in the currently bound framebuffer.
2831
2832 Framebuffer *framebuffer = getFramebuffer();
2833
2834 if (framebuffer)
2835 {
2836 framebuffer->detachRenderbuffer(renderbuffer);
2837 }
2838}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002839
2840Texture *Context::getIncompleteTexture(SamplerType type)
2841{
2842 Texture *t = mIncompleteTextures[type];
2843
2844 if (t == NULL)
2845 {
2846 static const GLubyte color[] = { 0, 0, 0, 255 };
2847
2848 switch (type)
2849 {
2850 default:
2851 UNREACHABLE();
2852 // default falls through to SAMPLER_2D
2853
2854 case SAMPLER_2D:
2855 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002856 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002857 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002858 t = incomplete2d;
2859 }
2860 break;
2861
2862 case SAMPLER_CUBE:
2863 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002864 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002865
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002866 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2867 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2868 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2869 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2870 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2871 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002872
2873 t = incompleteCube;
2874 }
2875 break;
2876 }
2877
2878 mIncompleteTextures[type] = t;
2879 }
2880
2881 return t;
2882}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002883
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002884bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002885{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002886 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002887}
2888
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002889bool Context::isTriangleMode(GLenum drawMode)
2890{
2891 switch (drawMode)
2892 {
2893 case GL_TRIANGLES:
2894 case GL_TRIANGLE_FAN:
2895 case GL_TRIANGLE_STRIP:
2896 return true;
2897 case GL_POINTS:
2898 case GL_LINES:
2899 case GL_LINE_LOOP:
2900 case GL_LINE_STRIP:
2901 return false;
2902 default: UNREACHABLE();
2903 }
2904
2905 return false;
2906}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002907
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002908bool Context::hasStencil()
2909{
2910 Framebuffer *framebufferObject = getFramebuffer();
2911
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002912 if (framebufferObject && framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002913 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002914 DepthStencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002915
2916 if (stencilbufferObject)
2917 {
2918 return stencilbufferObject->getStencilSize() > 0;
2919 }
2920 }
2921
2922 return false;
2923}
2924
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002925void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2926{
2927 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2928
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002929 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2930 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2931 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2932 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002933
2934 mVertexDataManager->dirtyCurrentValues();
2935}
2936
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002937void Context::initExtensionString()
2938{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002939 mExtensionString += "GL_OES_packed_depth_stencil ";
2940
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002941 if (mBufferBackEnd->supportIntIndices())
2942 {
2943 mExtensionString += "GL_OES_element_index_uint ";
2944 }
2945
2946 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2947 if (end != std::string::npos)
2948 {
2949 mExtensionString.resize(end+1);
2950 }
2951}
2952
2953const char *Context::getExtensionString() const
2954{
2955 return mExtensionString.c_str();
2956}
2957
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002958}
2959
2960extern "C"
2961{
2962gl::Context *glCreateContext(const egl::Config *config)
2963{
2964 return new gl::Context(config);
2965}
2966
2967void glDestroyContext(gl::Context *context)
2968{
2969 delete context;
2970
2971 if (context == gl::getContext())
2972 {
2973 gl::makeCurrent(NULL, NULL, NULL);
2974 }
2975}
2976
2977void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2978{
2979 gl::makeCurrent(context, display, surface);
2980}
2981
2982gl::Context *glGetCurrentContext()
2983{
2984 return gl::getContext();
2985}
2986}