blob: 9c9bc3f83484aaae63265aee8ae0415fca431b23 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Context.cpp: Implements the gl::Context class, managing all GL state and performing
8// rendering operations. It is the GLES2 specific implementation of EGLContext.
9
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/Context.h"
daniel@transgaming.com16973022010-03-11 19:22:19 +000011
12#include <algorithm>
13
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000014#include "libEGL/Display.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000015
16#include "libGLESv2/main.h"
17#include "libGLESv2/mathutil.h"
18#include "libGLESv2/utilities.h"
19#include "libGLESv2/Blit.h"
20#include "libGLESv2/Buffer.h"
21#include "libGLESv2/FrameBuffer.h"
22#include "libGLESv2/Program.h"
23#include "libGLESv2/RenderBuffer.h"
24#include "libGLESv2/Shader.h"
25#include "libGLESv2/Texture.h"
26#include "libGLESv2/geometry/backend.h"
27#include "libGLESv2/geometry/VertexDataManager.h"
28#include "libGLESv2/geometry/IndexDataManager.h"
29#include "libGLESv2/geometry/dx9.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030
daniel@transgaming.com86487c22010-03-11 19:41:43 +000031#undef near
32#undef far
33
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034namespace gl
35{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000036Context::Context(const egl::Config *config)
37 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038{
39 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
daniel@transgaming.com092bd482010-05-12 03:39:36 +000040
daniel@transgaming.com428d1582010-05-04 03:35:25 +000041 mState.depthClearValue = 1.0f;
42 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043
daniel@transgaming.com428d1582010-05-04 03:35:25 +000044 mState.cullFace = false;
45 mState.cullMode = GL_BACK;
46 mState.frontFace = GL_CCW;
47 mState.depthTest = false;
48 mState.depthFunc = GL_LESS;
49 mState.blend = false;
50 mState.sourceBlendRGB = GL_ONE;
51 mState.sourceBlendAlpha = GL_ONE;
52 mState.destBlendRGB = GL_ZERO;
53 mState.destBlendAlpha = GL_ZERO;
54 mState.blendEquationRGB = GL_FUNC_ADD;
55 mState.blendEquationAlpha = GL_FUNC_ADD;
56 mState.blendColor.red = 0;
57 mState.blendColor.green = 0;
58 mState.blendColor.blue = 0;
59 mState.blendColor.alpha = 0;
60 mState.stencilTest = false;
61 mState.stencilFunc = GL_ALWAYS;
62 mState.stencilRef = 0;
63 mState.stencilMask = -1;
64 mState.stencilWritemask = -1;
65 mState.stencilBackFunc = GL_ALWAYS;
66 mState.stencilBackRef = 0;
67 mState.stencilBackMask = - 1;
68 mState.stencilBackWritemask = -1;
69 mState.stencilFail = GL_KEEP;
70 mState.stencilPassDepthFail = GL_KEEP;
71 mState.stencilPassDepthPass = GL_KEEP;
72 mState.stencilBackFail = GL_KEEP;
73 mState.stencilBackPassDepthFail = GL_KEEP;
74 mState.stencilBackPassDepthPass = GL_KEEP;
75 mState.polygonOffsetFill = false;
76 mState.polygonOffsetFactor = 0.0f;
77 mState.polygonOffsetUnits = 0.0f;
78 mState.sampleAlphaToCoverage = false;
79 mState.sampleCoverage = false;
80 mState.sampleCoverageValue = 1.0f;
81 mState.sampleCoverageInvert = GL_FALSE;
82 mState.scissorTest = false;
83 mState.dither = true;
84 mState.generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085
daniel@transgaming.com428d1582010-05-04 03:35:25 +000086 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000087
daniel@transgaming.com428d1582010-05-04 03:35:25 +000088 mState.viewportX = 0;
89 mState.viewportY = 0;
90 mState.viewportWidth = config->mDisplayMode.Width;
91 mState.viewportHeight = config->mDisplayMode.Height;
92 mState.zNear = 0.0f;
93 mState.zFar = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000094
daniel@transgaming.com428d1582010-05-04 03:35:25 +000095 mState.scissorX = 0;
96 mState.scissorY = 0;
97 mState.scissorWidth = config->mDisplayMode.Width;
98 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000100 mState.colorMaskRed = true;
101 mState.colorMaskGreen = true;
102 mState.colorMaskBlue = true;
103 mState.colorMaskAlpha = true;
104 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105
106 // [OpenGL ES 2.0.24] section 3.7 page 83:
107 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
108 // and cube map texture state vectors respectively associated with them.
109 // In order that access to these initial textures not be lost, they are treated as texture
110 // objects all of whose names are 0.
111
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000112 mTexture2DZero = new Texture2D(this);
113 mTextureCubeMapZero = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114
115 mColorbufferZero = NULL;
116 mDepthbufferZero = NULL;
117 mStencilbufferZero = NULL;
118
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000119 mState.activeSampler = 0;
120 mState.arrayBuffer = 0;
121 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122 bindTextureCubeMap(0);
123 bindTexture2D(0);
124 bindFramebuffer(0);
125 bindRenderbuffer(0);
126
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000127 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000129 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
130 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000131 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000132 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133 }
134
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000135 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
136 {
137 mIncompleteTextures[type] = NULL;
138 }
139
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000140 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000142 mState.packAlignment = 4;
143 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000144
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000145 mBufferBackEnd = NULL;
146 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000147 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000148 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000149
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150 mInvalidEnum = false;
151 mInvalidValue = false;
152 mInvalidOperation = false;
153 mOutOfMemory = false;
154 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000155
156 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000157
158 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159}
160
161Context::~Context()
162{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000163 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000165 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
166 {
167 delete mIncompleteTextures[type];
168 }
169
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170 delete mTexture2DZero;
171 delete mTextureCubeMapZero;
172
173 delete mColorbufferZero;
174 delete mDepthbufferZero;
175 delete mStencilbufferZero;
176
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000177 delete mBufferBackEnd;
178 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000179 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000180 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000181
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182 while (!mBufferMap.empty())
183 {
184 deleteBuffer(mBufferMap.begin()->first);
185 }
186
187 while (!mProgramMap.empty())
188 {
189 deleteProgram(mProgramMap.begin()->first);
190 }
191
192 while (!mShaderMap.empty())
193 {
194 deleteShader(mShaderMap.begin()->first);
195 }
196
197 while (!mFramebufferMap.empty())
198 {
199 deleteFramebuffer(mFramebufferMap.begin()->first);
200 }
201
202 while (!mRenderbufferMap.empty())
203 {
204 deleteRenderbuffer(mRenderbufferMap.begin()->first);
205 }
206
207 while (!mTextureMap.empty())
208 {
209 deleteTexture(mTextureMap.begin()->first);
210 }
211}
212
213void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
214{
215 IDirect3DDevice9 *device = display->getDevice();
216
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000217 if (!mBufferBackEnd)
218 {
219 mBufferBackEnd = new Dx9BackEnd(device);
220 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000221 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000222 mBlit = new Blit(this);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000223 }
224
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
226 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000227 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228
229 Framebuffer *framebufferZero = new Framebuffer();
230 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000231 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
232 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233
234 setFramebufferZero(framebufferZero);
235 setColorbufferZero(colorbufferZero);
236 setDepthbufferZero(depthbufferZero);
237 setStencilbufferZero(stencilbufferZero);
238
239 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
240 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
241 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
242
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000243 if (!mHasBeenCurrent)
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000244 {
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +0000245 initExtensionString();
246
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000247 mState.viewportX = 0;
248 mState.viewportY = 0;
249 mState.viewportWidth = surface->getWidth();
250 mState.viewportHeight = surface->getHeight();
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000251
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000252 mState.scissorX = 0;
253 mState.scissorY = 0;
254 mState.scissorWidth = surface->getWidth();
255 mState.scissorHeight = surface->getHeight();
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000256
257 mHasBeenCurrent = true;
258 }
259
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000260 defaultRenderTarget->Release();
261
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000262 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000263 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000264 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000266
267 D3DCAPS9 capabilities;
268 device->GetDeviceCaps(&capabilities);
269
270 if (capabilities.PixelShaderVersion == D3DPS_VERSION(3, 0))
271 {
272 mPsProfile = "ps_3_0";
273 mVsProfile = "vs_3_0";
274 }
275 else // egl::Display guarantees support for at least 2.0
276 {
277 mPsProfile = "ps_2_0";
278 mVsProfile = "vs_2_0";
279 }
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000280
281 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282}
283
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000284// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000285void Context::markAllStateDirty()
286{
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000287 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000288 mAppliedDepthbufferSerial = 0;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000289 mAppliedProgram = 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000290
291 mClearStateDirty = true;
292 mCullStateDirty = true;
293 mDepthStateDirty = true;
294 mMaskStateDirty = true;
295 mBlendStateDirty = true;
296 mStencilStateDirty = true;
297 mPolygonOffsetStateDirty = true;
298 mScissorStateDirty = true;
299 mSampleStateDirty = true;
300 mDitherStateDirty = true;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000301}
302
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303void Context::setClearColor(float red, float green, float blue, float alpha)
304{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000305 mState.colorClearValue.red = red;
306 mState.colorClearValue.green = green;
307 mState.colorClearValue.blue = blue;
308 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309}
310
311void Context::setClearDepth(float depth)
312{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000313 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314}
315
316void Context::setClearStencil(int stencil)
317{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000318 mState.stencilClearValue = stencil;
319}
320
321void Context::setCullFace(bool enabled)
322{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000323 if (mState.cullFace != enabled)
324 {
325 mState.cullFace = enabled;
326 mCullStateDirty = true;
327 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000328}
329
330bool Context::isCullFaceEnabled() const
331{
332 return mState.cullFace;
333}
334
335void Context::setCullMode(GLenum mode)
336{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000337 if (mState.cullMode != mode)
338 {
339 mState.cullMode = mode;
340 mCullStateDirty = true;
341 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000342}
343
344void Context::setFrontFace(GLenum front)
345{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000346 if (mState.frontFace != front)
347 {
348 mState.frontFace = front;
349 mFrontFaceDirty = true;
350 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000351}
352
353void Context::setDepthTest(bool enabled)
354{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000355 if (mState.depthTest != enabled)
356 {
357 mState.depthTest = enabled;
358 mDepthStateDirty = true;
359 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000360}
361
362bool Context::isDepthTestEnabled() const
363{
364 return mState.depthTest;
365}
366
367void Context::setDepthFunc(GLenum depthFunc)
368{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000369 if (mState.depthFunc != depthFunc)
370 {
371 mState.depthFunc = depthFunc;
372 mDepthStateDirty = true;
373 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000374}
375
376void Context::setDepthRange(float zNear, float zFar)
377{
378 mState.zNear = zNear;
379 mState.zFar = zFar;
380}
381
382void Context::setBlend(bool enabled)
383{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000384 if (mState.blend != enabled)
385 {
386 mState.blend = enabled;
387 mBlendStateDirty = true;
388 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000389}
390
391bool Context::isBlendEnabled() const
392{
393 return mState.blend;
394}
395
396void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
397{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000398 if (mState.sourceBlendRGB != sourceRGB ||
399 mState.sourceBlendAlpha != sourceAlpha ||
400 mState.destBlendRGB != destRGB ||
401 mState.destBlendAlpha != destAlpha)
402 {
403 mState.sourceBlendRGB = sourceRGB;
404 mState.destBlendRGB = destRGB;
405 mState.sourceBlendAlpha = sourceAlpha;
406 mState.destBlendAlpha = destAlpha;
407 mBlendStateDirty = true;
408 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000409}
410
411void Context::setBlendColor(float red, float green, float blue, float alpha)
412{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000413 if (mState.blendColor.red != red ||
414 mState.blendColor.green != green ||
415 mState.blendColor.blue != blue ||
416 mState.blendColor.alpha != alpha)
417 {
418 mState.blendColor.red = red;
419 mState.blendColor.green = green;
420 mState.blendColor.blue = blue;
421 mState.blendColor.alpha = alpha;
422 mBlendStateDirty = true;
423 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000424}
425
426void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
427{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000428 if (mState.blendEquationRGB != rgbEquation ||
429 mState.blendEquationAlpha != alphaEquation)
430 {
431 mState.blendEquationRGB = rgbEquation;
432 mState.blendEquationAlpha = alphaEquation;
433 mBlendStateDirty = true;
434 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000435}
436
437void Context::setStencilTest(bool enabled)
438{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000439 if (mState.stencilTest != enabled)
440 {
441 mState.stencilTest = enabled;
442 mStencilStateDirty = true;
443 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000444}
445
446bool Context::isStencilTestEnabled() const
447{
448 return mState.stencilTest;
449}
450
451void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
452{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000453 if (mState.stencilFunc != stencilFunc ||
454 mState.stencilRef != stencilRef ||
455 mState.stencilMask != stencilMask)
456 {
457 mState.stencilFunc = stencilFunc;
458 mState.stencilRef = stencilRef;
459 mState.stencilMask = stencilMask;
460 mStencilStateDirty = true;
461 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000462}
463
464void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
465{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000466 if (mState.stencilBackFunc != stencilBackFunc ||
467 mState.stencilBackRef != stencilBackRef ||
468 mState.stencilBackMask != stencilBackMask)
469 {
470 mState.stencilBackFunc = stencilBackFunc;
471 mState.stencilBackRef = stencilBackRef;
472 mState.stencilBackMask = stencilBackMask;
473 mStencilStateDirty = true;
474 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000475}
476
477void Context::setStencilWritemask(GLuint stencilWritemask)
478{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000479 if (mState.stencilWritemask != stencilWritemask)
480 {
481 mState.stencilWritemask = stencilWritemask;
482 mStencilStateDirty = true;
483 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000484}
485
486void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
487{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000488 if (mState.stencilBackWritemask != stencilBackWritemask)
489 {
490 mState.stencilBackWritemask = stencilBackWritemask;
491 mStencilStateDirty = true;
492 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000493}
494
495void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
496{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000497 if (mState.stencilFail != stencilFail ||
498 mState.stencilPassDepthFail != stencilPassDepthFail ||
499 mState.stencilPassDepthPass != stencilPassDepthPass)
500 {
501 mState.stencilFail = stencilFail;
502 mState.stencilPassDepthFail = stencilPassDepthFail;
503 mState.stencilPassDepthPass = stencilPassDepthPass;
504 mStencilStateDirty = true;
505 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000506}
507
508void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
509{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000510 if (mState.stencilBackFail != stencilBackFail ||
511 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
512 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
513 {
514 mState.stencilBackFail = stencilBackFail;
515 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
516 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
517 mStencilStateDirty = true;
518 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000519}
520
521void Context::setPolygonOffsetFill(bool enabled)
522{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000523 if (mState.polygonOffsetFill != enabled)
524 {
525 mState.polygonOffsetFill = enabled;
526 mPolygonOffsetStateDirty = true;
527 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000528}
529
530bool Context::isPolygonOffsetFillEnabled() const
531{
532 return mState.polygonOffsetFill;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000533
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000534}
535
536void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
537{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000538 if (mState.polygonOffsetFactor != factor ||
539 mState.polygonOffsetUnits != units)
540 {
541 mState.polygonOffsetFactor = factor;
542 mState.polygonOffsetUnits = units;
543 mPolygonOffsetStateDirty = true;
544 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000545}
546
547void Context::setSampleAlphaToCoverage(bool enabled)
548{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000549 if (mState.sampleAlphaToCoverage != enabled)
550 {
551 mState.sampleAlphaToCoverage = enabled;
552 mSampleStateDirty = true;
553 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000554}
555
556bool Context::isSampleAlphaToCoverageEnabled() const
557{
558 return mState.sampleAlphaToCoverage;
559}
560
561void Context::setSampleCoverage(bool enabled)
562{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000563 if (mState.sampleCoverage != enabled)
564 {
565 mState.sampleCoverage = enabled;
566 mSampleStateDirty = true;
567 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000568}
569
570bool Context::isSampleCoverageEnabled() const
571{
572 return mState.sampleCoverage;
573}
574
575void Context::setSampleCoverageParams(GLclampf value, GLboolean invert)
576{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000577 if (mState.sampleCoverageValue != value ||
578 mState.sampleCoverageInvert != invert)
579 {
580 mState.sampleCoverageValue = value;
581 mState.sampleCoverageInvert = invert;
582 mSampleStateDirty = true;
583 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000584}
585
586void Context::setScissorTest(bool enabled)
587{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000588 if (mState.scissorTest != enabled)
589 {
590 mState.scissorTest = enabled;
591 mScissorStateDirty = true;
592 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000593}
594
595bool Context::isScissorTestEnabled() const
596{
597 return mState.scissorTest;
598}
599
600void Context::setDither(bool enabled)
601{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000602 if (mState.dither != enabled)
603 {
604 mState.dither = enabled;
605 mDitherStateDirty = true;
606 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000607}
608
609bool Context::isDitherEnabled() const
610{
611 return mState.dither;
612}
613
614void Context::setLineWidth(GLfloat width)
615{
616 mState.lineWidth = width;
617}
618
619void Context::setGenerateMipmapHint(GLenum hint)
620{
621 mState.generateMipmapHint = hint;
622}
623
624void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
625{
626 mState.viewportX = x;
627 mState.viewportY = y;
628 mState.viewportWidth = width;
629 mState.viewportHeight = height;
630}
631
632void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
633{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000634 if (mState.scissorX != x || mState.scissorY != y ||
635 mState.scissorWidth != width || mState.scissorHeight != height)
636 {
637 mState.scissorX = x;
638 mState.scissorY = y;
639 mState.scissorWidth = width;
640 mState.scissorHeight = height;
641 mScissorStateDirty = true;
642 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000643}
644
645void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
646{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000647 if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
648 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
649 {
650 mState.colorMaskRed = red;
651 mState.colorMaskGreen = green;
652 mState.colorMaskBlue = blue;
653 mState.colorMaskAlpha = alpha;
654 mMaskStateDirty = true;
655 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000656}
657
658void Context::setDepthMask(bool mask)
659{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000660 if (mState.depthMask != mask)
661 {
662 mState.depthMask = mask;
663 mMaskStateDirty = true;
664 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000665}
666
667void Context::setActiveSampler(int active)
668{
669 mState.activeSampler = active;
670}
671
672GLuint Context::getFramebufferHandle() const
673{
674 return mState.framebuffer;
675}
676
677GLuint Context::getRenderbufferHandle() const
678{
679 return mState.renderbuffer;
680}
681
682GLuint Context::getArrayBufferHandle() const
683{
684 return mState.arrayBuffer;
685}
686
687void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
688{
689 mState.vertexAttribute[attribNum].mEnabled = enabled;
690}
691
692const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
693{
694 return mState.vertexAttribute[attribNum];
695}
696
697void Context::setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type, bool normalized,
698 GLsizei stride, const void *pointer)
699{
700 mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer;
701 mState.vertexAttribute[attribNum].mSize = size;
702 mState.vertexAttribute[attribNum].mType = type;
703 mState.vertexAttribute[attribNum].mNormalized = normalized;
704 mState.vertexAttribute[attribNum].mStride = stride;
705 mState.vertexAttribute[attribNum].mPointer = pointer;
706}
707
708const void *Context::getVertexAttribPointer(unsigned int attribNum) const
709{
710 return mState.vertexAttribute[attribNum].mPointer;
711}
712
713// returns entire set of attributes as a block
714const AttributeState *Context::getVertexAttribBlock()
715{
716 return mState.vertexAttribute;
717}
718
719void Context::setPackAlignment(GLint alignment)
720{
721 mState.packAlignment = alignment;
722}
723
724GLint Context::getPackAlignment() const
725{
726 return mState.packAlignment;
727}
728
729void Context::setUnpackAlignment(GLint alignment)
730{
731 mState.unpackAlignment = alignment;
732}
733
734GLint Context::getUnpackAlignment() const
735{
736 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000737}
738
739// Returns an unused buffer name
740GLuint Context::createBuffer()
741{
742 unsigned int handle = 1;
743
744 while (mBufferMap.find(handle) != mBufferMap.end())
745 {
746 handle++;
747 }
748
749 mBufferMap[handle] = NULL;
750
751 return handle;
752}
753
754// Returns an unused shader/program name
755GLuint Context::createShader(GLenum type)
756{
757 unsigned int handle = 1;
758
759 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
760 {
761 handle++;
762 }
763
764 if (type == GL_VERTEX_SHADER)
765 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000766 mShaderMap[handle] = new VertexShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000767 }
768 else if (type == GL_FRAGMENT_SHADER)
769 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000770 mShaderMap[handle] = new FragmentShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000771 }
772 else UNREACHABLE();
773
774 return handle;
775}
776
777// Returns an unused program/shader name
778GLuint Context::createProgram()
779{
780 unsigned int handle = 1;
781
782 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
783 {
784 handle++;
785 }
786
787 mProgramMap[handle] = new Program();
788
789 return handle;
790}
791
792// Returns an unused texture name
793GLuint Context::createTexture()
794{
795 unsigned int handle = 1;
796
797 while (mTextureMap.find(handle) != mTextureMap.end())
798 {
799 handle++;
800 }
801
802 mTextureMap[handle] = NULL;
803
804 return handle;
805}
806
807// Returns an unused framebuffer name
808GLuint Context::createFramebuffer()
809{
810 unsigned int handle = 1;
811
812 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
813 {
814 handle++;
815 }
816
817 mFramebufferMap[handle] = NULL;
818
819 return handle;
820}
821
822// Returns an unused renderbuffer name
823GLuint Context::createRenderbuffer()
824{
825 unsigned int handle = 1;
826
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000827 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000828 {
829 handle++;
830 }
831
832 mRenderbufferMap[handle] = NULL;
833
834 return handle;
835}
836
837void Context::deleteBuffer(GLuint buffer)
838{
839 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
840
841 if (bufferObject != mBufferMap.end())
842 {
843 detachBuffer(buffer);
844
845 delete bufferObject->second;
846 mBufferMap.erase(bufferObject);
847 }
848}
849
850void Context::deleteShader(GLuint shader)
851{
852 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
853
854 if (shaderObject != mShaderMap.end())
855 {
856 if (!shaderObject->second->isAttached())
857 {
858 delete shaderObject->second;
859 mShaderMap.erase(shaderObject);
860 }
861 else
862 {
863 shaderObject->second->flagForDeletion();
864 }
865 }
866}
867
868void Context::deleteProgram(GLuint program)
869{
870 ProgramMap::iterator programObject = mProgramMap.find(program);
871
872 if (programObject != mProgramMap.end())
873 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000874 if (program != mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000875 {
876 delete programObject->second;
877 mProgramMap.erase(programObject);
878 }
879 else
880 {
881 programObject->second->flagForDeletion();
882 }
883 }
884}
885
886void Context::deleteTexture(GLuint texture)
887{
888 TextureMap::iterator textureObject = mTextureMap.find(texture);
889
890 if (textureObject != mTextureMap.end())
891 {
892 detachTexture(texture);
893
894 if (texture != 0)
895 {
896 delete textureObject->second;
897 }
898
899 mTextureMap.erase(textureObject);
900 }
901}
902
903void Context::deleteFramebuffer(GLuint framebuffer)
904{
905 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
906
907 if (framebufferObject != mFramebufferMap.end())
908 {
909 detachFramebuffer(framebuffer);
910
911 delete framebufferObject->second;
912 mFramebufferMap.erase(framebufferObject);
913 }
914}
915
916void Context::deleteRenderbuffer(GLuint renderbuffer)
917{
918 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
919
920 if (renderbufferObject != mRenderbufferMap.end())
921 {
922 detachRenderbuffer(renderbuffer);
923
924 delete renderbufferObject->second;
925 mRenderbufferMap.erase(renderbufferObject);
926 }
927}
928
929void Context::bindArrayBuffer(unsigned int buffer)
930{
931 if (buffer != 0 && !getBuffer(buffer))
932 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000933 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000934 }
935
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000936 mState.arrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000937}
938
939void Context::bindElementArrayBuffer(unsigned int buffer)
940{
941 if (buffer != 0 && !getBuffer(buffer))
942 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000943 mBufferMap[buffer] = new Buffer(mBufferBackEnd);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000944 }
945
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000946 mState.elementArrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000947}
948
949void Context::bindTexture2D(GLuint texture)
950{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000951 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000952 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000953 mTextureMap[texture] = new Texture2D(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000954 }
955
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000956 mState.texture2D = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000957
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000958 mState.samplerTexture[SAMPLER_2D][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000959}
960
961void Context::bindTextureCubeMap(GLuint texture)
962{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000963 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000964 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000965 mTextureMap[texture] = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000966 }
967
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000968 mState.textureCubeMap = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000969
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000970 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000971}
972
973void Context::bindFramebuffer(GLuint framebuffer)
974{
975 if (!getFramebuffer(framebuffer))
976 {
977 mFramebufferMap[framebuffer] = new Framebuffer();
978 }
979
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000980 mState.framebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000981}
982
983void Context::bindRenderbuffer(GLuint renderbuffer)
984{
985 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
986 {
987 mRenderbufferMap[renderbuffer] = new Renderbuffer();
988 }
989
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000990 mState.renderbuffer = renderbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000991}
992
993void Context::useProgram(GLuint program)
994{
995 Program *programObject = getCurrentProgram();
996
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000997 GLuint priorProgram = mState.currentProgram;
998 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000999
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001000 if (programObject && programObject->isFlaggedForDeletion())
1001 {
daniel@transgaming.com71cd8682010-04-29 03:35:25 +00001002 deleteProgram(priorProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001003 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001004}
1005
1006void Context::setFramebufferZero(Framebuffer *buffer)
1007{
1008 delete mFramebufferMap[0];
1009 mFramebufferMap[0] = buffer;
1010}
1011
1012void Context::setColorbufferZero(Colorbuffer *buffer)
1013{
1014 delete mColorbufferZero;
1015 mColorbufferZero = buffer;
1016}
1017
1018void Context::setDepthbufferZero(Depthbuffer *buffer)
1019{
1020 delete mDepthbufferZero;
1021 mDepthbufferZero = buffer;
1022}
1023
1024void Context::setStencilbufferZero(Stencilbuffer *buffer)
1025{
1026 delete mStencilbufferZero;
1027 mStencilbufferZero = buffer;
1028}
1029
1030void Context::setRenderbuffer(Renderbuffer *buffer)
1031{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001032 delete mRenderbufferMap[mState.renderbuffer];
1033 mRenderbufferMap[mState.renderbuffer] = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001034}
1035
1036Buffer *Context::getBuffer(unsigned int handle)
1037{
1038 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001039
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001040 if (buffer == mBufferMap.end())
1041 {
1042 return NULL;
1043 }
1044 else
1045 {
1046 return buffer->second;
1047 }
1048}
1049
1050Shader *Context::getShader(unsigned int handle)
1051{
1052 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001053
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001054 if (shader == mShaderMap.end())
1055 {
1056 return NULL;
1057 }
1058 else
1059 {
1060 return shader->second;
1061 }
1062}
1063
1064Program *Context::getProgram(unsigned int handle)
1065{
1066 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001067
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001068 if (program == mProgramMap.end())
1069 {
1070 return NULL;
1071 }
1072 else
1073 {
1074 return program->second;
1075 }
1076}
1077
1078Texture *Context::getTexture(unsigned int handle)
1079{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001080 if (handle == 0) return NULL;
1081
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001082 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001083
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001084 if (texture == mTextureMap.end())
1085 {
1086 return NULL;
1087 }
1088 else
1089 {
1090 return texture->second;
1091 }
1092}
1093
1094Framebuffer *Context::getFramebuffer(unsigned int handle)
1095{
1096 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001097
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001098 if (framebuffer == mFramebufferMap.end())
1099 {
1100 return NULL;
1101 }
1102 else
1103 {
1104 return framebuffer->second;
1105 }
1106}
1107
1108Renderbuffer *Context::getRenderbuffer(unsigned int handle)
1109{
1110 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001111
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001112 if (renderbuffer == mRenderbufferMap.end())
1113 {
1114 return NULL;
1115 }
1116 else
1117 {
1118 return renderbuffer->second;
1119 }
1120}
1121
1122Colorbuffer *Context::getColorbuffer(GLuint handle)
1123{
1124 if (handle != 0)
1125 {
1126 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1127
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001128 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001129 {
1130 return static_cast<Colorbuffer*>(renderbuffer);
1131 }
1132 }
1133 else // Special case: 0 refers to different initial render targets based on the attachment type
1134 {
1135 return mColorbufferZero;
1136 }
1137
1138 return NULL;
1139}
1140
1141Depthbuffer *Context::getDepthbuffer(GLuint handle)
1142{
1143 if (handle != 0)
1144 {
1145 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1146
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001147 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001148 {
1149 return static_cast<Depthbuffer*>(renderbuffer);
1150 }
1151 }
1152 else // Special case: 0 refers to different initial render targets based on the attachment type
1153 {
1154 return mDepthbufferZero;
1155 }
1156
1157 return NULL;
1158}
1159
1160Stencilbuffer *Context::getStencilbuffer(GLuint handle)
1161{
1162 if (handle != 0)
1163 {
1164 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1165
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001166 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001167 {
1168 return static_cast<Stencilbuffer*>(renderbuffer);
1169 }
1170 }
1171 else
1172 {
1173 return mStencilbufferZero;
1174 }
1175
1176 return NULL;
1177}
1178
1179Buffer *Context::getArrayBuffer()
1180{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001181 return getBuffer(mState.arrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001182}
1183
1184Buffer *Context::getElementArrayBuffer()
1185{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001186 return getBuffer(mState.elementArrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001187}
1188
1189Program *Context::getCurrentProgram()
1190{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001191 return getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001192}
1193
1194Texture2D *Context::getTexture2D()
1195{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001196 if (mState.texture2D == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001197 {
1198 return mTexture2DZero;
1199 }
1200
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001201 return (Texture2D*)getTexture(mState.texture2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001202}
1203
1204TextureCubeMap *Context::getTextureCubeMap()
1205{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001206 if (mState.textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001207 {
1208 return mTextureCubeMapZero;
1209 }
1210
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001211 return (TextureCubeMap*)getTexture(mState.textureCubeMap);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001212}
1213
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001214Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001215{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001216 GLuint texid = mState.samplerTexture[type][sampler];
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001217
1218 if (texid == 0)
1219 {
1220 switch (type)
1221 {
1222 default: UNREACHABLE();
1223 case SAMPLER_2D: return mTexture2DZero;
1224 case SAMPLER_CUBE: return mTextureCubeMapZero;
1225 }
1226 }
1227
1228 return getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001229}
1230
1231Framebuffer *Context::getFramebuffer()
1232{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001233 return getFramebuffer(mState.framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001234}
1235
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001236bool Context::getBooleanv(GLenum pname, GLboolean *params)
1237{
1238 switch (pname)
1239 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001240 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1241 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1242 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001243 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001244 params[0] = mState.colorMaskRed;
1245 params[1] = mState.colorMaskGreen;
1246 params[2] = mState.colorMaskBlue;
1247 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001248 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001249 case GL_CULL_FACE: *params = mState.cullFace;
1250 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
1251 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
1252 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
1253 case GL_SCISSOR_TEST: *params = mState.scissorTest;
1254 case GL_STENCIL_TEST: *params = mState.stencilTest;
1255 case GL_DEPTH_TEST: *params = mState.depthTest;
1256 case GL_BLEND: *params = mState.blend;
1257 case GL_DITHER: *params = mState.dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001258 default:
1259 return false;
1260 }
1261
1262 return true;
1263}
1264
1265bool Context::getFloatv(GLenum pname, GLfloat *params)
1266{
1267 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1268 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1269 // GetIntegerv as its native query function. As it would require conversion in any
1270 // case, this should make no difference to the calling application.
1271 switch (pname)
1272 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001273 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1274 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1275 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1276 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1277 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001278 case GL_ALIASED_LINE_WIDTH_RANGE:
1279 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1280 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1281 break;
1282 case GL_ALIASED_POINT_SIZE_RANGE:
1283 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
1284 params[1] = gl::ALIASED_POINT_SIZE_RANGE_MAX;
1285 break;
1286 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001287 params[0] = mState.zNear;
1288 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001289 break;
1290 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001291 params[0] = mState.colorClearValue.red;
1292 params[1] = mState.colorClearValue.green;
1293 params[2] = mState.colorClearValue.blue;
1294 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001295 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001296 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001297 params[0] = mState.blendColor.red;
1298 params[1] = mState.blendColor.green;
1299 params[2] = mState.blendColor.blue;
1300 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001301 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001302 default:
1303 return false;
1304 }
1305
1306 return true;
1307}
1308
1309bool Context::getIntegerv(GLenum pname, GLint *params)
1310{
1311 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1312 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1313 // GetIntegerv as its native query function. As it would require conversion in any
1314 // case, this should make no difference to the calling application. You may find it in
1315 // Context::getFloatv.
1316 switch (pname)
1317 {
1318 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1319 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1320 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
1321 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1322 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1323 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1324 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
1325 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
1326 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1327 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
1328 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
1329 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001330 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer; break;
1331 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer; break;
1332 case GL_FRAMEBUFFER_BINDING: *params = mState.framebuffer; break;
1333 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer; break;
1334 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1335 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1336 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1337 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1338 case GL_ACTIVE_TEXTURE: *params = mState.activeSampler; break;
1339 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1340 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1341 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1342 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1343 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1344 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1345 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1346 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1347 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1348 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1349 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1350 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1351 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1352 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1353 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1354 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1355 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1356 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1357 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1358 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1359 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1360 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001361 case GL_SUBPIXEL_BITS: *params = 4; break;
1362 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
1363 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
1364 case GL_SAMPLE_BUFFERS: *params = 0; break;
1365 case GL_SAMPLES: *params = 0; break;
1366 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1367 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1368 case GL_MAX_VIEWPORT_DIMS:
1369 {
1370 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
1371 params[0] = maxDimension;
1372 params[1] = maxDimension;
1373 }
1374 break;
1375 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001376 params[0] = mState.viewportX;
1377 params[1] = mState.viewportY;
1378 params[2] = mState.viewportWidth;
1379 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001380 break;
1381 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001382 params[0] = mState.scissorX;
1383 params[1] = mState.scissorY;
1384 params[2] = mState.scissorWidth;
1385 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001386 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001387 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1388 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001389 case GL_RED_BITS:
1390 case GL_GREEN_BITS:
1391 case GL_BLUE_BITS:
1392 case GL_ALPHA_BITS:
1393 {
1394 gl::Framebuffer *framebuffer = getFramebuffer();
1395 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1396
1397 if (colorbuffer)
1398 {
1399 switch (pname)
1400 {
1401 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1402 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1403 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1404 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1405 }
1406 }
1407 else
1408 {
1409 *params = 0;
1410 }
1411 }
1412 break;
1413 case GL_DEPTH_BITS:
1414 {
1415 gl::Framebuffer *framebuffer = getFramebuffer();
1416 gl::Depthbuffer *depthbuffer = framebuffer->getDepthbuffer();
1417
1418 if (depthbuffer)
1419 {
1420 *params = depthbuffer->getDepthSize();
1421 }
1422 else
1423 {
1424 *params = 0;
1425 }
1426 }
1427 break;
1428 case GL_STENCIL_BITS:
1429 {
1430 gl::Framebuffer *framebuffer = getFramebuffer();
1431 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1432
1433 if (stencilbuffer)
1434 {
1435 *params = stencilbuffer->getStencilSize();
1436 }
1437 else
1438 {
1439 *params = 0;
1440 }
1441 }
1442 break;
1443 case GL_TEXTURE_BINDING_2D:
1444 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001445 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001446 {
1447 error(GL_INVALID_OPERATION);
1448 return false;
1449 }
1450
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001451 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001452 }
1453 break;
1454 case GL_TEXTURE_BINDING_CUBE_MAP:
1455 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001456 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001457 {
1458 error(GL_INVALID_OPERATION);
1459 return false;
1460 }
1461
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001462 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001463 }
1464 break;
1465 default:
1466 return false;
1467 }
1468
1469 return true;
1470}
1471
1472bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1473{
1474 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1475 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1476 // to the fact that it is stored internally as a float, and so would require conversion
1477 // if returned from Context::getIntegerv. Since this conversion is already implemented
1478 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1479 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1480 // application.
1481 switch (pname)
1482 {
1483 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1484 case GL_SHADER_BINARY_FORMATS:
1485 {
1486 *type = GL_INT;
1487 *numParams = 0;
1488 }
1489 break;
1490 case GL_MAX_VERTEX_ATTRIBS:
1491 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1492 case GL_MAX_VARYING_VECTORS:
1493 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1494 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1495 case GL_MAX_TEXTURE_IMAGE_UNITS:
1496 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1497 case GL_MAX_RENDERBUFFER_SIZE:
1498 case GL_NUM_SHADER_BINARY_FORMATS:
1499 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1500 case GL_ARRAY_BUFFER_BINDING:
1501 case GL_FRAMEBUFFER_BINDING:
1502 case GL_RENDERBUFFER_BINDING:
1503 case GL_CURRENT_PROGRAM:
1504 case GL_PACK_ALIGNMENT:
1505 case GL_UNPACK_ALIGNMENT:
1506 case GL_GENERATE_MIPMAP_HINT:
1507 case GL_RED_BITS:
1508 case GL_GREEN_BITS:
1509 case GL_BLUE_BITS:
1510 case GL_ALPHA_BITS:
1511 case GL_DEPTH_BITS:
1512 case GL_STENCIL_BITS:
1513 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1514 case GL_CULL_FACE_MODE:
1515 case GL_FRONT_FACE:
1516 case GL_ACTIVE_TEXTURE:
1517 case GL_STENCIL_FUNC:
1518 case GL_STENCIL_VALUE_MASK:
1519 case GL_STENCIL_REF:
1520 case GL_STENCIL_FAIL:
1521 case GL_STENCIL_PASS_DEPTH_FAIL:
1522 case GL_STENCIL_PASS_DEPTH_PASS:
1523 case GL_STENCIL_BACK_FUNC:
1524 case GL_STENCIL_BACK_VALUE_MASK:
1525 case GL_STENCIL_BACK_REF:
1526 case GL_STENCIL_BACK_FAIL:
1527 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1528 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1529 case GL_DEPTH_FUNC:
1530 case GL_BLEND_SRC_RGB:
1531 case GL_BLEND_SRC_ALPHA:
1532 case GL_BLEND_DST_RGB:
1533 case GL_BLEND_DST_ALPHA:
1534 case GL_BLEND_EQUATION_RGB:
1535 case GL_BLEND_EQUATION_ALPHA:
1536 case GL_STENCIL_WRITEMASK:
1537 case GL_STENCIL_BACK_WRITEMASK:
1538 case GL_STENCIL_CLEAR_VALUE:
1539 case GL_SUBPIXEL_BITS:
1540 case GL_MAX_TEXTURE_SIZE:
1541 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1542 case GL_SAMPLE_BUFFERS:
1543 case GL_SAMPLES:
1544 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1545 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1546 case GL_TEXTURE_BINDING_2D:
1547 case GL_TEXTURE_BINDING_CUBE_MAP:
1548 {
1549 *type = GL_INT;
1550 *numParams = 1;
1551 }
1552 break;
1553 case GL_MAX_VIEWPORT_DIMS:
1554 {
1555 *type = GL_INT;
1556 *numParams = 2;
1557 }
1558 break;
1559 case GL_VIEWPORT:
1560 case GL_SCISSOR_BOX:
1561 {
1562 *type = GL_INT;
1563 *numParams = 4;
1564 }
1565 break;
1566 case GL_SHADER_COMPILER:
1567 case GL_SAMPLE_COVERAGE_INVERT:
1568 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001569 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1570 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1571 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1572 case GL_SAMPLE_COVERAGE:
1573 case GL_SCISSOR_TEST:
1574 case GL_STENCIL_TEST:
1575 case GL_DEPTH_TEST:
1576 case GL_BLEND:
1577 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001578 {
1579 *type = GL_BOOL;
1580 *numParams = 1;
1581 }
1582 break;
1583 case GL_COLOR_WRITEMASK:
1584 {
1585 *type = GL_BOOL;
1586 *numParams = 4;
1587 }
1588 break;
1589 case GL_POLYGON_OFFSET_FACTOR:
1590 case GL_POLYGON_OFFSET_UNITS:
1591 case GL_SAMPLE_COVERAGE_VALUE:
1592 case GL_DEPTH_CLEAR_VALUE:
1593 case GL_LINE_WIDTH:
1594 {
1595 *type = GL_FLOAT;
1596 *numParams = 1;
1597 }
1598 break;
1599 case GL_ALIASED_LINE_WIDTH_RANGE:
1600 case GL_ALIASED_POINT_SIZE_RANGE:
1601 case GL_DEPTH_RANGE:
1602 {
1603 *type = GL_FLOAT;
1604 *numParams = 2;
1605 }
1606 break;
1607 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001608 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001609 {
1610 *type = GL_FLOAT;
1611 *numParams = 4;
1612 }
1613 break;
1614 default:
1615 return false;
1616 }
1617
1618 return true;
1619}
1620
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001621// Applies the render target surface, depth stencil surface, viewport rectangle and
1622// scissor rectangle to the Direct3D 9 device
1623bool Context::applyRenderTarget(bool ignoreViewport)
1624{
1625 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001626
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001627 Framebuffer *framebufferObject = getFramebuffer();
1628
1629 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1630 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001631 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1632
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001633 return false;
1634 }
1635
1636 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1637 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1638
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001639 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
1640 if (renderTargetSerial != mAppliedRenderTargetSerial)
1641 {
1642 device->SetRenderTarget(0, renderTarget);
1643 mAppliedRenderTargetSerial = renderTargetSerial;
1644 }
1645
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001646 unsigned int depthbufferSerial = framebufferObject->getDepthbufferSerial();
1647 if (depthbufferSerial != mAppliedDepthbufferSerial)
1648 {
1649 device->SetDepthStencilSurface(depthStencil);
1650 mAppliedDepthbufferSerial = depthbufferSerial;
1651 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001652
1653 D3DVIEWPORT9 viewport;
1654 D3DSURFACE_DESC desc;
1655 renderTarget->GetDesc(&desc);
1656
1657 if (ignoreViewport)
1658 {
1659 viewport.X = 0;
1660 viewport.Y = 0;
1661 viewport.Width = desc.Width;
1662 viewport.Height = desc.Height;
1663 viewport.MinZ = 0.0f;
1664 viewport.MaxZ = 1.0f;
1665 }
1666 else
1667 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001668 viewport.X = std::max(mState.viewportX, 0);
1669 viewport.Y = std::max(mState.viewportY, 0);
1670 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1671 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1672 viewport.MinZ = clamp01(mState.zNear);
1673 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001674 }
1675
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001676 if (viewport.Width <= 0 || viewport.Height <= 0)
1677 {
1678 return false; // Nothing to render
1679 }
1680
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001681 device->SetViewport(&viewport);
1682
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001683 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001684 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001685 if (mState.scissorTest)
1686 {
1687 RECT rect = {mState.scissorX,
1688 mState.scissorY,
1689 mState.scissorX + mState.scissorWidth,
1690 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001691
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001692 device->SetScissorRect(&rect);
1693 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1694 }
1695 else
1696 {
1697 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1698 }
1699
1700 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001701 }
1702
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001703 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001704 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001705 Program *programObject = getCurrentProgram();
1706
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001707 GLint halfPixelSize = programObject->getUniformLocation("dx_HalfPixelSize");
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001708 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001709 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001710
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001711 GLint window = programObject->getUniformLocation("dx_Window");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001712 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1713 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1714 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001715 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1716
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001717 GLint depth = programObject->getUniformLocation("dx_Depth");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001718 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001719 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1720
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001721 GLint near = programObject->getUniformLocation("gl_DepthRange.near");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001722 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001723
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001724 GLint far = programObject->getUniformLocation("gl_DepthRange.far");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001725 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001726
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001727 GLint diff = programObject->getUniformLocation("gl_DepthRange.diff");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001728 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001729 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001730 }
1731
1732 return true;
1733}
1734
1735// 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 +00001736void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001737{
1738 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001739 Program *programObject = getCurrentProgram();
1740
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001741 GLint frontCCW = programObject->getUniformLocation("dx_FrontCCW");
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001742 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001743 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001744
daniel@transgaming.com09fbfef2010-04-22 13:35:31 +00001745 GLint pointsOrLines = programObject->getUniformLocation("dx_PointsOrLines");
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001746 GLint alwaysFront = !isTriangleMode(drawMode);
1747 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1748
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001749 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001750 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001751 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001752 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001753 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001754 }
1755 else
1756 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001757 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001758 }
1759
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001760 mCullStateDirty = false;
1761 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001762
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001763 if (mDepthStateDirty)
1764 {
1765 if (mState.depthTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001766 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001767 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1768 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001769 }
1770 else
1771 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001772 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001773 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001774
1775 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001776 }
1777
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001778 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001779 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001780 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001781 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001782 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1783
1784 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1785 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1786 {
1787 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1788 }
1789 else
1790 {
1791 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1792 unorm<8>(mState.blendColor.alpha),
1793 unorm<8>(mState.blendColor.alpha),
1794 unorm<8>(mState.blendColor.alpha)));
1795 }
1796
1797 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1798 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1799 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1800
1801 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1802 mState.destBlendRGB != mState.destBlendAlpha ||
1803 mState.blendEquationRGB != mState.blendEquationAlpha)
1804 {
1805 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1806
1807 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1808 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1809 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
1810
1811 }
1812 else
1813 {
1814 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1815 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001816 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001817 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001818 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001819 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001820 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001821
1822 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001823 }
1824
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001825 if (mStencilStateDirty || mFrontFaceDirty)
1826 {
1827 if (mState.stencilTest && hasStencil())
1828 {
1829 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1830 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1831
1832 // FIXME: Unsupported by D3D9
1833 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1834 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1835 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1836 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1837 mState.stencilRef != mState.stencilBackRef ||
1838 mState.stencilMask != mState.stencilBackMask)
1839 {
1840 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1841 return error(GL_INVALID_OPERATION);
1842 }
1843
1844 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1845 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1846 es2dx::ConvertComparison(mState.stencilFunc));
1847
1848 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilRef); // FIXME: Clamp to range
1849 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
1850
1851 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1852 es2dx::ConvertStencilOp(mState.stencilFail));
1853 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1854 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1855 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1856 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1857
1858 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1859 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1860 es2dx::ConvertComparison(mState.stencilBackFunc));
1861
1862 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilBackRef); // FIXME: Clamp to range
1863 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
1864
1865 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1866 es2dx::ConvertStencilOp(mState.stencilBackFail));
1867 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1868 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1869 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1870 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1871 }
1872 else
1873 {
1874 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1875 }
1876
1877 mStencilStateDirty = false;
1878 }
1879
1880 if (mMaskStateDirty)
1881 {
1882 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1883 mState.colorMaskBlue, mState.colorMaskAlpha));
1884 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1885
1886 mMaskStateDirty = false;
1887 }
1888
1889 if (mPolygonOffsetStateDirty)
1890 {
1891 if (mState.polygonOffsetFill)
1892 {
1893 gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
1894 if (depthbuffer)
1895 {
1896 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1897 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1898 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1899 }
1900 }
1901 else
1902 {
1903 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1904 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1905 }
1906
1907 mPolygonOffsetStateDirty = false;
1908 }
1909
1910 if (mConfig->mMultiSample != 0 && mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001911 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001912 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001913 {
1914 FIXME("Sample alpha to coverage is unimplemented.");
1915 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001916
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001917 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001918 {
1919 FIXME("Sample coverage is unimplemented.");
1920 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001921
1922 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001923 }
1924
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001925 if (mDitherStateDirty)
1926 {
1927 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
1928
1929 mDitherStateDirty = false;
1930 }
1931
1932 mFrontFaceDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001933}
1934
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001935// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001936void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001937{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001938 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001939 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001940 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001941 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001942 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001943 }
1944 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001945}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001946
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001947void Context::applyVertexBuffer(GLint first, GLsizei count)
1948{
1949 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1950
1951 mVertexDataManager->preRenderValidate(first, count, translated);
1952
1953 lookupAttributeMapping(translated);
1954
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001955 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001956}
1957
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001958void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001959{
1960 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1961
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00001962 mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001963
1964 lookupAttributeMapping(translated);
1965
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001966 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001967}
1968
1969// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001970TranslatedIndexData Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001971{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001972 TranslatedIndexData indexInfo = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001973 mBufferBackEnd->setupIndicesPreDraw(indexInfo);
1974 return indexInfo;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001975}
1976
1977// Applies the shaders and shader constants to the Direct3D 9 device
1978void Context::applyShaders()
1979{
1980 IDirect3DDevice9 *device = getDevice();
1981 Program *programObject = getCurrentProgram();
1982 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1983 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1984
1985 device->SetVertexShader(vertexShader);
1986 device->SetPixelShader(pixelShader);
1987
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001988 if (programObject->getSerial() != mAppliedProgram)
1989 {
1990 programObject->dirtyAllUniforms();
1991 mAppliedProgram = programObject->getSerial();
1992 }
1993
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001994 programObject->applyUniforms();
1995}
1996
1997// Applies the textures and sampler states to the Direct3D 9 device
1998void Context::applyTextures()
1999{
2000 IDirect3DDevice9 *device = getDevice();
2001 Program *programObject = getCurrentProgram();
2002
2003 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
2004 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002005 int textureUnit = programObject->getSamplerMapping(sampler);
2006 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002007 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002008 SamplerType textureType = programObject->getSamplerType(sampler);
2009
2010 Texture *texture = getSamplerTexture(textureUnit, textureType);
2011
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002012 if (texture->isComplete())
2013 {
2014 GLenum wrapS = texture->getWrapS();
2015 GLenum wrapT = texture->getWrapT();
2016 GLenum minFilter = texture->getMinFilter();
2017 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002018
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002019 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
2020 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002021
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002022 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
2023 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
2024 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
2025 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
2026 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002027
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002028 device->SetTexture(sampler, texture->getTexture());
2029 }
2030 else
2031 {
2032 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
2033 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002034 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002035 else
2036 {
2037 device->SetTexture(sampler, NULL);
2038 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002039 }
2040}
2041
2042void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
2043{
2044 Framebuffer *framebuffer = getFramebuffer();
2045 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
2046 IDirect3DDevice9 *device = getDevice();
2047
2048 D3DSURFACE_DESC desc;
2049 renderTarget->GetDesc(&desc);
2050
2051 IDirect3DSurface9 *systemSurface;
2052 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
2053
2054 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2055 {
2056 return error(GL_OUT_OF_MEMORY);
2057 }
2058
2059 ASSERT(SUCCEEDED(result));
2060
2061 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
2062 {
2063 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
2064 }
2065
2066 result = device->GetRenderTargetData(renderTarget, systemSurface);
2067
2068 if (result == D3DERR_DRIVERINTERNALERROR)
2069 {
2070 systemSurface->Release();
2071
2072 return error(GL_OUT_OF_MEMORY);
2073 }
2074
2075 if (FAILED(result))
2076 {
2077 UNREACHABLE();
2078 systemSurface->Release();
2079
2080 return; // No sensible error to generate
2081 }
2082
2083 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00002084 RECT rect = {std::max(x, 0),
2085 std::max(y, 0),
2086 std::min(x + width, (int)desc.Width),
2087 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002088
2089 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
2090
2091 if (FAILED(result))
2092 {
2093 UNREACHABLE();
2094 systemSurface->Release();
2095
2096 return; // No sensible error to generate
2097 }
2098
2099 unsigned char *source = (unsigned char*)lock.pBits;
2100 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002101 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002102
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002103 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002104
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002105 for (int j = 0; j < rect.bottom - rect.top; j++)
2106 {
2107 for (int i = 0; i < rect.right - rect.left; i++)
2108 {
2109 float r;
2110 float g;
2111 float b;
2112 float a;
2113
2114 switch (desc.Format)
2115 {
2116 case D3DFMT_R5G6B5:
2117 {
2118 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2119
2120 a = 1.0f;
2121 b = (rgb & 0x001F) * (1.0f / 0x001F);
2122 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2123 r = (rgb & 0xF800) * (1.0f / 0xF800);
2124 }
2125 break;
2126 case D3DFMT_X1R5G5B5:
2127 {
2128 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2129
2130 a = 1.0f;
2131 b = (xrgb & 0x001F) * (1.0f / 0x001F);
2132 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
2133 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
2134 }
2135 break;
2136 case D3DFMT_A1R5G5B5:
2137 {
2138 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2139
2140 a = (argb & 0x8000) ? 1.0f : 0.0f;
2141 b = (argb & 0x001F) * (1.0f / 0x001F);
2142 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2143 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2144 }
2145 break;
2146 case D3DFMT_A8R8G8B8:
2147 {
2148 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2149
2150 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2151 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2152 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2153 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2154 }
2155 break;
2156 case D3DFMT_X8R8G8B8:
2157 {
2158 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2159
2160 a = 1.0f;
2161 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2162 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2163 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2164 }
2165 break;
2166 case D3DFMT_A2R10G10B10:
2167 {
2168 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2169
2170 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2171 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2172 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2173 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2174 }
2175 break;
2176 default:
2177 UNIMPLEMENTED(); // FIXME
2178 UNREACHABLE();
2179 }
2180
2181 switch (format)
2182 {
2183 case GL_RGBA:
2184 switch (type)
2185 {
2186 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002187 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2188 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2189 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2190 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002191 break;
2192 default: UNREACHABLE();
2193 }
2194 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002195 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002196 switch (type)
2197 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002198 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002199 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2200 ((unsigned short)(31 * b + 0.5f) << 0) |
2201 ((unsigned short)(63 * g + 0.5f) << 5) |
2202 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002203 break;
2204 default: UNREACHABLE();
2205 }
2206 break;
2207 default: UNREACHABLE();
2208 }
2209 }
2210 }
2211
2212 systemSurface->UnlockRect();
2213
2214 systemSurface->Release();
2215}
2216
2217void Context::clear(GLbitfield mask)
2218{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002219 Framebuffer *framebufferObject = getFramebuffer();
2220
2221 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2222 {
2223 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2224
2225 return;
2226 }
2227
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002228 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002229 IDirect3DDevice9 *device = getDevice();
2230 DWORD flags = 0;
2231
2232 if (mask & GL_COLOR_BUFFER_BIT)
2233 {
2234 mask &= ~GL_COLOR_BUFFER_BIT;
2235 flags |= D3DCLEAR_TARGET;
2236 }
2237
2238 if (mask & GL_DEPTH_BUFFER_BIT)
2239 {
2240 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002241 if (mState.depthMask)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002242 {
2243 flags |= D3DCLEAR_ZBUFFER;
2244 }
2245 }
2246
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002247 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
2248
2249 GLuint stencilUnmasked = 0x0;
2250
2251 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
2252 {
2253 D3DSURFACE_DESC desc;
2254 depthStencil->GetDesc(&desc);
2255
2256 mask &= ~GL_STENCIL_BUFFER_BIT;
2257 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2258 stencilUnmasked = (0x1 << stencilSize) - 1;
2259
2260 if (stencilUnmasked != 0x0)
2261 {
2262 flags |= D3DCLEAR_STENCIL;
2263 }
2264 }
2265
2266 if (mask != 0)
2267 {
2268 return error(GL_INVALID_VALUE);
2269 }
2270
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002271 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2272 {
2273 return;
2274 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002275
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002276 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2277 unorm<8>(mState.colorClearValue.red),
2278 unorm<8>(mState.colorClearValue.green),
2279 unorm<8>(mState.colorClearValue.blue));
2280 float depth = clamp01(mState.depthClearValue);
2281 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002282
2283 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2284
2285 D3DSURFACE_DESC desc;
2286 renderTarget->GetDesc(&desc);
2287
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002288 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002289
2290 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002291 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002292 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002293 !(mState.colorMaskRed && mState.colorMaskGreen &&
2294 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002295
2296 if (needMaskedColorClear || needMaskedStencilClear)
2297 {
2298 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2299 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2300 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2301 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2302 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2303 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2304 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2305 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2306
2307 if (flags & D3DCLEAR_TARGET)
2308 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002309 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2310 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2311 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2312 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002313 }
2314 else
2315 {
2316 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2317 }
2318
2319 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2320 {
2321 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2322 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2323 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2324 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002325 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002326 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002327 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2328 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
2329 }
2330 else
2331 {
2332 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2333 }
2334
2335 device->SetPixelShader(NULL);
2336 device->SetVertexShader(NULL);
2337 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2338
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002339 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002340 {
2341 float x, y, z, w;
2342 D3DCOLOR diffuse;
2343 };
2344
2345 Vertex quad[4];
2346 quad[0].x = 0.0f;
2347 quad[0].y = (float)desc.Height;
2348 quad[0].z = 0.0f;
2349 quad[0].w = 1.0f;
2350 quad[0].diffuse = color;
2351
2352 quad[1].x = (float)desc.Width;
2353 quad[1].y = (float)desc.Height;
2354 quad[1].z = 0.0f;
2355 quad[1].w = 1.0f;
2356 quad[1].diffuse = color;
2357
2358 quad[2].x = 0.0f;
2359 quad[2].y = 0.0f;
2360 quad[2].z = 0.0f;
2361 quad[2].w = 1.0f;
2362 quad[2].diffuse = color;
2363
2364 quad[3].x = (float)desc.Width;
2365 quad[3].y = 0.0f;
2366 quad[3].z = 0.0f;
2367 quad[3].w = 1.0f;
2368 quad[3].diffuse = color;
2369
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002370 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002371 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002372
2373 if (flags & D3DCLEAR_ZBUFFER)
2374 {
2375 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2376 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2377 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2378 }
2379 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002380 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002381 {
2382 device->Clear(0, NULL, flags, color, depth, stencil);
2383 }
2384}
2385
2386void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2387{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002388 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002389 {
2390 return error(GL_INVALID_OPERATION);
2391 }
2392
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002393 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002394 IDirect3DDevice9 *device = getDevice();
2395 D3DPRIMITIVETYPE primitiveType;
2396 int primitiveCount;
2397
2398 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2399 return error(GL_INVALID_ENUM);
2400
2401 if (primitiveCount <= 0)
2402 {
2403 return;
2404 }
2405
2406 if (!applyRenderTarget(false))
2407 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002408 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002409 }
2410
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002411 applyState(mode);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002412 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002413 applyShaders();
2414 applyTextures();
2415
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002416 if (!getCurrentProgram()->validateSamplers())
2417 {
2418 return error(GL_INVALID_OPERATION);
2419 }
2420
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002421 if (!cullSkipsDraw(mode))
2422 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002423 display->startScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002424 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002425 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002426}
2427
2428void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2429{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002430 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002431 {
2432 return error(GL_INVALID_OPERATION);
2433 }
2434
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002435 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002436 {
2437 return error(GL_INVALID_OPERATION);
2438 }
2439
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002440 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002441 IDirect3DDevice9 *device = getDevice();
2442 D3DPRIMITIVETYPE primitiveType;
2443 int primitiveCount;
2444
2445 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2446 return error(GL_INVALID_ENUM);
2447
2448 if (primitiveCount <= 0)
2449 {
2450 return;
2451 }
2452
2453 if (!applyRenderTarget(false))
2454 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002455 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002456 }
2457
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002458 applyState(mode);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002459 TranslatedIndexData indexInfo = applyIndexBuffer(indices, count, mode, type);
2460 applyVertexBuffer(indexInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002461 applyShaders();
2462 applyTextures();
2463
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002464 if (!getCurrentProgram()->validateSamplers())
2465 {
2466 return error(GL_INVALID_OPERATION);
2467 }
2468
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002469 if (!cullSkipsDraw(mode))
2470 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002471 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002472 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 +00002473 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002474}
2475
2476void Context::finish()
2477{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002478 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002479 IDirect3DDevice9 *device = getDevice();
2480 IDirect3DQuery9 *occlusionQuery = NULL;
2481
2482 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2483
2484 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2485 {
2486 return error(GL_OUT_OF_MEMORY);
2487 }
2488
2489 ASSERT(SUCCEEDED(result));
2490
2491 if (occlusionQuery)
2492 {
2493 occlusionQuery->Issue(D3DISSUE_BEGIN);
2494
2495 // Render something outside the render target
2496 device->SetPixelShader(NULL);
2497 device->SetVertexShader(NULL);
2498 device->SetFVF(D3DFVF_XYZRHW);
2499 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002500 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002501 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002502
2503 occlusionQuery->Issue(D3DISSUE_END);
2504
2505 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2506 {
2507 // Keep polling, but allow other threads to do something useful first
2508 Sleep(0);
2509 }
2510
2511 occlusionQuery->Release();
2512 }
2513}
2514
2515void Context::flush()
2516{
2517 IDirect3DDevice9 *device = getDevice();
2518 IDirect3DQuery9 *eventQuery = NULL;
2519
2520 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2521
2522 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2523 {
2524 return error(GL_OUT_OF_MEMORY);
2525 }
2526
2527 ASSERT(SUCCEEDED(result));
2528
2529 if (eventQuery)
2530 {
2531 eventQuery->Issue(D3DISSUE_END);
2532
2533 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2534 {
2535 // Keep polling, but allow other threads to do something useful first
2536 Sleep(0);
2537 }
2538
2539 eventQuery->Release();
2540 }
2541}
2542
2543void Context::recordInvalidEnum()
2544{
2545 mInvalidEnum = true;
2546}
2547
2548void Context::recordInvalidValue()
2549{
2550 mInvalidValue = true;
2551}
2552
2553void Context::recordInvalidOperation()
2554{
2555 mInvalidOperation = true;
2556}
2557
2558void Context::recordOutOfMemory()
2559{
2560 mOutOfMemory = true;
2561}
2562
2563void Context::recordInvalidFramebufferOperation()
2564{
2565 mInvalidFramebufferOperation = true;
2566}
2567
2568// Get one of the recorded errors and clear its flag, if any.
2569// [OpenGL ES 2.0.24] section 2.5 page 13.
2570GLenum Context::getError()
2571{
2572 if (mInvalidEnum)
2573 {
2574 mInvalidEnum = false;
2575
2576 return GL_INVALID_ENUM;
2577 }
2578
2579 if (mInvalidValue)
2580 {
2581 mInvalidValue = false;
2582
2583 return GL_INVALID_VALUE;
2584 }
2585
2586 if (mInvalidOperation)
2587 {
2588 mInvalidOperation = false;
2589
2590 return GL_INVALID_OPERATION;
2591 }
2592
2593 if (mOutOfMemory)
2594 {
2595 mOutOfMemory = false;
2596
2597 return GL_OUT_OF_MEMORY;
2598 }
2599
2600 if (mInvalidFramebufferOperation)
2601 {
2602 mInvalidFramebufferOperation = false;
2603
2604 return GL_INVALID_FRAMEBUFFER_OPERATION;
2605 }
2606
2607 return GL_NO_ERROR;
2608}
2609
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002610const char *Context::getPixelShaderProfile()
2611{
2612 return mPsProfile;
2613}
2614
2615const char *Context::getVertexShaderProfile()
2616{
2617 return mVsProfile;
2618}
2619
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002620void Context::detachBuffer(GLuint buffer)
2621{
2622 // [OpenGL ES 2.0.24] section 2.9 page 22:
2623 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2624 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2625
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002626 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002627 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002628 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002629 }
2630
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002631 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002632 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002633 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002634 }
2635
2636 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2637 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002638 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002639 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002640 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002641 }
2642 }
2643}
2644
2645void Context::detachTexture(GLuint texture)
2646{
2647 // [OpenGL ES 2.0.24] section 3.8 page 84:
2648 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2649 // rebound to texture object zero
2650
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002651 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002652 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002653 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002654 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002655 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002656 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002657 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002658 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002659 }
2660 }
2661
2662 // [OpenGL ES 2.0.24] section 4.4 page 112:
2663 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2664 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2665 // image was attached in the currently bound framebuffer.
2666
2667 Framebuffer *framebuffer = getFramebuffer();
2668
2669 if (framebuffer)
2670 {
2671 framebuffer->detachTexture(texture);
2672 }
2673}
2674
2675void Context::detachFramebuffer(GLuint framebuffer)
2676{
2677 // [OpenGL ES 2.0.24] section 4.4 page 107:
2678 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2679 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2680
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002681 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002682 {
2683 bindFramebuffer(0);
2684 }
2685}
2686
2687void Context::detachRenderbuffer(GLuint renderbuffer)
2688{
2689 // [OpenGL ES 2.0.24] section 4.4 page 109:
2690 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2691 // had been executed with the target RENDERBUFFER and name of zero.
2692
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002693 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002694 {
2695 bindRenderbuffer(0);
2696 }
2697
2698 // [OpenGL ES 2.0.24] section 4.4 page 111:
2699 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2700 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2701 // point to which this image was attached in the currently bound framebuffer.
2702
2703 Framebuffer *framebuffer = getFramebuffer();
2704
2705 if (framebuffer)
2706 {
2707 framebuffer->detachRenderbuffer(renderbuffer);
2708 }
2709}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002710
2711Texture *Context::getIncompleteTexture(SamplerType type)
2712{
2713 Texture *t = mIncompleteTextures[type];
2714
2715 if (t == NULL)
2716 {
2717 static const GLubyte color[] = { 0, 0, 0, 255 };
2718
2719 switch (type)
2720 {
2721 default:
2722 UNREACHABLE();
2723 // default falls through to SAMPLER_2D
2724
2725 case SAMPLER_2D:
2726 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002727 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002728 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002729 t = incomplete2d;
2730 }
2731 break;
2732
2733 case SAMPLER_CUBE:
2734 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002735 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002736
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002737 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2738 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2739 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2740 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2741 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2742 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002743
2744 t = incompleteCube;
2745 }
2746 break;
2747 }
2748
2749 mIncompleteTextures[type] = t;
2750 }
2751
2752 return t;
2753}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002754
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002755bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002756{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002757 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002758}
2759
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002760bool Context::isTriangleMode(GLenum drawMode)
2761{
2762 switch (drawMode)
2763 {
2764 case GL_TRIANGLES:
2765 case GL_TRIANGLE_FAN:
2766 case GL_TRIANGLE_STRIP:
2767 return true;
2768 case GL_POINTS:
2769 case GL_LINES:
2770 case GL_LINE_LOOP:
2771 case GL_LINE_STRIP:
2772 return false;
2773 default: UNREACHABLE();
2774 }
2775
2776 return false;
2777}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002778
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002779bool Context::hasStencil()
2780{
2781 Framebuffer *framebufferObject = getFramebuffer();
2782
2783 if (framebufferObject)
2784 {
2785 Stencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
2786
2787 if (stencilbufferObject)
2788 {
2789 return stencilbufferObject->getStencilSize() > 0;
2790 }
2791 }
2792
2793 return false;
2794}
2795
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002796void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2797{
2798 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2799
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002800 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2801 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2802 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2803 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002804
2805 mVertexDataManager->dirtyCurrentValues();
2806}
2807
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002808void Context::initExtensionString()
2809{
2810 if (mBufferBackEnd->supportIntIndices())
2811 {
2812 mExtensionString += "GL_OES_element_index_uint ";
2813 }
2814
2815 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2816 if (end != std::string::npos)
2817 {
2818 mExtensionString.resize(end+1);
2819 }
2820}
2821
2822const char *Context::getExtensionString() const
2823{
2824 return mExtensionString.c_str();
2825}
2826
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002827}
2828
2829extern "C"
2830{
2831gl::Context *glCreateContext(const egl::Config *config)
2832{
2833 return new gl::Context(config);
2834}
2835
2836void glDestroyContext(gl::Context *context)
2837{
2838 delete context;
2839
2840 if (context == gl::getContext())
2841 {
2842 gl::makeCurrent(NULL, NULL, NULL);
2843 }
2844}
2845
2846void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2847{
2848 gl::makeCurrent(context, display, surface);
2849}
2850
2851gl::Context *glGetCurrentContext()
2852{
2853 return gl::getContext();
2854}
2855}