blob: 2eb592eaddeacc1087a5df2bd4068dc9847120b4 [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"
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000020#include "libGLESv2/ResourceManager.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000021#include "libGLESv2/Buffer.h"
22#include "libGLESv2/FrameBuffer.h"
23#include "libGLESv2/Program.h"
24#include "libGLESv2/RenderBuffer.h"
25#include "libGLESv2/Shader.h"
26#include "libGLESv2/Texture.h"
27#include "libGLESv2/geometry/backend.h"
28#include "libGLESv2/geometry/VertexDataManager.h"
29#include "libGLESv2/geometry/IndexDataManager.h"
30#include "libGLESv2/geometry/dx9.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031
daniel@transgaming.com86487c22010-03-11 19:41:43 +000032#undef near
33#undef far
34
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000035namespace gl
36{
daniel@transgaming.com0d25b002010-07-28 19:21:07 +000037Context::Context(const egl::Config *config, const gl::Context *shareContext)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000038 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000039{
40 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
daniel@transgaming.com092bd482010-05-12 03:39:36 +000041
daniel@transgaming.com428d1582010-05-04 03:35:25 +000042 mState.depthClearValue = 1.0f;
43 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000044
daniel@transgaming.com428d1582010-05-04 03:35:25 +000045 mState.cullFace = false;
46 mState.cullMode = GL_BACK;
47 mState.frontFace = GL_CCW;
48 mState.depthTest = false;
49 mState.depthFunc = GL_LESS;
50 mState.blend = false;
51 mState.sourceBlendRGB = GL_ONE;
52 mState.sourceBlendAlpha = GL_ONE;
53 mState.destBlendRGB = GL_ZERO;
54 mState.destBlendAlpha = GL_ZERO;
55 mState.blendEquationRGB = GL_FUNC_ADD;
56 mState.blendEquationAlpha = GL_FUNC_ADD;
57 mState.blendColor.red = 0;
58 mState.blendColor.green = 0;
59 mState.blendColor.blue = 0;
60 mState.blendColor.alpha = 0;
61 mState.stencilTest = false;
62 mState.stencilFunc = GL_ALWAYS;
63 mState.stencilRef = 0;
64 mState.stencilMask = -1;
65 mState.stencilWritemask = -1;
66 mState.stencilBackFunc = GL_ALWAYS;
67 mState.stencilBackRef = 0;
68 mState.stencilBackMask = - 1;
69 mState.stencilBackWritemask = -1;
70 mState.stencilFail = GL_KEEP;
71 mState.stencilPassDepthFail = GL_KEEP;
72 mState.stencilPassDepthPass = GL_KEEP;
73 mState.stencilBackFail = GL_KEEP;
74 mState.stencilBackPassDepthFail = GL_KEEP;
75 mState.stencilBackPassDepthPass = GL_KEEP;
76 mState.polygonOffsetFill = false;
77 mState.polygonOffsetFactor = 0.0f;
78 mState.polygonOffsetUnits = 0.0f;
79 mState.sampleAlphaToCoverage = false;
80 mState.sampleCoverage = false;
81 mState.sampleCoverageValue = 1.0f;
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +000082 mState.sampleCoverageInvert = false;
daniel@transgaming.com428d1582010-05-04 03:35:25 +000083 mState.scissorTest = false;
84 mState.dither = true;
85 mState.generateMipmapHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000086
daniel@transgaming.com428d1582010-05-04 03:35:25 +000087 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000088
daniel@transgaming.com428d1582010-05-04 03:35:25 +000089 mState.viewportX = 0;
90 mState.viewportY = 0;
91 mState.viewportWidth = config->mDisplayMode.Width;
92 mState.viewportHeight = config->mDisplayMode.Height;
93 mState.zNear = 0.0f;
94 mState.zFar = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095
daniel@transgaming.com428d1582010-05-04 03:35:25 +000096 mState.scissorX = 0;
97 mState.scissorY = 0;
98 mState.scissorWidth = config->mDisplayMode.Width;
99 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000101 mState.colorMaskRed = true;
102 mState.colorMaskGreen = true;
103 mState.colorMaskBlue = true;
104 mState.colorMaskAlpha = true;
105 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106
daniel@transgaming.com0d25b002010-07-28 19:21:07 +0000107 if (shareContext != NULL)
108 {
109 mResourceManager = shareContext->mResourceManager;
110 mResourceManager->addRef();
111 }
112 else
113 {
114 mResourceManager = new ResourceManager();
115 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000116
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000117 // [OpenGL ES 2.0.24] section 3.7 page 83:
118 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
119 // and cube map texture state vectors respectively associated with them.
120 // In order that access to these initial textures not be lost, they are treated as texture
121 // objects all of whose names are 0.
122
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000123 mTexture2DZero = new Texture2D(0);
124 mTextureCubeMapZero = new TextureCubeMap(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125
126 mColorbufferZero = NULL;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000127 mDepthStencilbufferZero = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000128
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000129 mState.activeSampler = 0;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000130 bindArrayBuffer(0);
131 bindElementArrayBuffer(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000132 bindTextureCubeMap(0);
133 bindTexture2D(0);
134 bindFramebuffer(0);
135 bindRenderbuffer(0);
136
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000137 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000138 {
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000139 mIncompleteTextures[type] = NULL;
140 }
141
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000142 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000143
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000144 mState.packAlignment = 4;
145 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000146
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000147 mBufferBackEnd = NULL;
148 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000149 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000150 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000151
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000152 mInvalidEnum = false;
153 mInvalidValue = false;
154 mInvalidOperation = false;
155 mOutOfMemory = false;
156 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000157
158 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000159
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000160 mMaskedClearSavedState = NULL;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000161 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162}
163
164Context::~Context()
165{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000166 if (mState.currentProgram != 0)
167 {
168 Program *programObject = mResourceManager->getProgram(mState.currentProgram);
169 if (programObject)
170 {
171 programObject->release();
172 }
173 mState.currentProgram = 0;
174 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000176 while (!mFramebufferMap.empty())
177 {
178 deleteFramebuffer(mFramebufferMap.begin()->first);
179 }
180
181 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
182 {
183 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
184 {
185 mState.samplerTexture[type][sampler].set(NULL);
186 }
187 }
188
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000189 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
190 {
191 delete mIncompleteTextures[type];
192 }
193
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000194 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
195 {
196 mState.vertexAttribute[i].mBoundBuffer.set(NULL);
197 }
198
199 mState.arrayBuffer.set(NULL);
200 mState.elementArrayBuffer.set(NULL);
201 mState.texture2D.set(NULL);
202 mState.textureCubeMap.set(NULL);
203 mState.renderbuffer.set(NULL);
204
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000205 delete mTexture2DZero;
206 delete mTextureCubeMapZero;
207
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000208 delete mBufferBackEnd;
209 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000210 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000211 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000212
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000213 if (mMaskedClearSavedState)
214 {
215 mMaskedClearSavedState->Release();
216 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000217
daniel@transgaming.com0d25b002010-07-28 19:21:07 +0000218 mResourceManager->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219}
220
221void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
222{
223 IDirect3DDevice9 *device = display->getDevice();
224
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000225 if (!mHasBeenCurrent)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000226 {
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000227 mDeviceCaps = display->getDeviceCaps();
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000228
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000229 mBufferBackEnd = new Dx9BackEnd(this, device);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000230 mVertexDataManager = new VertexDataManager(this, mBufferBackEnd);
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000231 mIndexDataManager = new IndexDataManager(this, mBufferBackEnd);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000232 mBlit = new Blit(this);
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000233
234 initExtensionString();
235
236 mState.viewportX = 0;
237 mState.viewportY = 0;
238 mState.viewportWidth = surface->getWidth();
239 mState.viewportHeight = surface->getHeight();
240
241 mState.scissorX = 0;
242 mState.scissorY = 0;
243 mState.scissorWidth = surface->getWidth();
244 mState.scissorHeight = surface->getHeight();
245
246 mHasBeenCurrent = true;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000247 }
248
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
250 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000251 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000254 DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000255 Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256
257 setFramebufferZero(framebufferZero);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258
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
daniel@transgaming.combe5a0862010-07-28 19:20:37 +0000266 mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000267
268 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269}
270
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000271// 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 +0000272void Context::markAllStateDirty()
273{
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000274 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000275 mAppliedDepthbufferSerial = 0;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000276 mAppliedProgram = 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000277
278 mClearStateDirty = true;
279 mCullStateDirty = true;
280 mDepthStateDirty = true;
281 mMaskStateDirty = true;
282 mBlendStateDirty = true;
283 mStencilStateDirty = true;
284 mPolygonOffsetStateDirty = true;
285 mScissorStateDirty = true;
286 mSampleStateDirty = true;
287 mDitherStateDirty = true;
daniel@transgaming.com0d25b002010-07-28 19:21:07 +0000288 mFrontFaceDirty = true;
289
290 if (mBufferBackEnd != NULL)
291 {
292 mBufferBackEnd->invalidate();
293 }
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000294}
295
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000296void Context::setClearColor(float red, float green, float blue, float alpha)
297{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000298 mState.colorClearValue.red = red;
299 mState.colorClearValue.green = green;
300 mState.colorClearValue.blue = blue;
301 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302}
303
304void Context::setClearDepth(float depth)
305{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000306 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000307}
308
309void Context::setClearStencil(int stencil)
310{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000311 mState.stencilClearValue = stencil;
312}
313
314void Context::setCullFace(bool enabled)
315{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000316 if (mState.cullFace != enabled)
317 {
318 mState.cullFace = enabled;
319 mCullStateDirty = true;
320 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000321}
322
323bool Context::isCullFaceEnabled() const
324{
325 return mState.cullFace;
326}
327
328void Context::setCullMode(GLenum mode)
329{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000330 if (mState.cullMode != mode)
331 {
332 mState.cullMode = mode;
333 mCullStateDirty = true;
334 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000335}
336
337void Context::setFrontFace(GLenum front)
338{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000339 if (mState.frontFace != front)
340 {
341 mState.frontFace = front;
342 mFrontFaceDirty = true;
343 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000344}
345
346void Context::setDepthTest(bool enabled)
347{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000348 if (mState.depthTest != enabled)
349 {
350 mState.depthTest = enabled;
351 mDepthStateDirty = true;
352 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000353}
354
355bool Context::isDepthTestEnabled() const
356{
357 return mState.depthTest;
358}
359
360void Context::setDepthFunc(GLenum depthFunc)
361{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000362 if (mState.depthFunc != depthFunc)
363 {
364 mState.depthFunc = depthFunc;
365 mDepthStateDirty = true;
366 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000367}
368
369void Context::setDepthRange(float zNear, float zFar)
370{
371 mState.zNear = zNear;
372 mState.zFar = zFar;
373}
374
375void Context::setBlend(bool enabled)
376{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000377 if (mState.blend != enabled)
378 {
379 mState.blend = enabled;
380 mBlendStateDirty = true;
381 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000382}
383
384bool Context::isBlendEnabled() const
385{
386 return mState.blend;
387}
388
389void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
390{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000391 if (mState.sourceBlendRGB != sourceRGB ||
392 mState.sourceBlendAlpha != sourceAlpha ||
393 mState.destBlendRGB != destRGB ||
394 mState.destBlendAlpha != destAlpha)
395 {
396 mState.sourceBlendRGB = sourceRGB;
397 mState.destBlendRGB = destRGB;
398 mState.sourceBlendAlpha = sourceAlpha;
399 mState.destBlendAlpha = destAlpha;
400 mBlendStateDirty = true;
401 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000402}
403
404void Context::setBlendColor(float red, float green, float blue, float alpha)
405{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000406 if (mState.blendColor.red != red ||
407 mState.blendColor.green != green ||
408 mState.blendColor.blue != blue ||
409 mState.blendColor.alpha != alpha)
410 {
411 mState.blendColor.red = red;
412 mState.blendColor.green = green;
413 mState.blendColor.blue = blue;
414 mState.blendColor.alpha = alpha;
415 mBlendStateDirty = true;
416 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000417}
418
419void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
420{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000421 if (mState.blendEquationRGB != rgbEquation ||
422 mState.blendEquationAlpha != alphaEquation)
423 {
424 mState.blendEquationRGB = rgbEquation;
425 mState.blendEquationAlpha = alphaEquation;
426 mBlendStateDirty = true;
427 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000428}
429
430void Context::setStencilTest(bool enabled)
431{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000432 if (mState.stencilTest != enabled)
433 {
434 mState.stencilTest = enabled;
435 mStencilStateDirty = true;
436 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000437}
438
439bool Context::isStencilTestEnabled() const
440{
441 return mState.stencilTest;
442}
443
444void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
445{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000446 if (mState.stencilFunc != stencilFunc ||
447 mState.stencilRef != stencilRef ||
448 mState.stencilMask != stencilMask)
449 {
450 mState.stencilFunc = stencilFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000451 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000452 mState.stencilMask = stencilMask;
453 mStencilStateDirty = true;
454 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000455}
456
457void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
458{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000459 if (mState.stencilBackFunc != stencilBackFunc ||
460 mState.stencilBackRef != stencilBackRef ||
461 mState.stencilBackMask != stencilBackMask)
462 {
463 mState.stencilBackFunc = stencilBackFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000464 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000465 mState.stencilBackMask = stencilBackMask;
466 mStencilStateDirty = true;
467 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000468}
469
470void Context::setStencilWritemask(GLuint stencilWritemask)
471{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000472 if (mState.stencilWritemask != stencilWritemask)
473 {
474 mState.stencilWritemask = stencilWritemask;
475 mStencilStateDirty = true;
476 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000477}
478
479void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
480{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000481 if (mState.stencilBackWritemask != stencilBackWritemask)
482 {
483 mState.stencilBackWritemask = stencilBackWritemask;
484 mStencilStateDirty = true;
485 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000486}
487
488void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
489{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000490 if (mState.stencilFail != stencilFail ||
491 mState.stencilPassDepthFail != stencilPassDepthFail ||
492 mState.stencilPassDepthPass != stencilPassDepthPass)
493 {
494 mState.stencilFail = stencilFail;
495 mState.stencilPassDepthFail = stencilPassDepthFail;
496 mState.stencilPassDepthPass = stencilPassDepthPass;
497 mStencilStateDirty = true;
498 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000499}
500
501void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
502{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000503 if (mState.stencilBackFail != stencilBackFail ||
504 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
505 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
506 {
507 mState.stencilBackFail = stencilBackFail;
508 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
509 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
510 mStencilStateDirty = true;
511 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000512}
513
514void Context::setPolygonOffsetFill(bool enabled)
515{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000516 if (mState.polygonOffsetFill != enabled)
517 {
518 mState.polygonOffsetFill = enabled;
519 mPolygonOffsetStateDirty = true;
520 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000521}
522
523bool Context::isPolygonOffsetFillEnabled() const
524{
525 return mState.polygonOffsetFill;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000526
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000527}
528
529void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
530{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000531 if (mState.polygonOffsetFactor != factor ||
532 mState.polygonOffsetUnits != units)
533 {
534 mState.polygonOffsetFactor = factor;
535 mState.polygonOffsetUnits = units;
536 mPolygonOffsetStateDirty = true;
537 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000538}
539
540void Context::setSampleAlphaToCoverage(bool enabled)
541{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000542 if (mState.sampleAlphaToCoverage != enabled)
543 {
544 mState.sampleAlphaToCoverage = enabled;
545 mSampleStateDirty = true;
546 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000547}
548
549bool Context::isSampleAlphaToCoverageEnabled() const
550{
551 return mState.sampleAlphaToCoverage;
552}
553
554void Context::setSampleCoverage(bool enabled)
555{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000556 if (mState.sampleCoverage != enabled)
557 {
558 mState.sampleCoverage = enabled;
559 mSampleStateDirty = true;
560 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000561}
562
563bool Context::isSampleCoverageEnabled() const
564{
565 return mState.sampleCoverage;
566}
567
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +0000568void Context::setSampleCoverageParams(GLclampf value, bool invert)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000569{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000570 if (mState.sampleCoverageValue != value ||
571 mState.sampleCoverageInvert != invert)
572 {
573 mState.sampleCoverageValue = value;
574 mState.sampleCoverageInvert = invert;
575 mSampleStateDirty = true;
576 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000577}
578
579void Context::setScissorTest(bool enabled)
580{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000581 if (mState.scissorTest != enabled)
582 {
583 mState.scissorTest = enabled;
584 mScissorStateDirty = true;
585 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000586}
587
588bool Context::isScissorTestEnabled() const
589{
590 return mState.scissorTest;
591}
592
593void Context::setDither(bool enabled)
594{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000595 if (mState.dither != enabled)
596 {
597 mState.dither = enabled;
598 mDitherStateDirty = true;
599 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000600}
601
602bool Context::isDitherEnabled() const
603{
604 return mState.dither;
605}
606
607void Context::setLineWidth(GLfloat width)
608{
609 mState.lineWidth = width;
610}
611
612void Context::setGenerateMipmapHint(GLenum hint)
613{
614 mState.generateMipmapHint = hint;
615}
616
617void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
618{
619 mState.viewportX = x;
620 mState.viewportY = y;
621 mState.viewportWidth = width;
622 mState.viewportHeight = height;
623}
624
625void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
626{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000627 if (mState.scissorX != x || mState.scissorY != y ||
628 mState.scissorWidth != width || mState.scissorHeight != height)
629 {
630 mState.scissorX = x;
631 mState.scissorY = y;
632 mState.scissorWidth = width;
633 mState.scissorHeight = height;
634 mScissorStateDirty = true;
635 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000636}
637
638void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
639{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000640 if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
641 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
642 {
643 mState.colorMaskRed = red;
644 mState.colorMaskGreen = green;
645 mState.colorMaskBlue = blue;
646 mState.colorMaskAlpha = alpha;
647 mMaskStateDirty = true;
648 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000649}
650
651void Context::setDepthMask(bool mask)
652{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000653 if (mState.depthMask != mask)
654 {
655 mState.depthMask = mask;
656 mMaskStateDirty = true;
657 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000658}
659
660void Context::setActiveSampler(int active)
661{
662 mState.activeSampler = active;
663}
664
665GLuint Context::getFramebufferHandle() const
666{
667 return mState.framebuffer;
668}
669
670GLuint Context::getRenderbufferHandle() const
671{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000672 return mState.renderbuffer.id();
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000673}
674
675GLuint Context::getArrayBufferHandle() const
676{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000677 return mState.arrayBuffer.id();
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000678}
679
680void Context::setVertexAttribEnabled(unsigned int attribNum, bool enabled)
681{
682 mState.vertexAttribute[attribNum].mEnabled = enabled;
683}
684
685const AttributeState &Context::getVertexAttribState(unsigned int attribNum)
686{
687 return mState.vertexAttribute[attribNum];
688}
689
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000690void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000691 GLsizei stride, const void *pointer)
692{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000693 mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000694 mState.vertexAttribute[attribNum].mSize = size;
695 mState.vertexAttribute[attribNum].mType = type;
696 mState.vertexAttribute[attribNum].mNormalized = normalized;
697 mState.vertexAttribute[attribNum].mStride = stride;
698 mState.vertexAttribute[attribNum].mPointer = pointer;
699}
700
701const void *Context::getVertexAttribPointer(unsigned int attribNum) const
702{
703 return mState.vertexAttribute[attribNum].mPointer;
704}
705
706// returns entire set of attributes as a block
707const AttributeState *Context::getVertexAttribBlock()
708{
709 return mState.vertexAttribute;
710}
711
712void Context::setPackAlignment(GLint alignment)
713{
714 mState.packAlignment = alignment;
715}
716
717GLint Context::getPackAlignment() const
718{
719 return mState.packAlignment;
720}
721
722void Context::setUnpackAlignment(GLint alignment)
723{
724 mState.unpackAlignment = alignment;
725}
726
727GLint Context::getUnpackAlignment() const
728{
729 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000730}
731
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000732GLuint Context::createBuffer()
733{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000734 return mResourceManager->createBuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000735}
736
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000737GLuint Context::createProgram()
738{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000739 return mResourceManager->createProgram();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000740}
741
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000742GLuint Context::createShader(GLenum type)
743{
744 return mResourceManager->createShader(type);
745}
746
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000747GLuint Context::createTexture()
748{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000749 return mResourceManager->createTexture();
750}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000751
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000752GLuint Context::createRenderbuffer()
753{
754 return mResourceManager->createRenderbuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000755}
756
757// Returns an unused framebuffer name
758GLuint Context::createFramebuffer()
759{
760 unsigned int handle = 1;
761
762 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
763 {
764 handle++;
765 }
766
767 mFramebufferMap[handle] = NULL;
768
769 return handle;
770}
771
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000772void Context::deleteBuffer(GLuint buffer)
773{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000774 if (mResourceManager->getBuffer(buffer))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000775 {
776 detachBuffer(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000777 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000778
779 mResourceManager->deleteBuffer(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000780}
781
782void Context::deleteShader(GLuint shader)
783{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000784 mResourceManager->deleteShader(shader);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000785}
786
787void Context::deleteProgram(GLuint program)
788{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000789 mResourceManager->deleteProgram(program);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000790}
791
792void Context::deleteTexture(GLuint texture)
793{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000794 if (mResourceManager->getTexture(texture))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000795 {
796 detachTexture(texture);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000797 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000798
799 mResourceManager->deleteTexture(texture);
800}
801
802void Context::deleteRenderbuffer(GLuint renderbuffer)
803{
804 if (mResourceManager->getRenderbuffer(renderbuffer))
805 {
806 detachRenderbuffer(renderbuffer);
807 }
808
809 mResourceManager->deleteRenderbuffer(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000810}
811
812void Context::deleteFramebuffer(GLuint framebuffer)
813{
814 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
815
816 if (framebufferObject != mFramebufferMap.end())
817 {
818 detachFramebuffer(framebuffer);
819
820 delete framebufferObject->second;
821 mFramebufferMap.erase(framebufferObject);
822 }
823}
824
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000825Buffer *Context::getBuffer(GLuint handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000826{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000827 return mResourceManager->getBuffer(handle);
828}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000829
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000830Shader *Context::getShader(GLuint handle)
831{
832 return mResourceManager->getShader(handle);
833}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000834
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000835Program *Context::getProgram(GLuint handle)
836{
837 return mResourceManager->getProgram(handle);
838}
839
840Texture *Context::getTexture(GLuint handle)
841{
842 return mResourceManager->getTexture(handle);
843}
844
845Renderbuffer *Context::getRenderbuffer(GLuint handle)
846{
847 return mResourceManager->getRenderbuffer(handle);
848}
849
850Framebuffer *Context::getFramebuffer()
851{
852 return getFramebuffer(mState.framebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000853}
854
855void Context::bindArrayBuffer(unsigned int buffer)
856{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000857 mResourceManager->checkBufferAllocation(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000858
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000859 mState.arrayBuffer.set(getBuffer(buffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000860}
861
862void Context::bindElementArrayBuffer(unsigned int buffer)
863{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000864 mResourceManager->checkBufferAllocation(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000865
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000866 mState.elementArrayBuffer.set(getBuffer(buffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000867}
868
869void Context::bindTexture2D(GLuint texture)
870{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000871 mResourceManager->checkTextureAllocation(texture, SAMPLER_2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000872
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000873 mState.texture2D.set(getTexture(texture));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000874
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000875 mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(mState.texture2D.get());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000876}
877
878void Context::bindTextureCubeMap(GLuint texture)
879{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000880 mResourceManager->checkTextureAllocation(texture, SAMPLER_CUBE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000881
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000882 mState.textureCubeMap.set(getTexture(texture));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000883
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000884 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(mState.textureCubeMap.get());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000885}
886
887void Context::bindFramebuffer(GLuint framebuffer)
888{
889 if (!getFramebuffer(framebuffer))
890 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000891 mFramebufferMap[framebuffer] = new Framebuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000892 }
893
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000894 mState.framebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000895}
896
897void Context::bindRenderbuffer(GLuint renderbuffer)
898{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000899 mResourceManager->checkRenderbufferAllocation(renderbuffer);
900
901 mState.renderbuffer.set(getRenderbuffer(renderbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000902}
903
904void Context::useProgram(GLuint program)
905{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000906 GLuint priorProgram = mState.currentProgram;
907 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +0000908
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000909 if (priorProgram != program)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000910 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000911 Program *newProgram = mResourceManager->getProgram(program);
912 Program *oldProgram = mResourceManager->getProgram(priorProgram);
913
914 if (newProgram)
915 {
916 newProgram->addRef();
917 }
918
919 if (oldProgram)
920 {
921 oldProgram->release();
922 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000923 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000924}
925
926void Context::setFramebufferZero(Framebuffer *buffer)
927{
928 delete mFramebufferMap[0];
929 mFramebufferMap[0] = buffer;
930}
931
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000932void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000933{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000934 Renderbuffer *renderbufferObject = mState.renderbuffer.get();
935 renderbufferObject->setStorage(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000936}
937
938Framebuffer *Context::getFramebuffer(unsigned int handle)
939{
940 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +0000941
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000942 if (framebuffer == mFramebufferMap.end())
943 {
944 return NULL;
945 }
946 else
947 {
948 return framebuffer->second;
949 }
950}
951
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000952Buffer *Context::getArrayBuffer()
953{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000954 return mState.arrayBuffer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000955}
956
957Buffer *Context::getElementArrayBuffer()
958{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000959 return mState.elementArrayBuffer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000960}
961
962Program *Context::getCurrentProgram()
963{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000964 return mResourceManager->getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000965}
966
967Texture2D *Context::getTexture2D()
968{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000969 if (mState.texture2D.id() == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000970 {
971 return mTexture2DZero;
972 }
973
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000974 return static_cast<Texture2D*>(mState.texture2D.get());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000975}
976
977TextureCubeMap *Context::getTextureCubeMap()
978{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000979 if (mState.textureCubeMap.id() == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000980 {
981 return mTextureCubeMapZero;
982 }
983
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000984 return static_cast<TextureCubeMap*>(mState.textureCubeMap.get());
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000985}
986
daniel@transgaming.com416485f2010-03-16 06:23:23 +0000987Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000988{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000989 GLuint texid = mState.samplerTexture[type][sampler].id();
daniel@transgaming.com4195fc42010-04-08 03:51:09 +0000990
991 if (texid == 0)
992 {
993 switch (type)
994 {
995 default: UNREACHABLE();
996 case SAMPLER_2D: return mTexture2DZero;
997 case SAMPLER_CUBE: return mTextureCubeMapZero;
998 }
999 }
1000
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001001 return mState.samplerTexture[type][sampler].get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001002}
1003
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001004bool Context::getBooleanv(GLenum pname, GLboolean *params)
1005{
1006 switch (pname)
1007 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001008 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1009 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1010 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001011 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001012 params[0] = mState.colorMaskRed;
1013 params[1] = mState.colorMaskGreen;
1014 params[2] = mState.colorMaskBlue;
1015 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001016 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001017 case GL_CULL_FACE: *params = mState.cullFace;
1018 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill;
1019 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage;
1020 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage;
1021 case GL_SCISSOR_TEST: *params = mState.scissorTest;
1022 case GL_STENCIL_TEST: *params = mState.stencilTest;
1023 case GL_DEPTH_TEST: *params = mState.depthTest;
1024 case GL_BLEND: *params = mState.blend;
1025 case GL_DITHER: *params = mState.dither;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001026 default:
1027 return false;
1028 }
1029
1030 return true;
1031}
1032
1033bool Context::getFloatv(GLenum pname, GLfloat *params)
1034{
1035 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1036 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1037 // GetIntegerv as its native query function. As it would require conversion in any
1038 // case, this should make no difference to the calling application.
1039 switch (pname)
1040 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001041 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1042 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1043 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1044 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1045 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001046 case GL_ALIASED_LINE_WIDTH_RANGE:
1047 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1048 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1049 break;
1050 case GL_ALIASED_POINT_SIZE_RANGE:
1051 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001052 params[1] = supportsShaderModel3() ? gl::ALIASED_POINT_SIZE_RANGE_MAX_SM3 : gl::ALIASED_POINT_SIZE_RANGE_MAX_SM2;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001053 break;
1054 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001055 params[0] = mState.zNear;
1056 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001057 break;
1058 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001059 params[0] = mState.colorClearValue.red;
1060 params[1] = mState.colorClearValue.green;
1061 params[2] = mState.colorClearValue.blue;
1062 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001063 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001064 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001065 params[0] = mState.blendColor.red;
1066 params[1] = mState.blendColor.green;
1067 params[2] = mState.blendColor.blue;
1068 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001069 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001070 default:
1071 return false;
1072 }
1073
1074 return true;
1075}
1076
1077bool Context::getIntegerv(GLenum pname, GLint *params)
1078{
1079 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1080 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1081 // GetIntegerv as its native query function. As it would require conversion in any
1082 // case, this should make no difference to the calling application. You may find it in
1083 // Context::getFloatv.
1084 switch (pname)
1085 {
1086 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1087 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1088 case GL_MAX_VARYING_VECTORS: *params = gl::MAX_VARYING_VECTORS; break;
1089 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1090 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1091 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1092 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = gl::MAX_FRAGMENT_UNIFORM_VECTORS; break;
1093 case GL_MAX_RENDERBUFFER_SIZE: *params = gl::MAX_RENDERBUFFER_SIZE; break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001094 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1095 case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = 0; break;
1096 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */ break;
1097 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001098 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break;
1099 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001100 case GL_FRAMEBUFFER_BINDING: *params = mState.framebuffer; break;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001101 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001102 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1103 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1104 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1105 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1106 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
1107 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1108 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1109 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1110 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1111 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1112 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1113 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1114 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1115 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1116 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1117 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1118 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1119 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1120 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1121 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1122 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1123 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1124 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1125 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1126 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1127 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1128 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
1129 case GL_SUBPIXEL_BITS: *params = 4; break;
1130 case GL_MAX_TEXTURE_SIZE: *params = gl::MAX_TEXTURE_SIZE; break;
1131 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = gl::MAX_CUBE_MAP_TEXTURE_SIZE; break;
1132 case GL_SAMPLE_BUFFERS: *params = 0; break;
1133 case GL_SAMPLES: *params = 0; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001134 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1135 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1136 case GL_MAX_VIEWPORT_DIMS:
1137 {
1138 int maxDimension = std::max((int)gl::MAX_RENDERBUFFER_SIZE, (int)gl::MAX_TEXTURE_SIZE);
1139 params[0] = maxDimension;
1140 params[1] = maxDimension;
1141 }
1142 break;
1143 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001144 params[0] = mState.viewportX;
1145 params[1] = mState.viewportY;
1146 params[2] = mState.viewportWidth;
1147 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001148 break;
1149 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001150 params[0] = mState.scissorX;
1151 params[1] = mState.scissorY;
1152 params[2] = mState.scissorWidth;
1153 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001154 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001155 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1156 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001157 case GL_RED_BITS:
1158 case GL_GREEN_BITS:
1159 case GL_BLUE_BITS:
1160 case GL_ALPHA_BITS:
1161 {
1162 gl::Framebuffer *framebuffer = getFramebuffer();
1163 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1164
1165 if (colorbuffer)
1166 {
1167 switch (pname)
1168 {
1169 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1170 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1171 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1172 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1173 }
1174 }
1175 else
1176 {
1177 *params = 0;
1178 }
1179 }
1180 break;
1181 case GL_DEPTH_BITS:
1182 {
1183 gl::Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001184 gl::DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001185
1186 if (depthbuffer)
1187 {
1188 *params = depthbuffer->getDepthSize();
1189 }
1190 else
1191 {
1192 *params = 0;
1193 }
1194 }
1195 break;
1196 case GL_STENCIL_BITS:
1197 {
1198 gl::Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001199 gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001200
1201 if (stencilbuffer)
1202 {
1203 *params = stencilbuffer->getStencilSize();
1204 }
1205 else
1206 {
1207 *params = 0;
1208 }
1209 }
1210 break;
1211 case GL_TEXTURE_BINDING_2D:
1212 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001213 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001214 {
1215 error(GL_INVALID_OPERATION);
1216 return false;
1217 }
1218
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001219 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler].id();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001220 }
1221 break;
1222 case GL_TEXTURE_BINDING_CUBE_MAP:
1223 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001224 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001225 {
1226 error(GL_INVALID_OPERATION);
1227 return false;
1228 }
1229
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001230 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].id();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001231 }
1232 break;
1233 default:
1234 return false;
1235 }
1236
1237 return true;
1238}
1239
1240bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1241{
1242 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1243 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1244 // to the fact that it is stored internally as a float, and so would require conversion
1245 // if returned from Context::getIntegerv. Since this conversion is already implemented
1246 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1247 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1248 // application.
1249 switch (pname)
1250 {
1251 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1252 case GL_SHADER_BINARY_FORMATS:
1253 {
1254 *type = GL_INT;
1255 *numParams = 0;
1256 }
1257 break;
1258 case GL_MAX_VERTEX_ATTRIBS:
1259 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1260 case GL_MAX_VARYING_VECTORS:
1261 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1262 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1263 case GL_MAX_TEXTURE_IMAGE_UNITS:
1264 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1265 case GL_MAX_RENDERBUFFER_SIZE:
1266 case GL_NUM_SHADER_BINARY_FORMATS:
1267 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1268 case GL_ARRAY_BUFFER_BINDING:
1269 case GL_FRAMEBUFFER_BINDING:
1270 case GL_RENDERBUFFER_BINDING:
1271 case GL_CURRENT_PROGRAM:
1272 case GL_PACK_ALIGNMENT:
1273 case GL_UNPACK_ALIGNMENT:
1274 case GL_GENERATE_MIPMAP_HINT:
1275 case GL_RED_BITS:
1276 case GL_GREEN_BITS:
1277 case GL_BLUE_BITS:
1278 case GL_ALPHA_BITS:
1279 case GL_DEPTH_BITS:
1280 case GL_STENCIL_BITS:
1281 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1282 case GL_CULL_FACE_MODE:
1283 case GL_FRONT_FACE:
1284 case GL_ACTIVE_TEXTURE:
1285 case GL_STENCIL_FUNC:
1286 case GL_STENCIL_VALUE_MASK:
1287 case GL_STENCIL_REF:
1288 case GL_STENCIL_FAIL:
1289 case GL_STENCIL_PASS_DEPTH_FAIL:
1290 case GL_STENCIL_PASS_DEPTH_PASS:
1291 case GL_STENCIL_BACK_FUNC:
1292 case GL_STENCIL_BACK_VALUE_MASK:
1293 case GL_STENCIL_BACK_REF:
1294 case GL_STENCIL_BACK_FAIL:
1295 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1296 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1297 case GL_DEPTH_FUNC:
1298 case GL_BLEND_SRC_RGB:
1299 case GL_BLEND_SRC_ALPHA:
1300 case GL_BLEND_DST_RGB:
1301 case GL_BLEND_DST_ALPHA:
1302 case GL_BLEND_EQUATION_RGB:
1303 case GL_BLEND_EQUATION_ALPHA:
1304 case GL_STENCIL_WRITEMASK:
1305 case GL_STENCIL_BACK_WRITEMASK:
1306 case GL_STENCIL_CLEAR_VALUE:
1307 case GL_SUBPIXEL_BITS:
1308 case GL_MAX_TEXTURE_SIZE:
1309 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1310 case GL_SAMPLE_BUFFERS:
1311 case GL_SAMPLES:
1312 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1313 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1314 case GL_TEXTURE_BINDING_2D:
1315 case GL_TEXTURE_BINDING_CUBE_MAP:
1316 {
1317 *type = GL_INT;
1318 *numParams = 1;
1319 }
1320 break;
1321 case GL_MAX_VIEWPORT_DIMS:
1322 {
1323 *type = GL_INT;
1324 *numParams = 2;
1325 }
1326 break;
1327 case GL_VIEWPORT:
1328 case GL_SCISSOR_BOX:
1329 {
1330 *type = GL_INT;
1331 *numParams = 4;
1332 }
1333 break;
1334 case GL_SHADER_COMPILER:
1335 case GL_SAMPLE_COVERAGE_INVERT:
1336 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001337 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1338 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1339 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1340 case GL_SAMPLE_COVERAGE:
1341 case GL_SCISSOR_TEST:
1342 case GL_STENCIL_TEST:
1343 case GL_DEPTH_TEST:
1344 case GL_BLEND:
1345 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001346 {
1347 *type = GL_BOOL;
1348 *numParams = 1;
1349 }
1350 break;
1351 case GL_COLOR_WRITEMASK:
1352 {
1353 *type = GL_BOOL;
1354 *numParams = 4;
1355 }
1356 break;
1357 case GL_POLYGON_OFFSET_FACTOR:
1358 case GL_POLYGON_OFFSET_UNITS:
1359 case GL_SAMPLE_COVERAGE_VALUE:
1360 case GL_DEPTH_CLEAR_VALUE:
1361 case GL_LINE_WIDTH:
1362 {
1363 *type = GL_FLOAT;
1364 *numParams = 1;
1365 }
1366 break;
1367 case GL_ALIASED_LINE_WIDTH_RANGE:
1368 case GL_ALIASED_POINT_SIZE_RANGE:
1369 case GL_DEPTH_RANGE:
1370 {
1371 *type = GL_FLOAT;
1372 *numParams = 2;
1373 }
1374 break;
1375 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001376 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001377 {
1378 *type = GL_FLOAT;
1379 *numParams = 4;
1380 }
1381 break;
1382 default:
1383 return false;
1384 }
1385
1386 return true;
1387}
1388
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001389// Applies the render target surface, depth stencil surface, viewport rectangle and
1390// scissor rectangle to the Direct3D 9 device
1391bool Context::applyRenderTarget(bool ignoreViewport)
1392{
1393 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001394
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001395 Framebuffer *framebufferObject = getFramebuffer();
1396
1397 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1398 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001399 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1400
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001401 return false;
1402 }
1403
1404 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001405 IDirect3DSurface9 *depthStencil = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001406
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001407 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
1408 if (renderTargetSerial != mAppliedRenderTargetSerial)
1409 {
1410 device->SetRenderTarget(0, renderTarget);
1411 mAppliedRenderTargetSerial = renderTargetSerial;
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001412 mScissorStateDirty = true; // Scissor area must be clamped to render target's size-- this is different for different render targets.
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001413 }
1414
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001415 unsigned int depthbufferSerial = 0;
1416 unsigned int stencilbufferSerial = 0;
1417 if (framebufferObject->getDepthbufferType() != GL_NONE)
1418 {
1419 depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil();
1420 depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial();
1421 }
1422 else if (framebufferObject->getStencilbufferType() != GL_NONE)
1423 {
1424 depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
1425 stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial();
1426 }
1427
1428 if (depthbufferSerial != mAppliedDepthbufferSerial ||
1429 stencilbufferSerial != mAppliedStencilbufferSerial)
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001430 {
1431 device->SetDepthStencilSurface(depthStencil);
1432 mAppliedDepthbufferSerial = depthbufferSerial;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001433 mAppliedStencilbufferSerial = stencilbufferSerial;
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001434 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001435
1436 D3DVIEWPORT9 viewport;
1437 D3DSURFACE_DESC desc;
1438 renderTarget->GetDesc(&desc);
1439
1440 if (ignoreViewport)
1441 {
1442 viewport.X = 0;
1443 viewport.Y = 0;
1444 viewport.Width = desc.Width;
1445 viewport.Height = desc.Height;
1446 viewport.MinZ = 0.0f;
1447 viewport.MaxZ = 1.0f;
1448 }
1449 else
1450 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001451 viewport.X = std::max(mState.viewportX, 0);
1452 viewport.Y = std::max(mState.viewportY, 0);
1453 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1454 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1455 viewport.MinZ = clamp01(mState.zNear);
1456 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001457 }
1458
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001459 if (viewport.Width <= 0 || viewport.Height <= 0)
1460 {
1461 return false; // Nothing to render
1462 }
1463
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001464 device->SetViewport(&viewport);
1465
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001466 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001467 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001468 if (mState.scissorTest)
1469 {
1470 RECT rect = {mState.scissorX,
1471 mState.scissorY,
1472 mState.scissorX + mState.scissorWidth,
1473 mState.scissorY + mState.scissorHeight};
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001474 rect.right = std::min(static_cast<UINT>(rect.right), desc.Width);
1475 rect.bottom = std::min(static_cast<UINT>(rect.bottom), desc.Height);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001476 device->SetScissorRect(&rect);
1477 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1478 }
1479 else
1480 {
1481 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1482 }
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001483
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001484 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001485 }
1486
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001487 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001488 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001489 Program *programObject = getCurrentProgram();
1490
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001491 GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001492 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001493 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001494
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00001495 GLint window = programObject->getDxViewportLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001496 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1497 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1498 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001499 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1500
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001501 GLint depth = programObject->getDxDepthLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001502 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001503 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1504
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001505 GLint near = programObject->getDepthRangeNearLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001506 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001507
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001508 GLint far = programObject->getDepthRangeFarLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001509 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001510
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001511 GLint diff = programObject->getDepthRangeDiffLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001512 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001513 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001514 }
1515
1516 return true;
1517}
1518
1519// 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 +00001520void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001521{
1522 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001523 Program *programObject = getCurrentProgram();
1524
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001525 GLint frontCCW = programObject->getDxFrontCCWLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001526 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001527 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001528
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001529 GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001530 GLint alwaysFront = !isTriangleMode(drawMode);
1531 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1532
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001533 Framebuffer *framebufferObject = getFramebuffer();
1534
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001535 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001536 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001537 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001538 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001539 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001540 }
1541 else
1542 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001543 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001544 }
1545
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001546 mCullStateDirty = false;
1547 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001548
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001549 if (mDepthStateDirty)
1550 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001551 if (mState.depthTest && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001552 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001553 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1554 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001555 }
1556 else
1557 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001558 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001559 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001560
1561 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001562 }
1563
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001564 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001565 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001566 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001567 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001568 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1569
1570 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1571 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1572 {
1573 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1574 }
1575 else
1576 {
1577 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1578 unorm<8>(mState.blendColor.alpha),
1579 unorm<8>(mState.blendColor.alpha),
1580 unorm<8>(mState.blendColor.alpha)));
1581 }
1582
1583 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1584 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1585 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1586
1587 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1588 mState.destBlendRGB != mState.destBlendAlpha ||
1589 mState.blendEquationRGB != mState.blendEquationAlpha)
1590 {
1591 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1592
1593 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1594 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1595 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
1596
1597 }
1598 else
1599 {
1600 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1601 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001602 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001603 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001604 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001605 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001606 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001607
1608 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001609 }
1610
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001611 if (mStencilStateDirty || mFrontFaceDirty)
1612 {
1613 if (mState.stencilTest && hasStencil())
1614 {
1615 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1616 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1617
1618 // FIXME: Unsupported by D3D9
1619 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1620 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1621 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1622 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1623 mState.stencilRef != mState.stencilBackRef ||
1624 mState.stencilMask != mState.stencilBackMask)
1625 {
1626 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1627 return error(GL_INVALID_OPERATION);
1628 }
1629
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001630 // get the maximum size of the stencil ref
1631 gl::Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001632 gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001633 GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
1634
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001635 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1636 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1637 es2dx::ConvertComparison(mState.stencilFunc));
1638
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001639 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001640 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
1641
1642 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1643 es2dx::ConvertStencilOp(mState.stencilFail));
1644 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1645 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1646 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1647 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1648
1649 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1650 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1651 es2dx::ConvertComparison(mState.stencilBackFunc));
1652
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001653 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001654 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
1655
1656 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1657 es2dx::ConvertStencilOp(mState.stencilBackFail));
1658 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1659 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1660 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1661 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1662 }
1663 else
1664 {
1665 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1666 }
1667
1668 mStencilStateDirty = false;
1669 }
1670
1671 if (mMaskStateDirty)
1672 {
1673 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1674 mState.colorMaskBlue, mState.colorMaskAlpha));
1675 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1676
1677 mMaskStateDirty = false;
1678 }
1679
1680 if (mPolygonOffsetStateDirty)
1681 {
1682 if (mState.polygonOffsetFill)
1683 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001684 gl::DepthStencilbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001685 if (depthbuffer)
1686 {
1687 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1688 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1689 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1690 }
1691 }
1692 else
1693 {
1694 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1695 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1696 }
1697
1698 mPolygonOffsetStateDirty = false;
1699 }
1700
1701 if (mConfig->mMultiSample != 0 && mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001702 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001703 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001704 {
1705 FIXME("Sample alpha to coverage is unimplemented.");
1706 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001707
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001708 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001709 {
1710 FIXME("Sample coverage is unimplemented.");
1711 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001712
1713 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001714 }
1715
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001716 if (mDitherStateDirty)
1717 {
1718 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
1719
1720 mDitherStateDirty = false;
1721 }
1722
1723 mFrontFaceDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001724}
1725
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001726// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001727void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001728{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001729 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001730 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001731 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001732 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001733 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001734 }
1735 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001736}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001737
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001738GLenum Context::applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool *useIndexing, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001739{
1740 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1741
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001742 GLenum err = mVertexDataManager->preRenderValidate(first, count, translated);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001743 if (err != GL_NO_ERROR)
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001744 {
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001745 return err;
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001746 }
1747
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001748 lookupAttributeMapping(translated);
1749
1750 mBufferBackEnd->setupAttributesPreDraw(translated);
1751
1752 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
1753 {
1754 if (translated[i].enabled && translated[i].nonArray)
1755 {
1756 err = mIndexDataManager->preRenderValidateUnindexed(mode, count, indexInfo);
1757 if (err != GL_NO_ERROR)
1758 {
1759 return err;
1760 }
1761
1762 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
1763
1764 *useIndexing = true;
1765 return GL_NO_ERROR;
1766 }
1767 }
1768
1769 *useIndexing = false;
1770 return GL_NO_ERROR;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001771}
1772
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001773GLenum Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001774{
1775 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1776
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001777 GLenum err = mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001778
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001779 if (err == GL_NO_ERROR)
1780 {
1781 lookupAttributeMapping(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001782
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001783 mBufferBackEnd->setupAttributesPreDraw(translated);
1784 }
1785
1786 return err;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001787}
1788
1789// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001790GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001791{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001792 GLenum err = mIndexDataManager->preRenderValidate(mode, type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001793
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001794 if (err == GL_NO_ERROR)
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001795 {
1796 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
1797 }
1798
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001799 return err;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001800}
1801
1802// Applies the shaders and shader constants to the Direct3D 9 device
1803void Context::applyShaders()
1804{
1805 IDirect3DDevice9 *device = getDevice();
1806 Program *programObject = getCurrentProgram();
1807 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1808 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1809
1810 device->SetVertexShader(vertexShader);
1811 device->SetPixelShader(pixelShader);
1812
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001813 if (programObject->getSerial() != mAppliedProgram)
1814 {
1815 programObject->dirtyAllUniforms();
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001816 programObject->dirtyAllSamplers();
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001817 mAppliedProgram = programObject->getSerial();
1818 }
1819
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001820 programObject->applyUniforms();
1821}
1822
1823// Applies the textures and sampler states to the Direct3D 9 device
1824void Context::applyTextures()
1825{
1826 IDirect3DDevice9 *device = getDevice();
1827 Program *programObject = getCurrentProgram();
1828
1829 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1830 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001831 int textureUnit = programObject->getSamplerMapping(sampler);
1832 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001833 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001834 SamplerType textureType = programObject->getSamplerType(sampler);
1835
1836 Texture *texture = getSamplerTexture(textureUnit, textureType);
1837
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001838 if (programObject->isSamplerDirty(sampler) || texture->isDirty())
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001839 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001840 if (texture->isComplete())
1841 {
1842 GLenum wrapS = texture->getWrapS();
1843 GLenum wrapT = texture->getWrapT();
1844 GLenum minFilter = texture->getMinFilter();
1845 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001846
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001847 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1848 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001849
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001850 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1851 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1852 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1853 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1854 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001855
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001856 device->SetTexture(sampler, texture->getTexture());
1857 }
1858 else
1859 {
1860 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1861 }
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001862 }
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001863
1864 programObject->setSamplerDirty(sampler, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001865 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001866 else
1867 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001868 if (programObject->isSamplerDirty(sampler))
1869 {
1870 device->SetTexture(sampler, NULL);
1871 programObject->setSamplerDirty(sampler, false);
1872 }
1873 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001874 }
1875}
1876
1877void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1878{
1879 Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.combbc57792010-07-28 19:21:05 +00001880
1881 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1882 {
1883 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1884 }
1885
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001886 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1887 IDirect3DDevice9 *device = getDevice();
1888
1889 D3DSURFACE_DESC desc;
1890 renderTarget->GetDesc(&desc);
1891
1892 IDirect3DSurface9 *systemSurface;
1893 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1894
1895 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1896 {
1897 return error(GL_OUT_OF_MEMORY);
1898 }
1899
1900 ASSERT(SUCCEEDED(result));
1901
1902 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1903 {
1904 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1905 }
1906
1907 result = device->GetRenderTargetData(renderTarget, systemSurface);
1908
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001909 if (FAILED(result))
1910 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001911 systemSurface->Release();
1912
apatrick@chromium.org6db8cab2010-07-22 20:39:50 +00001913 switch (result)
1914 {
1915 case D3DERR_DRIVERINTERNALERROR:
1916 case D3DERR_DEVICELOST:
1917 return error(GL_OUT_OF_MEMORY);
1918 default:
1919 UNREACHABLE();
1920 return; // No sensible error to generate
1921 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001922 }
1923
1924 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001925 RECT rect = {std::max(x, 0),
1926 std::max(y, 0),
1927 std::min(x + width, (int)desc.Width),
1928 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001929
1930 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1931
1932 if (FAILED(result))
1933 {
1934 UNREACHABLE();
1935 systemSurface->Release();
1936
1937 return; // No sensible error to generate
1938 }
1939
1940 unsigned char *source = (unsigned char*)lock.pBits;
1941 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001942 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001943
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001944 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001945
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001946 for (int j = 0; j < rect.bottom - rect.top; j++)
1947 {
1948 for (int i = 0; i < rect.right - rect.left; i++)
1949 {
1950 float r;
1951 float g;
1952 float b;
1953 float a;
1954
1955 switch (desc.Format)
1956 {
1957 case D3DFMT_R5G6B5:
1958 {
1959 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1960
1961 a = 1.0f;
1962 b = (rgb & 0x001F) * (1.0f / 0x001F);
1963 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1964 r = (rgb & 0xF800) * (1.0f / 0xF800);
1965 }
1966 break;
1967 case D3DFMT_X1R5G5B5:
1968 {
1969 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1970
1971 a = 1.0f;
1972 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1973 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1974 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1975 }
1976 break;
1977 case D3DFMT_A1R5G5B5:
1978 {
1979 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1980
1981 a = (argb & 0x8000) ? 1.0f : 0.0f;
1982 b = (argb & 0x001F) * (1.0f / 0x001F);
1983 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1984 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1985 }
1986 break;
1987 case D3DFMT_A8R8G8B8:
1988 {
1989 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1990
1991 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1992 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1993 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1994 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1995 }
1996 break;
1997 case D3DFMT_X8R8G8B8:
1998 {
1999 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2000
2001 a = 1.0f;
2002 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2003 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2004 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2005 }
2006 break;
2007 case D3DFMT_A2R10G10B10:
2008 {
2009 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2010
2011 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2012 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2013 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2014 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2015 }
2016 break;
2017 default:
2018 UNIMPLEMENTED(); // FIXME
2019 UNREACHABLE();
2020 }
2021
2022 switch (format)
2023 {
2024 case GL_RGBA:
2025 switch (type)
2026 {
2027 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002028 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2029 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2030 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2031 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002032 break;
2033 default: UNREACHABLE();
2034 }
2035 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002036 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002037 switch (type)
2038 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002039 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002040 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2041 ((unsigned short)(31 * b + 0.5f) << 0) |
2042 ((unsigned short)(63 * g + 0.5f) << 5) |
2043 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002044 break;
2045 default: UNREACHABLE();
2046 }
2047 break;
2048 default: UNREACHABLE();
2049 }
2050 }
2051 }
2052
2053 systemSurface->UnlockRect();
2054
2055 systemSurface->Release();
2056}
2057
2058void Context::clear(GLbitfield mask)
2059{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002060 Framebuffer *framebufferObject = getFramebuffer();
2061
2062 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2063 {
2064 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2065
2066 return;
2067 }
2068
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002069 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002070 IDirect3DDevice9 *device = getDevice();
2071 DWORD flags = 0;
2072
2073 if (mask & GL_COLOR_BUFFER_BIT)
2074 {
2075 mask &= ~GL_COLOR_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002076
2077 if (framebufferObject->getColorbufferType() != GL_NONE)
2078 {
2079 flags |= D3DCLEAR_TARGET;
2080 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002081 }
2082
2083 if (mask & GL_DEPTH_BUFFER_BIT)
2084 {
2085 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002086 if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002087 {
2088 flags |= D3DCLEAR_ZBUFFER;
2089 }
2090 }
2091
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002092 GLuint stencilUnmasked = 0x0;
2093
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002094 if (mask & GL_STENCIL_BUFFER_BIT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002095 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002096 mask &= ~GL_STENCIL_BUFFER_BIT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002097 if (framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002098 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002099 IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
2100 D3DSURFACE_DESC desc;
2101 depthStencil->GetDesc(&desc);
2102
2103 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2104 stencilUnmasked = (0x1 << stencilSize) - 1;
2105
2106 if (stencilUnmasked != 0x0)
2107 {
2108 flags |= D3DCLEAR_STENCIL;
2109 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002110 }
2111 }
2112
2113 if (mask != 0)
2114 {
2115 return error(GL_INVALID_VALUE);
2116 }
2117
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002118 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2119 {
2120 return;
2121 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002122
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002123 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2124 unorm<8>(mState.colorClearValue.red),
2125 unorm<8>(mState.colorClearValue.green),
2126 unorm<8>(mState.colorClearValue.blue));
2127 float depth = clamp01(mState.depthClearValue);
2128 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002129
2130 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2131
2132 D3DSURFACE_DESC desc;
2133 renderTarget->GetDesc(&desc);
2134
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002135 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002136
2137 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002138 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002139 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002140 !(mState.colorMaskRed && mState.colorMaskGreen &&
2141 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002142
2143 if (needMaskedColorClear || needMaskedStencilClear)
2144 {
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002145 // State which is altered in all paths from this point to the clear call is saved.
2146 // State which is altered in only some paths will be flagged dirty in the case that
2147 // that path is taken.
2148 HRESULT hr;
2149 if (mMaskedClearSavedState == NULL)
2150 {
2151 hr = device->BeginStateBlock();
2152 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2153
2154 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2155 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2156 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2157 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2158 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2159 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2160 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2161 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2162 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2163 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2164 device->SetPixelShader(NULL);
2165 device->SetVertexShader(NULL);
2166 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2167 device->SetStreamSourceFreq(0, 1);
2168
2169 hr = device->EndStateBlock(&mMaskedClearSavedState);
2170 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2171 }
2172
2173 ASSERT(mMaskedClearSavedState != NULL);
2174
2175 if (mMaskedClearSavedState != NULL)
2176 {
2177 hr = mMaskedClearSavedState->Capture();
2178 ASSERT(SUCCEEDED(hr));
2179 }
2180
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002181 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2182 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2183 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2184 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2185 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2186 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2187 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2188 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2189
2190 if (flags & D3DCLEAR_TARGET)
2191 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002192 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2193 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2194 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2195 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002196 }
2197 else
2198 {
2199 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2200 }
2201
2202 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2203 {
2204 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2205 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2206 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2207 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002208 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002209 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002210 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2211 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002212 mStencilStateDirty = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002213 }
2214 else
2215 {
2216 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2217 }
2218
2219 device->SetPixelShader(NULL);
2220 device->SetVertexShader(NULL);
2221 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002222 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002223
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002224 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002225 {
2226 float x, y, z, w;
2227 D3DCOLOR diffuse;
2228 };
2229
2230 Vertex quad[4];
2231 quad[0].x = 0.0f;
2232 quad[0].y = (float)desc.Height;
2233 quad[0].z = 0.0f;
2234 quad[0].w = 1.0f;
2235 quad[0].diffuse = color;
2236
2237 quad[1].x = (float)desc.Width;
2238 quad[1].y = (float)desc.Height;
2239 quad[1].z = 0.0f;
2240 quad[1].w = 1.0f;
2241 quad[1].diffuse = color;
2242
2243 quad[2].x = 0.0f;
2244 quad[2].y = 0.0f;
2245 quad[2].z = 0.0f;
2246 quad[2].w = 1.0f;
2247 quad[2].diffuse = color;
2248
2249 quad[3].x = (float)desc.Width;
2250 quad[3].y = 0.0f;
2251 quad[3].z = 0.0f;
2252 quad[3].w = 1.0f;
2253 quad[3].diffuse = color;
2254
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002255 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002256 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002257
2258 if (flags & D3DCLEAR_ZBUFFER)
2259 {
2260 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2261 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2262 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2263 }
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002264
2265 if (mMaskedClearSavedState != NULL)
2266 {
2267 mMaskedClearSavedState->Apply();
2268 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002269 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002270 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002271 {
2272 device->Clear(0, NULL, flags, color, depth, stencil);
2273 }
2274}
2275
2276void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2277{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002278 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002279 {
2280 return error(GL_INVALID_OPERATION);
2281 }
2282
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002283 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002284 IDirect3DDevice9 *device = getDevice();
2285 D3DPRIMITIVETYPE primitiveType;
2286 int primitiveCount;
2287
2288 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2289 return error(GL_INVALID_ENUM);
2290
2291 if (primitiveCount <= 0)
2292 {
2293 return;
2294 }
2295
2296 if (!applyRenderTarget(false))
2297 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002298 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002299 }
2300
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002301 applyState(mode);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002302
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002303 TranslatedIndexData indexInfo;
2304 bool useIndexing;
2305 GLenum err = applyVertexBuffer(mode, first, count, &useIndexing, &indexInfo);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002306 if (err != GL_NO_ERROR)
2307 {
2308 return error(err);
2309 }
2310
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002311 applyShaders();
2312 applyTextures();
2313
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002314 if (!getCurrentProgram()->validateSamplers())
2315 {
2316 return error(GL_INVALID_OPERATION);
2317 }
2318
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002319 if (!cullSkipsDraw(mode))
2320 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002321 display->startScene();
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002322 if (useIndexing)
2323 {
2324 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
2325 }
2326 else
2327 {
2328 device->DrawPrimitive(primitiveType, 0, primitiveCount);
2329 }
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002330 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002331}
2332
2333void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2334{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002335 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002336 {
2337 return error(GL_INVALID_OPERATION);
2338 }
2339
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002340 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002341 {
2342 return error(GL_INVALID_OPERATION);
2343 }
2344
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002345 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002346 IDirect3DDevice9 *device = getDevice();
2347 D3DPRIMITIVETYPE primitiveType;
2348 int primitiveCount;
2349
2350 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2351 return error(GL_INVALID_ENUM);
2352
2353 if (primitiveCount <= 0)
2354 {
2355 return;
2356 }
2357
2358 if (!applyRenderTarget(false))
2359 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002360 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002361 }
2362
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002363 applyState(mode);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002364
2365 TranslatedIndexData indexInfo;
2366 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2367 if (err != GL_NO_ERROR)
2368 {
2369 return error(err);
2370 }
2371
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002372 err = applyVertexBuffer(indexInfo);
2373 if (err != GL_NO_ERROR)
2374 {
2375 return error(err);
2376 }
2377
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002378 applyShaders();
2379 applyTextures();
2380
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002381 if (!getCurrentProgram()->validateSamplers())
2382 {
2383 return error(GL_INVALID_OPERATION);
2384 }
2385
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002386 if (!cullSkipsDraw(mode))
2387 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002388 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002389 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 +00002390 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002391}
2392
2393void Context::finish()
2394{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002395 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002396 IDirect3DDevice9 *device = getDevice();
2397 IDirect3DQuery9 *occlusionQuery = NULL;
2398
2399 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2400
2401 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2402 {
2403 return error(GL_OUT_OF_MEMORY);
2404 }
2405
2406 ASSERT(SUCCEEDED(result));
2407
2408 if (occlusionQuery)
2409 {
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002410 IDirect3DStateBlock9 *savedState = NULL;
2411 device->CreateStateBlock(D3DSBT_ALL, &savedState);
2412
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002413 occlusionQuery->Issue(D3DISSUE_BEGIN);
2414
2415 // Render something outside the render target
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002416 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002417 device->SetPixelShader(NULL);
2418 device->SetVertexShader(NULL);
2419 device->SetFVF(D3DFVF_XYZRHW);
2420 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002421 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002422 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002423
2424 occlusionQuery->Issue(D3DISSUE_END);
2425
2426 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2427 {
2428 // Keep polling, but allow other threads to do something useful first
2429 Sleep(0);
2430 }
2431
2432 occlusionQuery->Release();
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002433
2434 if (savedState)
2435 {
2436 savedState->Apply();
2437 savedState->Release();
2438 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002439 }
2440}
2441
2442void Context::flush()
2443{
2444 IDirect3DDevice9 *device = getDevice();
2445 IDirect3DQuery9 *eventQuery = NULL;
2446
2447 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2448
2449 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2450 {
2451 return error(GL_OUT_OF_MEMORY);
2452 }
2453
2454 ASSERT(SUCCEEDED(result));
2455
2456 if (eventQuery)
2457 {
2458 eventQuery->Issue(D3DISSUE_END);
2459
2460 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2461 {
2462 // Keep polling, but allow other threads to do something useful first
2463 Sleep(0);
2464 }
2465
2466 eventQuery->Release();
2467 }
2468}
2469
2470void Context::recordInvalidEnum()
2471{
2472 mInvalidEnum = true;
2473}
2474
2475void Context::recordInvalidValue()
2476{
2477 mInvalidValue = true;
2478}
2479
2480void Context::recordInvalidOperation()
2481{
2482 mInvalidOperation = true;
2483}
2484
2485void Context::recordOutOfMemory()
2486{
2487 mOutOfMemory = true;
2488}
2489
2490void Context::recordInvalidFramebufferOperation()
2491{
2492 mInvalidFramebufferOperation = true;
2493}
2494
2495// Get one of the recorded errors and clear its flag, if any.
2496// [OpenGL ES 2.0.24] section 2.5 page 13.
2497GLenum Context::getError()
2498{
2499 if (mInvalidEnum)
2500 {
2501 mInvalidEnum = false;
2502
2503 return GL_INVALID_ENUM;
2504 }
2505
2506 if (mInvalidValue)
2507 {
2508 mInvalidValue = false;
2509
2510 return GL_INVALID_VALUE;
2511 }
2512
2513 if (mInvalidOperation)
2514 {
2515 mInvalidOperation = false;
2516
2517 return GL_INVALID_OPERATION;
2518 }
2519
2520 if (mOutOfMemory)
2521 {
2522 mOutOfMemory = false;
2523
2524 return GL_OUT_OF_MEMORY;
2525 }
2526
2527 if (mInvalidFramebufferOperation)
2528 {
2529 mInvalidFramebufferOperation = false;
2530
2531 return GL_INVALID_FRAMEBUFFER_OPERATION;
2532 }
2533
2534 return GL_NO_ERROR;
2535}
2536
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002537bool Context::supportsShaderModel3() const
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002538{
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002539 return mSupportsShaderModel3;
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002540}
2541
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002542void Context::detachBuffer(GLuint buffer)
2543{
2544 // [OpenGL ES 2.0.24] section 2.9 page 22:
2545 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2546 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2547
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002548 if (mState.arrayBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002549 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002550 mState.arrayBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002551 }
2552
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002553 if (mState.elementArrayBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002554 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002555 mState.elementArrayBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002556 }
2557
2558 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2559 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002560 if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002561 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002562 mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002563 }
2564 }
2565}
2566
2567void Context::detachTexture(GLuint texture)
2568{
2569 // [OpenGL ES 2.0.24] section 3.8 page 84:
2570 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2571 // rebound to texture object zero
2572
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002573 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002574 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002575 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002576 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002577 if (mState.samplerTexture[type][sampler].id() == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002578 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002579 mState.samplerTexture[type][sampler].set(NULL);
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002580 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002581 }
2582 }
2583
2584 // [OpenGL ES 2.0.24] section 4.4 page 112:
2585 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2586 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2587 // image was attached in the currently bound framebuffer.
2588
2589 Framebuffer *framebuffer = getFramebuffer();
2590
2591 if (framebuffer)
2592 {
2593 framebuffer->detachTexture(texture);
2594 }
2595}
2596
2597void Context::detachFramebuffer(GLuint framebuffer)
2598{
2599 // [OpenGL ES 2.0.24] section 4.4 page 107:
2600 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2601 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2602
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002603 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002604 {
2605 bindFramebuffer(0);
2606 }
2607}
2608
2609void Context::detachRenderbuffer(GLuint renderbuffer)
2610{
2611 // [OpenGL ES 2.0.24] section 4.4 page 109:
2612 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2613 // had been executed with the target RENDERBUFFER and name of zero.
2614
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002615 if (mState.renderbuffer.id() == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002616 {
2617 bindRenderbuffer(0);
2618 }
2619
2620 // [OpenGL ES 2.0.24] section 4.4 page 111:
2621 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2622 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2623 // point to which this image was attached in the currently bound framebuffer.
2624
2625 Framebuffer *framebuffer = getFramebuffer();
2626
2627 if (framebuffer)
2628 {
2629 framebuffer->detachRenderbuffer(renderbuffer);
2630 }
2631}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002632
2633Texture *Context::getIncompleteTexture(SamplerType type)
2634{
2635 Texture *t = mIncompleteTextures[type];
2636
2637 if (t == NULL)
2638 {
2639 static const GLubyte color[] = { 0, 0, 0, 255 };
2640
2641 switch (type)
2642 {
2643 default:
2644 UNREACHABLE();
2645 // default falls through to SAMPLER_2D
2646
2647 case SAMPLER_2D:
2648 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002649 Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002650 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002651 t = incomplete2d;
2652 }
2653 break;
2654
2655 case SAMPLER_CUBE:
2656 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002657 TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002658
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002659 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2660 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2661 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2662 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2663 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2664 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002665
2666 t = incompleteCube;
2667 }
2668 break;
2669 }
2670
2671 mIncompleteTextures[type] = t;
2672 }
2673
2674 return t;
2675}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002676
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002677bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002678{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002679 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002680}
2681
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002682bool Context::isTriangleMode(GLenum drawMode)
2683{
2684 switch (drawMode)
2685 {
2686 case GL_TRIANGLES:
2687 case GL_TRIANGLE_FAN:
2688 case GL_TRIANGLE_STRIP:
2689 return true;
2690 case GL_POINTS:
2691 case GL_LINES:
2692 case GL_LINE_LOOP:
2693 case GL_LINE_STRIP:
2694 return false;
2695 default: UNREACHABLE();
2696 }
2697
2698 return false;
2699}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002700
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002701bool Context::hasStencil()
2702{
2703 Framebuffer *framebufferObject = getFramebuffer();
2704
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002705 if (framebufferObject && framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002706 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002707 DepthStencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002708
2709 if (stencilbufferObject)
2710 {
2711 return stencilbufferObject->getStencilSize() > 0;
2712 }
2713 }
2714
2715 return false;
2716}
2717
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002718void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2719{
2720 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2721
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002722 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2723 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2724 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2725 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002726
2727 mVertexDataManager->dirtyCurrentValues();
2728}
2729
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002730void Context::initExtensionString()
2731{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002732 mExtensionString += "GL_OES_packed_depth_stencil ";
2733
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002734 if (mBufferBackEnd->supportIntIndices())
2735 {
2736 mExtensionString += "GL_OES_element_index_uint ";
2737 }
2738
2739 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2740 if (end != std::string::npos)
2741 {
2742 mExtensionString.resize(end+1);
2743 }
2744}
2745
2746const char *Context::getExtensionString() const
2747{
2748 return mExtensionString.c_str();
2749}
2750
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002751}
2752
2753extern "C"
2754{
daniel@transgaming.com0d25b002010-07-28 19:21:07 +00002755gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002756{
daniel@transgaming.com0d25b002010-07-28 19:21:07 +00002757 return new gl::Context(config, shareContext);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002758}
2759
2760void glDestroyContext(gl::Context *context)
2761{
2762 delete context;
2763
2764 if (context == gl::getContext())
2765 {
2766 gl::makeCurrent(NULL, NULL, NULL);
2767 }
2768}
2769
2770void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2771{
2772 gl::makeCurrent(context, display, surface);
2773}
2774
2775gl::Context *glGetCurrentContext()
2776{
2777 return gl::getContext();
2778}
2779}