blob: dda0e3535f142952e2fa10388635b98795b11c6c [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;
81 mState.sampleCoverageInvert = GL_FALSE;
82 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
158 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159}
160
161Context::~Context()
162{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000163 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000165 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
166 {
167 delete mIncompleteTextures[type];
168 }
169
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170 delete mTexture2DZero;
171 delete mTextureCubeMapZero;
172
173 delete mColorbufferZero;
174 delete mDepthbufferZero;
175 delete mStencilbufferZero;
176
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000177 delete mBufferBackEnd;
178 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000179 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000180 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000181
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182 while (!mBufferMap.empty())
183 {
184 deleteBuffer(mBufferMap.begin()->first);
185 }
186
187 while (!mProgramMap.empty())
188 {
189 deleteProgram(mProgramMap.begin()->first);
190 }
191
192 while (!mShaderMap.empty())
193 {
194 deleteShader(mShaderMap.begin()->first);
195 }
196
197 while (!mFramebufferMap.empty())
198 {
199 deleteFramebuffer(mFramebufferMap.begin()->first);
200 }
201
202 while (!mRenderbufferMap.empty())
203 {
204 deleteRenderbuffer(mRenderbufferMap.begin()->first);
205 }
206
207 while (!mTextureMap.empty())
208 {
209 deleteTexture(mTextureMap.begin()->first);
210 }
211}
212
213void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
214{
215 IDirect3DDevice9 *device = display->getDevice();
216
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000217 if (!mBufferBackEnd)
218 {
219 mBufferBackEnd = new Dx9BackEnd(device);
220 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000221 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000222 mBlit = new Blit(this);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000223 }
224
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
226 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000227 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228
229 Framebuffer *framebufferZero = new Framebuffer();
230 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000231 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
232 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233
234 setFramebufferZero(framebufferZero);
235 setColorbufferZero(colorbufferZero);
236 setDepthbufferZero(depthbufferZero);
237 setStencilbufferZero(stencilbufferZero);
238
239 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
240 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
241 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
242
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000243 if (!mHasBeenCurrent)
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000244 {
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000245 initExtensionString();
246
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000247 mState.viewportX = 0;
248 mState.viewportY = 0;
249 mState.viewportWidth = surface->getWidth();
250 mState.viewportHeight = surface->getHeight();
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000251
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000252 mState.scissorX = 0;
253 mState.scissorY = 0;
254 mState.scissorWidth = surface->getWidth();
255 mState.scissorHeight = surface->getHeight();
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000256
257 mHasBeenCurrent = true;
258 }
259
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260 defaultRenderTarget->Release();
261
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000262 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000263 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000264 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000266
267 D3DCAPS9 capabilities;
268 device->GetDeviceCaps(&capabilities);
269
270 if (capabilities.PixelShaderVersion == D3DPS_VERSION(3, 0))
271 {
272 mPsProfile = "ps_3_0";
273 mVsProfile = "vs_3_0";
274 }
275 else // egl::Display guarantees support for at least 2.0
276 {
277 mPsProfile = "ps_2_0";
278 mVsProfile = "vs_2_0";
279 }
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000280
281 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282}
283
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000284// 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 +0000285void Context::markAllStateDirty()
286{
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000287 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000288 mAppliedProgram = 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000289
290 mClearStateDirty = true;
291 mCullStateDirty = true;
292 mDepthStateDirty = true;
293 mMaskStateDirty = true;
294 mBlendStateDirty = true;
295 mStencilStateDirty = true;
296 mPolygonOffsetStateDirty = true;
297 mScissorStateDirty = true;
298 mSampleStateDirty = true;
299 mDitherStateDirty = true;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000300}
301
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302void Context::setClearColor(float red, float green, float blue, float alpha)
303{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000304 mState.colorClearValue.red = red;
305 mState.colorClearValue.green = green;
306 mState.colorClearValue.blue = blue;
307 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308}
309
310void Context::setClearDepth(float depth)
311{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000312 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313}
314
315void Context::setClearStencil(int stencil)
316{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000317 mState.stencilClearValue = stencil;
318}
319
320void Context::setCullFace(bool enabled)
321{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000322 if (mState.cullFace != enabled)
323 {
324 mState.cullFace = enabled;
325 mCullStateDirty = true;
326 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000327}
328
329bool Context::isCullFaceEnabled() const
330{
331 return mState.cullFace;
332}
333
334void Context::setCullMode(GLenum mode)
335{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000336 if (mState.cullMode != mode)
337 {
338 mState.cullMode = mode;
339 mCullStateDirty = true;
340 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000341}
342
343void Context::setFrontFace(GLenum front)
344{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000345 if (mState.frontFace != front)
346 {
347 mState.frontFace = front;
348 mFrontFaceDirty = true;
349 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000350}
351
352void Context::setDepthTest(bool enabled)
353{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000354 if (mState.depthTest != enabled)
355 {
356 mState.depthTest = enabled;
357 mDepthStateDirty = true;
358 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000359}
360
361bool Context::isDepthTestEnabled() const
362{
363 return mState.depthTest;
364}
365
366void Context::setDepthFunc(GLenum depthFunc)
367{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000368 if (mState.depthFunc != depthFunc)
369 {
370 mState.depthFunc = depthFunc;
371 mDepthStateDirty = true;
372 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000373}
374
375void Context::setDepthRange(float zNear, float zFar)
376{
377 mState.zNear = zNear;
378 mState.zFar = zFar;
379}
380
381void Context::setBlend(bool enabled)
382{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000383 if (mState.blend != enabled)
384 {
385 mState.blend = enabled;
386 mBlendStateDirty = true;
387 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000388}
389
390bool Context::isBlendEnabled() const
391{
392 return mState.blend;
393}
394
395void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
396{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000397 if (mState.sourceBlendRGB != sourceRGB ||
398 mState.sourceBlendAlpha != sourceAlpha ||
399 mState.destBlendRGB != destRGB ||
400 mState.destBlendAlpha != destAlpha)
401 {
402 mState.sourceBlendRGB = sourceRGB;
403 mState.destBlendRGB = destRGB;
404 mState.sourceBlendAlpha = sourceAlpha;
405 mState.destBlendAlpha = destAlpha;
406 mBlendStateDirty = true;
407 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000408}
409
410void Context::setBlendColor(float red, float green, float blue, float alpha)
411{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000412 if (mState.blendColor.red != red ||
413 mState.blendColor.green != green ||
414 mState.blendColor.blue != blue ||
415 mState.blendColor.alpha != alpha)
416 {
417 mState.blendColor.red = red;
418 mState.blendColor.green = green;
419 mState.blendColor.blue = blue;
420 mState.blendColor.alpha = alpha;
421 mBlendStateDirty = true;
422 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000423}
424
425void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
426{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000427 if (mState.blendEquationRGB != rgbEquation ||
428 mState.blendEquationAlpha != alphaEquation)
429 {
430 mState.blendEquationRGB = rgbEquation;
431 mState.blendEquationAlpha = alphaEquation;
432 mBlendStateDirty = true;
433 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000434}
435
436void Context::setStencilTest(bool enabled)
437{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000438 if (mState.stencilTest != enabled)
439 {
440 mState.stencilTest = enabled;
441 mStencilStateDirty = true;
442 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000443}
444
445bool Context::isStencilTestEnabled() const
446{
447 return mState.stencilTest;
448}
449
450void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
451{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000452 if (mState.stencilFunc != stencilFunc ||
453 mState.stencilRef != stencilRef ||
454 mState.stencilMask != stencilMask)
455 {
456 mState.stencilFunc = stencilFunc;
457 mState.stencilRef = stencilRef;
458 mState.stencilMask = stencilMask;
459 mStencilStateDirty = true;
460 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000461}
462
463void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
464{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000465 if (mState.stencilBackFunc != stencilBackFunc ||
466 mState.stencilBackRef != stencilBackRef ||
467 mState.stencilBackMask != stencilBackMask)
468 {
469 mState.stencilBackFunc = stencilBackFunc;
470 mState.stencilBackRef = stencilBackRef;
471 mState.stencilBackMask = stencilBackMask;
472 mStencilStateDirty = true;
473 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000474}
475
476void Context::setStencilWritemask(GLuint stencilWritemask)
477{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000478 if (mState.stencilWritemask != stencilWritemask)
479 {
480 mState.stencilWritemask = stencilWritemask;
481 mStencilStateDirty = true;
482 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000483}
484
485void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
486{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000487 if (mState.stencilBackWritemask != stencilBackWritemask)
488 {
489 mState.stencilBackWritemask = stencilBackWritemask;
490 mStencilStateDirty = true;
491 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000492}
493
494void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
495{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000496 if (mState.stencilFail != stencilFail ||
497 mState.stencilPassDepthFail != stencilPassDepthFail ||
498 mState.stencilPassDepthPass != stencilPassDepthPass)
499 {
500 mState.stencilFail = stencilFail;
501 mState.stencilPassDepthFail = stencilPassDepthFail;
502 mState.stencilPassDepthPass = stencilPassDepthPass;
503 mStencilStateDirty = true;
504 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000505}
506
507void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
508{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000509 if (mState.stencilBackFail != stencilBackFail ||
510 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
511 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
512 {
513 mState.stencilBackFail = stencilBackFail;
514 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
515 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
516 mStencilStateDirty = true;
517 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000518}
519
520void Context::setPolygonOffsetFill(bool enabled)
521{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000522 if (mState.polygonOffsetFill != enabled)
523 {
524 mState.polygonOffsetFill = enabled;
525 mPolygonOffsetStateDirty = true;
526 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000527}
528
529bool Context::isPolygonOffsetFillEnabled() const
530{
531 return mState.polygonOffsetFill;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000532
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000533}
534
535void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
536{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000537 if (mState.polygonOffsetFactor != factor ||
538 mState.polygonOffsetUnits != units)
539 {
540 mState.polygonOffsetFactor = factor;
541 mState.polygonOffsetUnits = units;
542 mPolygonOffsetStateDirty = true;
543 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000544}
545
546void Context::setSampleAlphaToCoverage(bool enabled)
547{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000548 if (mState.sampleAlphaToCoverage != enabled)
549 {
550 mState.sampleAlphaToCoverage = enabled;
551 mSampleStateDirty = true;
552 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000553}
554
555bool Context::isSampleAlphaToCoverageEnabled() const
556{
557 return mState.sampleAlphaToCoverage;
558}
559
560void Context::setSampleCoverage(bool enabled)
561{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000562 if (mState.sampleCoverage != enabled)
563 {
564 mState.sampleCoverage = enabled;
565 mSampleStateDirty = true;
566 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000567}
568
569bool Context::isSampleCoverageEnabled() const
570{
571 return mState.sampleCoverage;
572}
573
574void Context::setSampleCoverageParams(GLclampf value, GLboolean invert)
575{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000576 if (mState.sampleCoverageValue != value ||
577 mState.sampleCoverageInvert != invert)
578 {
579 mState.sampleCoverageValue = value;
580 mState.sampleCoverageInvert = invert;
581 mSampleStateDirty = true;
582 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000583}
584
585void Context::setScissorTest(bool enabled)
586{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000587 if (mState.scissorTest != enabled)
588 {
589 mState.scissorTest = enabled;
590 mScissorStateDirty = true;
591 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000592}
593
594bool Context::isScissorTestEnabled() const
595{
596 return mState.scissorTest;
597}
598
599void Context::setDither(bool enabled)
600{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000601 if (mState.dither != enabled)
602 {
603 mState.dither = enabled;
604 mDitherStateDirty = true;
605 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000606}
607
608bool Context::isDitherEnabled() const
609{
610 return mState.dither;
611}
612
613void Context::setLineWidth(GLfloat width)
614{
615 mState.lineWidth = width;
616}
617
618void Context::setGenerateMipmapHint(GLenum hint)
619{
620 mState.generateMipmapHint = hint;
621}
622
623void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
624{
625 mState.viewportX = x;
626 mState.viewportY = y;
627 mState.viewportWidth = width;
628 mState.viewportHeight = height;
629}
630
631void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
632{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000633 if (mState.scissorX != x || mState.scissorY != y ||
634 mState.scissorWidth != width || mState.scissorHeight != height)
635 {
636 mState.scissorX = x;
637 mState.scissorY = y;
638 mState.scissorWidth = width;
639 mState.scissorHeight = height;
640 mScissorStateDirty = true;
641 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000642}
643
644void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
645{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000646 if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
647 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
648 {
649 mState.colorMaskRed = red;
650 mState.colorMaskGreen = green;
651 mState.colorMaskBlue = blue;
652 mState.colorMaskAlpha = alpha;
653 mMaskStateDirty = true;
654 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000655}
656
657void Context::setDepthMask(bool mask)
658{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000659 if (mState.depthMask != mask)
660 {
661 mState.depthMask = mask;
662 mMaskStateDirty = true;
663 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000664}
665
666void Context::setActiveSampler(int active)
667{
668 mState.activeSampler = active;
669}
670
671GLuint Context::getFramebufferHandle() const
672{
673 return mState.framebuffer;
674}
675
676GLuint Context::getRenderbufferHandle() const
677{
678 return mState.renderbuffer;
679}
680
681GLuint Context::getArrayBufferHandle() const
682{
683 return mState.arrayBuffer;
684}
685
686void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
687{
688 mState.vertexAttribute[attribNum].mEnabled = enabled;
689}
690
691const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
692{
693 return mState.vertexAttribute[attribNum];
694}
695
696void Context::setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type, bool normalized,
697 GLsizei stride, const void *pointer)
698{
699 mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer;
700 mState.vertexAttribute[attribNum].mSize = size;
701 mState.vertexAttribute[attribNum].mType = type;
702 mState.vertexAttribute[attribNum].mNormalized = normalized;
703 mState.vertexAttribute[attribNum].mStride = stride;
704 mState.vertexAttribute[attribNum].mPointer = pointer;
705}
706
707const void *Context::getVertexAttribPointer(unsigned int attribNum) const
708{
709 return mState.vertexAttribute[attribNum].mPointer;
710}
711
712// returns entire set of attributes as a block
713const AttributeState *Context::getVertexAttribBlock()
714{
715 return mState.vertexAttribute;
716}
717
718void Context::setPackAlignment(GLint alignment)
719{
720 mState.packAlignment = alignment;
721}
722
723GLint Context::getPackAlignment() const
724{
725 return mState.packAlignment;
726}
727
728void Context::setUnpackAlignment(GLint alignment)
729{
730 mState.unpackAlignment = alignment;
731}
732
733GLint Context::getUnpackAlignment() const
734{
735 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000736}
737
738// Returns an unused buffer name
739GLuint Context::createBuffer()
740{
741 unsigned int handle = 1;
742
743 while (mBufferMap.find(handle) != mBufferMap.end())
744 {
745 handle++;
746 }
747
748 mBufferMap[handle] = NULL;
749
750 return handle;
751}
752
753// Returns an unused shader/program name
754GLuint Context::createShader(GLenum type)
755{
756 unsigned int handle = 1;
757
758 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
759 {
760 handle++;
761 }
762
763 if (type == GL_VERTEX_SHADER)
764 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000765 mShaderMap[handle] = new VertexShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000766 }
767 else if (type == GL_FRAGMENT_SHADER)
768 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000769 mShaderMap[handle] = new FragmentShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000770 }
771 else UNREACHABLE();
772
773 return handle;
774}
775
776// Returns an unused program/shader name
777GLuint Context::createProgram()
778{
779 unsigned int handle = 1;
780
781 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
782 {
783 handle++;
784 }
785
786 mProgramMap[handle] = new Program();
787
788 return handle;
789}
790
791// Returns an unused texture name
792GLuint Context::createTexture()
793{
794 unsigned int handle = 1;
795
796 while (mTextureMap.find(handle) != mTextureMap.end())
797 {
798 handle++;
799 }
800
801 mTextureMap[handle] = NULL;
802
803 return handle;
804}
805
806// Returns an unused framebuffer name
807GLuint Context::createFramebuffer()
808{
809 unsigned int handle = 1;
810
811 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
812 {
813 handle++;
814 }
815
816 mFramebufferMap[handle] = NULL;
817
818 return handle;
819}
820
821// Returns an unused renderbuffer name
822GLuint Context::createRenderbuffer()
823{
824 unsigned int handle = 1;
825
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000826 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000827 {
828 handle++;
829 }
830
831 mRenderbufferMap[handle] = NULL;
832
833 return handle;
834}
835
836void Context::deleteBuffer(GLuint buffer)
837{
838 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
839
840 if (bufferObject != mBufferMap.end())
841 {
842 detachBuffer(buffer);
843
844 delete bufferObject->second;
845 mBufferMap.erase(bufferObject);
846 }
847}
848
849void Context::deleteShader(GLuint shader)
850{
851 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
852
853 if (shaderObject != mShaderMap.end())
854 {
855 if (!shaderObject->second->isAttached())
856 {
857 delete shaderObject->second;
858 mShaderMap.erase(shaderObject);
859 }
860 else
861 {
862 shaderObject->second->flagForDeletion();
863 }
864 }
865}
866
867void Context::deleteProgram(GLuint program)
868{
869 ProgramMap::iterator programObject = mProgramMap.find(program);
870
871 if (programObject != mProgramMap.end())
872 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000873 if (program != mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000874 {
875 delete programObject->second;
876 mProgramMap.erase(programObject);
877 }
878 else
879 {
880 programObject->second->flagForDeletion();
881 }
882 }
883}
884
885void Context::deleteTexture(GLuint texture)
886{
887 TextureMap::iterator textureObject = mTextureMap.find(texture);
888
889 if (textureObject != mTextureMap.end())
890 {
891 detachTexture(texture);
892
893 if (texture != 0)
894 {
895 delete textureObject->second;
896 }
897
898 mTextureMap.erase(textureObject);
899 }
900}
901
902void Context::deleteFramebuffer(GLuint framebuffer)
903{
904 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
905
906 if (framebufferObject != mFramebufferMap.end())
907 {
908 detachFramebuffer(framebuffer);
909
910 delete framebufferObject->second;
911 mFramebufferMap.erase(framebufferObject);
912 }
913}
914
915void Context::deleteRenderbuffer(GLuint renderbuffer)
916{
917 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
918
919 if (renderbufferObject != mRenderbufferMap.end())
920 {
921 detachRenderbuffer(renderbuffer);
922
923 delete renderbufferObject->second;
924 mRenderbufferMap.erase(renderbufferObject);
925 }
926}
927
928void Context::bindArrayBuffer(unsigned int buffer)
929{
930 if (buffer != 0 && !getBuffer(buffer))
931 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000932 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000933 }
934
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000935 mState.arrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000936}
937
938void Context::bindElementArrayBuffer(unsigned int buffer)
939{
940 if (buffer != 0 && !getBuffer(buffer))
941 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000942 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000943 }
944
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000945 mState.elementArrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000946}
947
948void Context::bindTexture2D(GLuint texture)
949{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000950 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000951 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000952 mTextureMap[texture] = new Texture2D(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000953 }
954
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000955 mState.texture2D = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000956
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000957 mState.samplerTexture[SAMPLER_2D][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000958}
959
960void Context::bindTextureCubeMap(GLuint texture)
961{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000962 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000963 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000964 mTextureMap[texture] = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000965 }
966
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000967 mState.textureCubeMap = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000969 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000970}
971
972void Context::bindFramebuffer(GLuint framebuffer)
973{
974 if (!getFramebuffer(framebuffer))
975 {
976 mFramebufferMap[framebuffer] = new Framebuffer();
977 }
978
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000979 mState.framebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000980}
981
982void Context::bindRenderbuffer(GLuint renderbuffer)
983{
984 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
985 {
986 mRenderbufferMap[renderbuffer] = new Renderbuffer();
987 }
988
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000989 mState.renderbuffer = renderbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000990}
991
992void Context::useProgram(GLuint program)
993{
994 Program *programObject = getCurrentProgram();
995
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000996 GLuint priorProgram = mState.currentProgram;
997 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000998
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000999 if (programObject && programObject->isFlaggedForDeletion())
1000 {
daniel@transgaming.com71cd8682010-04-29 03:35:25 +00001001 deleteProgram(priorProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001002 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001003}
1004
1005void Context::setFramebufferZero(Framebuffer *buffer)
1006{
1007 delete mFramebufferMap[0];
1008 mFramebufferMap[0] = buffer;
1009}
1010
1011void Context::setColorbufferZero(Colorbuffer *buffer)
1012{
1013 delete mColorbufferZero;
1014 mColorbufferZero = buffer;
1015}
1016
1017void Context::setDepthbufferZero(Depthbuffer *buffer)
1018{
1019 delete mDepthbufferZero;
1020 mDepthbufferZero = buffer;
1021}
1022
1023void Context::setStencilbufferZero(Stencilbuffer *buffer)
1024{
1025 delete mStencilbufferZero;
1026 mStencilbufferZero = buffer;
1027}
1028
1029void Context::setRenderbuffer(Renderbuffer *buffer)
1030{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001031 delete mRenderbufferMap[mState.renderbuffer];
1032 mRenderbufferMap[mState.renderbuffer] = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001033}
1034
1035Buffer *Context::getBuffer(unsigned int handle)
1036{
1037 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001038
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001039 if (buffer == mBufferMap.end())
1040 {
1041 return NULL;
1042 }
1043 else
1044 {
1045 return buffer->second;
1046 }
1047}
1048
1049Shader *Context::getShader(unsigned int handle)
1050{
1051 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001052
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001053 if (shader == mShaderMap.end())
1054 {
1055 return NULL;
1056 }
1057 else
1058 {
1059 return shader->second;
1060 }
1061}
1062
1063Program *Context::getProgram(unsigned int handle)
1064{
1065 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001066
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001067 if (program == mProgramMap.end())
1068 {
1069 return NULL;
1070 }
1071 else
1072 {
1073 return program->second;
1074 }
1075}
1076
1077Texture *Context::getTexture(unsigned int handle)
1078{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001079 if (handle == 0) return NULL;
1080
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001081 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001082
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001083 if (texture == mTextureMap.end())
1084 {
1085 return NULL;
1086 }
1087 else
1088 {
1089 return texture->second;
1090 }
1091}
1092
1093Framebuffer *Context::getFramebuffer(unsigned int handle)
1094{
1095 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001096
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001097 if (framebuffer == mFramebufferMap.end())
1098 {
1099 return NULL;
1100 }
1101 else
1102 {
1103 return framebuffer->second;
1104 }
1105}
1106
1107Renderbuffer *Context::getRenderbuffer(unsigned int handle)
1108{
1109 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001110
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001111 if (renderbuffer == mRenderbufferMap.end())
1112 {
1113 return NULL;
1114 }
1115 else
1116 {
1117 return renderbuffer->second;
1118 }
1119}
1120
1121Colorbuffer *Context::getColorbuffer(GLuint handle)
1122{
1123 if (handle != 0)
1124 {
1125 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1126
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001127 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001128 {
1129 return static_cast<Colorbuffer*>(renderbuffer);
1130 }
1131 }
1132 else // Special case: 0 refers to different initial render targets based on the attachment type
1133 {
1134 return mColorbufferZero;
1135 }
1136
1137 return NULL;
1138}
1139
1140Depthbuffer *Context::getDepthbuffer(GLuint handle)
1141{
1142 if (handle != 0)
1143 {
1144 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1145
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001146 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001147 {
1148 return static_cast<Depthbuffer*>(renderbuffer);
1149 }
1150 }
1151 else // Special case: 0 refers to different initial render targets based on the attachment type
1152 {
1153 return mDepthbufferZero;
1154 }
1155
1156 return NULL;
1157}
1158
1159Stencilbuffer *Context::getStencilbuffer(GLuint handle)
1160{
1161 if (handle != 0)
1162 {
1163 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1164
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001165 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001166 {
1167 return static_cast<Stencilbuffer*>(renderbuffer);
1168 }
1169 }
1170 else
1171 {
1172 return mStencilbufferZero;
1173 }
1174
1175 return NULL;
1176}
1177
1178Buffer *Context::getArrayBuffer()
1179{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001180 return getBuffer(mState.arrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001181}
1182
1183Buffer *Context::getElementArrayBuffer()
1184{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001185 return getBuffer(mState.elementArrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001186}
1187
1188Program *Context::getCurrentProgram()
1189{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001190 return getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001191}
1192
1193Texture2D *Context::getTexture2D()
1194{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001195 if (mState.texture2D == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001196 {
1197 return mTexture2DZero;
1198 }
1199
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001200 return (Texture2D*)getTexture(mState.texture2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001201}
1202
1203TextureCubeMap *Context::getTextureCubeMap()
1204{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001205 if (mState.textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001206 {
1207 return mTextureCubeMapZero;
1208 }
1209
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001210 return (TextureCubeMap*)getTexture(mState.textureCubeMap);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001211}
1212
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001213Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001214{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001215 GLuint texid = mState.samplerTexture[type][sampler];
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001216
1217 if (texid == 0)
1218 {
1219 switch (type)
1220 {
1221 default: UNREACHABLE();
1222 case SAMPLER_2D: return mTexture2DZero;
1223 case SAMPLER_CUBE: return mTextureCubeMapZero;
1224 }
1225 }
1226
1227 return getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001228}
1229
1230Framebuffer *Context::getFramebuffer()
1231{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001232 return getFramebuffer(mState.framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001233}
1234
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001235bool Context::getBooleanv(GLenum pname, GLboolean *params)
1236{
1237 switch (pname)
1238 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001239 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1240 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1241 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001242 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001243 params[0] = mState.colorMaskRed;
1244 params[1] = mState.colorMaskGreen;
1245 params[2] = mState.colorMaskBlue;
1246 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001247 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001248 case GL_CULL_FACE: *params = mState.cullFace;
1249 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
1250 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
1251 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
1252 case GL_SCISSOR_TEST: *params = mState.scissorTest;
1253 case GL_STENCIL_TEST: *params = mState.stencilTest;
1254 case GL_DEPTH_TEST: *params = mState.depthTest;
1255 case GL_BLEND: *params = mState.blend;
1256 case GL_DITHER: *params = mState.dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001257 default:
1258 return false;
1259 }
1260
1261 return true;
1262}
1263
1264bool Context::getFloatv(GLenum pname, GLfloat *params)
1265{
1266 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1267 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1268 // GetIntegerv as its native query function. As it would require conversion in any
1269 // case, this should make no difference to the calling application.
1270 switch (pname)
1271 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001272 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1273 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1274 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1275 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1276 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001277 case GL_ALIASED_LINE_WIDTH_RANGE:
1278 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1279 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1280 break;
1281 case GL_ALIASED_POINT_SIZE_RANGE:
1282 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
1283 params[1] = gl::ALIASED_POINT_SIZE_RANGE_MAX;
1284 break;
1285 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001286 params[0] = mState.zNear;
1287 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001288 break;
1289 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001290 params[0] = mState.colorClearValue.red;
1291 params[1] = mState.colorClearValue.green;
1292 params[2] = mState.colorClearValue.blue;
1293 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001294 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001295 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001296 params[0] = mState.blendColor.red;
1297 params[1] = mState.blendColor.green;
1298 params[2] = mState.blendColor.blue;
1299 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001300 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001301 default:
1302 return false;
1303 }
1304
1305 return true;
1306}
1307
1308bool Context::getIntegerv(GLenum pname, GLint *params)
1309{
1310 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1311 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1312 // GetIntegerv as its native query function. As it would require conversion in any
1313 // case, this should make no difference to the calling application. You may find it in
1314 // Context::getFloatv.
1315 switch (pname)
1316 {
1317 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1318 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1319 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
1320 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1321 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1322 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1323 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
1324 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
1325 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1326 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
1327 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
1328 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001329 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer; break;
1330 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer; break;
1331 case GL_FRAMEBUFFER_BINDING: *params = mState.framebuffer; break;
1332 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer; break;
1333 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1334 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1335 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1336 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1337 case GL_ACTIVE_TEXTURE: *params = mState.activeSampler; break;
1338 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1339 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1340 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1341 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1342 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1343 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1344 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1345 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1346 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1347 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1348 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1349 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1350 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1351 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1352 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1353 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1354 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1355 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1356 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1357 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1358 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1359 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001360 case GL_SUBPIXEL_BITS: *params = 4; break;
1361 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
1362 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
1363 case GL_SAMPLE_BUFFERS: *params = 0; break;
1364 case GL_SAMPLES: *params = 0; break;
1365 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1366 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1367 case GL_MAX_VIEWPORT_DIMS:
1368 {
1369 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
1370 params[0] = maxDimension;
1371 params[1] = maxDimension;
1372 }
1373 break;
1374 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001375 params[0] = mState.viewportX;
1376 params[1] = mState.viewportY;
1377 params[2] = mState.viewportWidth;
1378 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001379 break;
1380 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001381 params[0] = mState.scissorX;
1382 params[1] = mState.scissorY;
1383 params[2] = mState.scissorWidth;
1384 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001385 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001386 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1387 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001388 case GL_RED_BITS:
1389 case GL_GREEN_BITS:
1390 case GL_BLUE_BITS:
1391 case GL_ALPHA_BITS:
1392 {
1393 gl::Framebuffer *framebuffer = getFramebuffer();
1394 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1395
1396 if (colorbuffer)
1397 {
1398 switch (pname)
1399 {
1400 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1401 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1402 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1403 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1404 }
1405 }
1406 else
1407 {
1408 *params = 0;
1409 }
1410 }
1411 break;
1412 case GL_DEPTH_BITS:
1413 {
1414 gl::Framebuffer *framebuffer = getFramebuffer();
1415 gl::Depthbuffer *depthbuffer = framebuffer->getDepthbuffer();
1416
1417 if (depthbuffer)
1418 {
1419 *params = depthbuffer->getDepthSize();
1420 }
1421 else
1422 {
1423 *params = 0;
1424 }
1425 }
1426 break;
1427 case GL_STENCIL_BITS:
1428 {
1429 gl::Framebuffer *framebuffer = getFramebuffer();
1430 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1431
1432 if (stencilbuffer)
1433 {
1434 *params = stencilbuffer->getStencilSize();
1435 }
1436 else
1437 {
1438 *params = 0;
1439 }
1440 }
1441 break;
1442 case GL_TEXTURE_BINDING_2D:
1443 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001444 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001445 {
1446 error(GL_INVALID_OPERATION);
1447 return false;
1448 }
1449
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001450 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001451 }
1452 break;
1453 case GL_TEXTURE_BINDING_CUBE_MAP:
1454 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001455 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001456 {
1457 error(GL_INVALID_OPERATION);
1458 return false;
1459 }
1460
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001461 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001462 }
1463 break;
1464 default:
1465 return false;
1466 }
1467
1468 return true;
1469}
1470
1471bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1472{
1473 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1474 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1475 // to the fact that it is stored internally as a float, and so would require conversion
1476 // if returned from Context::getIntegerv. Since this conversion is already implemented
1477 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1478 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1479 // application.
1480 switch (pname)
1481 {
1482 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1483 case GL_SHADER_BINARY_FORMATS:
1484 {
1485 *type = GL_INT;
1486 *numParams = 0;
1487 }
1488 break;
1489 case GL_MAX_VERTEX_ATTRIBS:
1490 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1491 case GL_MAX_VARYING_VECTORS:
1492 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1493 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1494 case GL_MAX_TEXTURE_IMAGE_UNITS:
1495 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1496 case GL_MAX_RENDERBUFFER_SIZE:
1497 case GL_NUM_SHADER_BINARY_FORMATS:
1498 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1499 case GL_ARRAY_BUFFER_BINDING:
1500 case GL_FRAMEBUFFER_BINDING:
1501 case GL_RENDERBUFFER_BINDING:
1502 case GL_CURRENT_PROGRAM:
1503 case GL_PACK_ALIGNMENT:
1504 case GL_UNPACK_ALIGNMENT:
1505 case GL_GENERATE_MIPMAP_HINT:
1506 case GL_RED_BITS:
1507 case GL_GREEN_BITS:
1508 case GL_BLUE_BITS:
1509 case GL_ALPHA_BITS:
1510 case GL_DEPTH_BITS:
1511 case GL_STENCIL_BITS:
1512 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1513 case GL_CULL_FACE_MODE:
1514 case GL_FRONT_FACE:
1515 case GL_ACTIVE_TEXTURE:
1516 case GL_STENCIL_FUNC:
1517 case GL_STENCIL_VALUE_MASK:
1518 case GL_STENCIL_REF:
1519 case GL_STENCIL_FAIL:
1520 case GL_STENCIL_PASS_DEPTH_FAIL:
1521 case GL_STENCIL_PASS_DEPTH_PASS:
1522 case GL_STENCIL_BACK_FUNC:
1523 case GL_STENCIL_BACK_VALUE_MASK:
1524 case GL_STENCIL_BACK_REF:
1525 case GL_STENCIL_BACK_FAIL:
1526 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1527 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1528 case GL_DEPTH_FUNC:
1529 case GL_BLEND_SRC_RGB:
1530 case GL_BLEND_SRC_ALPHA:
1531 case GL_BLEND_DST_RGB:
1532 case GL_BLEND_DST_ALPHA:
1533 case GL_BLEND_EQUATION_RGB:
1534 case GL_BLEND_EQUATION_ALPHA:
1535 case GL_STENCIL_WRITEMASK:
1536 case GL_STENCIL_BACK_WRITEMASK:
1537 case GL_STENCIL_CLEAR_VALUE:
1538 case GL_SUBPIXEL_BITS:
1539 case GL_MAX_TEXTURE_SIZE:
1540 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1541 case GL_SAMPLE_BUFFERS:
1542 case GL_SAMPLES:
1543 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1544 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1545 case GL_TEXTURE_BINDING_2D:
1546 case GL_TEXTURE_BINDING_CUBE_MAP:
1547 {
1548 *type = GL_INT;
1549 *numParams = 1;
1550 }
1551 break;
1552 case GL_MAX_VIEWPORT_DIMS:
1553 {
1554 *type = GL_INT;
1555 *numParams = 2;
1556 }
1557 break;
1558 case GL_VIEWPORT:
1559 case GL_SCISSOR_BOX:
1560 {
1561 *type = GL_INT;
1562 *numParams = 4;
1563 }
1564 break;
1565 case GL_SHADER_COMPILER:
1566 case GL_SAMPLE_COVERAGE_INVERT:
1567 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001568 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1569 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1570 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1571 case GL_SAMPLE_COVERAGE:
1572 case GL_SCISSOR_TEST:
1573 case GL_STENCIL_TEST:
1574 case GL_DEPTH_TEST:
1575 case GL_BLEND:
1576 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001577 {
1578 *type = GL_BOOL;
1579 *numParams = 1;
1580 }
1581 break;
1582 case GL_COLOR_WRITEMASK:
1583 {
1584 *type = GL_BOOL;
1585 *numParams = 4;
1586 }
1587 break;
1588 case GL_POLYGON_OFFSET_FACTOR:
1589 case GL_POLYGON_OFFSET_UNITS:
1590 case GL_SAMPLE_COVERAGE_VALUE:
1591 case GL_DEPTH_CLEAR_VALUE:
1592 case GL_LINE_WIDTH:
1593 {
1594 *type = GL_FLOAT;
1595 *numParams = 1;
1596 }
1597 break;
1598 case GL_ALIASED_LINE_WIDTH_RANGE:
1599 case GL_ALIASED_POINT_SIZE_RANGE:
1600 case GL_DEPTH_RANGE:
1601 {
1602 *type = GL_FLOAT;
1603 *numParams = 2;
1604 }
1605 break;
1606 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001607 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001608 {
1609 *type = GL_FLOAT;
1610 *numParams = 4;
1611 }
1612 break;
1613 default:
1614 return false;
1615 }
1616
1617 return true;
1618}
1619
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001620// Applies the render target surface, depth stencil surface, viewport rectangle and
1621// scissor rectangle to the Direct3D 9 device
1622bool Context::applyRenderTarget(bool ignoreViewport)
1623{
1624 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001625
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001626 Framebuffer *framebufferObject = getFramebuffer();
1627
1628 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1629 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001630 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1631
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001632 return false;
1633 }
1634
1635 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1636 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1637
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001638 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
1639 if (renderTargetSerial != mAppliedRenderTargetSerial)
1640 {
1641 device->SetRenderTarget(0, renderTarget);
1642 mAppliedRenderTargetSerial = renderTargetSerial;
1643 }
1644
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001645 device->SetDepthStencilSurface(depthStencil);
1646
1647 D3DVIEWPORT9 viewport;
1648 D3DSURFACE_DESC desc;
1649 renderTarget->GetDesc(&desc);
1650
1651 if (ignoreViewport)
1652 {
1653 viewport.X = 0;
1654 viewport.Y = 0;
1655 viewport.Width = desc.Width;
1656 viewport.Height = desc.Height;
1657 viewport.MinZ = 0.0f;
1658 viewport.MaxZ = 1.0f;
1659 }
1660 else
1661 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001662 viewport.X = std::max(mState.viewportX, 0);
1663 viewport.Y = std::max(mState.viewportY, 0);
1664 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1665 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1666 viewport.MinZ = clamp01(mState.zNear);
1667 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001668 }
1669
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001670 if (viewport.Width <= 0 || viewport.Height <= 0)
1671 {
1672 return false; // Nothing to render
1673 }
1674
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001675 device->SetViewport(&viewport);
1676
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001677 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001678 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001679 if (mState.scissorTest)
1680 {
1681 RECT rect = {mState.scissorX,
1682 mState.scissorY,
1683 mState.scissorX + mState.scissorWidth,
1684 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001685
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001686 device->SetScissorRect(&rect);
1687 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1688 }
1689 else
1690 {
1691 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1692 }
1693
1694 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001695 }
1696
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001697 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001698 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001699 Program *programObject = getCurrentProgram();
1700
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001701 GLint halfPixelSize = programObject->getUniformLocation("dx_HalfPixelSize");
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001702 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001703 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001704
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001705 GLint window = programObject->getUniformLocation("dx_Window");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001706 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1707 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1708 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001709 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1710
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001711 GLint depth = programObject->getUniformLocation("dx_Depth");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001712 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001713 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1714
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001715 GLint near = programObject->getUniformLocation("gl_DepthRange.near");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001716 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001717
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001718 GLint far = programObject->getUniformLocation("gl_DepthRange.far");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001719 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001720
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001721 GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001722 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001723 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001724 }
1725
1726 return true;
1727}
1728
1729// 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 +00001730void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001731{
1732 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001733 Program *programObject = getCurrentProgram();
1734
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001735 GLint frontCCW = programObject->getUniformLocation("dx_FrontCCW");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001736 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001737 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001738
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001739 GLint pointsOrLines = programObject->getUniformLocation("dx_PointsOrLines");
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001740 GLint alwaysFront = !isTriangleMode(drawMode);
1741 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1742
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001743 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001744 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001745 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001746 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001747 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001748 }
1749 else
1750 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001751 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001752 }
1753
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001754 mCullStateDirty = false;
1755 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001756
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001757 if (mDepthStateDirty)
1758 {
1759 if (mState.depthTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001760 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001761 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1762 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001763 }
1764 else
1765 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001766 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001767 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001768
1769 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001770 }
1771
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001772 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001773 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001774 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001775 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001776 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1777
1778 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1779 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1780 {
1781 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1782 }
1783 else
1784 {
1785 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1786 unorm<8>(mState.blendColor.alpha),
1787 unorm<8>(mState.blendColor.alpha),
1788 unorm<8>(mState.blendColor.alpha)));
1789 }
1790
1791 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1792 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1793 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1794
1795 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1796 mState.destBlendRGB != mState.destBlendAlpha ||
1797 mState.blendEquationRGB != mState.blendEquationAlpha)
1798 {
1799 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1800
1801 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1802 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1803 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
1804
1805 }
1806 else
1807 {
1808 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1809 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001810 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001811 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001812 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001813 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001814 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001815
1816 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001817 }
1818
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001819 if (mStencilStateDirty || mFrontFaceDirty)
1820 {
1821 if (mState.stencilTest && hasStencil())
1822 {
1823 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1824 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1825
1826 // FIXME: Unsupported by D3D9
1827 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1828 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1829 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1830 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1831 mState.stencilRef != mState.stencilBackRef ||
1832 mState.stencilMask != mState.stencilBackMask)
1833 {
1834 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1835 return error(GL_INVALID_OPERATION);
1836 }
1837
1838 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1839 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1840 es2dx::ConvertComparison(mState.stencilFunc));
1841
1842 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilRef); // FIXME: Clamp to range
1843 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
1844
1845 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1846 es2dx::ConvertStencilOp(mState.stencilFail));
1847 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1848 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1849 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1850 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1851
1852 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1853 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1854 es2dx::ConvertComparison(mState.stencilBackFunc));
1855
1856 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilBackRef); // FIXME: Clamp to range
1857 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
1858
1859 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1860 es2dx::ConvertStencilOp(mState.stencilBackFail));
1861 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1862 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1863 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1864 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1865 }
1866 else
1867 {
1868 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1869 }
1870
1871 mStencilStateDirty = false;
1872 }
1873
1874 if (mMaskStateDirty)
1875 {
1876 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1877 mState.colorMaskBlue, mState.colorMaskAlpha));
1878 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1879
1880 mMaskStateDirty = false;
1881 }
1882
1883 if (mPolygonOffsetStateDirty)
1884 {
1885 if (mState.polygonOffsetFill)
1886 {
1887 gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
1888 if (depthbuffer)
1889 {
1890 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1891 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1892 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1893 }
1894 }
1895 else
1896 {
1897 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1898 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1899 }
1900
1901 mPolygonOffsetStateDirty = false;
1902 }
1903
1904 if (mConfig->mMultiSample != 0 && mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001905 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001906 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001907 {
1908 FIXME("Sample alpha to coverage is unimplemented.");
1909 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001910
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001911 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001912 {
1913 FIXME("Sample coverage is unimplemented.");
1914 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001915
1916 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001917 }
1918
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001919 if (mDitherStateDirty)
1920 {
1921 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
1922
1923 mDitherStateDirty = false;
1924 }
1925
1926 mFrontFaceDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001927}
1928
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001929// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001930void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001931{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001932 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001933 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001934 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001935 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001936 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001937 }
1938 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001939}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001940
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001941void Context::applyVertexBuffer(GLint first, GLsizei count)
1942{
1943 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1944
1945 mVertexDataManager->preRenderValidate(first, count, translated);
1946
1947 lookupAttributeMapping(translated);
1948
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001949 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001950}
1951
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001952void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001953{
1954 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1955
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00001956 mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001957
1958 lookupAttributeMapping(translated);
1959
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001960 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001961}
1962
1963// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001964TranslatedIndexData Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001965{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001966 TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001967 mBufferBackEnd->setupIndicesPreDraw(indexInfo);
1968 return indexInfo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001969}
1970
1971// Applies the shaders and shader constants to the Direct3D 9 device
1972void Context::applyShaders()
1973{
1974 IDirect3DDevice9 *device = getDevice();
1975 Program *programObject = getCurrentProgram();
1976 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1977 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1978
1979 device->SetVertexShader(vertexShader);
1980 device->SetPixelShader(pixelShader);
1981
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001982 if (programObject->getSerial() != mAppliedProgram)
1983 {
1984 programObject->dirtyAllUniforms();
1985 mAppliedProgram = programObject->getSerial();
1986 }
1987
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001988 programObject->applyUniforms();
1989}
1990
1991// Applies the textures and sampler states to the Direct3D 9 device
1992void Context::applyTextures()
1993{
1994 IDirect3DDevice9 *device = getDevice();
1995 Program *programObject = getCurrentProgram();
1996
1997 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1998 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001999 int textureUnit = programObject->getSamplerMapping(sampler);
2000 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002001 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002002 SamplerType textureType = programObject->getSamplerType(sampler);
2003
2004 Texture *texture = getSamplerTexture(textureUnit, textureType);
2005
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002006 if (texture->isComplete())
2007 {
2008 GLenum wrapS = texture->getWrapS();
2009 GLenum wrapT = texture->getWrapT();
2010 GLenum minFilter = texture->getMinFilter();
2011 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002012
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002013 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
2014 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002015
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002016 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
2017 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
2018 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
2019 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
2020 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002021
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002022 device->SetTexture(sampler, texture->getTexture());
2023 }
2024 else
2025 {
2026 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
2027 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002028 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002029 else
2030 {
2031 device->SetTexture(sampler, NULL);
2032 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002033 }
2034}
2035
2036void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
2037{
2038 Framebuffer *framebuffer = getFramebuffer();
2039 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
2040 IDirect3DDevice9 *device = getDevice();
2041
2042 D3DSURFACE_DESC desc;
2043 renderTarget->GetDesc(&desc);
2044
2045 IDirect3DSurface9 *systemSurface;
2046 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
2047
2048 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2049 {
2050 return error(GL_OUT_OF_MEMORY);
2051 }
2052
2053 ASSERT(SUCCEEDED(result));
2054
2055 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
2056 {
2057 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
2058 }
2059
2060 result = device->GetRenderTargetData(renderTarget, systemSurface);
2061
2062 if (result == D3DERR_DRIVERINTERNALERROR)
2063 {
2064 systemSurface->Release();
2065
2066 return error(GL_OUT_OF_MEMORY);
2067 }
2068
2069 if (FAILED(result))
2070 {
2071 UNREACHABLE();
2072 systemSurface->Release();
2073
2074 return; // No sensible error to generate
2075 }
2076
2077 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00002078 RECT rect = {std::max(x, 0),
2079 std::max(y, 0),
2080 std::min(x + width, (int)desc.Width),
2081 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002082
2083 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
2084
2085 if (FAILED(result))
2086 {
2087 UNREACHABLE();
2088 systemSurface->Release();
2089
2090 return; // No sensible error to generate
2091 }
2092
2093 unsigned char *source = (unsigned char*)lock.pBits;
2094 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002095 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002096
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002097 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002098
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002099 for (int j = 0; j < rect.bottom - rect.top; j++)
2100 {
2101 for (int i = 0; i < rect.right - rect.left; i++)
2102 {
2103 float r;
2104 float g;
2105 float b;
2106 float a;
2107
2108 switch (desc.Format)
2109 {
2110 case D3DFMT_R5G6B5:
2111 {
2112 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2113
2114 a = 1.0f;
2115 b = (rgb & 0x001F) * (1.0f / 0x001F);
2116 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2117 r = (rgb & 0xF800) * (1.0f / 0xF800);
2118 }
2119 break;
2120 case D3DFMT_X1R5G5B5:
2121 {
2122 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2123
2124 a = 1.0f;
2125 b = (xrgb & 0x001F) * (1.0f / 0x001F);
2126 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
2127 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
2128 }
2129 break;
2130 case D3DFMT_A1R5G5B5:
2131 {
2132 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2133
2134 a = (argb & 0x8000) ? 1.0f : 0.0f;
2135 b = (argb & 0x001F) * (1.0f / 0x001F);
2136 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2137 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2138 }
2139 break;
2140 case D3DFMT_A8R8G8B8:
2141 {
2142 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2143
2144 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2145 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2146 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2147 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2148 }
2149 break;
2150 case D3DFMT_X8R8G8B8:
2151 {
2152 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2153
2154 a = 1.0f;
2155 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2156 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2157 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2158 }
2159 break;
2160 case D3DFMT_A2R10G10B10:
2161 {
2162 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2163
2164 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2165 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2166 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2167 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2168 }
2169 break;
2170 default:
2171 UNIMPLEMENTED(); // FIXME
2172 UNREACHABLE();
2173 }
2174
2175 switch (format)
2176 {
2177 case GL_RGBA:
2178 switch (type)
2179 {
2180 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002181 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2182 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2183 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2184 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002185 break;
2186 default: UNREACHABLE();
2187 }
2188 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002189 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002190 switch (type)
2191 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002192 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002193 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2194 ((unsigned short)(31 * b + 0.5f) << 0) |
2195 ((unsigned short)(63 * g + 0.5f) << 5) |
2196 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002197 break;
2198 default: UNREACHABLE();
2199 }
2200 break;
2201 default: UNREACHABLE();
2202 }
2203 }
2204 }
2205
2206 systemSurface->UnlockRect();
2207
2208 systemSurface->Release();
2209}
2210
2211void Context::clear(GLbitfield mask)
2212{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002213 Framebuffer *framebufferObject = getFramebuffer();
2214
2215 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2216 {
2217 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2218
2219 return;
2220 }
2221
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002222 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002223 IDirect3DDevice9 *device = getDevice();
2224 DWORD flags = 0;
2225
2226 if (mask & GL_COLOR_BUFFER_BIT)
2227 {
2228 mask &= ~GL_COLOR_BUFFER_BIT;
2229 flags |= D3DCLEAR_TARGET;
2230 }
2231
2232 if (mask & GL_DEPTH_BUFFER_BIT)
2233 {
2234 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002235 if (mState.depthMask)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002236 {
2237 flags |= D3DCLEAR_ZBUFFER;
2238 }
2239 }
2240
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002241 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
2242
2243 GLuint stencilUnmasked = 0x0;
2244
2245 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
2246 {
2247 D3DSURFACE_DESC desc;
2248 depthStencil->GetDesc(&desc);
2249
2250 mask &= ~GL_STENCIL_BUFFER_BIT;
2251 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2252 stencilUnmasked = (0x1 << stencilSize) - 1;
2253
2254 if (stencilUnmasked != 0x0)
2255 {
2256 flags |= D3DCLEAR_STENCIL;
2257 }
2258 }
2259
2260 if (mask != 0)
2261 {
2262 return error(GL_INVALID_VALUE);
2263 }
2264
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002265 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2266 {
2267 return;
2268 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002269
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002270 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2271 unorm<8>(mState.colorClearValue.red),
2272 unorm<8>(mState.colorClearValue.green),
2273 unorm<8>(mState.colorClearValue.blue));
2274 float depth = clamp01(mState.depthClearValue);
2275 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002276
2277 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2278
2279 D3DSURFACE_DESC desc;
2280 renderTarget->GetDesc(&desc);
2281
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002282 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002283
2284 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002285 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002286 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002287 !(mState.colorMaskRed && mState.colorMaskGreen &&
2288 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002289
2290 if (needMaskedColorClear || needMaskedStencilClear)
2291 {
2292 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2293 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2294 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2295 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2296 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2297 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2298 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2299 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2300
2301 if (flags & D3DCLEAR_TARGET)
2302 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002303 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2304 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2305 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2306 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002307 }
2308 else
2309 {
2310 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2311 }
2312
2313 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2314 {
2315 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2316 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2317 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2318 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002319 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002320 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002321 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2322 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
2323 }
2324 else
2325 {
2326 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2327 }
2328
2329 device->SetPixelShader(NULL);
2330 device->SetVertexShader(NULL);
2331 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2332
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002333 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002334 {
2335 float x, y, z, w;
2336 D3DCOLOR diffuse;
2337 };
2338
2339 Vertex quad[4];
2340 quad[0].x = 0.0f;
2341 quad[0].y = (float)desc.Height;
2342 quad[0].z = 0.0f;
2343 quad[0].w = 1.0f;
2344 quad[0].diffuse = color;
2345
2346 quad[1].x = (float)desc.Width;
2347 quad[1].y = (float)desc.Height;
2348 quad[1].z = 0.0f;
2349 quad[1].w = 1.0f;
2350 quad[1].diffuse = color;
2351
2352 quad[2].x = 0.0f;
2353 quad[2].y = 0.0f;
2354 quad[2].z = 0.0f;
2355 quad[2].w = 1.0f;
2356 quad[2].diffuse = color;
2357
2358 quad[3].x = (float)desc.Width;
2359 quad[3].y = 0.0f;
2360 quad[3].z = 0.0f;
2361 quad[3].w = 1.0f;
2362 quad[3].diffuse = color;
2363
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002364 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002365 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002366
2367 if (flags & D3DCLEAR_ZBUFFER)
2368 {
2369 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2370 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2371 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2372 }
2373 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002374 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002375 {
2376 device->Clear(0, NULL, flags, color, depth, stencil);
2377 }
2378}
2379
2380void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2381{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002382 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002383 {
2384 return error(GL_INVALID_OPERATION);
2385 }
2386
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002387 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002388 IDirect3DDevice9 *device = getDevice();
2389 D3DPRIMITIVETYPE primitiveType;
2390 int primitiveCount;
2391
2392 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2393 return error(GL_INVALID_ENUM);
2394
2395 if (primitiveCount <= 0)
2396 {
2397 return;
2398 }
2399
2400 if (!applyRenderTarget(false))
2401 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002402 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002403 }
2404
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002405 applyState(mode);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002406 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002407 applyShaders();
2408 applyTextures();
2409
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002410 if (!getCurrentProgram()->validateSamplers())
2411 {
2412 return error(GL_INVALID_OPERATION);
2413 }
2414
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002415 if (!cullSkipsDraw(mode))
2416 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002417 display->startScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002418 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002419 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002420}
2421
2422void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2423{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002424 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002425 {
2426 return error(GL_INVALID_OPERATION);
2427 }
2428
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002429 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002430 {
2431 return error(GL_INVALID_OPERATION);
2432 }
2433
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002434 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002435 IDirect3DDevice9 *device = getDevice();
2436 D3DPRIMITIVETYPE primitiveType;
2437 int primitiveCount;
2438
2439 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2440 return error(GL_INVALID_ENUM);
2441
2442 if (primitiveCount <= 0)
2443 {
2444 return;
2445 }
2446
2447 if (!applyRenderTarget(false))
2448 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002449 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002450 }
2451
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002452 applyState(mode);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002453 TranslatedIndexData indexInfo = applyIndexBuffer(indices, count, mode, type);
2454 applyVertexBuffer(indexInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002455 applyShaders();
2456 applyTextures();
2457
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002458 if (!getCurrentProgram()->validateSamplers())
2459 {
2460 return error(GL_INVALID_OPERATION);
2461 }
2462
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002463 if (!cullSkipsDraw(mode))
2464 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002465 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002466 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 +00002467 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002468}
2469
2470void Context::finish()
2471{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002472 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002473 IDirect3DDevice9 *device = getDevice();
2474 IDirect3DQuery9 *occlusionQuery = NULL;
2475
2476 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2477
2478 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2479 {
2480 return error(GL_OUT_OF_MEMORY);
2481 }
2482
2483 ASSERT(SUCCEEDED(result));
2484
2485 if (occlusionQuery)
2486 {
2487 occlusionQuery->Issue(D3DISSUE_BEGIN);
2488
2489 // Render something outside the render target
2490 device->SetPixelShader(NULL);
2491 device->SetVertexShader(NULL);
2492 device->SetFVF(D3DFVF_XYZRHW);
2493 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002494 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002495 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002496
2497 occlusionQuery->Issue(D3DISSUE_END);
2498
2499 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2500 {
2501 // Keep polling, but allow other threads to do something useful first
2502 Sleep(0);
2503 }
2504
2505 occlusionQuery->Release();
2506 }
2507}
2508
2509void Context::flush()
2510{
2511 IDirect3DDevice9 *device = getDevice();
2512 IDirect3DQuery9 *eventQuery = NULL;
2513
2514 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2515
2516 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2517 {
2518 return error(GL_OUT_OF_MEMORY);
2519 }
2520
2521 ASSERT(SUCCEEDED(result));
2522
2523 if (eventQuery)
2524 {
2525 eventQuery->Issue(D3DISSUE_END);
2526
2527 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2528 {
2529 // Keep polling, but allow other threads to do something useful first
2530 Sleep(0);
2531 }
2532
2533 eventQuery->Release();
2534 }
2535}
2536
2537void Context::recordInvalidEnum()
2538{
2539 mInvalidEnum = true;
2540}
2541
2542void Context::recordInvalidValue()
2543{
2544 mInvalidValue = true;
2545}
2546
2547void Context::recordInvalidOperation()
2548{
2549 mInvalidOperation = true;
2550}
2551
2552void Context::recordOutOfMemory()
2553{
2554 mOutOfMemory = true;
2555}
2556
2557void Context::recordInvalidFramebufferOperation()
2558{
2559 mInvalidFramebufferOperation = true;
2560}
2561
2562// Get one of the recorded errors and clear its flag, if any.
2563// [OpenGL ES 2.0.24] section 2.5 page 13.
2564GLenum Context::getError()
2565{
2566 if (mInvalidEnum)
2567 {
2568 mInvalidEnum = false;
2569
2570 return GL_INVALID_ENUM;
2571 }
2572
2573 if (mInvalidValue)
2574 {
2575 mInvalidValue = false;
2576
2577 return GL_INVALID_VALUE;
2578 }
2579
2580 if (mInvalidOperation)
2581 {
2582 mInvalidOperation = false;
2583
2584 return GL_INVALID_OPERATION;
2585 }
2586
2587 if (mOutOfMemory)
2588 {
2589 mOutOfMemory = false;
2590
2591 return GL_OUT_OF_MEMORY;
2592 }
2593
2594 if (mInvalidFramebufferOperation)
2595 {
2596 mInvalidFramebufferOperation = false;
2597
2598 return GL_INVALID_FRAMEBUFFER_OPERATION;
2599 }
2600
2601 return GL_NO_ERROR;
2602}
2603
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002604const char *Context::getPixelShaderProfile()
2605{
2606 return mPsProfile;
2607}
2608
2609const char *Context::getVertexShaderProfile()
2610{
2611 return mVsProfile;
2612}
2613
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002614void Context::detachBuffer(GLuint buffer)
2615{
2616 // [OpenGL ES 2.0.24] section 2.9 page 22:
2617 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2618 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2619
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002620 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002621 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002622 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002623 }
2624
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002625 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002626 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002627 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002628 }
2629
2630 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2631 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002632 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002633 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002634 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002635 }
2636 }
2637}
2638
2639void Context::detachTexture(GLuint texture)
2640{
2641 // [OpenGL ES 2.0.24] section 3.8 page 84:
2642 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2643 // rebound to texture object zero
2644
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002645 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002646 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002647 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002648 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002649 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002650 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002651 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002652 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002653 }
2654 }
2655
2656 // [OpenGL ES 2.0.24] section 4.4 page 112:
2657 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2658 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2659 // image was attached in the currently bound framebuffer.
2660
2661 Framebuffer *framebuffer = getFramebuffer();
2662
2663 if (framebuffer)
2664 {
2665 framebuffer->detachTexture(texture);
2666 }
2667}
2668
2669void Context::detachFramebuffer(GLuint framebuffer)
2670{
2671 // [OpenGL ES 2.0.24] section 4.4 page 107:
2672 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2673 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2674
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002675 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002676 {
2677 bindFramebuffer(0);
2678 }
2679}
2680
2681void Context::detachRenderbuffer(GLuint renderbuffer)
2682{
2683 // [OpenGL ES 2.0.24] section 4.4 page 109:
2684 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2685 // had been executed with the target RENDERBUFFER and name of zero.
2686
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002687 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002688 {
2689 bindRenderbuffer(0);
2690 }
2691
2692 // [OpenGL ES 2.0.24] section 4.4 page 111:
2693 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2694 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2695 // point to which this image was attached in the currently bound framebuffer.
2696
2697 Framebuffer *framebuffer = getFramebuffer();
2698
2699 if (framebuffer)
2700 {
2701 framebuffer->detachRenderbuffer(renderbuffer);
2702 }
2703}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002704
2705Texture *Context::getIncompleteTexture(SamplerType type)
2706{
2707 Texture *t = mIncompleteTextures[type];
2708
2709 if (t == NULL)
2710 {
2711 static const GLubyte color[] = { 0, 0, 0, 255 };
2712
2713 switch (type)
2714 {
2715 default:
2716 UNREACHABLE();
2717 // default falls through to SAMPLER_2D
2718
2719 case SAMPLER_2D:
2720 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002721 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002722 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002723 t = incomplete2d;
2724 }
2725 break;
2726
2727 case SAMPLER_CUBE:
2728 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002729 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002730
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002731 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2732 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2733 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2734 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2735 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2736 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002737
2738 t = incompleteCube;
2739 }
2740 break;
2741 }
2742
2743 mIncompleteTextures[type] = t;
2744 }
2745
2746 return t;
2747}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002748
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002749bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002750{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002751 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002752}
2753
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002754bool Context::isTriangleMode(GLenum drawMode)
2755{
2756 switch (drawMode)
2757 {
2758 case GL_TRIANGLES:
2759 case GL_TRIANGLE_FAN:
2760 case GL_TRIANGLE_STRIP:
2761 return true;
2762 case GL_POINTS:
2763 case GL_LINES:
2764 case GL_LINE_LOOP:
2765 case GL_LINE_STRIP:
2766 return false;
2767 default: UNREACHABLE();
2768 }
2769
2770 return false;
2771}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002772
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002773bool Context::hasStencil()
2774{
2775 Framebuffer *framebufferObject = getFramebuffer();
2776
2777 if (framebufferObject)
2778 {
2779 Stencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
2780
2781 if (stencilbufferObject)
2782 {
2783 return stencilbufferObject->getStencilSize() > 0;
2784 }
2785 }
2786
2787 return false;
2788}
2789
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002790void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2791{
2792 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2793
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002794 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2795 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2796 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2797 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002798
2799 mVertexDataManager->dirtyCurrentValues();
2800}
2801
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002802void Context::initExtensionString()
2803{
2804 if (mBufferBackEnd->supportIntIndices())
2805 {
2806 mExtensionString += "GL_OES_element_index_uint ";
2807 }
2808
2809 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2810 if (end != std::string::npos)
2811 {
2812 mExtensionString.resize(end+1);
2813 }
2814}
2815
2816const char *Context::getExtensionString() const
2817{
2818 return mExtensionString.c_str();
2819}
2820
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002821}
2822
2823extern "C"
2824{
2825gl::Context *glCreateContext(const egl::Config *config)
2826{
2827 return new gl::Context(config);
2828}
2829
2830void glDestroyContext(gl::Context *context)
2831{
2832 delete context;
2833
2834 if (context == gl::getContext())
2835 {
2836 gl::makeCurrent(NULL, NULL, NULL);
2837 }
2838}
2839
2840void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2841{
2842 gl::makeCurrent(context, display, surface);
2843}
2844
2845gl::Context *glGetCurrentContext()
2846{
2847 return gl::getContext();
2848}
2849}