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