blob: 92535ca5ecccff8f82ad741391c2ba2d98d8e800 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Context.cpp: Implements the gl::Context class, managing all GL state and performing
8// rendering operations. It is the GLES2 specific implementation of EGLContext.
9
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/Context.h"
daniel@transgaming.com16973022010-03-11 19:22:19 +000011
12#include <algorithm>
13
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000014#include "libEGL/Display.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000015
16#include "libGLESv2/main.h"
17#include "libGLESv2/mathutil.h"
18#include "libGLESv2/utilities.h"
19#include "libGLESv2/Blit.h"
20#include "libGLESv2/Buffer.h"
21#include "libGLESv2/FrameBuffer.h"
22#include "libGLESv2/Program.h"
23#include "libGLESv2/RenderBuffer.h"
24#include "libGLESv2/Shader.h"
25#include "libGLESv2/Texture.h"
26#include "libGLESv2/geometry/backend.h"
27#include "libGLESv2/geometry/VertexDataManager.h"
28#include "libGLESv2/geometry/IndexDataManager.h"
29#include "libGLESv2/geometry/dx9.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030
daniel@transgaming.com86487c22010-03-11 19:41:43 +000031#undef near
32#undef far
33
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034namespace gl
35{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000036Context::Context(const egl::Config *config)
37 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038{
39 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
daniel@transgaming.com092bd482010-05-12 03:39:36 +000040
daniel@transgaming.com428d1582010-05-04 03:35:25 +000041 mState.depthClearValue = 1.0f;
42 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043
daniel@transgaming.com428d1582010-05-04 03:35:25 +000044 mState.cullFace = false;
45 mState.cullMode = GL_BACK;
46 mState.frontFace = GL_CCW;
47 mState.depthTest = false;
48 mState.depthFunc = GL_LESS;
49 mState.blend = false;
50 mState.sourceBlendRGB = GL_ONE;
51 mState.sourceBlendAlpha = GL_ONE;
52 mState.destBlendRGB = GL_ZERO;
53 mState.destBlendAlpha = GL_ZERO;
54 mState.blendEquationRGB = GL_FUNC_ADD;
55 mState.blendEquationAlpha = GL_FUNC_ADD;
56 mState.blendColor.red = 0;
57 mState.blendColor.green = 0;
58 mState.blendColor.blue = 0;
59 mState.blendColor.alpha = 0;
60 mState.stencilTest = false;
61 mState.stencilFunc = GL_ALWAYS;
62 mState.stencilRef = 0;
63 mState.stencilMask = -1;
64 mState.stencilWritemask = -1;
65 mState.stencilBackFunc = GL_ALWAYS;
66 mState.stencilBackRef = 0;
67 mState.stencilBackMask = - 1;
68 mState.stencilBackWritemask = -1;
69 mState.stencilFail = GL_KEEP;
70 mState.stencilPassDepthFail = GL_KEEP;
71 mState.stencilPassDepthPass = GL_KEEP;
72 mState.stencilBackFail = GL_KEEP;
73 mState.stencilBackPassDepthFail = GL_KEEP;
74 mState.stencilBackPassDepthPass = GL_KEEP;
75 mState.polygonOffsetFill = false;
76 mState.polygonOffsetFactor = 0.0f;
77 mState.polygonOffsetUnits = 0.0f;
78 mState.sampleAlphaToCoverage = false;
79 mState.sampleCoverage = false;
80 mState.sampleCoverageValue = 1.0f;
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +000081 mState.sampleCoverageInvert = false;
daniel@transgaming.com428d1582010-05-04 03:35:25 +000082 mState.scissorTest = false;
83 mState.dither = true;
84 mState.generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085
daniel@transgaming.com428d1582010-05-04 03:35:25 +000086 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000087
daniel@transgaming.com428d1582010-05-04 03:35:25 +000088 mState.viewportX = 0;
89 mState.viewportY = 0;
90 mState.viewportWidth = config->mDisplayMode.Width;
91 mState.viewportHeight = config->mDisplayMode.Height;
92 mState.zNear = 0.0f;
93 mState.zFar = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000094
daniel@transgaming.com428d1582010-05-04 03:35:25 +000095 mState.scissorX = 0;
96 mState.scissorY = 0;
97 mState.scissorWidth = config->mDisplayMode.Width;
98 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000100 mState.colorMaskRed = true;
101 mState.colorMaskGreen = true;
102 mState.colorMaskBlue = true;
103 mState.colorMaskAlpha = true;
104 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105
106 // [OpenGL ES 2.0.24] section 3.7 page 83:
107 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
108 // and cube map texture state vectors respectively associated with them.
109 // In order that access to these initial textures not be lost, they are treated as texture
110 // objects all of whose names are 0.
111
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000112 mTexture2DZero = new Texture2D(this);
113 mTextureCubeMapZero = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114
115 mColorbufferZero = NULL;
116 mDepthbufferZero = NULL;
117 mStencilbufferZero = NULL;
118
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000119 mState.activeSampler = 0;
120 mState.arrayBuffer = 0;
121 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122 bindTextureCubeMap(0);
123 bindTexture2D(0);
124 bindFramebuffer(0);
125 bindRenderbuffer(0);
126
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000127 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000129 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
130 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000131 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000132 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133 }
134
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000135 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
136 {
137 mIncompleteTextures[type] = NULL;
138 }
139
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000140 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000142 mState.packAlignment = 4;
143 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000144
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000145 mBufferBackEnd = NULL;
146 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000147 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000148 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000149
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150 mInvalidEnum = false;
151 mInvalidValue = false;
152 mInvalidOperation = false;
153 mOutOfMemory = false;
154 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000155
156 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000157
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.comc808c5a2010-05-14 17:31:01 +0000217 if (!mHasBeenCurrent)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000218 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000219 device->GetDeviceCaps(&mDeviceCaps);
220
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000221 mBufferBackEnd = new Dx9BackEnd(device);
222 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000223 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000224 mBlit = new Blit(this);
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000225
226 initExtensionString();
227
228 mState.viewportX = 0;
229 mState.viewportY = 0;
230 mState.viewportWidth = surface->getWidth();
231 mState.viewportHeight = surface->getHeight();
232
233 mState.scissorX = 0;
234 mState.scissorY = 0;
235 mState.scissorWidth = surface->getWidth();
236 mState.scissorHeight = surface->getHeight();
237
238 mHasBeenCurrent = true;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000239 }
240
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
242 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000243 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244
245 Framebuffer *framebufferZero = new Framebuffer();
246 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000247 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
248 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
250 setFramebufferZero(framebufferZero);
251 setColorbufferZero(colorbufferZero);
252 setDepthbufferZero(depthbufferZero);
253 setStencilbufferZero(stencilbufferZero);
254
255 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
256 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
257 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
258
259 defaultRenderTarget->Release();
260
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000261 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000263 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000265
266 D3DCAPS9 capabilities;
267 device->GetDeviceCaps(&capabilities);
268
269 if (capabilities.PixelShaderVersion == D3DPS_VERSION(3, 0))
270 {
271 mPsProfile = "ps_3_0";
272 mVsProfile = "vs_3_0";
273 }
274 else // egl::Display guarantees support for at least 2.0
275 {
276 mPsProfile = "ps_2_0";
277 mVsProfile = "vs_2_0";
278 }
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000279
280 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281}
282
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000283// 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 +0000284void Context::markAllStateDirty()
285{
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000286 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000287 mAppliedDepthbufferSerial = 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
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +0000574void Context::setSampleCoverageParams(GLclampf value, bool invert)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000575{
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.comdefa1c32010-05-18 18:51:45 +0000932 mBufferMap[buffer] = new Buffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000933 }
934
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000935 mState.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.comdefa1c32010-05-18 18:51:45 +0000942 mBufferMap[buffer] = new Buffer();
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.com339ae702010-05-12 03:40:20 +00001645 unsigned int depthbufferSerial = framebufferObject->getDepthbufferSerial();
1646 if (depthbufferSerial != mAppliedDepthbufferSerial)
1647 {
1648 device->SetDepthStencilSurface(depthStencil);
1649 mAppliedDepthbufferSerial = depthbufferSerial;
1650 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001651
1652 D3DVIEWPORT9 viewport;
1653 D3DSURFACE_DESC desc;
1654 renderTarget->GetDesc(&desc);
1655
1656 if (ignoreViewport)
1657 {
1658 viewport.X = 0;
1659 viewport.Y = 0;
1660 viewport.Width = desc.Width;
1661 viewport.Height = desc.Height;
1662 viewport.MinZ = 0.0f;
1663 viewport.MaxZ = 1.0f;
1664 }
1665 else
1666 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001667 viewport.X = std::max(mState.viewportX, 0);
1668 viewport.Y = std::max(mState.viewportY, 0);
1669 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1670 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1671 viewport.MinZ = clamp01(mState.zNear);
1672 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001673 }
1674
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001675 if (viewport.Width <= 0 || viewport.Height <= 0)
1676 {
1677 return false; // Nothing to render
1678 }
1679
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001680 device->SetViewport(&viewport);
1681
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001682 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001683 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001684 if (mState.scissorTest)
1685 {
1686 RECT rect = {mState.scissorX,
1687 mState.scissorY,
1688 mState.scissorX + mState.scissorWidth,
1689 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001690
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001691 device->SetScissorRect(&rect);
1692 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1693 }
1694 else
1695 {
1696 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1697 }
1698
1699 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001700 }
1701
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001702 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001703 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001704 Program *programObject = getCurrentProgram();
1705
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001706 GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001707 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001708 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001709
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001710 GLint window = programObject->getDxWindowLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001711 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1712 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1713 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001714 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1715
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001716 GLint depth = programObject->getDxDepthLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001717 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001718 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1719
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001720 GLint near = programObject->getDepthRangeNearLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001721 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001722
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001723 GLint far = programObject->getDepthRangeFarLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001724 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001725
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001726 GLint diff = programObject->getDepthRangeDiffLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001727 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001728 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001729 }
1730
1731 return true;
1732}
1733
1734// 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 +00001735void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001736{
1737 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001738 Program *programObject = getCurrentProgram();
1739
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001740 GLint frontCCW = programObject->getDxFrontCCWLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001741 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001742 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001743
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001744 GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001745 GLint alwaysFront = !isTriangleMode(drawMode);
1746 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1747
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001748 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001749 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001750 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001751 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001752 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001753 }
1754 else
1755 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001756 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001757 }
1758
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001759 mCullStateDirty = false;
1760 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001761
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001762 if (mDepthStateDirty)
1763 {
1764 if (mState.depthTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001765 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001766 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1767 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001768 }
1769 else
1770 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001771 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001772 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001773
1774 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001775 }
1776
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001777 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001778 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001779 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001780 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001781 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1782
1783 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1784 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1785 {
1786 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1787 }
1788 else
1789 {
1790 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1791 unorm<8>(mState.blendColor.alpha),
1792 unorm<8>(mState.blendColor.alpha),
1793 unorm<8>(mState.blendColor.alpha)));
1794 }
1795
1796 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1797 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1798 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1799
1800 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1801 mState.destBlendRGB != mState.destBlendAlpha ||
1802 mState.blendEquationRGB != mState.blendEquationAlpha)
1803 {
1804 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1805
1806 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1807 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1808 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
1809
1810 }
1811 else
1812 {
1813 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1814 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001815 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001816 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001817 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001818 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001819 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001820
1821 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001822 }
1823
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001824 if (mStencilStateDirty || mFrontFaceDirty)
1825 {
1826 if (mState.stencilTest && hasStencil())
1827 {
1828 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1829 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1830
1831 // FIXME: Unsupported by D3D9
1832 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1833 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1834 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1835 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1836 mState.stencilRef != mState.stencilBackRef ||
1837 mState.stencilMask != mState.stencilBackMask)
1838 {
1839 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1840 return error(GL_INVALID_OPERATION);
1841 }
1842
1843 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1844 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1845 es2dx::ConvertComparison(mState.stencilFunc));
1846
1847 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilRef); // FIXME: Clamp to range
1848 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
1849
1850 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1851 es2dx::ConvertStencilOp(mState.stencilFail));
1852 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1853 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1854 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1855 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1856
1857 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1858 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1859 es2dx::ConvertComparison(mState.stencilBackFunc));
1860
1861 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilBackRef); // FIXME: Clamp to range
1862 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
1863
1864 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1865 es2dx::ConvertStencilOp(mState.stencilBackFail));
1866 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1867 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1868 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1869 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1870 }
1871 else
1872 {
1873 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1874 }
1875
1876 mStencilStateDirty = false;
1877 }
1878
1879 if (mMaskStateDirty)
1880 {
1881 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1882 mState.colorMaskBlue, mState.colorMaskAlpha));
1883 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1884
1885 mMaskStateDirty = false;
1886 }
1887
1888 if (mPolygonOffsetStateDirty)
1889 {
1890 if (mState.polygonOffsetFill)
1891 {
1892 gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
1893 if (depthbuffer)
1894 {
1895 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1896 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1897 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1898 }
1899 }
1900 else
1901 {
1902 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1903 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1904 }
1905
1906 mPolygonOffsetStateDirty = false;
1907 }
1908
1909 if (mConfig->mMultiSample != 0 && mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001910 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001911 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001912 {
1913 FIXME("Sample alpha to coverage is unimplemented.");
1914 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001915
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001916 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001917 {
1918 FIXME("Sample coverage is unimplemented.");
1919 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001920
1921 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001922 }
1923
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001924 if (mDitherStateDirty)
1925 {
1926 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
1927
1928 mDitherStateDirty = false;
1929 }
1930
1931 mFrontFaceDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001932}
1933
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001934// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001935void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001936{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001937 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001938 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001939 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001940 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001941 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001942 }
1943 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001944}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001945
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001946GLenum Context::applyVertexBuffer(GLint first, GLsizei count)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001947{
1948 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1949
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001950 GLenum err = mVertexDataManager->preRenderValidate(first, count, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001951
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001952 if (err == GL_NO_ERROR)
1953 {
1954 lookupAttributeMapping(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001955
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001956 mBufferBackEnd->setupAttributesPreDraw(translated);
1957 }
1958
1959 return err;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001960}
1961
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001962GLenum Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001963{
1964 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1965
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001966 GLenum err = mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001967
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001968 if (err == GL_NO_ERROR)
1969 {
1970 lookupAttributeMapping(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001971
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001972 mBufferBackEnd->setupAttributesPreDraw(translated);
1973 }
1974
1975 return err;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001976}
1977
1978// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001979GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001980{
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001981 GLenum error = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices, indexInfo);
1982
1983 if (error == GL_NO_ERROR)
1984 {
1985 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
1986 }
1987
1988 return error;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001989}
1990
1991// Applies the shaders and shader constants to the Direct3D 9 device
1992void Context::applyShaders()
1993{
1994 IDirect3DDevice9 *device = getDevice();
1995 Program *programObject = getCurrentProgram();
1996 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1997 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1998
1999 device->SetVertexShader(vertexShader);
2000 device->SetPixelShader(pixelShader);
2001
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002002 if (programObject->getSerial() != mAppliedProgram)
2003 {
2004 programObject->dirtyAllUniforms();
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002005 programObject->dirtyAllSamplers();
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002006 mAppliedProgram = programObject->getSerial();
2007 }
2008
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002009 programObject->applyUniforms();
2010}
2011
2012// Applies the textures and sampler states to the Direct3D 9 device
2013void Context::applyTextures()
2014{
2015 IDirect3DDevice9 *device = getDevice();
2016 Program *programObject = getCurrentProgram();
2017
2018 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
2019 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002020 int textureUnit = programObject->getSamplerMapping(sampler);
2021 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002022 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002023 SamplerType textureType = programObject->getSamplerType(sampler);
2024
2025 Texture *texture = getSamplerTexture(textureUnit, textureType);
2026
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002027 if (programObject->isSamplerDirty(sampler) || texture->isDirty())
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002028 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002029 if (texture->isComplete())
2030 {
2031 GLenum wrapS = texture->getWrapS();
2032 GLenum wrapT = texture->getWrapT();
2033 GLenum minFilter = texture->getMinFilter();
2034 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002035
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002036 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
2037 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002038
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002039 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
2040 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
2041 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
2042 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
2043 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002044
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002045 device->SetTexture(sampler, texture->getTexture());
2046 }
2047 else
2048 {
2049 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
2050 }
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002051 }
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002052
2053 programObject->setSamplerDirty(sampler, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002054 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002055 else
2056 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002057 if (programObject->isSamplerDirty(sampler))
2058 {
2059 device->SetTexture(sampler, NULL);
2060 programObject->setSamplerDirty(sampler, false);
2061 }
2062 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002063 }
2064}
2065
2066void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
2067{
2068 Framebuffer *framebuffer = getFramebuffer();
2069 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
2070 IDirect3DDevice9 *device = getDevice();
2071
2072 D3DSURFACE_DESC desc;
2073 renderTarget->GetDesc(&desc);
2074
2075 IDirect3DSurface9 *systemSurface;
2076 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
2077
2078 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2079 {
2080 return error(GL_OUT_OF_MEMORY);
2081 }
2082
2083 ASSERT(SUCCEEDED(result));
2084
2085 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
2086 {
2087 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
2088 }
2089
2090 result = device->GetRenderTargetData(renderTarget, systemSurface);
2091
2092 if (result == D3DERR_DRIVERINTERNALERROR)
2093 {
2094 systemSurface->Release();
2095
2096 return error(GL_OUT_OF_MEMORY);
2097 }
2098
2099 if (FAILED(result))
2100 {
2101 UNREACHABLE();
2102 systemSurface->Release();
2103
2104 return; // No sensible error to generate
2105 }
2106
2107 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00002108 RECT rect = {std::max(x, 0),
2109 std::max(y, 0),
2110 std::min(x + width, (int)desc.Width),
2111 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002112
2113 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
2114
2115 if (FAILED(result))
2116 {
2117 UNREACHABLE();
2118 systemSurface->Release();
2119
2120 return; // No sensible error to generate
2121 }
2122
2123 unsigned char *source = (unsigned char*)lock.pBits;
2124 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002125 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002126
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002127 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002128
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002129 for (int j = 0; j < rect.bottom - rect.top; j++)
2130 {
2131 for (int i = 0; i < rect.right - rect.left; i++)
2132 {
2133 float r;
2134 float g;
2135 float b;
2136 float a;
2137
2138 switch (desc.Format)
2139 {
2140 case D3DFMT_R5G6B5:
2141 {
2142 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2143
2144 a = 1.0f;
2145 b = (rgb & 0x001F) * (1.0f / 0x001F);
2146 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2147 r = (rgb & 0xF800) * (1.0f / 0xF800);
2148 }
2149 break;
2150 case D3DFMT_X1R5G5B5:
2151 {
2152 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2153
2154 a = 1.0f;
2155 b = (xrgb & 0x001F) * (1.0f / 0x001F);
2156 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
2157 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
2158 }
2159 break;
2160 case D3DFMT_A1R5G5B5:
2161 {
2162 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2163
2164 a = (argb & 0x8000) ? 1.0f : 0.0f;
2165 b = (argb & 0x001F) * (1.0f / 0x001F);
2166 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2167 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2168 }
2169 break;
2170 case D3DFMT_A8R8G8B8:
2171 {
2172 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2173
2174 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2175 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2176 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2177 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2178 }
2179 break;
2180 case D3DFMT_X8R8G8B8:
2181 {
2182 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2183
2184 a = 1.0f;
2185 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2186 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2187 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2188 }
2189 break;
2190 case D3DFMT_A2R10G10B10:
2191 {
2192 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2193
2194 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2195 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2196 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2197 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2198 }
2199 break;
2200 default:
2201 UNIMPLEMENTED(); // FIXME
2202 UNREACHABLE();
2203 }
2204
2205 switch (format)
2206 {
2207 case GL_RGBA:
2208 switch (type)
2209 {
2210 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002211 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2212 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2213 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2214 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002215 break;
2216 default: UNREACHABLE();
2217 }
2218 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002219 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002220 switch (type)
2221 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002222 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002223 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2224 ((unsigned short)(31 * b + 0.5f) << 0) |
2225 ((unsigned short)(63 * g + 0.5f) << 5) |
2226 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002227 break;
2228 default: UNREACHABLE();
2229 }
2230 break;
2231 default: UNREACHABLE();
2232 }
2233 }
2234 }
2235
2236 systemSurface->UnlockRect();
2237
2238 systemSurface->Release();
2239}
2240
2241void Context::clear(GLbitfield mask)
2242{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002243 Framebuffer *framebufferObject = getFramebuffer();
2244
2245 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2246 {
2247 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2248
2249 return;
2250 }
2251
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002252 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002253 IDirect3DDevice9 *device = getDevice();
2254 DWORD flags = 0;
2255
2256 if (mask & GL_COLOR_BUFFER_BIT)
2257 {
2258 mask &= ~GL_COLOR_BUFFER_BIT;
2259 flags |= D3DCLEAR_TARGET;
2260 }
2261
2262 if (mask & GL_DEPTH_BUFFER_BIT)
2263 {
2264 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002265 if (mState.depthMask)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002266 {
2267 flags |= D3DCLEAR_ZBUFFER;
2268 }
2269 }
2270
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002271 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
2272
2273 GLuint stencilUnmasked = 0x0;
2274
2275 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
2276 {
2277 D3DSURFACE_DESC desc;
2278 depthStencil->GetDesc(&desc);
2279
2280 mask &= ~GL_STENCIL_BUFFER_BIT;
2281 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2282 stencilUnmasked = (0x1 << stencilSize) - 1;
2283
2284 if (stencilUnmasked != 0x0)
2285 {
2286 flags |= D3DCLEAR_STENCIL;
2287 }
2288 }
2289
2290 if (mask != 0)
2291 {
2292 return error(GL_INVALID_VALUE);
2293 }
2294
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002295 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2296 {
2297 return;
2298 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002299
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002300 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2301 unorm<8>(mState.colorClearValue.red),
2302 unorm<8>(mState.colorClearValue.green),
2303 unorm<8>(mState.colorClearValue.blue));
2304 float depth = clamp01(mState.depthClearValue);
2305 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002306
2307 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2308
2309 D3DSURFACE_DESC desc;
2310 renderTarget->GetDesc(&desc);
2311
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002312 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002313
2314 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002315 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002316 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002317 !(mState.colorMaskRed && mState.colorMaskGreen &&
2318 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002319
2320 if (needMaskedColorClear || needMaskedStencilClear)
2321 {
2322 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2323 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2324 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2325 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2326 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2327 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2328 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2329 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2330
2331 if (flags & D3DCLEAR_TARGET)
2332 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002333 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2334 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2335 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2336 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002337 }
2338 else
2339 {
2340 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2341 }
2342
2343 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2344 {
2345 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2346 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2347 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2348 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002349 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002350 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002351 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2352 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
2353 }
2354 else
2355 {
2356 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2357 }
2358
2359 device->SetPixelShader(NULL);
2360 device->SetVertexShader(NULL);
2361 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2362
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002363 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002364 {
2365 float x, y, z, w;
2366 D3DCOLOR diffuse;
2367 };
2368
2369 Vertex quad[4];
2370 quad[0].x = 0.0f;
2371 quad[0].y = (float)desc.Height;
2372 quad[0].z = 0.0f;
2373 quad[0].w = 1.0f;
2374 quad[0].diffuse = color;
2375
2376 quad[1].x = (float)desc.Width;
2377 quad[1].y = (float)desc.Height;
2378 quad[1].z = 0.0f;
2379 quad[1].w = 1.0f;
2380 quad[1].diffuse = color;
2381
2382 quad[2].x = 0.0f;
2383 quad[2].y = 0.0f;
2384 quad[2].z = 0.0f;
2385 quad[2].w = 1.0f;
2386 quad[2].diffuse = color;
2387
2388 quad[3].x = (float)desc.Width;
2389 quad[3].y = 0.0f;
2390 quad[3].z = 0.0f;
2391 quad[3].w = 1.0f;
2392 quad[3].diffuse = color;
2393
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002394 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002395 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002396
2397 if (flags & D3DCLEAR_ZBUFFER)
2398 {
2399 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2400 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2401 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2402 }
2403 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002404 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002405 {
2406 device->Clear(0, NULL, flags, color, depth, stencil);
2407 }
2408}
2409
2410void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2411{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002412 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002413 {
2414 return error(GL_INVALID_OPERATION);
2415 }
2416
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002417 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002418 IDirect3DDevice9 *device = getDevice();
2419 D3DPRIMITIVETYPE primitiveType;
2420 int primitiveCount;
2421
2422 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2423 return error(GL_INVALID_ENUM);
2424
2425 if (primitiveCount <= 0)
2426 {
2427 return;
2428 }
2429
2430 if (!applyRenderTarget(false))
2431 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002432 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002433 }
2434
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002435 applyState(mode);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002436
2437 GLenum err = applyVertexBuffer(first, count);
2438 if (err != GL_NO_ERROR)
2439 {
2440 return error(err);
2441 }
2442
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002443 applyShaders();
2444 applyTextures();
2445
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002446 if (!getCurrentProgram()->validateSamplers())
2447 {
2448 return error(GL_INVALID_OPERATION);
2449 }
2450
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002451 if (!cullSkipsDraw(mode))
2452 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002453 display->startScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002454 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002455 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002456}
2457
2458void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2459{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002460 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002461 {
2462 return error(GL_INVALID_OPERATION);
2463 }
2464
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002465 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002466 {
2467 return error(GL_INVALID_OPERATION);
2468 }
2469
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002470 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002471 IDirect3DDevice9 *device = getDevice();
2472 D3DPRIMITIVETYPE primitiveType;
2473 int primitiveCount;
2474
2475 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2476 return error(GL_INVALID_ENUM);
2477
2478 if (primitiveCount <= 0)
2479 {
2480 return;
2481 }
2482
2483 if (!applyRenderTarget(false))
2484 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002485 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002486 }
2487
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002488 applyState(mode);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002489
2490 TranslatedIndexData indexInfo;
2491 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2492 if (err != GL_NO_ERROR)
2493 {
2494 return error(err);
2495 }
2496
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002497 err = applyVertexBuffer(indexInfo);
2498 if (err != GL_NO_ERROR)
2499 {
2500 return error(err);
2501 }
2502
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002503 applyShaders();
2504 applyTextures();
2505
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002506 if (!getCurrentProgram()->validateSamplers())
2507 {
2508 return error(GL_INVALID_OPERATION);
2509 }
2510
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002511 if (!cullSkipsDraw(mode))
2512 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002513 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002514 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 +00002515 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002516}
2517
2518void Context::finish()
2519{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002520 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002521 IDirect3DDevice9 *device = getDevice();
2522 IDirect3DQuery9 *occlusionQuery = NULL;
2523
2524 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2525
2526 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2527 {
2528 return error(GL_OUT_OF_MEMORY);
2529 }
2530
2531 ASSERT(SUCCEEDED(result));
2532
2533 if (occlusionQuery)
2534 {
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002535 IDirect3DStateBlock9 *savedState = NULL;
2536 device->CreateStateBlock(D3DSBT_ALL, &savedState);
2537
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002538 occlusionQuery->Issue(D3DISSUE_BEGIN);
2539
2540 // Render something outside the render target
2541 device->SetPixelShader(NULL);
2542 device->SetVertexShader(NULL);
2543 device->SetFVF(D3DFVF_XYZRHW);
2544 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002545 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002546 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002547
2548 occlusionQuery->Issue(D3DISSUE_END);
2549
2550 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2551 {
2552 // Keep polling, but allow other threads to do something useful first
2553 Sleep(0);
2554 }
2555
2556 occlusionQuery->Release();
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002557
2558 if (savedState)
2559 {
2560 savedState->Apply();
2561 savedState->Release();
2562 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002563 }
2564}
2565
2566void Context::flush()
2567{
2568 IDirect3DDevice9 *device = getDevice();
2569 IDirect3DQuery9 *eventQuery = NULL;
2570
2571 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2572
2573 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2574 {
2575 return error(GL_OUT_OF_MEMORY);
2576 }
2577
2578 ASSERT(SUCCEEDED(result));
2579
2580 if (eventQuery)
2581 {
2582 eventQuery->Issue(D3DISSUE_END);
2583
2584 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2585 {
2586 // Keep polling, but allow other threads to do something useful first
2587 Sleep(0);
2588 }
2589
2590 eventQuery->Release();
2591 }
2592}
2593
2594void Context::recordInvalidEnum()
2595{
2596 mInvalidEnum = true;
2597}
2598
2599void Context::recordInvalidValue()
2600{
2601 mInvalidValue = true;
2602}
2603
2604void Context::recordInvalidOperation()
2605{
2606 mInvalidOperation = true;
2607}
2608
2609void Context::recordOutOfMemory()
2610{
2611 mOutOfMemory = true;
2612}
2613
2614void Context::recordInvalidFramebufferOperation()
2615{
2616 mInvalidFramebufferOperation = true;
2617}
2618
2619// Get one of the recorded errors and clear its flag, if any.
2620// [OpenGL ES 2.0.24] section 2.5 page 13.
2621GLenum Context::getError()
2622{
2623 if (mInvalidEnum)
2624 {
2625 mInvalidEnum = false;
2626
2627 return GL_INVALID_ENUM;
2628 }
2629
2630 if (mInvalidValue)
2631 {
2632 mInvalidValue = false;
2633
2634 return GL_INVALID_VALUE;
2635 }
2636
2637 if (mInvalidOperation)
2638 {
2639 mInvalidOperation = false;
2640
2641 return GL_INVALID_OPERATION;
2642 }
2643
2644 if (mOutOfMemory)
2645 {
2646 mOutOfMemory = false;
2647
2648 return GL_OUT_OF_MEMORY;
2649 }
2650
2651 if (mInvalidFramebufferOperation)
2652 {
2653 mInvalidFramebufferOperation = false;
2654
2655 return GL_INVALID_FRAMEBUFFER_OPERATION;
2656 }
2657
2658 return GL_NO_ERROR;
2659}
2660
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002661const char *Context::getPixelShaderProfile()
2662{
2663 return mPsProfile;
2664}
2665
2666const char *Context::getVertexShaderProfile()
2667{
2668 return mVsProfile;
2669}
2670
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002671void Context::detachBuffer(GLuint buffer)
2672{
2673 // [OpenGL ES 2.0.24] section 2.9 page 22:
2674 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2675 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2676
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002677 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002678 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002679 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002680 }
2681
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002682 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002683 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002684 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002685 }
2686
2687 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2688 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002689 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002690 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002691 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002692 }
2693 }
2694}
2695
2696void Context::detachTexture(GLuint texture)
2697{
2698 // [OpenGL ES 2.0.24] section 3.8 page 84:
2699 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2700 // rebound to texture object zero
2701
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002702 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002703 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002704 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002705 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002706 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002707 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002708 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002709 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002710 }
2711 }
2712
2713 // [OpenGL ES 2.0.24] section 4.4 page 112:
2714 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2715 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2716 // image was attached in the currently bound framebuffer.
2717
2718 Framebuffer *framebuffer = getFramebuffer();
2719
2720 if (framebuffer)
2721 {
2722 framebuffer->detachTexture(texture);
2723 }
2724}
2725
2726void Context::detachFramebuffer(GLuint framebuffer)
2727{
2728 // [OpenGL ES 2.0.24] section 4.4 page 107:
2729 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2730 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2731
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002732 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002733 {
2734 bindFramebuffer(0);
2735 }
2736}
2737
2738void Context::detachRenderbuffer(GLuint renderbuffer)
2739{
2740 // [OpenGL ES 2.0.24] section 4.4 page 109:
2741 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2742 // had been executed with the target RENDERBUFFER and name of zero.
2743
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002744 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002745 {
2746 bindRenderbuffer(0);
2747 }
2748
2749 // [OpenGL ES 2.0.24] section 4.4 page 111:
2750 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2751 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2752 // point to which this image was attached in the currently bound framebuffer.
2753
2754 Framebuffer *framebuffer = getFramebuffer();
2755
2756 if (framebuffer)
2757 {
2758 framebuffer->detachRenderbuffer(renderbuffer);
2759 }
2760}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002761
2762Texture *Context::getIncompleteTexture(SamplerType type)
2763{
2764 Texture *t = mIncompleteTextures[type];
2765
2766 if (t == NULL)
2767 {
2768 static const GLubyte color[] = { 0, 0, 0, 255 };
2769
2770 switch (type)
2771 {
2772 default:
2773 UNREACHABLE();
2774 // default falls through to SAMPLER_2D
2775
2776 case SAMPLER_2D:
2777 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002778 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002779 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002780 t = incomplete2d;
2781 }
2782 break;
2783
2784 case SAMPLER_CUBE:
2785 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002786 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002787
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002788 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2789 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2790 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2791 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2792 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2793 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002794
2795 t = incompleteCube;
2796 }
2797 break;
2798 }
2799
2800 mIncompleteTextures[type] = t;
2801 }
2802
2803 return t;
2804}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002805
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002806bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002807{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002808 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002809}
2810
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002811bool Context::isTriangleMode(GLenum drawMode)
2812{
2813 switch (drawMode)
2814 {
2815 case GL_TRIANGLES:
2816 case GL_TRIANGLE_FAN:
2817 case GL_TRIANGLE_STRIP:
2818 return true;
2819 case GL_POINTS:
2820 case GL_LINES:
2821 case GL_LINE_LOOP:
2822 case GL_LINE_STRIP:
2823 return false;
2824 default: UNREACHABLE();
2825 }
2826
2827 return false;
2828}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002829
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002830bool Context::hasStencil()
2831{
2832 Framebuffer *framebufferObject = getFramebuffer();
2833
2834 if (framebufferObject)
2835 {
2836 Stencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
2837
2838 if (stencilbufferObject)
2839 {
2840 return stencilbufferObject->getStencilSize() > 0;
2841 }
2842 }
2843
2844 return false;
2845}
2846
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002847void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2848{
2849 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2850
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002851 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2852 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2853 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2854 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002855
2856 mVertexDataManager->dirtyCurrentValues();
2857}
2858
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002859void Context::initExtensionString()
2860{
2861 if (mBufferBackEnd->supportIntIndices())
2862 {
2863 mExtensionString += "GL_OES_element_index_uint ";
2864 }
2865
2866 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2867 if (end != std::string::npos)
2868 {
2869 mExtensionString.resize(end+1);
2870 }
2871}
2872
2873const char *Context::getExtensionString() const
2874{
2875 return mExtensionString.c_str();
2876}
2877
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002878}
2879
2880extern "C"
2881{
2882gl::Context *glCreateContext(const egl::Config *config)
2883{
2884 return new gl::Context(config);
2885}
2886
2887void glDestroyContext(gl::Context *context)
2888{
2889 delete context;
2890
2891 if (context == gl::getContext())
2892 {
2893 gl::makeCurrent(NULL, NULL, NULL);
2894 }
2895}
2896
2897void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2898{
2899 gl::makeCurrent(context, display, surface);
2900}
2901
2902gl::Context *glGetCurrentContext()
2903{
2904 return gl::getContext();
2905}
2906}