blob: 480c6888a96e405de32b8f1456476b859427cab8 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Context.cpp: Implements the gl::Context class, managing all GL state and performing
8// rendering operations. It is the GLES2 specific implementation of EGLContext.
9
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/Context.h"
daniel@transgaming.com16973022010-03-11 19:22:19 +000011
12#include <algorithm>
13
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000014#include "libEGL/Display.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000015
16#include "libGLESv2/main.h"
17#include "libGLESv2/mathutil.h"
18#include "libGLESv2/utilities.h"
19#include "libGLESv2/Blit.h"
20#include "libGLESv2/Buffer.h"
21#include "libGLESv2/FrameBuffer.h"
22#include "libGLESv2/Program.h"
23#include "libGLESv2/RenderBuffer.h"
24#include "libGLESv2/Shader.h"
25#include "libGLESv2/Texture.h"
26#include "libGLESv2/geometry/backend.h"
27#include "libGLESv2/geometry/VertexDataManager.h"
28#include "libGLESv2/geometry/IndexDataManager.h"
29#include "libGLESv2/geometry/dx9.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030
daniel@transgaming.com86487c22010-03-11 19:41:43 +000031#undef near
32#undef far
33
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034namespace gl
35{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000036Context::Context(const egl::Config *config)
37 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038{
39 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
daniel@transgaming.com092bd482010-05-12 03:39:36 +000040
daniel@transgaming.com428d1582010-05-04 03:35:25 +000041 mState.depthClearValue = 1.0f;
42 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043
daniel@transgaming.com428d1582010-05-04 03:35:25 +000044 mState.cullFace = false;
45 mState.cullMode = GL_BACK;
46 mState.frontFace = GL_CCW;
47 mState.depthTest = false;
48 mState.depthFunc = GL_LESS;
49 mState.blend = false;
50 mState.sourceBlendRGB = GL_ONE;
51 mState.sourceBlendAlpha = GL_ONE;
52 mState.destBlendRGB = GL_ZERO;
53 mState.destBlendAlpha = GL_ZERO;
54 mState.blendEquationRGB = GL_FUNC_ADD;
55 mState.blendEquationAlpha = GL_FUNC_ADD;
56 mState.blendColor.red = 0;
57 mState.blendColor.green = 0;
58 mState.blendColor.blue = 0;
59 mState.blendColor.alpha = 0;
60 mState.stencilTest = false;
61 mState.stencilFunc = GL_ALWAYS;
62 mState.stencilRef = 0;
63 mState.stencilMask = -1;
64 mState.stencilWritemask = -1;
65 mState.stencilBackFunc = GL_ALWAYS;
66 mState.stencilBackRef = 0;
67 mState.stencilBackMask = - 1;
68 mState.stencilBackWritemask = -1;
69 mState.stencilFail = GL_KEEP;
70 mState.stencilPassDepthFail = GL_KEEP;
71 mState.stencilPassDepthPass = GL_KEEP;
72 mState.stencilBackFail = GL_KEEP;
73 mState.stencilBackPassDepthFail = GL_KEEP;
74 mState.stencilBackPassDepthPass = GL_KEEP;
75 mState.polygonOffsetFill = false;
76 mState.polygonOffsetFactor = 0.0f;
77 mState.polygonOffsetUnits = 0.0f;
78 mState.sampleAlphaToCoverage = false;
79 mState.sampleCoverage = false;
80 mState.sampleCoverageValue = 1.0f;
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +000081 mState.sampleCoverageInvert = false;
daniel@transgaming.com428d1582010-05-04 03:35:25 +000082 mState.scissorTest = false;
83 mState.dither = true;
84 mState.generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085
daniel@transgaming.com428d1582010-05-04 03:35:25 +000086 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000087
daniel@transgaming.com428d1582010-05-04 03:35:25 +000088 mState.viewportX = 0;
89 mState.viewportY = 0;
90 mState.viewportWidth = config->mDisplayMode.Width;
91 mState.viewportHeight = config->mDisplayMode.Height;
92 mState.zNear = 0.0f;
93 mState.zFar = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000094
daniel@transgaming.com428d1582010-05-04 03:35:25 +000095 mState.scissorX = 0;
96 mState.scissorY = 0;
97 mState.scissorWidth = config->mDisplayMode.Width;
98 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000100 mState.colorMaskRed = true;
101 mState.colorMaskGreen = true;
102 mState.colorMaskBlue = true;
103 mState.colorMaskAlpha = true;
104 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105
106 // [OpenGL ES 2.0.24] section 3.7 page 83:
107 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
108 // and cube map texture state vectors respectively associated with them.
109 // In order that access to these initial textures not be lost, they are treated as texture
110 // objects all of whose names are 0.
111
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000112 mTexture2DZero = new Texture2D(this);
113 mTextureCubeMapZero = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114
115 mColorbufferZero = NULL;
116 mDepthbufferZero = NULL;
117 mStencilbufferZero = NULL;
118
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000119 mState.activeSampler = 0;
120 mState.arrayBuffer = 0;
121 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122 bindTextureCubeMap(0);
123 bindTexture2D(0);
124 bindFramebuffer(0);
125 bindRenderbuffer(0);
126
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000127 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000129 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
130 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000131 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000132 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133 }
134
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000135 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
136 {
137 mIncompleteTextures[type] = NULL;
138 }
139
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000140 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000142 mState.packAlignment = 4;
143 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000144
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000145 mBufferBackEnd = NULL;
146 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000147 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000148 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000149
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150 mInvalidEnum = false;
151 mInvalidValue = false;
152 mInvalidOperation = false;
153 mOutOfMemory = false;
154 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000155
156 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000157
158 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159}
160
161Context::~Context()
162{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000163 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000165 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
166 {
167 delete mIncompleteTextures[type];
168 }
169
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170 delete mTexture2DZero;
171 delete mTextureCubeMapZero;
172
173 delete mColorbufferZero;
174 delete mDepthbufferZero;
175 delete mStencilbufferZero;
176
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000177 delete mBufferBackEnd;
178 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000179 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000180 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000181
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182 while (!mBufferMap.empty())
183 {
184 deleteBuffer(mBufferMap.begin()->first);
185 }
186
187 while (!mProgramMap.empty())
188 {
189 deleteProgram(mProgramMap.begin()->first);
190 }
191
192 while (!mShaderMap.empty())
193 {
194 deleteShader(mShaderMap.begin()->first);
195 }
196
197 while (!mFramebufferMap.empty())
198 {
199 deleteFramebuffer(mFramebufferMap.begin()->first);
200 }
201
202 while (!mRenderbufferMap.empty())
203 {
204 deleteRenderbuffer(mRenderbufferMap.begin()->first);
205 }
206
207 while (!mTextureMap.empty())
208 {
209 deleteTexture(mTextureMap.begin()->first);
210 }
211}
212
213void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
214{
215 IDirect3DDevice9 *device = display->getDevice();
216
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000217 if (!mHasBeenCurrent)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000218 {
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000219 device->GetDeviceCaps(&mDeviceCaps);
220
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000221 mBufferBackEnd = new Dx9BackEnd(device);
222 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000223 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000224 mBlit = new Blit(this);
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000225
226 initExtensionString();
227
228 mState.viewportX = 0;
229 mState.viewportY = 0;
230 mState.viewportWidth = surface->getWidth();
231 mState.viewportHeight = surface->getHeight();
232
233 mState.scissorX = 0;
234 mState.scissorY = 0;
235 mState.scissorWidth = surface->getWidth();
236 mState.scissorHeight = surface->getHeight();
237
238 mHasBeenCurrent = true;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000239 }
240
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000241 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
242 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000243 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244
245 Framebuffer *framebufferZero = new Framebuffer();
246 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000247 Depthbuffer *depthbufferZero = new Depthbuffer(depthStencil);
248 Stencilbuffer *stencilbufferZero = new Stencilbuffer(depthStencil);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249
250 setFramebufferZero(framebufferZero);
251 setColorbufferZero(colorbufferZero);
252 setDepthbufferZero(depthbufferZero);
253 setStencilbufferZero(stencilbufferZero);
254
255 framebufferZero->setColorbuffer(GL_RENDERBUFFER, 0);
256 framebufferZero->setDepthbuffer(GL_RENDERBUFFER, 0);
257 framebufferZero->setStencilbuffer(GL_RENDERBUFFER, 0);
258
259 defaultRenderTarget->Release();
260
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000261 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000263 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000265
266 D3DCAPS9 capabilities;
267 device->GetDeviceCaps(&capabilities);
268
269 if (capabilities.PixelShaderVersion == D3DPS_VERSION(3, 0))
270 {
271 mPsProfile = "ps_3_0";
272 mVsProfile = "vs_3_0";
273 }
274 else // egl::Display guarantees support for at least 2.0
275 {
276 mPsProfile = "ps_2_0";
277 mVsProfile = "vs_2_0";
278 }
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000279
280 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000281}
282
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000283// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000284void Context::markAllStateDirty()
285{
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000286 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000287 mAppliedDepthbufferSerial = 0;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000288 mAppliedProgram = 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000289
290 mClearStateDirty = true;
291 mCullStateDirty = true;
292 mDepthStateDirty = true;
293 mMaskStateDirty = true;
294 mBlendStateDirty = true;
295 mStencilStateDirty = true;
296 mPolygonOffsetStateDirty = true;
297 mScissorStateDirty = true;
298 mSampleStateDirty = true;
299 mDitherStateDirty = true;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000300}
301
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302void Context::setClearColor(float red, float green, float blue, float alpha)
303{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000304 mState.colorClearValue.red = red;
305 mState.colorClearValue.green = green;
306 mState.colorClearValue.blue = blue;
307 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308}
309
310void Context::setClearDepth(float depth)
311{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000312 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313}
314
315void Context::setClearStencil(int stencil)
316{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000317 mState.stencilClearValue = stencil;
318}
319
320void Context::setCullFace(bool enabled)
321{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000322 if (mState.cullFace != enabled)
323 {
324 mState.cullFace = enabled;
325 mCullStateDirty = true;
326 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000327}
328
329bool Context::isCullFaceEnabled() const
330{
331 return mState.cullFace;
332}
333
334void Context::setCullMode(GLenum mode)
335{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000336 if (mState.cullMode != mode)
337 {
338 mState.cullMode = mode;
339 mCullStateDirty = true;
340 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000341}
342
343void Context::setFrontFace(GLenum front)
344{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000345 if (mState.frontFace != front)
346 {
347 mState.frontFace = front;
348 mFrontFaceDirty = true;
349 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000350}
351
352void Context::setDepthTest(bool enabled)
353{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000354 if (mState.depthTest != enabled)
355 {
356 mState.depthTest = enabled;
357 mDepthStateDirty = true;
358 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000359}
360
361bool Context::isDepthTestEnabled() const
362{
363 return mState.depthTest;
364}
365
366void Context::setDepthFunc(GLenum depthFunc)
367{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000368 if (mState.depthFunc != depthFunc)
369 {
370 mState.depthFunc = depthFunc;
371 mDepthStateDirty = true;
372 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000373}
374
375void Context::setDepthRange(float zNear, float zFar)
376{
377 mState.zNear = zNear;
378 mState.zFar = zFar;
379}
380
381void Context::setBlend(bool enabled)
382{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000383 if (mState.blend != enabled)
384 {
385 mState.blend = enabled;
386 mBlendStateDirty = true;
387 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000388}
389
390bool Context::isBlendEnabled() const
391{
392 return mState.blend;
393}
394
395void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
396{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000397 if (mState.sourceBlendRGB != sourceRGB ||
398 mState.sourceBlendAlpha != sourceAlpha ||
399 mState.destBlendRGB != destRGB ||
400 mState.destBlendAlpha != destAlpha)
401 {
402 mState.sourceBlendRGB = sourceRGB;
403 mState.destBlendRGB = destRGB;
404 mState.sourceBlendAlpha = sourceAlpha;
405 mState.destBlendAlpha = destAlpha;
406 mBlendStateDirty = true;
407 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000408}
409
410void Context::setBlendColor(float red, float green, float blue, float alpha)
411{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000412 if (mState.blendColor.red != red ||
413 mState.blendColor.green != green ||
414 mState.blendColor.blue != blue ||
415 mState.blendColor.alpha != alpha)
416 {
417 mState.blendColor.red = red;
418 mState.blendColor.green = green;
419 mState.blendColor.blue = blue;
420 mState.blendColor.alpha = alpha;
421 mBlendStateDirty = true;
422 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000423}
424
425void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
426{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000427 if (mState.blendEquationRGB != rgbEquation ||
428 mState.blendEquationAlpha != alphaEquation)
429 {
430 mState.blendEquationRGB = rgbEquation;
431 mState.blendEquationAlpha = alphaEquation;
432 mBlendStateDirty = true;
433 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000434}
435
436void Context::setStencilTest(bool enabled)
437{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000438 if (mState.stencilTest != enabled)
439 {
440 mState.stencilTest = enabled;
441 mStencilStateDirty = true;
442 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000443}
444
445bool Context::isStencilTestEnabled() const
446{
447 return mState.stencilTest;
448}
449
450void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
451{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000452 if (mState.stencilFunc != stencilFunc ||
453 mState.stencilRef != stencilRef ||
454 mState.stencilMask != stencilMask)
455 {
456 mState.stencilFunc = stencilFunc;
457 mState.stencilRef = stencilRef;
458 mState.stencilMask = stencilMask;
459 mStencilStateDirty = true;
460 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000461}
462
463void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
464{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000465 if (mState.stencilBackFunc != stencilBackFunc ||
466 mState.stencilBackRef != stencilBackRef ||
467 mState.stencilBackMask != stencilBackMask)
468 {
469 mState.stencilBackFunc = stencilBackFunc;
470 mState.stencilBackRef = stencilBackRef;
471 mState.stencilBackMask = stencilBackMask;
472 mStencilStateDirty = true;
473 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000474}
475
476void Context::setStencilWritemask(GLuint stencilWritemask)
477{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000478 if (mState.stencilWritemask != stencilWritemask)
479 {
480 mState.stencilWritemask = stencilWritemask;
481 mStencilStateDirty = true;
482 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000483}
484
485void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
486{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000487 if (mState.stencilBackWritemask != stencilBackWritemask)
488 {
489 mState.stencilBackWritemask = stencilBackWritemask;
490 mStencilStateDirty = true;
491 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000492}
493
494void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
495{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000496 if (mState.stencilFail != stencilFail ||
497 mState.stencilPassDepthFail != stencilPassDepthFail ||
498 mState.stencilPassDepthPass != stencilPassDepthPass)
499 {
500 mState.stencilFail = stencilFail;
501 mState.stencilPassDepthFail = stencilPassDepthFail;
502 mState.stencilPassDepthPass = stencilPassDepthPass;
503 mStencilStateDirty = true;
504 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000505}
506
507void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
508{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000509 if (mState.stencilBackFail != stencilBackFail ||
510 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
511 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
512 {
513 mState.stencilBackFail = stencilBackFail;
514 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
515 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
516 mStencilStateDirty = true;
517 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000518}
519
520void Context::setPolygonOffsetFill(bool enabled)
521{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000522 if (mState.polygonOffsetFill != enabled)
523 {
524 mState.polygonOffsetFill = enabled;
525 mPolygonOffsetStateDirty = true;
526 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000527}
528
529bool Context::isPolygonOffsetFillEnabled() const
530{
531 return mState.polygonOffsetFill;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000532
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000533}
534
535void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
536{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000537 if (mState.polygonOffsetFactor != factor ||
538 mState.polygonOffsetUnits != units)
539 {
540 mState.polygonOffsetFactor = factor;
541 mState.polygonOffsetUnits = units;
542 mPolygonOffsetStateDirty = true;
543 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000544}
545
546void Context::setSampleAlphaToCoverage(bool enabled)
547{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000548 if (mState.sampleAlphaToCoverage != enabled)
549 {
550 mState.sampleAlphaToCoverage = enabled;
551 mSampleStateDirty = true;
552 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000553}
554
555bool Context::isSampleAlphaToCoverageEnabled() const
556{
557 return mState.sampleAlphaToCoverage;
558}
559
560void Context::setSampleCoverage(bool enabled)
561{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000562 if (mState.sampleCoverage != enabled)
563 {
564 mState.sampleCoverage = enabled;
565 mSampleStateDirty = true;
566 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000567}
568
569bool Context::isSampleCoverageEnabled() const
570{
571 return mState.sampleCoverage;
572}
573
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +0000574void Context::setSampleCoverageParams(GLclampf value, bool invert)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000575{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000576 if (mState.sampleCoverageValue != value ||
577 mState.sampleCoverageInvert != invert)
578 {
579 mState.sampleCoverageValue = value;
580 mState.sampleCoverageInvert = invert;
581 mSampleStateDirty = true;
582 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000583}
584
585void Context::setScissorTest(bool enabled)
586{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000587 if (mState.scissorTest != enabled)
588 {
589 mState.scissorTest = enabled;
590 mScissorStateDirty = true;
591 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000592}
593
594bool Context::isScissorTestEnabled() const
595{
596 return mState.scissorTest;
597}
598
599void Context::setDither(bool enabled)
600{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000601 if (mState.dither != enabled)
602 {
603 mState.dither = enabled;
604 mDitherStateDirty = true;
605 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000606}
607
608bool Context::isDitherEnabled() const
609{
610 return mState.dither;
611}
612
613void Context::setLineWidth(GLfloat width)
614{
615 mState.lineWidth = width;
616}
617
618void Context::setGenerateMipmapHint(GLenum hint)
619{
620 mState.generateMipmapHint = hint;
621}
622
623void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
624{
625 mState.viewportX = x;
626 mState.viewportY = y;
627 mState.viewportWidth = width;
628 mState.viewportHeight = height;
629}
630
631void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
632{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000633 if (mState.scissorX != x || mState.scissorY != y ||
634 mState.scissorWidth != width || mState.scissorHeight != height)
635 {
636 mState.scissorX = x;
637 mState.scissorY = y;
638 mState.scissorWidth = width;
639 mState.scissorHeight = height;
640 mScissorStateDirty = true;
641 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000642}
643
644void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
645{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000646 if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
647 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
648 {
649 mState.colorMaskRed = red;
650 mState.colorMaskGreen = green;
651 mState.colorMaskBlue = blue;
652 mState.colorMaskAlpha = alpha;
653 mMaskStateDirty = true;
654 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000655}
656
657void Context::setDepthMask(bool mask)
658{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000659 if (mState.depthMask != mask)
660 {
661 mState.depthMask = mask;
662 mMaskStateDirty = true;
663 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000664}
665
666void Context::setActiveSampler(int active)
667{
668 mState.activeSampler = active;
669}
670
671GLuint Context::getFramebufferHandle() const
672{
673 return mState.framebuffer;
674}
675
676GLuint Context::getRenderbufferHandle() const
677{
678 return mState.renderbuffer;
679}
680
681GLuint Context::getArrayBufferHandle() const
682{
683 return mState.arrayBuffer;
684}
685
686void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
687{
688 mState.vertexAttribute[attribNum].mEnabled = enabled;
689}
690
691const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
692{
693 return mState.vertexAttribute[attribNum];
694}
695
696void Context::setVertexAttribState(unsigned int attribNum, GLuint boundBuffer, GLint size, GLenum type, bool normalized,
697 GLsizei stride, const void *pointer)
698{
699 mState.vertexAttribute[attribNum].mBoundBuffer = boundBuffer;
700 mState.vertexAttribute[attribNum].mSize = size;
701 mState.vertexAttribute[attribNum].mType = type;
702 mState.vertexAttribute[attribNum].mNormalized = normalized;
703 mState.vertexAttribute[attribNum].mStride = stride;
704 mState.vertexAttribute[attribNum].mPointer = pointer;
705}
706
707const void *Context::getVertexAttribPointer(unsigned int attribNum) const
708{
709 return mState.vertexAttribute[attribNum].mPointer;
710}
711
712// returns entire set of attributes as a block
713const AttributeState *Context::getVertexAttribBlock()
714{
715 return mState.vertexAttribute;
716}
717
718void Context::setPackAlignment(GLint alignment)
719{
720 mState.packAlignment = alignment;
721}
722
723GLint Context::getPackAlignment() const
724{
725 return mState.packAlignment;
726}
727
728void Context::setUnpackAlignment(GLint alignment)
729{
730 mState.unpackAlignment = alignment;
731}
732
733GLint Context::getUnpackAlignment() const
734{
735 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000736}
737
738// Returns an unused buffer name
739GLuint Context::createBuffer()
740{
741 unsigned int handle = 1;
742
743 while (mBufferMap.find(handle) != mBufferMap.end())
744 {
745 handle++;
746 }
747
748 mBufferMap[handle] = NULL;
749
750 return handle;
751}
752
753// Returns an unused shader/program name
754GLuint Context::createShader(GLenum type)
755{
756 unsigned int handle = 1;
757
758 while (mShaderMap.find(handle) != mShaderMap.end() || mProgramMap.find(handle) != mProgramMap.end()) // Shared name space
759 {
760 handle++;
761 }
762
763 if (type == GL_VERTEX_SHADER)
764 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000765 mShaderMap[handle] = new VertexShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000766 }
767 else if (type == GL_FRAGMENT_SHADER)
768 {
daniel@transgaming.com95124342010-04-29 03:38:58 +0000769 mShaderMap[handle] = new FragmentShader(this, handle);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000770 }
771 else UNREACHABLE();
772
773 return handle;
774}
775
776// Returns an unused program/shader name
777GLuint Context::createProgram()
778{
779 unsigned int handle = 1;
780
781 while (mProgramMap.find(handle) != mProgramMap.end() || mShaderMap.find(handle) != mShaderMap.end()) // Shared name space
782 {
783 handle++;
784 }
785
786 mProgramMap[handle] = new Program();
787
788 return handle;
789}
790
791// Returns an unused texture name
792GLuint Context::createTexture()
793{
794 unsigned int handle = 1;
795
796 while (mTextureMap.find(handle) != mTextureMap.end())
797 {
798 handle++;
799 }
800
801 mTextureMap[handle] = NULL;
802
803 return handle;
804}
805
806// Returns an unused framebuffer name
807GLuint Context::createFramebuffer()
808{
809 unsigned int handle = 1;
810
811 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
812 {
813 handle++;
814 }
815
816 mFramebufferMap[handle] = NULL;
817
818 return handle;
819}
820
821// Returns an unused renderbuffer name
822GLuint Context::createRenderbuffer()
823{
824 unsigned int handle = 1;
825
daniel@transgaming.come2b22122010-03-11 19:22:14 +0000826 while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000827 {
828 handle++;
829 }
830
831 mRenderbufferMap[handle] = NULL;
832
833 return handle;
834}
835
836void Context::deleteBuffer(GLuint buffer)
837{
838 BufferMap::iterator bufferObject = mBufferMap.find(buffer);
839
840 if (bufferObject != mBufferMap.end())
841 {
842 detachBuffer(buffer);
843
844 delete bufferObject->second;
845 mBufferMap.erase(bufferObject);
846 }
847}
848
849void Context::deleteShader(GLuint shader)
850{
851 ShaderMap::iterator shaderObject = mShaderMap.find(shader);
852
853 if (shaderObject != mShaderMap.end())
854 {
855 if (!shaderObject->second->isAttached())
856 {
857 delete shaderObject->second;
858 mShaderMap.erase(shaderObject);
859 }
860 else
861 {
862 shaderObject->second->flagForDeletion();
863 }
864 }
865}
866
867void Context::deleteProgram(GLuint program)
868{
869 ProgramMap::iterator programObject = mProgramMap.find(program);
870
871 if (programObject != mProgramMap.end())
872 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000873 if (program != mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000874 {
875 delete programObject->second;
876 mProgramMap.erase(programObject);
877 }
878 else
879 {
880 programObject->second->flagForDeletion();
881 }
882 }
883}
884
885void Context::deleteTexture(GLuint texture)
886{
887 TextureMap::iterator textureObject = mTextureMap.find(texture);
888
889 if (textureObject != mTextureMap.end())
890 {
891 detachTexture(texture);
892
893 if (texture != 0)
894 {
895 delete textureObject->second;
896 }
897
898 mTextureMap.erase(textureObject);
899 }
900}
901
902void Context::deleteFramebuffer(GLuint framebuffer)
903{
904 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
905
906 if (framebufferObject != mFramebufferMap.end())
907 {
908 detachFramebuffer(framebuffer);
909
910 delete framebufferObject->second;
911 mFramebufferMap.erase(framebufferObject);
912 }
913}
914
915void Context::deleteRenderbuffer(GLuint renderbuffer)
916{
917 RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
918
919 if (renderbufferObject != mRenderbufferMap.end())
920 {
921 detachRenderbuffer(renderbuffer);
922
923 delete renderbufferObject->second;
924 mRenderbufferMap.erase(renderbufferObject);
925 }
926}
927
928void Context::bindArrayBuffer(unsigned int buffer)
929{
930 if (buffer != 0 && !getBuffer(buffer))
931 {
daniel@transgaming.comdefa1c32010-05-18 18:51:45 +0000932 mBufferMap[buffer] = new Buffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000933 }
934
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000935 mState.arrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000936}
937
938void Context::bindElementArrayBuffer(unsigned int buffer)
939{
940 if (buffer != 0 && !getBuffer(buffer))
941 {
daniel@transgaming.comdefa1c32010-05-18 18:51:45 +0000942 mBufferMap[buffer] = new Buffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000943 }
944
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000945 mState.elementArrayBuffer = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000946}
947
948void Context::bindTexture2D(GLuint texture)
949{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000950 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000951 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000952 mTextureMap[texture] = new Texture2D(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000953 }
954
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000955 mState.texture2D = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000956
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000957 mState.samplerTexture[SAMPLER_2D][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000958}
959
960void Context::bindTextureCubeMap(GLuint texture)
961{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000962 if (!getTexture(texture) && texture != 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000963 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000964 mTextureMap[texture] = new TextureCubeMap(this);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000965 }
966
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000967 mState.textureCubeMap = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000969 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler] = texture;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000970}
971
972void Context::bindFramebuffer(GLuint framebuffer)
973{
974 if (!getFramebuffer(framebuffer))
975 {
976 mFramebufferMap[framebuffer] = new Framebuffer();
977 }
978
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000979 mState.framebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000980}
981
982void Context::bindRenderbuffer(GLuint renderbuffer)
983{
984 if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
985 {
986 mRenderbufferMap[renderbuffer] = new Renderbuffer();
987 }
988
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000989 mState.renderbuffer = renderbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000990}
991
992void Context::useProgram(GLuint program)
993{
994 Program *programObject = getCurrentProgram();
995
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000996 GLuint priorProgram = mState.currentProgram;
997 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000998
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000999 if (programObject && programObject->isFlaggedForDeletion())
1000 {
daniel@transgaming.com71cd8682010-04-29 03:35:25 +00001001 deleteProgram(priorProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001002 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001003}
1004
1005void Context::setFramebufferZero(Framebuffer *buffer)
1006{
1007 delete mFramebufferMap[0];
1008 mFramebufferMap[0] = buffer;
1009}
1010
1011void Context::setColorbufferZero(Colorbuffer *buffer)
1012{
1013 delete mColorbufferZero;
1014 mColorbufferZero = buffer;
1015}
1016
1017void Context::setDepthbufferZero(Depthbuffer *buffer)
1018{
1019 delete mDepthbufferZero;
1020 mDepthbufferZero = buffer;
1021}
1022
1023void Context::setStencilbufferZero(Stencilbuffer *buffer)
1024{
1025 delete mStencilbufferZero;
1026 mStencilbufferZero = buffer;
1027}
1028
1029void Context::setRenderbuffer(Renderbuffer *buffer)
1030{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001031 delete mRenderbufferMap[mState.renderbuffer];
1032 mRenderbufferMap[mState.renderbuffer] = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001033}
1034
1035Buffer *Context::getBuffer(unsigned int handle)
1036{
1037 BufferMap::iterator buffer = mBufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001038
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001039 if (buffer == mBufferMap.end())
1040 {
1041 return NULL;
1042 }
1043 else
1044 {
1045 return buffer->second;
1046 }
1047}
1048
1049Shader *Context::getShader(unsigned int handle)
1050{
1051 ShaderMap::iterator shader = mShaderMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001052
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001053 if (shader == mShaderMap.end())
1054 {
1055 return NULL;
1056 }
1057 else
1058 {
1059 return shader->second;
1060 }
1061}
1062
1063Program *Context::getProgram(unsigned int handle)
1064{
1065 ProgramMap::iterator program = mProgramMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001066
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001067 if (program == mProgramMap.end())
1068 {
1069 return NULL;
1070 }
1071 else
1072 {
1073 return program->second;
1074 }
1075}
1076
1077Texture *Context::getTexture(unsigned int handle)
1078{
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001079 if (handle == 0) return NULL;
1080
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001081 TextureMap::iterator texture = mTextureMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001082
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001083 if (texture == mTextureMap.end())
1084 {
1085 return NULL;
1086 }
1087 else
1088 {
1089 return texture->second;
1090 }
1091}
1092
1093Framebuffer *Context::getFramebuffer(unsigned int handle)
1094{
1095 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001096
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001097 if (framebuffer == mFramebufferMap.end())
1098 {
1099 return NULL;
1100 }
1101 else
1102 {
1103 return framebuffer->second;
1104 }
1105}
1106
1107Renderbuffer *Context::getRenderbuffer(unsigned int handle)
1108{
1109 RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00001110
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001111 if (renderbuffer == mRenderbufferMap.end())
1112 {
1113 return NULL;
1114 }
1115 else
1116 {
1117 return renderbuffer->second;
1118 }
1119}
1120
1121Colorbuffer *Context::getColorbuffer(GLuint handle)
1122{
1123 if (handle != 0)
1124 {
1125 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1126
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001127 if (renderbuffer && renderbuffer->isColorbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001128 {
1129 return static_cast<Colorbuffer*>(renderbuffer);
1130 }
1131 }
1132 else // Special case: 0 refers to different initial render targets based on the attachment type
1133 {
1134 return mColorbufferZero;
1135 }
1136
1137 return NULL;
1138}
1139
1140Depthbuffer *Context::getDepthbuffer(GLuint handle)
1141{
1142 if (handle != 0)
1143 {
1144 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1145
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001146 if (renderbuffer && renderbuffer->isDepthbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001147 {
1148 return static_cast<Depthbuffer*>(renderbuffer);
1149 }
1150 }
1151 else // Special case: 0 refers to different initial render targets based on the attachment type
1152 {
1153 return mDepthbufferZero;
1154 }
1155
1156 return NULL;
1157}
1158
1159Stencilbuffer *Context::getStencilbuffer(GLuint handle)
1160{
1161 if (handle != 0)
1162 {
1163 Renderbuffer *renderbuffer = getRenderbuffer(handle);
1164
daniel@transgaming.come2b22122010-03-11 19:22:14 +00001165 if (renderbuffer && renderbuffer->isStencilbuffer())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001166 {
1167 return static_cast<Stencilbuffer*>(renderbuffer);
1168 }
1169 }
1170 else
1171 {
1172 return mStencilbufferZero;
1173 }
1174
1175 return NULL;
1176}
1177
1178Buffer *Context::getArrayBuffer()
1179{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001180 return getBuffer(mState.arrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001181}
1182
1183Buffer *Context::getElementArrayBuffer()
1184{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001185 return getBuffer(mState.elementArrayBuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001186}
1187
1188Program *Context::getCurrentProgram()
1189{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001190 return getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001191}
1192
1193Texture2D *Context::getTexture2D()
1194{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001195 if (mState.texture2D == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001196 {
1197 return mTexture2DZero;
1198 }
1199
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001200 return (Texture2D*)getTexture(mState.texture2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001201}
1202
1203TextureCubeMap *Context::getTextureCubeMap()
1204{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001205 if (mState.textureCubeMap == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001206 {
1207 return mTextureCubeMapZero;
1208 }
1209
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001210 return (TextureCubeMap*)getTexture(mState.textureCubeMap);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001211}
1212
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001213Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001214{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001215 GLuint texid = mState.samplerTexture[type][sampler];
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001216
1217 if (texid == 0)
1218 {
1219 switch (type)
1220 {
1221 default: UNREACHABLE();
1222 case SAMPLER_2D: return mTexture2DZero;
1223 case SAMPLER_CUBE: return mTextureCubeMapZero;
1224 }
1225 }
1226
1227 return getTexture(texid);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001228}
1229
1230Framebuffer *Context::getFramebuffer()
1231{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001232 return getFramebuffer(mState.framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001233}
1234
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001235bool Context::getBooleanv(GLenum pname, GLboolean *params)
1236{
1237 switch (pname)
1238 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001239 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1240 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1241 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001242 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001243 params[0] = mState.colorMaskRed;
1244 params[1] = mState.colorMaskGreen;
1245 params[2] = mState.colorMaskBlue;
1246 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001247 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001248 case GL_CULL_FACE: *params = mState.cullFace;
1249 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
1250 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
1251 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
1252 case GL_SCISSOR_TEST: *params = mState.scissorTest;
1253 case GL_STENCIL_TEST: *params = mState.stencilTest;
1254 case GL_DEPTH_TEST: *params = mState.depthTest;
1255 case GL_BLEND: *params = mState.blend;
1256 case GL_DITHER: *params = mState.dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001257 default:
1258 return false;
1259 }
1260
1261 return true;
1262}
1263
1264bool Context::getFloatv(GLenum pname, GLfloat *params)
1265{
1266 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1267 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1268 // GetIntegerv as its native query function. As it would require conversion in any
1269 // case, this should make no difference to the calling application.
1270 switch (pname)
1271 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001272 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1273 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1274 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1275 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1276 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001277 case GL_ALIASED_LINE_WIDTH_RANGE:
1278 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1279 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1280 break;
1281 case GL_ALIASED_POINT_SIZE_RANGE:
1282 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
1283 params[1] = gl::ALIASED_POINT_SIZE_RANGE_MAX;
1284 break;
1285 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001286 params[0] = mState.zNear;
1287 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001288 break;
1289 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001290 params[0] = mState.colorClearValue.red;
1291 params[1] = mState.colorClearValue.green;
1292 params[2] = mState.colorClearValue.blue;
1293 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001294 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001295 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001296 params[0] = mState.blendColor.red;
1297 params[1] = mState.blendColor.green;
1298 params[2] = mState.blendColor.blue;
1299 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001300 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001301 default:
1302 return false;
1303 }
1304
1305 return true;
1306}
1307
1308bool Context::getIntegerv(GLenum pname, GLint *params)
1309{
1310 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1311 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1312 // GetIntegerv as its native query function. As it would require conversion in any
1313 // case, this should make no difference to the calling application. You may find it in
1314 // Context::getFloatv.
1315 switch (pname)
1316 {
1317 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1318 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1319 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
1320 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1321 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1322 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1323 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
1324 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
1325 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1326 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
1327 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
1328 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001329 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer; break;
1330 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer; break;
1331 case GL_FRAMEBUFFER_BINDING: *params = mState.framebuffer; break;
1332 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer; break;
1333 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1334 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1335 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1336 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1337 case GL_ACTIVE_TEXTURE: *params = mState.activeSampler; break;
1338 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1339 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1340 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1341 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1342 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1343 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1344 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1345 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1346 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1347 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1348 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1349 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1350 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1351 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1352 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1353 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1354 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1355 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1356 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1357 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1358 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1359 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001360 case GL_SUBPIXEL_BITS: *params = 4; break;
1361 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
1362 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
1363 case GL_SAMPLE_BUFFERS: *params = 0; break;
1364 case GL_SAMPLES: *params = 0; break;
1365 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1366 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1367 case GL_MAX_VIEWPORT_DIMS:
1368 {
1369 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
1370 params[0] = maxDimension;
1371 params[1] = maxDimension;
1372 }
1373 break;
1374 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001375 params[0] = mState.viewportX;
1376 params[1] = mState.viewportY;
1377 params[2] = mState.viewportWidth;
1378 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001379 break;
1380 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001381 params[0] = mState.scissorX;
1382 params[1] = mState.scissorY;
1383 params[2] = mState.scissorWidth;
1384 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001385 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001386 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1387 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001388 case GL_RED_BITS:
1389 case GL_GREEN_BITS:
1390 case GL_BLUE_BITS:
1391 case GL_ALPHA_BITS:
1392 {
1393 gl::Framebuffer *framebuffer = getFramebuffer();
1394 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1395
1396 if (colorbuffer)
1397 {
1398 switch (pname)
1399 {
1400 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1401 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1402 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1403 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1404 }
1405 }
1406 else
1407 {
1408 *params = 0;
1409 }
1410 }
1411 break;
1412 case GL_DEPTH_BITS:
1413 {
1414 gl::Framebuffer *framebuffer = getFramebuffer();
1415 gl::Depthbuffer *depthbuffer = framebuffer->getDepthbuffer();
1416
1417 if (depthbuffer)
1418 {
1419 *params = depthbuffer->getDepthSize();
1420 }
1421 else
1422 {
1423 *params = 0;
1424 }
1425 }
1426 break;
1427 case GL_STENCIL_BITS:
1428 {
1429 gl::Framebuffer *framebuffer = getFramebuffer();
1430 gl::Stencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1431
1432 if (stencilbuffer)
1433 {
1434 *params = stencilbuffer->getStencilSize();
1435 }
1436 else
1437 {
1438 *params = 0;
1439 }
1440 }
1441 break;
1442 case GL_TEXTURE_BINDING_2D:
1443 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001444 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001445 {
1446 error(GL_INVALID_OPERATION);
1447 return false;
1448 }
1449
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001450 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001451 }
1452 break;
1453 case GL_TEXTURE_BINDING_CUBE_MAP:
1454 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001455 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001456 {
1457 error(GL_INVALID_OPERATION);
1458 return false;
1459 }
1460
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001461 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler];
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001462 }
1463 break;
1464 default:
1465 return false;
1466 }
1467
1468 return true;
1469}
1470
1471bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1472{
1473 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1474 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1475 // to the fact that it is stored internally as a float, and so would require conversion
1476 // if returned from Context::getIntegerv. Since this conversion is already implemented
1477 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1478 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1479 // application.
1480 switch (pname)
1481 {
1482 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1483 case GL_SHADER_BINARY_FORMATS:
1484 {
1485 *type = GL_INT;
1486 *numParams = 0;
1487 }
1488 break;
1489 case GL_MAX_VERTEX_ATTRIBS:
1490 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1491 case GL_MAX_VARYING_VECTORS:
1492 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1493 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1494 case GL_MAX_TEXTURE_IMAGE_UNITS:
1495 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1496 case GL_MAX_RENDERBUFFER_SIZE:
1497 case GL_NUM_SHADER_BINARY_FORMATS:
1498 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1499 case GL_ARRAY_BUFFER_BINDING:
1500 case GL_FRAMEBUFFER_BINDING:
1501 case GL_RENDERBUFFER_BINDING:
1502 case GL_CURRENT_PROGRAM:
1503 case GL_PACK_ALIGNMENT:
1504 case GL_UNPACK_ALIGNMENT:
1505 case GL_GENERATE_MIPMAP_HINT:
1506 case GL_RED_BITS:
1507 case GL_GREEN_BITS:
1508 case GL_BLUE_BITS:
1509 case GL_ALPHA_BITS:
1510 case GL_DEPTH_BITS:
1511 case GL_STENCIL_BITS:
1512 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1513 case GL_CULL_FACE_MODE:
1514 case GL_FRONT_FACE:
1515 case GL_ACTIVE_TEXTURE:
1516 case GL_STENCIL_FUNC:
1517 case GL_STENCIL_VALUE_MASK:
1518 case GL_STENCIL_REF:
1519 case GL_STENCIL_FAIL:
1520 case GL_STENCIL_PASS_DEPTH_FAIL:
1521 case GL_STENCIL_PASS_DEPTH_PASS:
1522 case GL_STENCIL_BACK_FUNC:
1523 case GL_STENCIL_BACK_VALUE_MASK:
1524 case GL_STENCIL_BACK_REF:
1525 case GL_STENCIL_BACK_FAIL:
1526 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1527 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1528 case GL_DEPTH_FUNC:
1529 case GL_BLEND_SRC_RGB:
1530 case GL_BLEND_SRC_ALPHA:
1531 case GL_BLEND_DST_RGB:
1532 case GL_BLEND_DST_ALPHA:
1533 case GL_BLEND_EQUATION_RGB:
1534 case GL_BLEND_EQUATION_ALPHA:
1535 case GL_STENCIL_WRITEMASK:
1536 case GL_STENCIL_BACK_WRITEMASK:
1537 case GL_STENCIL_CLEAR_VALUE:
1538 case GL_SUBPIXEL_BITS:
1539 case GL_MAX_TEXTURE_SIZE:
1540 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1541 case GL_SAMPLE_BUFFERS:
1542 case GL_SAMPLES:
1543 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1544 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1545 case GL_TEXTURE_BINDING_2D:
1546 case GL_TEXTURE_BINDING_CUBE_MAP:
1547 {
1548 *type = GL_INT;
1549 *numParams = 1;
1550 }
1551 break;
1552 case GL_MAX_VIEWPORT_DIMS:
1553 {
1554 *type = GL_INT;
1555 *numParams = 2;
1556 }
1557 break;
1558 case GL_VIEWPORT:
1559 case GL_SCISSOR_BOX:
1560 {
1561 *type = GL_INT;
1562 *numParams = 4;
1563 }
1564 break;
1565 case GL_SHADER_COMPILER:
1566 case GL_SAMPLE_COVERAGE_INVERT:
1567 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001568 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1569 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1570 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1571 case GL_SAMPLE_COVERAGE:
1572 case GL_SCISSOR_TEST:
1573 case GL_STENCIL_TEST:
1574 case GL_DEPTH_TEST:
1575 case GL_BLEND:
1576 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001577 {
1578 *type = GL_BOOL;
1579 *numParams = 1;
1580 }
1581 break;
1582 case GL_COLOR_WRITEMASK:
1583 {
1584 *type = GL_BOOL;
1585 *numParams = 4;
1586 }
1587 break;
1588 case GL_POLYGON_OFFSET_FACTOR:
1589 case GL_POLYGON_OFFSET_UNITS:
1590 case GL_SAMPLE_COVERAGE_VALUE:
1591 case GL_DEPTH_CLEAR_VALUE:
1592 case GL_LINE_WIDTH:
1593 {
1594 *type = GL_FLOAT;
1595 *numParams = 1;
1596 }
1597 break;
1598 case GL_ALIASED_LINE_WIDTH_RANGE:
1599 case GL_ALIASED_POINT_SIZE_RANGE:
1600 case GL_DEPTH_RANGE:
1601 {
1602 *type = GL_FLOAT;
1603 *numParams = 2;
1604 }
1605 break;
1606 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001607 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001608 {
1609 *type = GL_FLOAT;
1610 *numParams = 4;
1611 }
1612 break;
1613 default:
1614 return false;
1615 }
1616
1617 return true;
1618}
1619
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001620// Applies the render target surface, depth stencil surface, viewport rectangle and
1621// scissor rectangle to the Direct3D 9 device
1622bool Context::applyRenderTarget(bool ignoreViewport)
1623{
1624 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001625
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001626 Framebuffer *framebufferObject = getFramebuffer();
1627
1628 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1629 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001630 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1631
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001632 return false;
1633 }
1634
1635 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
1636 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
1637
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001638 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
1639 if (renderTargetSerial != mAppliedRenderTargetSerial)
1640 {
1641 device->SetRenderTarget(0, renderTarget);
1642 mAppliedRenderTargetSerial = renderTargetSerial;
1643 }
1644
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001645 unsigned int depthbufferSerial = framebufferObject->getDepthbufferSerial();
1646 if (depthbufferSerial != mAppliedDepthbufferSerial)
1647 {
1648 device->SetDepthStencilSurface(depthStencil);
1649 mAppliedDepthbufferSerial = depthbufferSerial;
1650 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001651
1652 D3DVIEWPORT9 viewport;
1653 D3DSURFACE_DESC desc;
1654 renderTarget->GetDesc(&desc);
1655
1656 if (ignoreViewport)
1657 {
1658 viewport.X = 0;
1659 viewport.Y = 0;
1660 viewport.Width = desc.Width;
1661 viewport.Height = desc.Height;
1662 viewport.MinZ = 0.0f;
1663 viewport.MaxZ = 1.0f;
1664 }
1665 else
1666 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001667 viewport.X = std::max(mState.viewportX, 0);
1668 viewport.Y = std::max(mState.viewportY, 0);
1669 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1670 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1671 viewport.MinZ = clamp01(mState.zNear);
1672 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001673 }
1674
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001675 if (viewport.Width <= 0 || viewport.Height <= 0)
1676 {
1677 return false; // Nothing to render
1678 }
1679
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001680 device->SetViewport(&viewport);
1681
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001682 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001683 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001684 if (mState.scissorTest)
1685 {
1686 RECT rect = {mState.scissorX,
1687 mState.scissorY,
1688 mState.scissorX + mState.scissorWidth,
1689 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001690
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001691 device->SetScissorRect(&rect);
1692 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1693 }
1694 else
1695 {
1696 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1697 }
1698
1699 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001700 }
1701
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001702 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001703 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001704 Program *programObject = getCurrentProgram();
1705
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001706 GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001707 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001708 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001709
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001710 GLint window = programObject->getDxWindowLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001711 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1712 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1713 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001714 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1715
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001716 GLint depth = programObject->getDxDepthLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001717 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001718 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1719
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001720 GLint near = programObject->getDepthRangeNearLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001721 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001722
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001723 GLint far = programObject->getDepthRangeFarLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001724 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001725
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001726 GLint diff = programObject->getDepthRangeDiffLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001727 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001728 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001729 }
1730
1731 return true;
1732}
1733
1734// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001735void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001736{
1737 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001738 Program *programObject = getCurrentProgram();
1739
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001740 GLint frontCCW = programObject->getDxFrontCCWLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001741 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001742 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001743
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001744 GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001745 GLint alwaysFront = !isTriangleMode(drawMode);
1746 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1747
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001748 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001749 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001750 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001751 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001752 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001753 }
1754 else
1755 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001756 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001757 }
1758
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001759 mCullStateDirty = false;
1760 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001761
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001762 if (mDepthStateDirty)
1763 {
1764 if (mState.depthTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001765 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001766 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1767 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001768 }
1769 else
1770 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001771 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001772 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001773
1774 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001775 }
1776
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001777 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001778 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001779 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001780 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001781 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1782
1783 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1784 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1785 {
1786 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1787 }
1788 else
1789 {
1790 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1791 unorm<8>(mState.blendColor.alpha),
1792 unorm<8>(mState.blendColor.alpha),
1793 unorm<8>(mState.blendColor.alpha)));
1794 }
1795
1796 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1797 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1798 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1799
1800 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1801 mState.destBlendRGB != mState.destBlendAlpha ||
1802 mState.blendEquationRGB != mState.blendEquationAlpha)
1803 {
1804 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1805
1806 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1807 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1808 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
1809
1810 }
1811 else
1812 {
1813 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1814 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001815 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001816 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001817 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001818 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001819 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001820
1821 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001822 }
1823
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001824 if (mStencilStateDirty || mFrontFaceDirty)
1825 {
1826 if (mState.stencilTest && hasStencil())
1827 {
1828 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1829 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1830
1831 // FIXME: Unsupported by D3D9
1832 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1833 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1834 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1835 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1836 mState.stencilRef != mState.stencilBackRef ||
1837 mState.stencilMask != mState.stencilBackMask)
1838 {
1839 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1840 return error(GL_INVALID_OPERATION);
1841 }
1842
1843 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1844 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1845 es2dx::ConvertComparison(mState.stencilFunc));
1846
1847 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilRef); // FIXME: Clamp to range
1848 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
1849
1850 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1851 es2dx::ConvertStencilOp(mState.stencilFail));
1852 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1853 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1854 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1855 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1856
1857 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1858 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1859 es2dx::ConvertComparison(mState.stencilBackFunc));
1860
1861 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, mState.stencilBackRef); // FIXME: Clamp to range
1862 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
1863
1864 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1865 es2dx::ConvertStencilOp(mState.stencilBackFail));
1866 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1867 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1868 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1869 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1870 }
1871 else
1872 {
1873 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1874 }
1875
1876 mStencilStateDirty = false;
1877 }
1878
1879 if (mMaskStateDirty)
1880 {
1881 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1882 mState.colorMaskBlue, mState.colorMaskAlpha));
1883 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1884
1885 mMaskStateDirty = false;
1886 }
1887
1888 if (mPolygonOffsetStateDirty)
1889 {
1890 if (mState.polygonOffsetFill)
1891 {
1892 gl::Depthbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
1893 if (depthbuffer)
1894 {
1895 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1896 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1897 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1898 }
1899 }
1900 else
1901 {
1902 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1903 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1904 }
1905
1906 mPolygonOffsetStateDirty = false;
1907 }
1908
1909 if (mConfig->mMultiSample != 0 && mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001910 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001911 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001912 {
1913 FIXME("Sample alpha to coverage is unimplemented.");
1914 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001915
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001916 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001917 {
1918 FIXME("Sample coverage is unimplemented.");
1919 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001920
1921 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001922 }
1923
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001924 if (mDitherStateDirty)
1925 {
1926 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
1927
1928 mDitherStateDirty = false;
1929 }
1930
1931 mFrontFaceDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001932}
1933
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001934// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001935void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001936{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001937 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001938 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001939 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001940 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001941 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001942 }
1943 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001944}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001945
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001946void Context::applyVertexBuffer(GLint first, GLsizei count)
1947{
1948 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1949
1950 mVertexDataManager->preRenderValidate(first, count, translated);
1951
1952 lookupAttributeMapping(translated);
1953
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001954 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001955}
1956
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001957void Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001958{
1959 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1960
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00001961 mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001962
1963 lookupAttributeMapping(translated);
1964
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00001965 mBufferBackEnd->setupAttributesPreDraw(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001966}
1967
1968// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001969GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001970{
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001971 GLenum error = mIndexDataManager->preRenderValidate(mode, type, count, getBuffer(mState.elementArrayBuffer), indices, indexInfo);
1972
1973 if (error == GL_NO_ERROR)
1974 {
1975 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
1976 }
1977
1978 return error;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001979}
1980
1981// Applies the shaders and shader constants to the Direct3D 9 device
1982void Context::applyShaders()
1983{
1984 IDirect3DDevice9 *device = getDevice();
1985 Program *programObject = getCurrentProgram();
1986 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1987 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1988
1989 device->SetVertexShader(vertexShader);
1990 device->SetPixelShader(pixelShader);
1991
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001992 if (programObject->getSerial() != mAppliedProgram)
1993 {
1994 programObject->dirtyAllUniforms();
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001995 programObject->dirtyAllSamplers();
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001996 mAppliedProgram = programObject->getSerial();
1997 }
1998
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001999 programObject->applyUniforms();
2000}
2001
2002// Applies the textures and sampler states to the Direct3D 9 device
2003void Context::applyTextures()
2004{
2005 IDirect3DDevice9 *device = getDevice();
2006 Program *programObject = getCurrentProgram();
2007
2008 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
2009 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002010 int textureUnit = programObject->getSamplerMapping(sampler);
2011 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002012 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002013 SamplerType textureType = programObject->getSamplerType(sampler);
2014
2015 Texture *texture = getSamplerTexture(textureUnit, textureType);
2016
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002017 if (programObject->isSamplerDirty(sampler) || texture->isDirty())
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002018 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002019 if (texture->isComplete())
2020 {
2021 GLenum wrapS = texture->getWrapS();
2022 GLenum wrapT = texture->getWrapT();
2023 GLenum minFilter = texture->getMinFilter();
2024 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002025
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002026 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
2027 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002028
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002029 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
2030 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
2031 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
2032 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
2033 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002034
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002035 device->SetTexture(sampler, texture->getTexture());
2036 }
2037 else
2038 {
2039 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
2040 }
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002041 }
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002042
2043 programObject->setSamplerDirty(sampler, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002044 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002045 else
2046 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002047 if (programObject->isSamplerDirty(sampler))
2048 {
2049 device->SetTexture(sampler, NULL);
2050 programObject->setSamplerDirty(sampler, false);
2051 }
2052 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002053 }
2054}
2055
2056void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
2057{
2058 Framebuffer *framebuffer = getFramebuffer();
2059 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
2060 IDirect3DDevice9 *device = getDevice();
2061
2062 D3DSURFACE_DESC desc;
2063 renderTarget->GetDesc(&desc);
2064
2065 IDirect3DSurface9 *systemSurface;
2066 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
2067
2068 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2069 {
2070 return error(GL_OUT_OF_MEMORY);
2071 }
2072
2073 ASSERT(SUCCEEDED(result));
2074
2075 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
2076 {
2077 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
2078 }
2079
2080 result = device->GetRenderTargetData(renderTarget, systemSurface);
2081
2082 if (result == D3DERR_DRIVERINTERNALERROR)
2083 {
2084 systemSurface->Release();
2085
2086 return error(GL_OUT_OF_MEMORY);
2087 }
2088
2089 if (FAILED(result))
2090 {
2091 UNREACHABLE();
2092 systemSurface->Release();
2093
2094 return; // No sensible error to generate
2095 }
2096
2097 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00002098 RECT rect = {std::max(x, 0),
2099 std::max(y, 0),
2100 std::min(x + width, (int)desc.Width),
2101 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002102
2103 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
2104
2105 if (FAILED(result))
2106 {
2107 UNREACHABLE();
2108 systemSurface->Release();
2109
2110 return; // No sensible error to generate
2111 }
2112
2113 unsigned char *source = (unsigned char*)lock.pBits;
2114 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002115 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002116
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002117 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002118
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002119 for (int j = 0; j < rect.bottom - rect.top; j++)
2120 {
2121 for (int i = 0; i < rect.right - rect.left; i++)
2122 {
2123 float r;
2124 float g;
2125 float b;
2126 float a;
2127
2128 switch (desc.Format)
2129 {
2130 case D3DFMT_R5G6B5:
2131 {
2132 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2133
2134 a = 1.0f;
2135 b = (rgb & 0x001F) * (1.0f / 0x001F);
2136 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2137 r = (rgb & 0xF800) * (1.0f / 0xF800);
2138 }
2139 break;
2140 case D3DFMT_X1R5G5B5:
2141 {
2142 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2143
2144 a = 1.0f;
2145 b = (xrgb & 0x001F) * (1.0f / 0x001F);
2146 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
2147 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
2148 }
2149 break;
2150 case D3DFMT_A1R5G5B5:
2151 {
2152 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2153
2154 a = (argb & 0x8000) ? 1.0f : 0.0f;
2155 b = (argb & 0x001F) * (1.0f / 0x001F);
2156 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2157 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2158 }
2159 break;
2160 case D3DFMT_A8R8G8B8:
2161 {
2162 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2163
2164 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2165 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2166 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2167 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2168 }
2169 break;
2170 case D3DFMT_X8R8G8B8:
2171 {
2172 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2173
2174 a = 1.0f;
2175 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2176 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2177 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2178 }
2179 break;
2180 case D3DFMT_A2R10G10B10:
2181 {
2182 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2183
2184 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2185 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2186 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2187 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2188 }
2189 break;
2190 default:
2191 UNIMPLEMENTED(); // FIXME
2192 UNREACHABLE();
2193 }
2194
2195 switch (format)
2196 {
2197 case GL_RGBA:
2198 switch (type)
2199 {
2200 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002201 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2202 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2203 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2204 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002205 break;
2206 default: UNREACHABLE();
2207 }
2208 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002209 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002210 switch (type)
2211 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002212 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002213 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2214 ((unsigned short)(31 * b + 0.5f) << 0) |
2215 ((unsigned short)(63 * g + 0.5f) << 5) |
2216 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002217 break;
2218 default: UNREACHABLE();
2219 }
2220 break;
2221 default: UNREACHABLE();
2222 }
2223 }
2224 }
2225
2226 systemSurface->UnlockRect();
2227
2228 systemSurface->Release();
2229}
2230
2231void Context::clear(GLbitfield mask)
2232{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002233 Framebuffer *framebufferObject = getFramebuffer();
2234
2235 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2236 {
2237 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2238
2239 return;
2240 }
2241
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002242 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002243 IDirect3DDevice9 *device = getDevice();
2244 DWORD flags = 0;
2245
2246 if (mask & GL_COLOR_BUFFER_BIT)
2247 {
2248 mask &= ~GL_COLOR_BUFFER_BIT;
2249 flags |= D3DCLEAR_TARGET;
2250 }
2251
2252 if (mask & GL_DEPTH_BUFFER_BIT)
2253 {
2254 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002255 if (mState.depthMask)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002256 {
2257 flags |= D3DCLEAR_ZBUFFER;
2258 }
2259 }
2260
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002261 IDirect3DSurface9 *depthStencil = framebufferObject->getDepthStencil();
2262
2263 GLuint stencilUnmasked = 0x0;
2264
2265 if ((mask & GL_STENCIL_BUFFER_BIT) && depthStencil)
2266 {
2267 D3DSURFACE_DESC desc;
2268 depthStencil->GetDesc(&desc);
2269
2270 mask &= ~GL_STENCIL_BUFFER_BIT;
2271 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2272 stencilUnmasked = (0x1 << stencilSize) - 1;
2273
2274 if (stencilUnmasked != 0x0)
2275 {
2276 flags |= D3DCLEAR_STENCIL;
2277 }
2278 }
2279
2280 if (mask != 0)
2281 {
2282 return error(GL_INVALID_VALUE);
2283 }
2284
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002285 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2286 {
2287 return;
2288 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002289
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002290 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2291 unorm<8>(mState.colorClearValue.red),
2292 unorm<8>(mState.colorClearValue.green),
2293 unorm<8>(mState.colorClearValue.blue));
2294 float depth = clamp01(mState.depthClearValue);
2295 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002296
2297 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2298
2299 D3DSURFACE_DESC desc;
2300 renderTarget->GetDesc(&desc);
2301
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002302 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002303
2304 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002305 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002306 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002307 !(mState.colorMaskRed && mState.colorMaskGreen &&
2308 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002309
2310 if (needMaskedColorClear || needMaskedStencilClear)
2311 {
2312 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2313 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2314 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2315 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2316 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2317 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2318 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2319 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2320
2321 if (flags & D3DCLEAR_TARGET)
2322 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002323 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2324 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2325 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2326 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002327 }
2328 else
2329 {
2330 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2331 }
2332
2333 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2334 {
2335 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2336 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2337 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2338 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002339 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002340 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002341 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2342 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
2343 }
2344 else
2345 {
2346 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2347 }
2348
2349 device->SetPixelShader(NULL);
2350 device->SetVertexShader(NULL);
2351 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2352
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002353 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002354 {
2355 float x, y, z, w;
2356 D3DCOLOR diffuse;
2357 };
2358
2359 Vertex quad[4];
2360 quad[0].x = 0.0f;
2361 quad[0].y = (float)desc.Height;
2362 quad[0].z = 0.0f;
2363 quad[0].w = 1.0f;
2364 quad[0].diffuse = color;
2365
2366 quad[1].x = (float)desc.Width;
2367 quad[1].y = (float)desc.Height;
2368 quad[1].z = 0.0f;
2369 quad[1].w = 1.0f;
2370 quad[1].diffuse = color;
2371
2372 quad[2].x = 0.0f;
2373 quad[2].y = 0.0f;
2374 quad[2].z = 0.0f;
2375 quad[2].w = 1.0f;
2376 quad[2].diffuse = color;
2377
2378 quad[3].x = (float)desc.Width;
2379 quad[3].y = 0.0f;
2380 quad[3].z = 0.0f;
2381 quad[3].w = 1.0f;
2382 quad[3].diffuse = color;
2383
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002384 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002385 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002386
2387 if (flags & D3DCLEAR_ZBUFFER)
2388 {
2389 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2390 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2391 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2392 }
2393 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002394 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002395 {
2396 device->Clear(0, NULL, flags, color, depth, stencil);
2397 }
2398}
2399
2400void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2401{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002402 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002403 {
2404 return error(GL_INVALID_OPERATION);
2405 }
2406
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002407 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002408 IDirect3DDevice9 *device = getDevice();
2409 D3DPRIMITIVETYPE primitiveType;
2410 int primitiveCount;
2411
2412 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2413 return error(GL_INVALID_ENUM);
2414
2415 if (primitiveCount <= 0)
2416 {
2417 return;
2418 }
2419
2420 if (!applyRenderTarget(false))
2421 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002422 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002423 }
2424
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002425 applyState(mode);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002426 applyVertexBuffer(first, count);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002427 applyShaders();
2428 applyTextures();
2429
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002430 if (!getCurrentProgram()->validateSamplers())
2431 {
2432 return error(GL_INVALID_OPERATION);
2433 }
2434
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002435 if (!cullSkipsDraw(mode))
2436 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002437 display->startScene();
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002438 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002439 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002440}
2441
2442void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2443{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002444 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002445 {
2446 return error(GL_INVALID_OPERATION);
2447 }
2448
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002449 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002450 {
2451 return error(GL_INVALID_OPERATION);
2452 }
2453
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002454 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002455 IDirect3DDevice9 *device = getDevice();
2456 D3DPRIMITIVETYPE primitiveType;
2457 int primitiveCount;
2458
2459 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2460 return error(GL_INVALID_ENUM);
2461
2462 if (primitiveCount <= 0)
2463 {
2464 return;
2465 }
2466
2467 if (!applyRenderTarget(false))
2468 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002469 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002470 }
2471
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002472 applyState(mode);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002473
2474 TranslatedIndexData indexInfo;
2475 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2476 if (err != GL_NO_ERROR)
2477 {
2478 return error(err);
2479 }
2480
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +00002481 applyVertexBuffer(indexInfo);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002482 applyShaders();
2483 applyTextures();
2484
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002485 if (!getCurrentProgram()->validateSamplers())
2486 {
2487 return error(GL_INVALID_OPERATION);
2488 }
2489
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002490 if (!cullSkipsDraw(mode))
2491 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002492 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002493 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 +00002494 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002495}
2496
2497void Context::finish()
2498{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002499 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002500 IDirect3DDevice9 *device = getDevice();
2501 IDirect3DQuery9 *occlusionQuery = NULL;
2502
2503 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2504
2505 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2506 {
2507 return error(GL_OUT_OF_MEMORY);
2508 }
2509
2510 ASSERT(SUCCEEDED(result));
2511
2512 if (occlusionQuery)
2513 {
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002514 IDirect3DStateBlock9 *savedState = NULL;
2515 device->CreateStateBlock(D3DSBT_ALL, &savedState);
2516
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002517 occlusionQuery->Issue(D3DISSUE_BEGIN);
2518
2519 // Render something outside the render target
2520 device->SetPixelShader(NULL);
2521 device->SetVertexShader(NULL);
2522 device->SetFVF(D3DFVF_XYZRHW);
2523 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002524 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002525 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002526
2527 occlusionQuery->Issue(D3DISSUE_END);
2528
2529 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2530 {
2531 // Keep polling, but allow other threads to do something useful first
2532 Sleep(0);
2533 }
2534
2535 occlusionQuery->Release();
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002536
2537 if (savedState)
2538 {
2539 savedState->Apply();
2540 savedState->Release();
2541 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002542 }
2543}
2544
2545void Context::flush()
2546{
2547 IDirect3DDevice9 *device = getDevice();
2548 IDirect3DQuery9 *eventQuery = NULL;
2549
2550 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2551
2552 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2553 {
2554 return error(GL_OUT_OF_MEMORY);
2555 }
2556
2557 ASSERT(SUCCEEDED(result));
2558
2559 if (eventQuery)
2560 {
2561 eventQuery->Issue(D3DISSUE_END);
2562
2563 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2564 {
2565 // Keep polling, but allow other threads to do something useful first
2566 Sleep(0);
2567 }
2568
2569 eventQuery->Release();
2570 }
2571}
2572
2573void Context::recordInvalidEnum()
2574{
2575 mInvalidEnum = true;
2576}
2577
2578void Context::recordInvalidValue()
2579{
2580 mInvalidValue = true;
2581}
2582
2583void Context::recordInvalidOperation()
2584{
2585 mInvalidOperation = true;
2586}
2587
2588void Context::recordOutOfMemory()
2589{
2590 mOutOfMemory = true;
2591}
2592
2593void Context::recordInvalidFramebufferOperation()
2594{
2595 mInvalidFramebufferOperation = true;
2596}
2597
2598// Get one of the recorded errors and clear its flag, if any.
2599// [OpenGL ES 2.0.24] section 2.5 page 13.
2600GLenum Context::getError()
2601{
2602 if (mInvalidEnum)
2603 {
2604 mInvalidEnum = false;
2605
2606 return GL_INVALID_ENUM;
2607 }
2608
2609 if (mInvalidValue)
2610 {
2611 mInvalidValue = false;
2612
2613 return GL_INVALID_VALUE;
2614 }
2615
2616 if (mInvalidOperation)
2617 {
2618 mInvalidOperation = false;
2619
2620 return GL_INVALID_OPERATION;
2621 }
2622
2623 if (mOutOfMemory)
2624 {
2625 mOutOfMemory = false;
2626
2627 return GL_OUT_OF_MEMORY;
2628 }
2629
2630 if (mInvalidFramebufferOperation)
2631 {
2632 mInvalidFramebufferOperation = false;
2633
2634 return GL_INVALID_FRAMEBUFFER_OPERATION;
2635 }
2636
2637 return GL_NO_ERROR;
2638}
2639
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002640const char *Context::getPixelShaderProfile()
2641{
2642 return mPsProfile;
2643}
2644
2645const char *Context::getVertexShaderProfile()
2646{
2647 return mVsProfile;
2648}
2649
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002650void Context::detachBuffer(GLuint buffer)
2651{
2652 // [OpenGL ES 2.0.24] section 2.9 page 22:
2653 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2654 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2655
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002656 if (mState.arrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002657 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002658 mState.arrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002659 }
2660
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002661 if (mState.elementArrayBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002662 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002663 mState.elementArrayBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002664 }
2665
2666 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2667 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002668 if (mState.vertexAttribute[attribute].mBoundBuffer == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002669 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002670 mState.vertexAttribute[attribute].mBoundBuffer = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002671 }
2672 }
2673}
2674
2675void Context::detachTexture(GLuint texture)
2676{
2677 // [OpenGL ES 2.0.24] section 3.8 page 84:
2678 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2679 // rebound to texture object zero
2680
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002681 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002682 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002683 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002684 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002685 if (mState.samplerTexture[type][sampler] == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002686 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002687 mState.samplerTexture[type][sampler] = 0;
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002688 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002689 }
2690 }
2691
2692 // [OpenGL ES 2.0.24] section 4.4 page 112:
2693 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2694 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2695 // image was attached in the currently bound framebuffer.
2696
2697 Framebuffer *framebuffer = getFramebuffer();
2698
2699 if (framebuffer)
2700 {
2701 framebuffer->detachTexture(texture);
2702 }
2703}
2704
2705void Context::detachFramebuffer(GLuint framebuffer)
2706{
2707 // [OpenGL ES 2.0.24] section 4.4 page 107:
2708 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2709 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2710
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002711 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002712 {
2713 bindFramebuffer(0);
2714 }
2715}
2716
2717void Context::detachRenderbuffer(GLuint renderbuffer)
2718{
2719 // [OpenGL ES 2.0.24] section 4.4 page 109:
2720 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2721 // had been executed with the target RENDERBUFFER and name of zero.
2722
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002723 if (mState.renderbuffer == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002724 {
2725 bindRenderbuffer(0);
2726 }
2727
2728 // [OpenGL ES 2.0.24] section 4.4 page 111:
2729 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2730 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2731 // point to which this image was attached in the currently bound framebuffer.
2732
2733 Framebuffer *framebuffer = getFramebuffer();
2734
2735 if (framebuffer)
2736 {
2737 framebuffer->detachRenderbuffer(renderbuffer);
2738 }
2739}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002740
2741Texture *Context::getIncompleteTexture(SamplerType type)
2742{
2743 Texture *t = mIncompleteTextures[type];
2744
2745 if (t == NULL)
2746 {
2747 static const GLubyte color[] = { 0, 0, 0, 255 };
2748
2749 switch (type)
2750 {
2751 default:
2752 UNREACHABLE();
2753 // default falls through to SAMPLER_2D
2754
2755 case SAMPLER_2D:
2756 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002757 Texture2D *incomplete2d = new Texture2D(this);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002758 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002759 t = incomplete2d;
2760 }
2761 break;
2762
2763 case SAMPLER_CUBE:
2764 {
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +00002765 TextureCubeMap *incompleteCube = new TextureCubeMap(this);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002766
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002767 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2768 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2769 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2770 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2771 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2772 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002773
2774 t = incompleteCube;
2775 }
2776 break;
2777 }
2778
2779 mIncompleteTextures[type] = t;
2780 }
2781
2782 return t;
2783}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002784
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002785bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002786{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002787 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002788}
2789
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002790bool Context::isTriangleMode(GLenum drawMode)
2791{
2792 switch (drawMode)
2793 {
2794 case GL_TRIANGLES:
2795 case GL_TRIANGLE_FAN:
2796 case GL_TRIANGLE_STRIP:
2797 return true;
2798 case GL_POINTS:
2799 case GL_LINES:
2800 case GL_LINE_LOOP:
2801 case GL_LINE_STRIP:
2802 return false;
2803 default: UNREACHABLE();
2804 }
2805
2806 return false;
2807}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002808
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002809bool Context::hasStencil()
2810{
2811 Framebuffer *framebufferObject = getFramebuffer();
2812
2813 if (framebufferObject)
2814 {
2815 Stencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
2816
2817 if (stencilbufferObject)
2818 {
2819 return stencilbufferObject->getStencilSize() > 0;
2820 }
2821 }
2822
2823 return false;
2824}
2825
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002826void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2827{
2828 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2829
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002830 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2831 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2832 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2833 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002834
2835 mVertexDataManager->dirtyCurrentValues();
2836}
2837
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002838void Context::initExtensionString()
2839{
2840 if (mBufferBackEnd->supportIntIndices())
2841 {
2842 mExtensionString += "GL_OES_element_index_uint ";
2843 }
2844
2845 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2846 if (end != std::string::npos)
2847 {
2848 mExtensionString.resize(end+1);
2849 }
2850}
2851
2852const char *Context::getExtensionString() const
2853{
2854 return mExtensionString.c_str();
2855}
2856
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002857}
2858
2859extern "C"
2860{
2861gl::Context *glCreateContext(const egl::Config *config)
2862{
2863 return new gl::Context(config);
2864}
2865
2866void glDestroyContext(gl::Context *context)
2867{
2868 delete context;
2869
2870 if (context == gl::getContext())
2871 {
2872 gl::makeCurrent(NULL, NULL, NULL);
2873 }
2874}
2875
2876void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2877{
2878 gl::makeCurrent(context, display, surface);
2879}
2880
2881gl::Context *glGetCurrentContext()
2882{
2883 return gl::getContext();
2884}
2885}