blob: 2257ed6795d0c022839c4a5962a6e9d8b17bbd66 [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;
116 mDepthbufferZero = NULL;
117 mStencilbufferZero = NULL;
118
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000119 mState.activeSampler = 0;
120 mState.arrayBuffer = 0;
121 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122 bindTextureCubeMap(0);
123 bindTexture2D(0);
124 bindFramebuffer(0);
125 bindRenderbuffer(0);
126
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000127 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000129 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
130 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000131 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000132 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133 }
134
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000135 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
136 {
137 mIncompleteTextures[type] = NULL;
138 }
139
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000140 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000142 mState.packAlignment = 4;
143 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000144
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000145 mBufferBackEnd = NULL;
146 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000147 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000148 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000149
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150 mInvalidEnum = false;
151 mInvalidValue = false;
152 mInvalidOperation = false;
153 mOutOfMemory = false;
154 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000155
156 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000157
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000158 mMaskedClearSavedState = NULL;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000159 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000160}
161
162Context::~Context()
163{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000164 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000165
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000166 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
167 {
168 delete mIncompleteTextures[type];
169 }
170
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000171 delete mTexture2DZero;
172 delete mTextureCubeMapZero;
173
174 delete mColorbufferZero;
175 delete mDepthbufferZero;
176 delete mStencilbufferZero;
177
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000178 delete mBufferBackEnd;
179 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000180 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000181 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000182
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183 while (!mBufferMap.empty())
184 {
185 deleteBuffer(mBufferMap.begin()->first);
186 }
187
188 while (!mProgramMap.empty())
189 {
190 deleteProgram(mProgramMap.begin()->first);
191 }
192
193 while (!mShaderMap.empty())
194 {
195 deleteShader(mShaderMap.begin()->first);
196 }
197
198 while (!mFramebufferMap.empty())
199 {
200 deleteFramebuffer(mFramebufferMap.begin()->first);
201 }
202
203 while (!mRenderbufferMap.empty())
204 {
205 deleteRenderbuffer(mRenderbufferMap.begin()->first);
206 }
207
208 while (!mTextureMap.empty())
209 {
210 deleteTexture(mTextureMap.begin()->first);
211 }
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000212
213 if (mMaskedClearSavedState)
214 {
215 mMaskedClearSavedState->Release();
216 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000217}
218
219void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
220{
221 IDirect3DDevice9 *device = display->getDevice();
222
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000223 if (!mHasBeenCurrent)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000224 {
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000225 mDeviceCaps = display->getDeviceCaps();
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000226
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000227 mBufferBackEnd = new Dx9BackEnd(this, device);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000228 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000229 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000230 mBlit = new Blit(this);
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000231
232 initExtensionString();
233
234 mState.viewportX = 0;
235 mState.viewportY = 0;
236 mState.viewportWidth = surface->getWidth();
237 mState.viewportHeight = surface->getHeight();
238
239 mState.scissorX = 0;
240 mState.scissorY = 0;
241 mState.scissorWidth = surface->getWidth();
242 mState.scissorHeight = surface->getHeight();
243
244 mHasBeenCurrent = true;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000245 }
246
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
248 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000249 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250
251 Framebuffer *framebufferZero = new Framebuffer();
252 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000253 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
254 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255
256 setFramebufferZero(framebufferZero);
257 setColorbufferZero(colorbufferZero);
258 setDepthbufferZero(depthbufferZero);
259 setStencilbufferZero(stencilbufferZero);
260
261 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
262 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
263 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
264
265 defaultRenderTarget->Release();
266
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000267 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000269 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000271
daniel@transgaming.combe5a0862010-07-28 19:20:37 +0000272 mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000273
274 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000275}
276
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000277// 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 +0000278void Context::markAllStateDirty()
279{
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000280 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000281 mAppliedDepthbufferSerial = 0;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000282 mAppliedProgram = 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000283
284 mClearStateDirty = true;
285 mCullStateDirty = true;
286 mDepthStateDirty = true;
287 mMaskStateDirty = true;
288 mBlendStateDirty = true;
289 mStencilStateDirty = true;
290 mPolygonOffsetStateDirty = true;
291 mScissorStateDirty = true;
292 mSampleStateDirty = true;
293 mDitherStateDirty = true;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000294}
295
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000296void Context::setClearColor(float red, float green, float blue, float alpha)
297{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000298 mState.colorClearValue.red = red;
299 mState.colorClearValue.green = green;
300 mState.colorClearValue.blue = blue;
301 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302}
303
304void Context::setClearDepth(float depth)
305{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000306 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000307}
308
309void Context::setClearStencil(int stencil)
310{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000311 mState.stencilClearValue = stencil;
312}
313
314void Context::setCullFace(bool enabled)
315{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000316 if (mState.cullFace != enabled)
317 {
318 mState.cullFace = enabled;
319 mCullStateDirty = true;
320 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000321}
322
323bool Context::isCullFaceEnabled() const
324{
325 return mState.cullFace;
326}
327
328void Context::setCullMode(GLenum mode)
329{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000330 if (mState.cullMode != mode)
331 {
332 mState.cullMode = mode;
333 mCullStateDirty = true;
334 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000335}
336
337void Context::setFrontFace(GLenum front)
338{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000339 if (mState.frontFace != front)
340 {
341 mState.frontFace = front;
342 mFrontFaceDirty = true;
343 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000344}
345
346void Context::setDepthTest(bool enabled)
347{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000348 if (mState.depthTest != enabled)
349 {
350 mState.depthTest = enabled;
351 mDepthStateDirty = true;
352 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000353}
354
355bool Context::isDepthTestEnabled() const
356{
357 return mState.depthTest;
358}
359
360void Context::setDepthFunc(GLenum depthFunc)
361{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000362 if (mState.depthFunc != depthFunc)
363 {
364 mState.depthFunc = depthFunc;
365 mDepthStateDirty = true;
366 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000367}
368
369void Context::setDepthRange(float zNear, float zFar)
370{
371 mState.zNear = zNear;
372 mState.zFar = zFar;
373}
374
375void Context::setBlend(bool enabled)
376{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000377 if (mState.blend != enabled)
378 {
379 mState.blend = enabled;
380 mBlendStateDirty = true;
381 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000382}
383
384bool Context::isBlendEnabled() const
385{
386 return mState.blend;
387}
388
389void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
390{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000391 if (mState.sourceBlendRGB != sourceRGB ||
392 mState.sourceBlendAlpha != sourceAlpha ||
393 mState.destBlendRGB != destRGB ||
394 mState.destBlendAlpha != destAlpha)
395 {
396 mState.sourceBlendRGB = sourceRGB;
397 mState.destBlendRGB = destRGB;
398 mState.sourceBlendAlpha = sourceAlpha;
399 mState.destBlendAlpha = destAlpha;
400 mBlendStateDirty = true;
401 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000402}
403
404void Context::setBlendColor(float red, float green, float blue, float alpha)
405{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000406 if (mState.blendColor.red != red ||
407 mState.blendColor.green != green ||
408 mState.blendColor.blue != blue ||
409 mState.blendColor.alpha != alpha)
410 {
411 mState.blendColor.red = red;
412 mState.blendColor.green = green;
413 mState.blendColor.blue = blue;
414 mState.blendColor.alpha = alpha;
415 mBlendStateDirty = true;
416 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000417}
418
419void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
420{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000421 if (mState.blendEquationRGB != rgbEquation ||
422 mState.blendEquationAlpha != alphaEquation)
423 {
424 mState.blendEquationRGB = rgbEquation;
425 mState.blendEquationAlpha = alphaEquation;
426 mBlendStateDirty = true;
427 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000428}
429
430void Context::setStencilTest(bool enabled)
431{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000432 if (mState.stencilTest != enabled)
433 {
434 mState.stencilTest = enabled;
435 mStencilStateDirty = true;
436 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000437}
438
439bool Context::isStencilTestEnabled() const
440{
441 return mState.stencilTest;
442}
443
444void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
445{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000446 if (mState.stencilFunc != stencilFunc ||
447 mState.stencilRef != stencilRef ||
448 mState.stencilMask != stencilMask)
449 {
450 mState.stencilFunc = stencilFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000451 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000452 mState.stencilMask = stencilMask;
453 mStencilStateDirty = true;
454 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000455}
456
457void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
458{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000459 if (mState.stencilBackFunc != stencilBackFunc ||
460 mState.stencilBackRef != stencilBackRef ||
461 mState.stencilBackMask != stencilBackMask)
462 {
463 mState.stencilBackFunc = stencilBackFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000464 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000465 mState.stencilBackMask = stencilBackMask;
466 mStencilStateDirty = true;
467 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000468}
469
470void Context::setStencilWritemask(GLuint stencilWritemask)
471{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000472 if (mState.stencilWritemask != stencilWritemask)
473 {
474 mState.stencilWritemask = stencilWritemask;
475 mStencilStateDirty = true;
476 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000477}
478
479void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
480{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000481 if (mState.stencilBackWritemask != stencilBackWritemask)
482 {
483 mState.stencilBackWritemask = stencilBackWritemask;
484 mStencilStateDirty = true;
485 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000486}
487
488void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
489{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000490 if (mState.stencilFail != stencilFail ||
491 mState.stencilPassDepthFail != stencilPassDepthFail ||
492 mState.stencilPassDepthPass != stencilPassDepthPass)
493 {
494 mState.stencilFail = stencilFail;
495 mState.stencilPassDepthFail = stencilPassDepthFail;
496 mState.stencilPassDepthPass = stencilPassDepthPass;
497 mStencilStateDirty = true;
498 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000499}
500
501void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
502{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000503 if (mState.stencilBackFail != stencilBackFail ||
504 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
505 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
506 {
507 mState.stencilBackFail = stencilBackFail;
508 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
509 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
510 mStencilStateDirty = true;
511 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000512}
513
514void Context::setPolygonOffsetFill(bool enabled)
515{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000516 if (mState.polygonOffsetFill != enabled)
517 {
518 mState.polygonOffsetFill = enabled;
519 mPolygonOffsetStateDirty = true;
520 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000521}
522
523bool Context::isPolygonOffsetFillEnabled() const
524{
525 return mState.polygonOffsetFill;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000526
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000527}
528
529void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
530{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000531 if (mState.polygonOffsetFactor != factor ||
532 mState.polygonOffsetUnits != units)
533 {
534 mState.polygonOffsetFactor = factor;
535 mState.polygonOffsetUnits = units;
536 mPolygonOffsetStateDirty = true;
537 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000538}
539
540void Context::setSampleAlphaToCoverage(bool enabled)
541{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000542 if (mState.sampleAlphaToCoverage != enabled)
543 {
544 mState.sampleAlphaToCoverage = enabled;
545 mSampleStateDirty = true;
546 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000547}
548
549bool Context::isSampleAlphaToCoverageEnabled() const
550{
551 return mState.sampleAlphaToCoverage;
552}
553
554void Context::setSampleCoverage(bool enabled)
555{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000556 if (mState.sampleCoverage != enabled)
557 {
558 mState.sampleCoverage = enabled;
559 mSampleStateDirty = true;
560 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000561}
562
563bool Context::isSampleCoverageEnabled() const
564{
565 return mState.sampleCoverage;
566}
567
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +0000568void Context::setSampleCoverageParams(GLclampf value, bool invert)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000569{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000570 if (mState.sampleCoverageValue != value ||
571 mState.sampleCoverageInvert != invert)
572 {
573 mState.sampleCoverageValue = value;
574 mState.sampleCoverageInvert = invert;
575 mSampleStateDirty = true;
576 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000577}
578
579void Context::setScissorTest(bool enabled)
580{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000581 if (mState.scissorTest != enabled)
582 {
583 mState.scissorTest = enabled;
584 mScissorStateDirty = true;
585 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000586}
587
588bool Context::isScissorTestEnabled() const
589{
590 return mState.scissorTest;
591}
592
593void Context::setDither(bool enabled)
594{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000595 if (mState.dither != enabled)
596 {
597 mState.dither = enabled;
598 mDitherStateDirty = true;
599 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000600}
601
602bool Context::isDitherEnabled() const
603{
604 return mState.dither;
605}
606
607void Context::setLineWidth(GLfloat width)
608{
609 mState.lineWidth = width;
610}
611
612void Context::setGenerateMipmapHint(GLenum hint)
613{
614 mState.generateMipmapHint = hint;
615}
616
617void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
618{
619 mState.viewportX = x;
620 mState.viewportY = y;
621 mState.viewportWidth = width;
622 mState.viewportHeight = height;
623}
624
625void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
626{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000627 if (mState.scissorX != x || mState.scissorY != y ||
628 mState.scissorWidth != width || mState.scissorHeight != height)
629 {
630 mState.scissorX = x;
631 mState.scissorY = y;
632 mState.scissorWidth = width;
633 mState.scissorHeight = height;
634 mScissorStateDirty = true;
635 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000636}
637
638void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
639{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000640 if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
641 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
642 {
643 mState.colorMaskRed = red;
644 mState.colorMaskGreen = green;
645 mState.colorMaskBlue = blue;
646 mState.colorMaskAlpha = alpha;
647 mMaskStateDirty = true;
648 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000649}
650
651void Context::setDepthMask(bool mask)
652{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000653 if (mState.depthMask != mask)
654 {
655 mState.depthMask = mask;
656 mMaskStateDirty = true;
657 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000658}
659
660void Context::setActiveSampler(int active)
661{
662 mState.activeSampler = active;
663}
664
665GLuint Context::getFramebufferHandle() const
666{
667 return mState.framebuffer;
668}
669
670GLuint Context::getRenderbufferHandle() const
671{
672 return mState.renderbuffer;
673}
674
675GLuint Context::getArrayBufferHandle() const
676{
677 return mState.arrayBuffer;
678}
679
680void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
681{
682 mState.vertexAttribute[attribNum].mEnabled = enabled;
683}
684
685const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
686{
687 return mState.vertexAttribute[attribNum];
688}
689
690void Context::setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type, bool normalized,
691 GLsizei stride, const void *pointer)
692{
693 mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer;
694 mState.vertexAttribute[attribNum].mSize = size;
695 mState.vertexAttribute[attribNum].mType = type;
696 mState.vertexAttribute[attribNum].mNormalized = normalized;
697 mState.vertexAttribute[attribNum].mStride = stride;
698 mState.vertexAttribute[attribNum].mPointer = pointer;
699}
700
701const void *Context::getVertexAttribPointer(unsigned int attribNum) const
702{
703 return mState.vertexAttribute[attribNum].mPointer;
704}
705
706// returns entire set of attributes as a block
707const AttributeState *Context::getVertexAttribBlock()
708{
709 return mState.vertexAttribute;
710}
711
712void Context::setPackAlignment(GLint alignment)
713{
714 mState.packAlignment = alignment;
715}
716
717GLint Context::getPackAlignment() const
718{
719 return mState.packAlignment;
720}
721
722void Context::setUnpackAlignment(GLint alignment)
723{
724 mState.unpackAlignment = alignment;
725}
726
727GLint Context::getUnpackAlignment() const
728{
729 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000730}
731
732// Returns an unused buffer name
733GLuint Context::createBuffer()
734{
735 unsigned int handle = 1;
736
737 while (mBufferMap.find(handle) != mBufferMap.end())
738 {
739 handle++;
740 }
741
742 mBufferMap[handle] = NULL;
743
744 return handle;
745}
746
747// Returns an unused shader/program name
748GLuint Context::createShader(GLenum type)
749{
750 unsigned int handle = 1;
751
752 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
753 {
754 handle++;
755 }
756
757 if (type == GL_VERTEX_SHADER)
758 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000759 mShaderMap[handle] = new VertexShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000760 }
761 else if (type == GL_FRAGMENT_SHADER)
762 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000763 mShaderMap[handle] = new FragmentShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000764 }
765 else UNREACHABLE();
766
767 return handle;
768}
769
770// Returns an unused program/shader name
771GLuint Context::createProgram()
772{
773 unsigned int handle = 1;
774
775 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
776 {
777 handle++;
778 }
779
780 mProgramMap[handle] = new Program();
781
782 return handle;
783}
784
785// Returns an unused texture name
786GLuint Context::createTexture()
787{
788 unsigned int handle = 1;
789
790 while (mTextureMap.find(handle) != mTextureMap.end())
791 {
792 handle++;
793 }
794
795 mTextureMap[handle] = NULL;
796
797 return handle;
798}
799
800// Returns an unused framebuffer name
801GLuint Context::createFramebuffer()
802{
803 unsigned int handle = 1;
804
805 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
806 {
807 handle++;
808 }
809
810 mFramebufferMap[handle] = NULL;
811
812 return handle;
813}
814
815// Returns an unused renderbuffer name
816GLuint Context::createRenderbuffer()
817{
818 unsigned int handle = 1;
819
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000820 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000821 {
822 handle++;
823 }
824
825 mRenderbufferMap[handle] = NULL;
826
827 return handle;
828}
829
830void Context::deleteBuffer(GLuint buffer)
831{
832 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
833
834 if (bufferObject != mBufferMap.end())
835 {
836 detachBuffer(buffer);
837
838 delete bufferObject->second;
839 mBufferMap.erase(bufferObject);
840 }
841}
842
843void Context::deleteShader(GLuint shader)
844{
845 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
846
847 if (shaderObject != mShaderMap.end())
848 {
849 if (!shaderObject->second->isAttached())
850 {
851 delete shaderObject->second;
852 mShaderMap.erase(shaderObject);
853 }
854 else
855 {
856 shaderObject->second->flagForDeletion();
857 }
858 }
859}
860
861void Context::deleteProgram(GLuint program)
862{
863 ProgramMap::iterator programObject = mProgramMap.find(program);
864
865 if (programObject != mProgramMap.end())
866 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000867 if (program != mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000868 {
869 delete programObject->second;
870 mProgramMap.erase(programObject);
871 }
872 else
873 {
874 programObject->second->flagForDeletion();
875 }
876 }
877}
878
879void Context::deleteTexture(GLuint texture)
880{
881 TextureMap::iterator textureObject = mTextureMap.find(texture);
882
883 if (textureObject != mTextureMap.end())
884 {
885 detachTexture(texture);
886
887 if (texture != 0)
888 {
889 delete textureObject->second;
890 }
891
892 mTextureMap.erase(textureObject);
893 }
894}
895
896void Context::deleteFramebuffer(GLuint framebuffer)
897{
898 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
899
900 if (framebufferObject != mFramebufferMap.end())
901 {
902 detachFramebuffer(framebuffer);
903
904 delete framebufferObject->second;
905 mFramebufferMap.erase(framebufferObject);
906 }
907}
908
909void Context::deleteRenderbuffer(GLuint renderbuffer)
910{
911 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
912
913 if (renderbufferObject != mRenderbufferMap.end())
914 {
915 detachRenderbuffer(renderbuffer);
916
917 delete renderbufferObject->second;
918 mRenderbufferMap.erase(renderbufferObject);
919 }
920}
921
922void Context::bindArrayBuffer(unsigned int buffer)
923{
924 if (buffer != 0 && !getBuffer(buffer))
925 {
daniel@transgaming.comdefa1c32010-05-18 18:51:45 +0000926 mBufferMap[buffer] = new Buffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000927 }
928
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000929 mState.arrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000930}
931
932void Context::bindElementArrayBuffer(unsigned int buffer)
933{
934 if (buffer != 0 && !getBuffer(buffer))
935 {
daniel@transgaming.comdefa1c32010-05-18 18:51:45 +0000936 mBufferMap[buffer] = new Buffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000937 }
938
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000939 mState.elementArrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000940}
941
942void Context::bindTexture2D(GLuint texture)
943{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000944 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000945 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000946 mTextureMap[texture] = new Texture2D(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000947 }
948
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000949 mState.texture2D = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000950
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000951 mState.samplerTexture[SAMPLER_2D][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000952}
953
954void Context::bindTextureCubeMap(GLuint texture)
955{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000956 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000957 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000958 mTextureMap[texture] = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000959 }
960
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000961 mState.textureCubeMap = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000962
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000963 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000964}
965
966void Context::bindFramebuffer(GLuint framebuffer)
967{
968 if (!getFramebuffer(framebuffer))
969 {
970 mFramebufferMap[framebuffer] = new Framebuffer();
971 }
972
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000973 mState.framebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000974}
975
976void Context::bindRenderbuffer(GLuint renderbuffer)
977{
978 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
979 {
980 mRenderbufferMap[renderbuffer] = new Renderbuffer();
981 }
982
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000983 mState.renderbuffer = renderbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000984}
985
986void Context::useProgram(GLuint program)
987{
988 Program *programObject = getCurrentProgram();
989
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000990 GLuint priorProgram = mState.currentProgram;
991 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000992
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000993 if (programObject && programObject->isFlaggedForDeletion())
994 {
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000995 deleteProgram(priorProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000996 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000997}
998
999void Context::setFramebufferZero(Framebuffer *buffer)
1000{
1001 delete mFramebufferMap[0];
1002 mFramebufferMap[0] = buffer;
1003}
1004
1005void Context::setColorbufferZero(Colorbuffer *buffer)
1006{
1007 delete mColorbufferZero;
1008 mColorbufferZero = buffer;
1009}
1010
1011void Context::setDepthbufferZero(Depthbuffer *buffer)
1012{
1013 delete mDepthbufferZero;
1014 mDepthbufferZero = buffer;
1015}
1016
1017void Context::setStencilbufferZero(Stencilbuffer *buffer)
1018{
1019 delete mStencilbufferZero;
1020 mStencilbufferZero = buffer;
1021}
1022
1023void Context::setRenderbuffer(Renderbuffer *buffer)
1024{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001025 delete mRenderbufferMap[mState.renderbuffer];
1026 mRenderbufferMap[mState.renderbuffer] = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001027}
1028
1029Buffer *Context::getBuffer(unsigned int handle)
1030{
1031 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001032
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001033 if (buffer == mBufferMap.end())
1034 {
1035 return NULL;
1036 }
1037 else
1038 {
1039 return buffer->second;
1040 }
1041}
1042
1043Shader *Context::getShader(unsigned int handle)
1044{
1045 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001046
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001047 if (shader == mShaderMap.end())
1048 {
1049 return NULL;
1050 }
1051 else
1052 {
1053 return shader->second;
1054 }
1055}
1056
1057Program *Context::getProgram(unsigned int handle)
1058{
1059 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001060
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001061 if (program == mProgramMap.end())
1062 {
1063 return NULL;
1064 }
1065 else
1066 {
1067 return program->second;
1068 }
1069}
1070
1071Texture *Context::getTexture(unsigned int handle)
1072{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001073 if (handle == 0) return NULL;
1074
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001075 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001076
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001077 if (texture == mTextureMap.end())
1078 {
1079 return NULL;
1080 }
1081 else
1082 {
1083 return texture->second;
1084 }
1085}
1086
1087Framebuffer *Context::getFramebuffer(unsigned int handle)
1088{
1089 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001090
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001091 if (framebuffer == mFramebufferMap.end())
1092 {
1093 return NULL;
1094 }
1095 else
1096 {
1097 return framebuffer->second;
1098 }
1099}
1100
1101Renderbuffer *Context::getRenderbuffer(unsigned int handle)
1102{
1103 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001104
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001105 if (renderbuffer == mRenderbufferMap.end())
1106 {
1107 return NULL;
1108 }
1109 else
1110 {
1111 return renderbuffer->second;
1112 }
1113}
1114
1115Colorbuffer *Context::getColorbuffer(GLuint handle)
1116{
1117 if (handle != 0)
1118 {
1119 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1120
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001121 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001122 {
1123 return static_cast<Colorbuffer*>(renderbuffer);
1124 }
1125 }
1126 else // Special case: 0 refers to different initial render targets based on the attachment type
1127 {
1128 return mColorbufferZero;
1129 }
1130
1131 return NULL;
1132}
1133
1134Depthbuffer *Context::getDepthbuffer(GLuint handle)
1135{
1136 if (handle != 0)
1137 {
1138 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1139
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001140 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001141 {
1142 return static_cast<Depthbuffer*>(renderbuffer);
1143 }
1144 }
1145 else // Special case: 0 refers to different initial render targets based on the attachment type
1146 {
1147 return mDepthbufferZero;
1148 }
1149
1150 return NULL;
1151}
1152
1153Stencilbuffer *Context::getStencilbuffer(GLuint handle)
1154{
1155 if (handle != 0)
1156 {
1157 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1158
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001159 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001160 {
1161 return static_cast<Stencilbuffer*>(renderbuffer);
1162 }
1163 }
1164 else
1165 {
1166 return mStencilbufferZero;
1167 }
1168
1169 return NULL;
1170}
1171
1172Buffer *Context::getArrayBuffer()
1173{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001174 return getBuffer(mState.arrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001175}
1176
1177Buffer *Context::getElementArrayBuffer()
1178{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001179 return getBuffer(mState.elementArrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001180}
1181
1182Program *Context::getCurrentProgram()
1183{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001184 return getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001185}
1186
1187Texture2D *Context::getTexture2D()
1188{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001189 if (mState.texture2D == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001190 {
1191 return mTexture2DZero;
1192 }
1193
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001194 return (Texture2D*)getTexture(mState.texture2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001195}
1196
1197TextureCubeMap *Context::getTextureCubeMap()
1198{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001199 if (mState.textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001200 {
1201 return mTextureCubeMapZero;
1202 }
1203
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001204 return (TextureCubeMap*)getTexture(mState.textureCubeMap);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001205}
1206
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001207Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001208{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001209 GLuint texid = mState.samplerTexture[type][sampler];
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001210
1211 if (texid == 0)
1212 {
1213 switch (type)
1214 {
1215 default: UNREACHABLE();
1216 case SAMPLER_2D: return mTexture2DZero;
1217 case SAMPLER_CUBE: return mTextureCubeMapZero;
1218 }
1219 }
1220
1221 return getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001222}
1223
1224Framebuffer *Context::getFramebuffer()
1225{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001226 return getFramebuffer(mState.framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001227}
1228
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001229bool Context::getBooleanv(GLenum pname, GLboolean *params)
1230{
1231 switch (pname)
1232 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001233 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1234 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1235 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001236 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001237 params[0] = mState.colorMaskRed;
1238 params[1] = mState.colorMaskGreen;
1239 params[2] = mState.colorMaskBlue;
1240 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001241 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001242 case GL_CULL_FACE: *params = mState.cullFace;
1243 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
1244 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
1245 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
1246 case GL_SCISSOR_TEST: *params = mState.scissorTest;
1247 case GL_STENCIL_TEST: *params = mState.stencilTest;
1248 case GL_DEPTH_TEST: *params = mState.depthTest;
1249 case GL_BLEND: *params = mState.blend;
1250 case GL_DITHER: *params = mState.dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001251 default:
1252 return false;
1253 }
1254
1255 return true;
1256}
1257
1258bool Context::getFloatv(GLenum pname, GLfloat *params)
1259{
1260 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1261 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1262 // GetIntegerv as its native query function. As it would require conversion in any
1263 // case, this should make no difference to the calling application.
1264 switch (pname)
1265 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001266 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1267 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1268 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1269 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1270 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001271 case GL_ALIASED_LINE_WIDTH_RANGE:
1272 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1273 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1274 break;
1275 case GL_ALIASED_POINT_SIZE_RANGE:
1276 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001277 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 +00001278 break;
1279 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001280 params[0] = mState.zNear;
1281 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001282 break;
1283 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001284 params[0] = mState.colorClearValue.red;
1285 params[1] = mState.colorClearValue.green;
1286 params[2] = mState.colorClearValue.blue;
1287 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001288 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001289 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001290 params[0] = mState.blendColor.red;
1291 params[1] = mState.blendColor.green;
1292 params[2] = mState.blendColor.blue;
1293 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001294 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001295 default:
1296 return false;
1297 }
1298
1299 return true;
1300}
1301
1302bool Context::getIntegerv(GLenum pname, GLint *params)
1303{
1304 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1305 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1306 // GetIntegerv as its native query function. As it would require conversion in any
1307 // case, this should make no difference to the calling application. You may find it in
1308 // Context::getFloatv.
1309 switch (pname)
1310 {
1311 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1312 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1313 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
1314 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1315 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1316 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1317 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
1318 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001319 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1320 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
1321 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
1322 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
1323 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer; break;
1324 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer; break;
1325 case GL_FRAMEBUFFER_BINDING: *params = mState.framebuffer; break;
1326 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer; break;
1327 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1328 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1329 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1330 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1331 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
1332 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1333 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1334 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1335 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1336 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1337 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1338 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1339 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1340 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1341 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1342 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1343 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1344 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1345 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1346 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1347 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1348 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1349 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1350 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1351 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1352 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1353 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
1354 case GL_SUBPIXEL_BITS: *params = 4; break;
1355 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
1356 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
1357 case GL_SAMPLE_BUFFERS: *params = 0; break;
1358 case GL_SAMPLES: *params = 0; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001359 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1360 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1361 case GL_MAX_VIEWPORT_DIMS:
1362 {
1363 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
1364 params[0] = maxDimension;
1365 params[1] = maxDimension;
1366 }
1367 break;
1368 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001369 params[0] = mState.viewportX;
1370 params[1] = mState.viewportY;
1371 params[2] = mState.viewportWidth;
1372 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001373 break;
1374 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001375 params[0] = mState.scissorX;
1376 params[1] = mState.scissorY;
1377 params[2] = mState.scissorWidth;
1378 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001379 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001380 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1381 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001382 case GL_RED_BITS:
1383 case GL_GREEN_BITS:
1384 case GL_BLUE_BITS:
1385 case GL_ALPHA_BITS:
1386 {
1387 gl::Framebuffer *framebuffer = getFramebuffer();
1388 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1389
1390 if (colorbuffer)
1391 {
1392 switch (pname)
1393 {
1394 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1395 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1396 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1397 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1398 }
1399 }
1400 else
1401 {
1402 *params = 0;
1403 }
1404 }
1405 break;
1406 case GL_DEPTH_BITS:
1407 {
1408 gl::Framebuffer *framebuffer = getFramebuffer();
1409 gl::Depthbuffer *depthbuffer = framebuffer->getDepthbuffer();
1410
1411 if (depthbuffer)
1412 {
1413 *params = depthbuffer->getDepthSize();
1414 }
1415 else
1416 {
1417 *params = 0;
1418 }
1419 }
1420 break;
1421 case GL_STENCIL_BITS:
1422 {
1423 gl::Framebuffer *framebuffer = getFramebuffer();
1424 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1425
1426 if (stencilbuffer)
1427 {
1428 *params = stencilbuffer->getStencilSize();
1429 }
1430 else
1431 {
1432 *params = 0;
1433 }
1434 }
1435 break;
1436 case GL_TEXTURE_BINDING_2D:
1437 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001438 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001439 {
1440 error(GL_INVALID_OPERATION);
1441 return false;
1442 }
1443
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001444 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001445 }
1446 break;
1447 case GL_TEXTURE_BINDING_CUBE_MAP:
1448 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001449 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001450 {
1451 error(GL_INVALID_OPERATION);
1452 return false;
1453 }
1454
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001455 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001456 }
1457 break;
1458 default:
1459 return false;
1460 }
1461
1462 return true;
1463}
1464
1465bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1466{
1467 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1468 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1469 // to the fact that it is stored internally as a float, and so would require conversion
1470 // if returned from Context::getIntegerv. Since this conversion is already implemented
1471 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1472 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1473 // application.
1474 switch (pname)
1475 {
1476 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1477 case GL_SHADER_BINARY_FORMATS:
1478 {
1479 *type = GL_INT;
1480 *numParams = 0;
1481 }
1482 break;
1483 case GL_MAX_VERTEX_ATTRIBS:
1484 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1485 case GL_MAX_VARYING_VECTORS:
1486 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1487 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1488 case GL_MAX_TEXTURE_IMAGE_UNITS:
1489 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1490 case GL_MAX_RENDERBUFFER_SIZE:
1491 case GL_NUM_SHADER_BINARY_FORMATS:
1492 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1493 case GL_ARRAY_BUFFER_BINDING:
1494 case GL_FRAMEBUFFER_BINDING:
1495 case GL_RENDERBUFFER_BINDING:
1496 case GL_CURRENT_PROGRAM:
1497 case GL_PACK_ALIGNMENT:
1498 case GL_UNPACK_ALIGNMENT:
1499 case GL_GENERATE_MIPMAP_HINT:
1500 case GL_RED_BITS:
1501 case GL_GREEN_BITS:
1502 case GL_BLUE_BITS:
1503 case GL_ALPHA_BITS:
1504 case GL_DEPTH_BITS:
1505 case GL_STENCIL_BITS:
1506 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1507 case GL_CULL_FACE_MODE:
1508 case GL_FRONT_FACE:
1509 case GL_ACTIVE_TEXTURE:
1510 case GL_STENCIL_FUNC:
1511 case GL_STENCIL_VALUE_MASK:
1512 case GL_STENCIL_REF:
1513 case GL_STENCIL_FAIL:
1514 case GL_STENCIL_PASS_DEPTH_FAIL:
1515 case GL_STENCIL_PASS_DEPTH_PASS:
1516 case GL_STENCIL_BACK_FUNC:
1517 case GL_STENCIL_BACK_VALUE_MASK:
1518 case GL_STENCIL_BACK_REF:
1519 case GL_STENCIL_BACK_FAIL:
1520 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1521 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1522 case GL_DEPTH_FUNC:
1523 case GL_BLEND_SRC_RGB:
1524 case GL_BLEND_SRC_ALPHA:
1525 case GL_BLEND_DST_RGB:
1526 case GL_BLEND_DST_ALPHA:
1527 case GL_BLEND_EQUATION_RGB:
1528 case GL_BLEND_EQUATION_ALPHA:
1529 case GL_STENCIL_WRITEMASK:
1530 case GL_STENCIL_BACK_WRITEMASK:
1531 case GL_STENCIL_CLEAR_VALUE:
1532 case GL_SUBPIXEL_BITS:
1533 case GL_MAX_TEXTURE_SIZE:
1534 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1535 case GL_SAMPLE_BUFFERS:
1536 case GL_SAMPLES:
1537 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1538 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1539 case GL_TEXTURE_BINDING_2D:
1540 case GL_TEXTURE_BINDING_CUBE_MAP:
1541 {
1542 *type = GL_INT;
1543 *numParams = 1;
1544 }
1545 break;
1546 case GL_MAX_VIEWPORT_DIMS:
1547 {
1548 *type = GL_INT;
1549 *numParams = 2;
1550 }
1551 break;
1552 case GL_VIEWPORT:
1553 case GL_SCISSOR_BOX:
1554 {
1555 *type = GL_INT;
1556 *numParams = 4;
1557 }
1558 break;
1559 case GL_SHADER_COMPILER:
1560 case GL_SAMPLE_COVERAGE_INVERT:
1561 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001562 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1563 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1564 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1565 case GL_SAMPLE_COVERAGE:
1566 case GL_SCISSOR_TEST:
1567 case GL_STENCIL_TEST:
1568 case GL_DEPTH_TEST:
1569 case GL_BLEND:
1570 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001571 {
1572 *type = GL_BOOL;
1573 *numParams = 1;
1574 }
1575 break;
1576 case GL_COLOR_WRITEMASK:
1577 {
1578 *type = GL_BOOL;
1579 *numParams = 4;
1580 }
1581 break;
1582 case GL_POLYGON_OFFSET_FACTOR:
1583 case GL_POLYGON_OFFSET_UNITS:
1584 case GL_SAMPLE_COVERAGE_VALUE:
1585 case GL_DEPTH_CLEAR_VALUE:
1586 case GL_LINE_WIDTH:
1587 {
1588 *type = GL_FLOAT;
1589 *numParams = 1;
1590 }
1591 break;
1592 case GL_ALIASED_LINE_WIDTH_RANGE:
1593 case GL_ALIASED_POINT_SIZE_RANGE:
1594 case GL_DEPTH_RANGE:
1595 {
1596 *type = GL_FLOAT;
1597 *numParams = 2;
1598 }
1599 break;
1600 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001601 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001602 {
1603 *type = GL_FLOAT;
1604 *numParams = 4;
1605 }
1606 break;
1607 default:
1608 return false;
1609 }
1610
1611 return true;
1612}
1613
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001614// Applies the render target surface, depth stencil surface, viewport rectangle and
1615// scissor rectangle to the Direct3D 9 device
1616bool Context::applyRenderTarget(bool ignoreViewport)
1617{
1618 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001619
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001620 Framebuffer *framebufferObject = getFramebuffer();
1621
1622 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1623 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001624 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1625
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001626 return false;
1627 }
1628
1629 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1630 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1631
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001632 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
1633 if (renderTargetSerial != mAppliedRenderTargetSerial)
1634 {
1635 device->SetRenderTarget(0, renderTarget);
1636 mAppliedRenderTargetSerial = renderTargetSerial;
1637 }
1638
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001639 unsigned int depthbufferSerial = framebufferObject->getDepthbufferSerial();
1640 if (depthbufferSerial != mAppliedDepthbufferSerial)
1641 {
1642 device->SetDepthStencilSurface(depthStencil);
1643 mAppliedDepthbufferSerial = depthbufferSerial;
1644 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001645
1646 D3DVIEWPORT9 viewport;
1647 D3DSURFACE_DESC desc;
1648 renderTarget->GetDesc(&desc);
1649
1650 if (ignoreViewport)
1651 {
1652 viewport.X = 0;
1653 viewport.Y = 0;
1654 viewport.Width = desc.Width;
1655 viewport.Height = desc.Height;
1656 viewport.MinZ = 0.0f;
1657 viewport.MaxZ = 1.0f;
1658 }
1659 else
1660 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001661 viewport.X = std::max(mState.viewportX, 0);
1662 viewport.Y = std::max(mState.viewportY, 0);
1663 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1664 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1665 viewport.MinZ = clamp01(mState.zNear);
1666 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001667 }
1668
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001669 if (viewport.Width <= 0 || viewport.Height <= 0)
1670 {
1671 return false; // Nothing to render
1672 }
1673
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001674 device->SetViewport(&viewport);
1675
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001676 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001677 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001678 if (mState.scissorTest)
1679 {
1680 RECT rect = {mState.scissorX,
1681 mState.scissorY,
1682 mState.scissorX + mState.scissorWidth,
1683 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001684
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001685 device->SetScissorRect(&rect);
1686 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1687 }
1688 else
1689 {
1690 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1691 }
1692
1693 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001694 }
1695
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001696 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001697 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001698 Program *programObject = getCurrentProgram();
1699
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001700 GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001701 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001702 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001703
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001704 GLint window = programObject->getDxWindowLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001705 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1706 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1707 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001708 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1709
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001710 GLint depth = programObject->getDxDepthLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001711 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001712 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1713
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001714 GLint near = programObject->getDepthRangeNearLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001715 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001716
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001717 GLint far = programObject->getDepthRangeFarLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001718 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001719
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001720 GLint diff = programObject->getDepthRangeDiffLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001721 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001722 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001723 }
1724
1725 return true;
1726}
1727
1728// 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 +00001729void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001730{
1731 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001732 Program *programObject = getCurrentProgram();
1733
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001734 GLint frontCCW = programObject->getDxFrontCCWLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001735 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001736 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001737
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001738 GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001739 GLint alwaysFront = !isTriangleMode(drawMode);
1740 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1741
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001742 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001743 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001744 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001745 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001746 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001747 }
1748 else
1749 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001750 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001751 }
1752
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001753 mCullStateDirty = false;
1754 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001755
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001756 if (mDepthStateDirty)
1757 {
1758 if (mState.depthTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001759 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001760 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1761 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001762 }
1763 else
1764 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001765 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001766 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001767
1768 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001769 }
1770
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001771 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001772 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001773 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001774 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001775 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1776
1777 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1778 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1779 {
1780 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1781 }
1782 else
1783 {
1784 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1785 unorm<8>(mState.blendColor.alpha),
1786 unorm<8>(mState.blendColor.alpha),
1787 unorm<8>(mState.blendColor.alpha)));
1788 }
1789
1790 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1791 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1792 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1793
1794 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1795 mState.destBlendRGB != mState.destBlendAlpha ||
1796 mState.blendEquationRGB != mState.blendEquationAlpha)
1797 {
1798 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1799
1800 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1801 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1802 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
1803
1804 }
1805 else
1806 {
1807 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1808 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001809 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001810 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001811 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001812 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001813 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001814
1815 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001816 }
1817
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001818 if (mStencilStateDirty || mFrontFaceDirty)
1819 {
1820 if (mState.stencilTest && hasStencil())
1821 {
1822 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1823 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1824
1825 // FIXME: Unsupported by D3D9
1826 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1827 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1828 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1829 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1830 mState.stencilRef != mState.stencilBackRef ||
1831 mState.stencilMask != mState.stencilBackMask)
1832 {
1833 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1834 return error(GL_INVALID_OPERATION);
1835 }
1836
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001837 // get the maximum size of the stencil ref
1838 gl::Framebuffer *framebuffer = getFramebuffer();
1839 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1840 GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
1841
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001842 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1843 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1844 es2dx::ConvertComparison(mState.stencilFunc));
1845
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001846 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 +00001847 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
1848
1849 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1850 es2dx::ConvertStencilOp(mState.stencilFail));
1851 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1852 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1853 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1854 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1855
1856 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1857 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1858 es2dx::ConvertComparison(mState.stencilBackFunc));
1859
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001860 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 +00001861 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
1862
1863 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1864 es2dx::ConvertStencilOp(mState.stencilBackFail));
1865 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1866 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1867 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1868 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1869 }
1870 else
1871 {
1872 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1873 }
1874
1875 mStencilStateDirty = false;
1876 }
1877
1878 if (mMaskStateDirty)
1879 {
1880 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1881 mState.colorMaskBlue, mState.colorMaskAlpha));
1882 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1883
1884 mMaskStateDirty = false;
1885 }
1886
1887 if (mPolygonOffsetStateDirty)
1888 {
1889 if (mState.polygonOffsetFill)
1890 {
1891 gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
1892 if (depthbuffer)
1893 {
1894 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1895 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1896 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1897 }
1898 }
1899 else
1900 {
1901 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1902 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1903 }
1904
1905 mPolygonOffsetStateDirty = false;
1906 }
1907
1908 if (mConfig->mMultiSample != 0 && mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001909 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001910 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001911 {
1912 FIXME("Sample alpha to coverage is unimplemented.");
1913 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001914
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001915 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001916 {
1917 FIXME("Sample coverage is unimplemented.");
1918 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001919
1920 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001921 }
1922
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001923 if (mDitherStateDirty)
1924 {
1925 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
1926
1927 mDitherStateDirty = false;
1928 }
1929
1930 mFrontFaceDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001931}
1932
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001933// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001934void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001935{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001936 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001937 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001938 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001939 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001940 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001941 }
1942 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001943}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001944
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001945GLenum Context::applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool *useIndexing, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001946{
1947 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1948
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001949 GLenum err = mVertexDataManager->preRenderValidate(first, count, translated);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001950 if (err != GL_NO_ERROR)
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001951 {
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001952 return err;
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001953 }
1954
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001955 lookupAttributeMapping(translated);
1956
1957 mBufferBackEnd->setupAttributesPreDraw(translated);
1958
1959 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
1960 {
1961 if (translated[i].enabled && translated[i].nonArray)
1962 {
1963 err = mIndexDataManager->preRenderValidateUnindexed(mode, count, indexInfo);
1964 if (err != GL_NO_ERROR)
1965 {
1966 return err;
1967 }
1968
1969 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
1970
1971 *useIndexing = true;
1972 return GL_NO_ERROR;
1973 }
1974 }
1975
1976 *useIndexing = false;
1977 return GL_NO_ERROR;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001978}
1979
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001980GLenum Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001981{
1982 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1983
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001984 GLenum err = mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001985
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001986 if (err == GL_NO_ERROR)
1987 {
1988 lookupAttributeMapping(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001989
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001990 mBufferBackEnd->setupAttributesPreDraw(translated);
1991 }
1992
1993 return err;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001994}
1995
1996// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001997GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001998{
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001999 GLenum err = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices, indexInfo);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002000
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002001 if (err == GL_NO_ERROR)
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002002 {
2003 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
2004 }
2005
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002006 return err;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002007}
2008
2009// Applies the shaders and shader constants to the Direct3D 9 device
2010void Context::applyShaders()
2011{
2012 IDirect3DDevice9 *device = getDevice();
2013 Program *programObject = getCurrentProgram();
2014 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
2015 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
2016
2017 device->SetVertexShader(vertexShader);
2018 device->SetPixelShader(pixelShader);
2019
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002020 if (programObject->getSerial() != mAppliedProgram)
2021 {
2022 programObject->dirtyAllUniforms();
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002023 programObject->dirtyAllSamplers();
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002024 mAppliedProgram = programObject->getSerial();
2025 }
2026
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002027 programObject->applyUniforms();
2028}
2029
2030// Applies the textures and sampler states to the Direct3D 9 device
2031void Context::applyTextures()
2032{
2033 IDirect3DDevice9 *device = getDevice();
2034 Program *programObject = getCurrentProgram();
2035
2036 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
2037 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002038 int textureUnit = programObject->getSamplerMapping(sampler);
2039 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002040 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002041 SamplerType textureType = programObject->getSamplerType(sampler);
2042
2043 Texture *texture = getSamplerTexture(textureUnit, textureType);
2044
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002045 if (programObject->isSamplerDirty(sampler) || texture->isDirty())
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002046 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002047 if (texture->isComplete())
2048 {
2049 GLenum wrapS = texture->getWrapS();
2050 GLenum wrapT = texture->getWrapT();
2051 GLenum minFilter = texture->getMinFilter();
2052 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002053
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002054 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
2055 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002056
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002057 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
2058 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
2059 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
2060 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
2061 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002062
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002063 device->SetTexture(sampler, texture->getTexture());
2064 }
2065 else
2066 {
2067 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
2068 }
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002069 }
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002070
2071 programObject->setSamplerDirty(sampler, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002072 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002073 else
2074 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002075 if (programObject->isSamplerDirty(sampler))
2076 {
2077 device->SetTexture(sampler, NULL);
2078 programObject->setSamplerDirty(sampler, false);
2079 }
2080 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002081 }
2082}
2083
2084void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
2085{
2086 Framebuffer *framebuffer = getFramebuffer();
2087 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
2088 IDirect3DDevice9 *device = getDevice();
2089
2090 D3DSURFACE_DESC desc;
2091 renderTarget->GetDesc(&desc);
2092
2093 IDirect3DSurface9 *systemSurface;
2094 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
2095
2096 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2097 {
2098 return error(GL_OUT_OF_MEMORY);
2099 }
2100
2101 ASSERT(SUCCEEDED(result));
2102
2103 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
2104 {
2105 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
2106 }
2107
2108 result = device->GetRenderTargetData(renderTarget, systemSurface);
2109
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002110 if (FAILED(result))
2111 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002112 systemSurface->Release();
2113
apatrick@chromium.org6db8cab2010-07-22 20:39:50 +00002114 switch (result)
2115 {
2116 case D3DERR_DRIVERINTERNALERROR:
2117 case D3DERR_DEVICELOST:
2118 return error(GL_OUT_OF_MEMORY);
2119 default:
2120 UNREACHABLE();
2121 return; // No sensible error to generate
2122 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002123 }
2124
2125 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00002126 RECT rect = {std::max(x, 0),
2127 std::max(y, 0),
2128 std::min(x + width, (int)desc.Width),
2129 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002130
2131 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
2132
2133 if (FAILED(result))
2134 {
2135 UNREACHABLE();
2136 systemSurface->Release();
2137
2138 return; // No sensible error to generate
2139 }
2140
2141 unsigned char *source = (unsigned char*)lock.pBits;
2142 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002143 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002144
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002145 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002146
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002147 for (int j = 0; j < rect.bottom - rect.top; j++)
2148 {
2149 for (int i = 0; i < rect.right - rect.left; i++)
2150 {
2151 float r;
2152 float g;
2153 float b;
2154 float a;
2155
2156 switch (desc.Format)
2157 {
2158 case D3DFMT_R5G6B5:
2159 {
2160 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2161
2162 a = 1.0f;
2163 b = (rgb & 0x001F) * (1.0f / 0x001F);
2164 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2165 r = (rgb & 0xF800) * (1.0f / 0xF800);
2166 }
2167 break;
2168 case D3DFMT_X1R5G5B5:
2169 {
2170 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2171
2172 a = 1.0f;
2173 b = (xrgb & 0x001F) * (1.0f / 0x001F);
2174 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
2175 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
2176 }
2177 break;
2178 case D3DFMT_A1R5G5B5:
2179 {
2180 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2181
2182 a = (argb & 0x8000) ? 1.0f : 0.0f;
2183 b = (argb & 0x001F) * (1.0f / 0x001F);
2184 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2185 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2186 }
2187 break;
2188 case D3DFMT_A8R8G8B8:
2189 {
2190 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2191
2192 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2193 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2194 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2195 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2196 }
2197 break;
2198 case D3DFMT_X8R8G8B8:
2199 {
2200 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2201
2202 a = 1.0f;
2203 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2204 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2205 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2206 }
2207 break;
2208 case D3DFMT_A2R10G10B10:
2209 {
2210 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2211
2212 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2213 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2214 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2215 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2216 }
2217 break;
2218 default:
2219 UNIMPLEMENTED(); // FIXME
2220 UNREACHABLE();
2221 }
2222
2223 switch (format)
2224 {
2225 case GL_RGBA:
2226 switch (type)
2227 {
2228 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002229 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2230 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2231 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2232 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002233 break;
2234 default: UNREACHABLE();
2235 }
2236 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002237 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002238 switch (type)
2239 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002240 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002241 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2242 ((unsigned short)(31 * b + 0.5f) << 0) |
2243 ((unsigned short)(63 * g + 0.5f) << 5) |
2244 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002245 break;
2246 default: UNREACHABLE();
2247 }
2248 break;
2249 default: UNREACHABLE();
2250 }
2251 }
2252 }
2253
2254 systemSurface->UnlockRect();
2255
2256 systemSurface->Release();
2257}
2258
2259void Context::clear(GLbitfield mask)
2260{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002261 Framebuffer *framebufferObject = getFramebuffer();
2262
2263 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2264 {
2265 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2266
2267 return;
2268 }
2269
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002270 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002271 IDirect3DDevice9 *device = getDevice();
2272 DWORD flags = 0;
2273
2274 if (mask & GL_COLOR_BUFFER_BIT)
2275 {
2276 mask &= ~GL_COLOR_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002277
2278 if (framebufferObject->getColorbufferType() != GL_NONE)
2279 {
2280 flags |= D3DCLEAR_TARGET;
2281 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002282 }
2283
2284 if (mask & GL_DEPTH_BUFFER_BIT)
2285 {
2286 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002287 if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002288 {
2289 flags |= D3DCLEAR_ZBUFFER;
2290 }
2291 }
2292
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002293 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
2294
2295 GLuint stencilUnmasked = 0x0;
2296
2297 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
2298 {
2299 D3DSURFACE_DESC desc;
2300 depthStencil->GetDesc(&desc);
2301
2302 mask &= ~GL_STENCIL_BUFFER_BIT;
2303 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2304 stencilUnmasked = (0x1 << stencilSize) - 1;
2305
2306 if (stencilUnmasked != 0x0)
2307 {
2308 flags |= D3DCLEAR_STENCIL;
2309 }
2310 }
2311
2312 if (mask != 0)
2313 {
2314 return error(GL_INVALID_VALUE);
2315 }
2316
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002317 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2318 {
2319 return;
2320 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002321
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002322 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2323 unorm<8>(mState.colorClearValue.red),
2324 unorm<8>(mState.colorClearValue.green),
2325 unorm<8>(mState.colorClearValue.blue));
2326 float depth = clamp01(mState.depthClearValue);
2327 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002328
2329 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2330
2331 D3DSURFACE_DESC desc;
2332 renderTarget->GetDesc(&desc);
2333
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002334 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002335
2336 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002337 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002338 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002339 !(mState.colorMaskRed && mState.colorMaskGreen &&
2340 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002341
2342 if (needMaskedColorClear || needMaskedStencilClear)
2343 {
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002344 // State which is altered in all paths from this point to the clear call is saved.
2345 // State which is altered in only some paths will be flagged dirty in the case that
2346 // that path is taken.
2347 HRESULT hr;
2348 if (mMaskedClearSavedState == NULL)
2349 {
2350 hr = device->BeginStateBlock();
2351 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2352
2353 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2354 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2355 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2356 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2357 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2358 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2359 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2360 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2361 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2362 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2363 device->SetPixelShader(NULL);
2364 device->SetVertexShader(NULL);
2365 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2366 device->SetStreamSourceFreq(0, 1);
2367
2368 hr = device->EndStateBlock(&mMaskedClearSavedState);
2369 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2370 }
2371
2372 ASSERT(mMaskedClearSavedState != NULL);
2373
2374 if (mMaskedClearSavedState != NULL)
2375 {
2376 hr = mMaskedClearSavedState->Capture();
2377 ASSERT(SUCCEEDED(hr));
2378 }
2379
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002380 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2381 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2382 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2383 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2384 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2385 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2386 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2387 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2388
2389 if (flags & D3DCLEAR_TARGET)
2390 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002391 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2392 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2393 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2394 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002395 }
2396 else
2397 {
2398 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2399 }
2400
2401 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2402 {
2403 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2404 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2405 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2406 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002407 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002408 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002409 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2410 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002411 mStencilStateDirty = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002412 }
2413 else
2414 {
2415 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2416 }
2417
2418 device->SetPixelShader(NULL);
2419 device->SetVertexShader(NULL);
2420 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002421 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002422
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002423 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002424 {
2425 float x, y, z, w;
2426 D3DCOLOR diffuse;
2427 };
2428
2429 Vertex quad[4];
2430 quad[0].x = 0.0f;
2431 quad[0].y = (float)desc.Height;
2432 quad[0].z = 0.0f;
2433 quad[0].w = 1.0f;
2434 quad[0].diffuse = color;
2435
2436 quad[1].x = (float)desc.Width;
2437 quad[1].y = (float)desc.Height;
2438 quad[1].z = 0.0f;
2439 quad[1].w = 1.0f;
2440 quad[1].diffuse = color;
2441
2442 quad[2].x = 0.0f;
2443 quad[2].y = 0.0f;
2444 quad[2].z = 0.0f;
2445 quad[2].w = 1.0f;
2446 quad[2].diffuse = color;
2447
2448 quad[3].x = (float)desc.Width;
2449 quad[3].y = 0.0f;
2450 quad[3].z = 0.0f;
2451 quad[3].w = 1.0f;
2452 quad[3].diffuse = color;
2453
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002454 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002455 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002456
2457 if (flags & D3DCLEAR_ZBUFFER)
2458 {
2459 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2460 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2461 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2462 }
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002463
2464 if (mMaskedClearSavedState != NULL)
2465 {
2466 mMaskedClearSavedState->Apply();
2467 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002468 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002469 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002470 {
2471 device->Clear(0, NULL, flags, color, depth, stencil);
2472 }
2473}
2474
2475void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2476{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002477 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002478 {
2479 return error(GL_INVALID_OPERATION);
2480 }
2481
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002482 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002483 IDirect3DDevice9 *device = getDevice();
2484 D3DPRIMITIVETYPE primitiveType;
2485 int primitiveCount;
2486
2487 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2488 return error(GL_INVALID_ENUM);
2489
2490 if (primitiveCount <= 0)
2491 {
2492 return;
2493 }
2494
2495 if (!applyRenderTarget(false))
2496 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002497 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002498 }
2499
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002500 applyState(mode);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002501
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002502 TranslatedIndexData indexInfo;
2503 bool useIndexing;
2504 GLenum err = applyVertexBuffer(mode, first, count, &useIndexing, &indexInfo);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002505 if (err != GL_NO_ERROR)
2506 {
2507 return error(err);
2508 }
2509
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002510 applyShaders();
2511 applyTextures();
2512
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002513 if (!getCurrentProgram()->validateSamplers())
2514 {
2515 return error(GL_INVALID_OPERATION);
2516 }
2517
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002518 if (!cullSkipsDraw(mode))
2519 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002520 display->startScene();
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002521 if (useIndexing)
2522 {
2523 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
2524 }
2525 else
2526 {
2527 device->DrawPrimitive(primitiveType, 0, primitiveCount);
2528 }
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002529 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002530}
2531
2532void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2533{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002534 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002535 {
2536 return error(GL_INVALID_OPERATION);
2537 }
2538
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002539 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002540 {
2541 return error(GL_INVALID_OPERATION);
2542 }
2543
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002544 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002545 IDirect3DDevice9 *device = getDevice();
2546 D3DPRIMITIVETYPE primitiveType;
2547 int primitiveCount;
2548
2549 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2550 return error(GL_INVALID_ENUM);
2551
2552 if (primitiveCount <= 0)
2553 {
2554 return;
2555 }
2556
2557 if (!applyRenderTarget(false))
2558 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002559 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002560 }
2561
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002562 applyState(mode);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002563
2564 TranslatedIndexData indexInfo;
2565 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2566 if (err != GL_NO_ERROR)
2567 {
2568 return error(err);
2569 }
2570
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002571 err = applyVertexBuffer(indexInfo);
2572 if (err != GL_NO_ERROR)
2573 {
2574 return error(err);
2575 }
2576
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002577 applyShaders();
2578 applyTextures();
2579
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002580 if (!getCurrentProgram()->validateSamplers())
2581 {
2582 return error(GL_INVALID_OPERATION);
2583 }
2584
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002585 if (!cullSkipsDraw(mode))
2586 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002587 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002588 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 +00002589 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002590}
2591
2592void Context::finish()
2593{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002594 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002595 IDirect3DDevice9 *device = getDevice();
2596 IDirect3DQuery9 *occlusionQuery = NULL;
2597
2598 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2599
2600 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2601 {
2602 return error(GL_OUT_OF_MEMORY);
2603 }
2604
2605 ASSERT(SUCCEEDED(result));
2606
2607 if (occlusionQuery)
2608 {
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002609 IDirect3DStateBlock9 *savedState = NULL;
2610 device->CreateStateBlock(D3DSBT_ALL, &savedState);
2611
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002612 occlusionQuery->Issue(D3DISSUE_BEGIN);
2613
2614 // Render something outside the render target
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002615 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002616 device->SetPixelShader(NULL);
2617 device->SetVertexShader(NULL);
2618 device->SetFVF(D3DFVF_XYZRHW);
2619 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002620 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002621 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002622
2623 occlusionQuery->Issue(D3DISSUE_END);
2624
2625 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2626 {
2627 // Keep polling, but allow other threads to do something useful first
2628 Sleep(0);
2629 }
2630
2631 occlusionQuery->Release();
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002632
2633 if (savedState)
2634 {
2635 savedState->Apply();
2636 savedState->Release();
2637 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002638 }
2639}
2640
2641void Context::flush()
2642{
2643 IDirect3DDevice9 *device = getDevice();
2644 IDirect3DQuery9 *eventQuery = NULL;
2645
2646 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2647
2648 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2649 {
2650 return error(GL_OUT_OF_MEMORY);
2651 }
2652
2653 ASSERT(SUCCEEDED(result));
2654
2655 if (eventQuery)
2656 {
2657 eventQuery->Issue(D3DISSUE_END);
2658
2659 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2660 {
2661 // Keep polling, but allow other threads to do something useful first
2662 Sleep(0);
2663 }
2664
2665 eventQuery->Release();
2666 }
2667}
2668
2669void Context::recordInvalidEnum()
2670{
2671 mInvalidEnum = true;
2672}
2673
2674void Context::recordInvalidValue()
2675{
2676 mInvalidValue = true;
2677}
2678
2679void Context::recordInvalidOperation()
2680{
2681 mInvalidOperation = true;
2682}
2683
2684void Context::recordOutOfMemory()
2685{
2686 mOutOfMemory = true;
2687}
2688
2689void Context::recordInvalidFramebufferOperation()
2690{
2691 mInvalidFramebufferOperation = true;
2692}
2693
2694// Get one of the recorded errors and clear its flag, if any.
2695// [OpenGL ES 2.0.24] section 2.5 page 13.
2696GLenum Context::getError()
2697{
2698 if (mInvalidEnum)
2699 {
2700 mInvalidEnum = false;
2701
2702 return GL_INVALID_ENUM;
2703 }
2704
2705 if (mInvalidValue)
2706 {
2707 mInvalidValue = false;
2708
2709 return GL_INVALID_VALUE;
2710 }
2711
2712 if (mInvalidOperation)
2713 {
2714 mInvalidOperation = false;
2715
2716 return GL_INVALID_OPERATION;
2717 }
2718
2719 if (mOutOfMemory)
2720 {
2721 mOutOfMemory = false;
2722
2723 return GL_OUT_OF_MEMORY;
2724 }
2725
2726 if (mInvalidFramebufferOperation)
2727 {
2728 mInvalidFramebufferOperation = false;
2729
2730 return GL_INVALID_FRAMEBUFFER_OPERATION;
2731 }
2732
2733 return GL_NO_ERROR;
2734}
2735
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002736bool Context::supportsShaderModel3() const
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002737{
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002738 return mSupportsShaderModel3;
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002739}
2740
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002741void Context::detachBuffer(GLuint buffer)
2742{
2743 // [OpenGL ES 2.0.24] section 2.9 page 22:
2744 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2745 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2746
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002747 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002748 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002749 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002750 }
2751
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002752 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002753 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002754 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002755 }
2756
2757 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2758 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002759 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002760 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002761 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002762 }
2763 }
2764}
2765
2766void Context::detachTexture(GLuint texture)
2767{
2768 // [OpenGL ES 2.0.24] section 3.8 page 84:
2769 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2770 // rebound to texture object zero
2771
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002772 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002773 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002774 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002775 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002776 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002777 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002778 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002779 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002780 }
2781 }
2782
2783 // [OpenGL ES 2.0.24] section 4.4 page 112:
2784 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2785 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2786 // image was attached in the currently bound framebuffer.
2787
2788 Framebuffer *framebuffer = getFramebuffer();
2789
2790 if (framebuffer)
2791 {
2792 framebuffer->detachTexture(texture);
2793 }
2794}
2795
2796void Context::detachFramebuffer(GLuint framebuffer)
2797{
2798 // [OpenGL ES 2.0.24] section 4.4 page 107:
2799 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2800 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2801
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002802 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002803 {
2804 bindFramebuffer(0);
2805 }
2806}
2807
2808void Context::detachRenderbuffer(GLuint renderbuffer)
2809{
2810 // [OpenGL ES 2.0.24] section 4.4 page 109:
2811 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2812 // had been executed with the target RENDERBUFFER and name of zero.
2813
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002814 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002815 {
2816 bindRenderbuffer(0);
2817 }
2818
2819 // [OpenGL ES 2.0.24] section 4.4 page 111:
2820 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2821 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2822 // point to which this image was attached in the currently bound framebuffer.
2823
2824 Framebuffer *framebuffer = getFramebuffer();
2825
2826 if (framebuffer)
2827 {
2828 framebuffer->detachRenderbuffer(renderbuffer);
2829 }
2830}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002831
2832Texture *Context::getIncompleteTexture(SamplerType type)
2833{
2834 Texture *t = mIncompleteTextures[type];
2835
2836 if (t == NULL)
2837 {
2838 static const GLubyte color[] = { 0, 0, 0, 255 };
2839
2840 switch (type)
2841 {
2842 default:
2843 UNREACHABLE();
2844 // default falls through to SAMPLER_2D
2845
2846 case SAMPLER_2D:
2847 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002848 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002849 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002850 t = incomplete2d;
2851 }
2852 break;
2853
2854 case SAMPLER_CUBE:
2855 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002856 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002857
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002858 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2859 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2860 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2861 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2862 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2863 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002864
2865 t = incompleteCube;
2866 }
2867 break;
2868 }
2869
2870 mIncompleteTextures[type] = t;
2871 }
2872
2873 return t;
2874}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002875
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002876bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002877{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002878 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002879}
2880
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002881bool Context::isTriangleMode(GLenum drawMode)
2882{
2883 switch (drawMode)
2884 {
2885 case GL_TRIANGLES:
2886 case GL_TRIANGLE_FAN:
2887 case GL_TRIANGLE_STRIP:
2888 return true;
2889 case GL_POINTS:
2890 case GL_LINES:
2891 case GL_LINE_LOOP:
2892 case GL_LINE_STRIP:
2893 return false;
2894 default: UNREACHABLE();
2895 }
2896
2897 return false;
2898}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002899
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002900bool Context::hasStencil()
2901{
2902 Framebuffer *framebufferObject = getFramebuffer();
2903
2904 if (framebufferObject)
2905 {
2906 Stencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
2907
2908 if (stencilbufferObject)
2909 {
2910 return stencilbufferObject->getStencilSize() > 0;
2911 }
2912 }
2913
2914 return false;
2915}
2916
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002917void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2918{
2919 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2920
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002921 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2922 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2923 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2924 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002925
2926 mVertexDataManager->dirtyCurrentValues();
2927}
2928
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002929void Context::initExtensionString()
2930{
2931 if (mBufferBackEnd->supportIntIndices())
2932 {
2933 mExtensionString += "GL_OES_element_index_uint ";
2934 }
2935
2936 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2937 if (end != std::string::npos)
2938 {
2939 mExtensionString.resize(end+1);
2940 }
2941}
2942
2943const char *Context::getExtensionString() const
2944{
2945 return mExtensionString.c_str();
2946}
2947
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002948}
2949
2950extern "C"
2951{
2952gl::Context *glCreateContext(const egl::Config *config)
2953{
2954 return new gl::Context(config);
2955}
2956
2957void glDestroyContext(gl::Context *context)
2958{
2959 delete context;
2960
2961 if (context == gl::getContext())
2962 {
2963 gl::makeCurrent(NULL, NULL, NULL);
2964 }
2965}
2966
2967void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2968{
2969 gl::makeCurrent(context, display, surface);
2970}
2971
2972gl::Context *glGetCurrentContext()
2973{
2974 return gl::getContext();
2975}
2976}