blob: 50e610f683948f0883f07aebd39ef45363bbeb02 [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;
1412 }
1413
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001414 unsigned int depthbufferSerial = 0;
1415 unsigned int stencilbufferSerial = 0;
1416 if (framebufferObject->getDepthbufferType() != GL_NONE)
1417 {
1418 depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil();
1419 depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial();
1420 }
1421 else if (framebufferObject->getStencilbufferType() != GL_NONE)
1422 {
1423 depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
1424 stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial();
1425 }
1426
1427 if (depthbufferSerial != mAppliedDepthbufferSerial ||
1428 stencilbufferSerial != mAppliedStencilbufferSerial)
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001429 {
1430 device->SetDepthStencilSurface(depthStencil);
1431 mAppliedDepthbufferSerial = depthbufferSerial;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001432 mAppliedStencilbufferSerial = stencilbufferSerial;
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001433 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001434
1435 D3DVIEWPORT9 viewport;
1436 D3DSURFACE_DESC desc;
1437 renderTarget->GetDesc(&desc);
1438
1439 if (ignoreViewport)
1440 {
1441 viewport.X = 0;
1442 viewport.Y = 0;
1443 viewport.Width = desc.Width;
1444 viewport.Height = desc.Height;
1445 viewport.MinZ = 0.0f;
1446 viewport.MaxZ = 1.0f;
1447 }
1448 else
1449 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001450 viewport.X = std::max(mState.viewportX, 0);
1451 viewport.Y = std::max(mState.viewportY, 0);
1452 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1453 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
1454 viewport.MinZ = clamp01(mState.zNear);
1455 viewport.MaxZ = clamp01(mState.zFar);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001456 }
1457
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001458 if (viewport.Width <= 0 || viewport.Height <= 0)
1459 {
1460 return false; // Nothing to render
1461 }
1462
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001463 device->SetViewport(&viewport);
1464
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001465 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001466 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001467 if (mState.scissorTest)
1468 {
1469 RECT rect = {mState.scissorX,
1470 mState.scissorY,
1471 mState.scissorX + mState.scissorWidth,
1472 mState.scissorY + mState.scissorHeight};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001473
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001474 device->SetScissorRect(&rect);
1475 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1476 }
1477 else
1478 {
1479 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1480 }
1481
1482 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001483 }
1484
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001485 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001486 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001487 Program *programObject = getCurrentProgram();
1488
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001489 GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001490 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001491 programObject->setUniform2fv(halfPixelSize, 1, (GLfloat*)&xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001492
daniel@transgaming.com4f921eb2010-07-28 19:20:44 +00001493 GLint window = programObject->getDxViewportLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001494 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1495 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1496 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001497 programObject->setUniform4fv(window, 1, (GLfloat*)&whxy);
1498
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001499 GLint depth = programObject->getDxDepthLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001500 GLfloat dz[2] = {(mState.zFar - mState.zNear) / 2.0f, (mState.zNear + mState.zFar) / 2.0f};
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001501 programObject->setUniform2fv(depth, 1, (GLfloat*)&dz);
1502
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001503 GLint near = programObject->getDepthRangeNearLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001504 programObject->setUniform1fv(near, 1, &mState.zNear);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001505
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001506 GLint far = programObject->getDepthRangeFarLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001507 programObject->setUniform1fv(far, 1, &mState.zFar);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001508
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001509 GLint diff = programObject->getDepthRangeDiffLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001510 GLfloat zDiff = mState.zFar - mState.zNear;
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001511 programObject->setUniform1fv(diff, 1, &zDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001512 }
1513
1514 return true;
1515}
1516
1517// 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 +00001518void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001519{
1520 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001521 Program *programObject = getCurrentProgram();
1522
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001523 GLint frontCCW = programObject->getDxFrontCCWLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001524 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001525 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001526
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001527 GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001528 GLint alwaysFront = !isTriangleMode(drawMode);
1529 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1530
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001531 Framebuffer *framebufferObject = getFramebuffer();
1532
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001533 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001534 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001535 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001536 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001537 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001538 }
1539 else
1540 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001541 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001542 }
1543
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001544 mCullStateDirty = false;
1545 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001546
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001547 if (mDepthStateDirty)
1548 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001549 if (mState.depthTest && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001550 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001551 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1552 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001553 }
1554 else
1555 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001556 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001557 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001558
1559 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001560 }
1561
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001562 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001563 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001564 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001565 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001566 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1567
1568 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1569 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1570 {
1571 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1572 }
1573 else
1574 {
1575 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1576 unorm<8>(mState.blendColor.alpha),
1577 unorm<8>(mState.blendColor.alpha),
1578 unorm<8>(mState.blendColor.alpha)));
1579 }
1580
1581 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1582 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1583 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1584
1585 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1586 mState.destBlendRGB != mState.destBlendAlpha ||
1587 mState.blendEquationRGB != mState.blendEquationAlpha)
1588 {
1589 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1590
1591 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1592 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1593 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
1594
1595 }
1596 else
1597 {
1598 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1599 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001600 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001601 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001602 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001603 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001604 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001605
1606 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001607 }
1608
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001609 if (mStencilStateDirty || mFrontFaceDirty)
1610 {
1611 if (mState.stencilTest && hasStencil())
1612 {
1613 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1614 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1615
1616 // FIXME: Unsupported by D3D9
1617 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1618 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1619 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1620 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1621 mState.stencilRef != mState.stencilBackRef ||
1622 mState.stencilMask != mState.stencilBackMask)
1623 {
1624 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1625 return error(GL_INVALID_OPERATION);
1626 }
1627
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001628 // get the maximum size of the stencil ref
1629 gl::Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001630 gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001631 GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
1632
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001633 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1634 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1635 es2dx::ConvertComparison(mState.stencilFunc));
1636
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001637 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 +00001638 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
1639
1640 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1641 es2dx::ConvertStencilOp(mState.stencilFail));
1642 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1643 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1644 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1645 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1646
1647 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1648 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1649 es2dx::ConvertComparison(mState.stencilBackFunc));
1650
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001651 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 +00001652 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
1653
1654 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1655 es2dx::ConvertStencilOp(mState.stencilBackFail));
1656 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1657 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1658 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1659 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1660 }
1661 else
1662 {
1663 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1664 }
1665
1666 mStencilStateDirty = false;
1667 }
1668
1669 if (mMaskStateDirty)
1670 {
1671 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1672 mState.colorMaskBlue, mState.colorMaskAlpha));
1673 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1674
1675 mMaskStateDirty = false;
1676 }
1677
1678 if (mPolygonOffsetStateDirty)
1679 {
1680 if (mState.polygonOffsetFill)
1681 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001682 gl::DepthStencilbuffer *depthbuffer = getFramebuffer()->getDepthbuffer();
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001683 if (depthbuffer)
1684 {
1685 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1686 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1687 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1688 }
1689 }
1690 else
1691 {
1692 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1693 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1694 }
1695
1696 mPolygonOffsetStateDirty = false;
1697 }
1698
1699 if (mConfig->mMultiSample != 0 && mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001700 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001701 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001702 {
1703 FIXME("Sample alpha to coverage is unimplemented.");
1704 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001705
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001706 if (mState.sampleCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001707 {
1708 FIXME("Sample coverage is unimplemented.");
1709 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001710
1711 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001712 }
1713
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001714 if (mDitherStateDirty)
1715 {
1716 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
1717
1718 mDitherStateDirty = false;
1719 }
1720
1721 mFrontFaceDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001722}
1723
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001724// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001725void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001726{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001727 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001728 {
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001729 if (attributes[i].enabled)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001730 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001731 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001732 }
1733 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001734}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001735
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001736GLenum Context::applyVertexBuffer(GLenum mode, GLint first, GLsizei count, bool *useIndexing, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001737{
1738 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1739
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001740 GLenum err = mVertexDataManager->preRenderValidate(first, count, translated);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001741 if (err != GL_NO_ERROR)
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001742 {
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001743 return err;
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001744 }
1745
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001746 lookupAttributeMapping(translated);
1747
1748 mBufferBackEnd->setupAttributesPreDraw(translated);
1749
1750 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
1751 {
1752 if (translated[i].enabled && translated[i].nonArray)
1753 {
1754 err = mIndexDataManager->preRenderValidateUnindexed(mode, count, indexInfo);
1755 if (err != GL_NO_ERROR)
1756 {
1757 return err;
1758 }
1759
1760 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
1761
1762 *useIndexing = true;
1763 return GL_NO_ERROR;
1764 }
1765 }
1766
1767 *useIndexing = false;
1768 return GL_NO_ERROR;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001769}
1770
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001771GLenum Context::applyVertexBuffer(const TranslatedIndexData &indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001772{
1773 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1774
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001775 GLenum err = mVertexDataManager->preRenderValidate(indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001776
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001777 if (err == GL_NO_ERROR)
1778 {
1779 lookupAttributeMapping(translated);
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001780
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001781 mBufferBackEnd->setupAttributesPreDraw(translated);
1782 }
1783
1784 return err;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001785}
1786
1787// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001788GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001789{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001790 GLenum err = mIndexDataManager->preRenderValidate(mode, type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001791
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001792 if (err == GL_NO_ERROR)
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001793 {
1794 mBufferBackEnd->setupIndicesPreDraw(*indexInfo);
1795 }
1796
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001797 return err;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001798}
1799
1800// Applies the shaders and shader constants to the Direct3D 9 device
1801void Context::applyShaders()
1802{
1803 IDirect3DDevice9 *device = getDevice();
1804 Program *programObject = getCurrentProgram();
1805 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
1806 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
1807
1808 device->SetVertexShader(vertexShader);
1809 device->SetPixelShader(pixelShader);
1810
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001811 if (programObject->getSerial() != mAppliedProgram)
1812 {
1813 programObject->dirtyAllUniforms();
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001814 programObject->dirtyAllSamplers();
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00001815 mAppliedProgram = programObject->getSerial();
1816 }
1817
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001818 programObject->applyUniforms();
1819}
1820
1821// Applies the textures and sampler states to the Direct3D 9 device
1822void Context::applyTextures()
1823{
1824 IDirect3DDevice9 *device = getDevice();
1825 Program *programObject = getCurrentProgram();
1826
1827 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
1828 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001829 int textureUnit = programObject->getSamplerMapping(sampler);
1830 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001831 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001832 SamplerType textureType = programObject->getSamplerType(sampler);
1833
1834 Texture *texture = getSamplerTexture(textureUnit, textureType);
1835
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001836 if (programObject->isSamplerDirty(sampler) || texture->isDirty())
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001837 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001838 if (texture->isComplete())
1839 {
1840 GLenum wrapS = texture->getWrapS();
1841 GLenum wrapT = texture->getWrapT();
1842 GLenum minFilter = texture->getMinFilter();
1843 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001844
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001845 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
1846 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001847
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001848 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
1849 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
1850 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
1851 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
1852 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001853
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001854 device->SetTexture(sampler, texture->getTexture());
1855 }
1856 else
1857 {
1858 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
1859 }
daniel@transgaming.com12d54072010-03-16 06:23:26 +00001860 }
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001861
1862 programObject->setSamplerDirty(sampler, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001863 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001864 else
1865 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00001866 if (programObject->isSamplerDirty(sampler))
1867 {
1868 device->SetTexture(sampler, NULL);
1869 programObject->setSamplerDirty(sampler, false);
1870 }
1871 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001872 }
1873}
1874
1875void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
1876{
1877 Framebuffer *framebuffer = getFramebuffer();
daniel@transgaming.combbc57792010-07-28 19:21:05 +00001878
1879 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1880 {
1881 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1882 }
1883
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001884 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
1885 IDirect3DDevice9 *device = getDevice();
1886
1887 D3DSURFACE_DESC desc;
1888 renderTarget->GetDesc(&desc);
1889
1890 IDirect3DSurface9 *systemSurface;
1891 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
1892
1893 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
1894 {
1895 return error(GL_OUT_OF_MEMORY);
1896 }
1897
1898 ASSERT(SUCCEEDED(result));
1899
1900 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
1901 {
1902 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
1903 }
1904
1905 result = device->GetRenderTargetData(renderTarget, systemSurface);
1906
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001907 if (FAILED(result))
1908 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001909 systemSurface->Release();
1910
apatrick@chromium.org6db8cab2010-07-22 20:39:50 +00001911 switch (result)
1912 {
1913 case D3DERR_DRIVERINTERNALERROR:
1914 case D3DERR_DEVICELOST:
1915 return error(GL_OUT_OF_MEMORY);
1916 default:
1917 UNREACHABLE();
1918 return; // No sensible error to generate
1919 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001920 }
1921
1922 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00001923 RECT rect = {std::max(x, 0),
1924 std::max(y, 0),
1925 std::min(x + width, (int)desc.Width),
1926 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001927
1928 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
1929
1930 if (FAILED(result))
1931 {
1932 UNREACHABLE();
1933 systemSurface->Release();
1934
1935 return; // No sensible error to generate
1936 }
1937
1938 unsigned char *source = (unsigned char*)lock.pBits;
1939 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00001940 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001941
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001942 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00001943
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001944 for (int j = 0; j < rect.bottom - rect.top; j++)
1945 {
1946 for (int i = 0; i < rect.right - rect.left; i++)
1947 {
1948 float r;
1949 float g;
1950 float b;
1951 float a;
1952
1953 switch (desc.Format)
1954 {
1955 case D3DFMT_R5G6B5:
1956 {
1957 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1958
1959 a = 1.0f;
1960 b = (rgb & 0x001F) * (1.0f / 0x001F);
1961 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
1962 r = (rgb & 0xF800) * (1.0f / 0xF800);
1963 }
1964 break;
1965 case D3DFMT_X1R5G5B5:
1966 {
1967 unsigned short xrgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1968
1969 a = 1.0f;
1970 b = (xrgb & 0x001F) * (1.0f / 0x001F);
1971 g = (xrgb & 0x03E0) * (1.0f / 0x03E0);
1972 r = (xrgb & 0x7C00) * (1.0f / 0x7C00);
1973 }
1974 break;
1975 case D3DFMT_A1R5G5B5:
1976 {
1977 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
1978
1979 a = (argb & 0x8000) ? 1.0f : 0.0f;
1980 b = (argb & 0x001F) * (1.0f / 0x001F);
1981 g = (argb & 0x03E0) * (1.0f / 0x03E0);
1982 r = (argb & 0x7C00) * (1.0f / 0x7C00);
1983 }
1984 break;
1985 case D3DFMT_A8R8G8B8:
1986 {
1987 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1988
1989 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
1990 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
1991 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
1992 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
1993 }
1994 break;
1995 case D3DFMT_X8R8G8B8:
1996 {
1997 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
1998
1999 a = 1.0f;
2000 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2001 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2002 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2003 }
2004 break;
2005 case D3DFMT_A2R10G10B10:
2006 {
2007 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2008
2009 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2010 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2011 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2012 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2013 }
2014 break;
2015 default:
2016 UNIMPLEMENTED(); // FIXME
2017 UNREACHABLE();
2018 }
2019
2020 switch (format)
2021 {
2022 case GL_RGBA:
2023 switch (type)
2024 {
2025 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002026 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2027 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2028 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2029 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002030 break;
2031 default: UNREACHABLE();
2032 }
2033 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002034 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002035 switch (type)
2036 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002037 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002038 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2039 ((unsigned short)(31 * b + 0.5f) << 0) |
2040 ((unsigned short)(63 * g + 0.5f) << 5) |
2041 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002042 break;
2043 default: UNREACHABLE();
2044 }
2045 break;
2046 default: UNREACHABLE();
2047 }
2048 }
2049 }
2050
2051 systemSurface->UnlockRect();
2052
2053 systemSurface->Release();
2054}
2055
2056void Context::clear(GLbitfield mask)
2057{
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002058 Framebuffer *framebufferObject = getFramebuffer();
2059
2060 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2061 {
2062 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2063
2064 return;
2065 }
2066
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002067 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002068 IDirect3DDevice9 *device = getDevice();
2069 DWORD flags = 0;
2070
2071 if (mask & GL_COLOR_BUFFER_BIT)
2072 {
2073 mask &= ~GL_COLOR_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002074
2075 if (framebufferObject->getColorbufferType() != GL_NONE)
2076 {
2077 flags |= D3DCLEAR_TARGET;
2078 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002079 }
2080
2081 if (mask & GL_DEPTH_BUFFER_BIT)
2082 {
2083 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002084 if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002085 {
2086 flags |= D3DCLEAR_ZBUFFER;
2087 }
2088 }
2089
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002090 GLuint stencilUnmasked = 0x0;
2091
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002092 if (mask & GL_STENCIL_BUFFER_BIT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002093 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002094 mask &= ~GL_STENCIL_BUFFER_BIT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002095 if (framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002096 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002097 IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
2098 D3DSURFACE_DESC desc;
2099 depthStencil->GetDesc(&desc);
2100
2101 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2102 stencilUnmasked = (0x1 << stencilSize) - 1;
2103
2104 if (stencilUnmasked != 0x0)
2105 {
2106 flags |= D3DCLEAR_STENCIL;
2107 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002108 }
2109 }
2110
2111 if (mask != 0)
2112 {
2113 return error(GL_INVALID_VALUE);
2114 }
2115
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002116 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2117 {
2118 return;
2119 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002120
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002121 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2122 unorm<8>(mState.colorClearValue.red),
2123 unorm<8>(mState.colorClearValue.green),
2124 unorm<8>(mState.colorClearValue.blue));
2125 float depth = clamp01(mState.depthClearValue);
2126 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002127
2128 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2129
2130 D3DSURFACE_DESC desc;
2131 renderTarget->GetDesc(&desc);
2132
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002133 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002134
2135 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002136 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002137 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002138 !(mState.colorMaskRed && mState.colorMaskGreen &&
2139 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002140
2141 if (needMaskedColorClear || needMaskedStencilClear)
2142 {
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002143 // State which is altered in all paths from this point to the clear call is saved.
2144 // State which is altered in only some paths will be flagged dirty in the case that
2145 // that path is taken.
2146 HRESULT hr;
2147 if (mMaskedClearSavedState == NULL)
2148 {
2149 hr = device->BeginStateBlock();
2150 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2151
2152 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2153 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2154 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2155 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2156 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2157 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2158 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2159 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2160 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2161 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2162 device->SetPixelShader(NULL);
2163 device->SetVertexShader(NULL);
2164 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
2165 device->SetStreamSourceFreq(0, 1);
2166
2167 hr = device->EndStateBlock(&mMaskedClearSavedState);
2168 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2169 }
2170
2171 ASSERT(mMaskedClearSavedState != NULL);
2172
2173 if (mMaskedClearSavedState != NULL)
2174 {
2175 hr = mMaskedClearSavedState->Capture();
2176 ASSERT(SUCCEEDED(hr));
2177 }
2178
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002179 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2180 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2181 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2182 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2183 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2184 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2185 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2186 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2187
2188 if (flags & D3DCLEAR_TARGET)
2189 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002190 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2191 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2192 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2193 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002194 }
2195 else
2196 {
2197 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2198 }
2199
2200 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2201 {
2202 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2203 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2204 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2205 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002206 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002207 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002208 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2209 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002210 mStencilStateDirty = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002211 }
2212 else
2213 {
2214 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2215 }
2216
2217 device->SetPixelShader(NULL);
2218 device->SetVertexShader(NULL);
2219 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002220 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002221
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002222 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002223 {
2224 float x, y, z, w;
2225 D3DCOLOR diffuse;
2226 };
2227
2228 Vertex quad[4];
2229 quad[0].x = 0.0f;
2230 quad[0].y = (float)desc.Height;
2231 quad[0].z = 0.0f;
2232 quad[0].w = 1.0f;
2233 quad[0].diffuse = color;
2234
2235 quad[1].x = (float)desc.Width;
2236 quad[1].y = (float)desc.Height;
2237 quad[1].z = 0.0f;
2238 quad[1].w = 1.0f;
2239 quad[1].diffuse = color;
2240
2241 quad[2].x = 0.0f;
2242 quad[2].y = 0.0f;
2243 quad[2].z = 0.0f;
2244 quad[2].w = 1.0f;
2245 quad[2].diffuse = color;
2246
2247 quad[3].x = (float)desc.Width;
2248 quad[3].y = 0.0f;
2249 quad[3].z = 0.0f;
2250 quad[3].w = 1.0f;
2251 quad[3].diffuse = color;
2252
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002253 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002254 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002255
2256 if (flags & D3DCLEAR_ZBUFFER)
2257 {
2258 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2259 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2260 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2261 }
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002262
2263 if (mMaskedClearSavedState != NULL)
2264 {
2265 mMaskedClearSavedState->Apply();
2266 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002267 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002268 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002269 {
2270 device->Clear(0, NULL, flags, color, depth, stencil);
2271 }
2272}
2273
2274void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2275{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002276 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002277 {
2278 return error(GL_INVALID_OPERATION);
2279 }
2280
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002281 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002282 IDirect3DDevice9 *device = getDevice();
2283 D3DPRIMITIVETYPE primitiveType;
2284 int primitiveCount;
2285
2286 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2287 return error(GL_INVALID_ENUM);
2288
2289 if (primitiveCount <= 0)
2290 {
2291 return;
2292 }
2293
2294 if (!applyRenderTarget(false))
2295 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002296 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002297 }
2298
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002299 applyState(mode);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002300
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002301 TranslatedIndexData indexInfo;
2302 bool useIndexing;
2303 GLenum err = applyVertexBuffer(mode, first, count, &useIndexing, &indexInfo);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002304 if (err != GL_NO_ERROR)
2305 {
2306 return error(err);
2307 }
2308
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002309 applyShaders();
2310 applyTextures();
2311
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002312 if (!getCurrentProgram()->validateSamplers())
2313 {
2314 return error(GL_INVALID_OPERATION);
2315 }
2316
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002317 if (!cullSkipsDraw(mode))
2318 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002319 display->startScene();
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002320 if (useIndexing)
2321 {
2322 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, indexInfo.maxIndex-indexInfo.minIndex+1, indexInfo.offset/indexInfo.indexSize, primitiveCount);
2323 }
2324 else
2325 {
2326 device->DrawPrimitive(primitiveType, 0, primitiveCount);
2327 }
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002328 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002329}
2330
2331void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void* indices)
2332{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002333 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002334 {
2335 return error(GL_INVALID_OPERATION);
2336 }
2337
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002338 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002339 {
2340 return error(GL_INVALID_OPERATION);
2341 }
2342
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002343 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002344 IDirect3DDevice9 *device = getDevice();
2345 D3DPRIMITIVETYPE primitiveType;
2346 int primitiveCount;
2347
2348 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2349 return error(GL_INVALID_ENUM);
2350
2351 if (primitiveCount <= 0)
2352 {
2353 return;
2354 }
2355
2356 if (!applyRenderTarget(false))
2357 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002358 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002359 }
2360
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002361 applyState(mode);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002362
2363 TranslatedIndexData indexInfo;
2364 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2365 if (err != GL_NO_ERROR)
2366 {
2367 return error(err);
2368 }
2369
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002370 err = applyVertexBuffer(indexInfo);
2371 if (err != GL_NO_ERROR)
2372 {
2373 return error(err);
2374 }
2375
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002376 applyShaders();
2377 applyTextures();
2378
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002379 if (!getCurrentProgram()->validateSamplers())
2380 {
2381 return error(GL_INVALID_OPERATION);
2382 }
2383
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002384 if (!cullSkipsDraw(mode))
2385 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002386 display->startScene();
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002387 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 +00002388 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002389}
2390
2391void Context::finish()
2392{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002393 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002394 IDirect3DDevice9 *device = getDevice();
2395 IDirect3DQuery9 *occlusionQuery = NULL;
2396
2397 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2398
2399 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2400 {
2401 return error(GL_OUT_OF_MEMORY);
2402 }
2403
2404 ASSERT(SUCCEEDED(result));
2405
2406 if (occlusionQuery)
2407 {
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002408 IDirect3DStateBlock9 *savedState = NULL;
2409 device->CreateStateBlock(D3DSBT_ALL, &savedState);
2410
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002411 occlusionQuery->Issue(D3DISSUE_BEGIN);
2412
2413 // Render something outside the render target
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002414 device->SetStreamSourceFreq(0, 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002415 device->SetPixelShader(NULL);
2416 device->SetVertexShader(NULL);
2417 device->SetFVF(D3DFVF_XYZRHW);
2418 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002419 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002420 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002421
2422 occlusionQuery->Issue(D3DISSUE_END);
2423
2424 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2425 {
2426 // Keep polling, but allow other threads to do something useful first
2427 Sleep(0);
2428 }
2429
2430 occlusionQuery->Release();
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002431
2432 if (savedState)
2433 {
2434 savedState->Apply();
2435 savedState->Release();
2436 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002437 }
2438}
2439
2440void Context::flush()
2441{
2442 IDirect3DDevice9 *device = getDevice();
2443 IDirect3DQuery9 *eventQuery = NULL;
2444
2445 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2446
2447 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2448 {
2449 return error(GL_OUT_OF_MEMORY);
2450 }
2451
2452 ASSERT(SUCCEEDED(result));
2453
2454 if (eventQuery)
2455 {
2456 eventQuery->Issue(D3DISSUE_END);
2457
2458 while (eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2459 {
2460 // Keep polling, but allow other threads to do something useful first
2461 Sleep(0);
2462 }
2463
2464 eventQuery->Release();
2465 }
2466}
2467
2468void Context::recordInvalidEnum()
2469{
2470 mInvalidEnum = true;
2471}
2472
2473void Context::recordInvalidValue()
2474{
2475 mInvalidValue = true;
2476}
2477
2478void Context::recordInvalidOperation()
2479{
2480 mInvalidOperation = true;
2481}
2482
2483void Context::recordOutOfMemory()
2484{
2485 mOutOfMemory = true;
2486}
2487
2488void Context::recordInvalidFramebufferOperation()
2489{
2490 mInvalidFramebufferOperation = true;
2491}
2492
2493// Get one of the recorded errors and clear its flag, if any.
2494// [OpenGL ES 2.0.24] section 2.5 page 13.
2495GLenum Context::getError()
2496{
2497 if (mInvalidEnum)
2498 {
2499 mInvalidEnum = false;
2500
2501 return GL_INVALID_ENUM;
2502 }
2503
2504 if (mInvalidValue)
2505 {
2506 mInvalidValue = false;
2507
2508 return GL_INVALID_VALUE;
2509 }
2510
2511 if (mInvalidOperation)
2512 {
2513 mInvalidOperation = false;
2514
2515 return GL_INVALID_OPERATION;
2516 }
2517
2518 if (mOutOfMemory)
2519 {
2520 mOutOfMemory = false;
2521
2522 return GL_OUT_OF_MEMORY;
2523 }
2524
2525 if (mInvalidFramebufferOperation)
2526 {
2527 mInvalidFramebufferOperation = false;
2528
2529 return GL_INVALID_FRAMEBUFFER_OPERATION;
2530 }
2531
2532 return GL_NO_ERROR;
2533}
2534
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002535bool Context::supportsShaderModel3() const
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002536{
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002537 return mSupportsShaderModel3;
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002538}
2539
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002540void Context::detachBuffer(GLuint buffer)
2541{
2542 // [OpenGL ES 2.0.24] section 2.9 page 22:
2543 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2544 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2545
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002546 if (mState.arrayBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002547 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002548 mState.arrayBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002549 }
2550
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002551 if (mState.elementArrayBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002552 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002553 mState.elementArrayBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002554 }
2555
2556 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2557 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002558 if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002559 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002560 mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002561 }
2562 }
2563}
2564
2565void Context::detachTexture(GLuint texture)
2566{
2567 // [OpenGL ES 2.0.24] section 3.8 page 84:
2568 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2569 // rebound to texture object zero
2570
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002571 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002572 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002573 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002574 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002575 if (mState.samplerTexture[type][sampler].id() == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002576 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002577 mState.samplerTexture[type][sampler].set(NULL);
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002578 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002579 }
2580 }
2581
2582 // [OpenGL ES 2.0.24] section 4.4 page 112:
2583 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2584 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2585 // image was attached in the currently bound framebuffer.
2586
2587 Framebuffer *framebuffer = getFramebuffer();
2588
2589 if (framebuffer)
2590 {
2591 framebuffer->detachTexture(texture);
2592 }
2593}
2594
2595void Context::detachFramebuffer(GLuint framebuffer)
2596{
2597 // [OpenGL ES 2.0.24] section 4.4 page 107:
2598 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2599 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2600
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002601 if (mState.framebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002602 {
2603 bindFramebuffer(0);
2604 }
2605}
2606
2607void Context::detachRenderbuffer(GLuint renderbuffer)
2608{
2609 // [OpenGL ES 2.0.24] section 4.4 page 109:
2610 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2611 // had been executed with the target RENDERBUFFER and name of zero.
2612
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002613 if (mState.renderbuffer.id() == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002614 {
2615 bindRenderbuffer(0);
2616 }
2617
2618 // [OpenGL ES 2.0.24] section 4.4 page 111:
2619 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2620 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2621 // point to which this image was attached in the currently bound framebuffer.
2622
2623 Framebuffer *framebuffer = getFramebuffer();
2624
2625 if (framebuffer)
2626 {
2627 framebuffer->detachRenderbuffer(renderbuffer);
2628 }
2629}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002630
2631Texture *Context::getIncompleteTexture(SamplerType type)
2632{
2633 Texture *t = mIncompleteTextures[type];
2634
2635 if (t == NULL)
2636 {
2637 static const GLubyte color[] = { 0, 0, 0, 255 };
2638
2639 switch (type)
2640 {
2641 default:
2642 UNREACHABLE();
2643 // default falls through to SAMPLER_2D
2644
2645 case SAMPLER_2D:
2646 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002647 Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002648 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002649 t = incomplete2d;
2650 }
2651 break;
2652
2653 case SAMPLER_CUBE:
2654 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00002655 TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002656
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00002657 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2658 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2659 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2660 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2661 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2662 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002663
2664 t = incompleteCube;
2665 }
2666 break;
2667 }
2668
2669 mIncompleteTextures[type] = t;
2670 }
2671
2672 return t;
2673}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002674
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002675bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002676{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002677 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002678}
2679
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002680bool Context::isTriangleMode(GLenum drawMode)
2681{
2682 switch (drawMode)
2683 {
2684 case GL_TRIANGLES:
2685 case GL_TRIANGLE_FAN:
2686 case GL_TRIANGLE_STRIP:
2687 return true;
2688 case GL_POINTS:
2689 case GL_LINES:
2690 case GL_LINE_LOOP:
2691 case GL_LINE_STRIP:
2692 return false;
2693 default: UNREACHABLE();
2694 }
2695
2696 return false;
2697}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002698
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002699bool Context::hasStencil()
2700{
2701 Framebuffer *framebufferObject = getFramebuffer();
2702
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002703 if (framebufferObject && framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002704 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002705 DepthStencilbuffer *stencilbufferObject = framebufferObject->getStencilbuffer();
daniel@transgaming.com5bd0ce32010-05-07 13:03:31 +00002706
2707 if (stencilbufferObject)
2708 {
2709 return stencilbufferObject->getStencilSize() > 0;
2710 }
2711 }
2712
2713 return false;
2714}
2715
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002716void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2717{
2718 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2719
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002720 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2721 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2722 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2723 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00002724
2725 mVertexDataManager->dirtyCurrentValues();
2726}
2727
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002728void Context::initExtensionString()
2729{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002730 mExtensionString += "GL_OES_packed_depth_stencil ";
2731
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00002732 if (mBufferBackEnd->supportIntIndices())
2733 {
2734 mExtensionString += "GL_OES_element_index_uint ";
2735 }
2736
2737 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2738 if (end != std::string::npos)
2739 {
2740 mExtensionString.resize(end+1);
2741 }
2742}
2743
2744const char *Context::getExtensionString() const
2745{
2746 return mExtensionString.c_str();
2747}
2748
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002749}
2750
2751extern "C"
2752{
daniel@transgaming.com0d25b002010-07-28 19:21:07 +00002753gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002754{
daniel@transgaming.com0d25b002010-07-28 19:21:07 +00002755 return new gl::Context(config, shareContext);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002756}
2757
2758void glDestroyContext(gl::Context *context)
2759{
2760 delete context;
2761
2762 if (context == gl::getContext())
2763 {
2764 gl::makeCurrent(NULL, NULL, NULL);
2765 }
2766}
2767
2768void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
2769{
2770 gl::makeCurrent(context, display, surface);
2771}
2772
2773gl::Context *glGetCurrentContext()
2774{
2775 return gl::getContext();
2776}
2777}