blob: 77fff26084f73761b6a97e9acc380eee2fb3963d [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
daniel@transgaming.comaf29cac2011-05-11 15:36:31 +00002// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// 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"
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +000022#include "libGLESv2/Fence.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000023#include "libGLESv2/FrameBuffer.h"
24#include "libGLESv2/Program.h"
25#include "libGLESv2/RenderBuffer.h"
26#include "libGLESv2/Shader.h"
27#include "libGLESv2/Texture.h"
daniel@transgaming.com8fd34bd2011-02-18 02:52:14 +000028#include "libGLESv2/VertexDataManager.h"
29#include "libGLESv2/IndexDataManager.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030
daniel@transgaming.com86487c22010-03-11 19:41:43 +000031#undef near
32#undef far
33
jbauman@chromium.org399c35f2011-04-28 23:19:51 +000034namespace
35{
36 enum { CLOSING_INDEX_BUFFER_SIZE = 4096 };
37}
38
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000039namespace gl
40{
daniel@transgaming.com09c2c1a2011-04-13 14:57:16 +000041Context::Context(const egl::Config *config, const gl::Context *shareContext) : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042{
benvanik@google.com1a233342011-04-28 19:44:39 +000043 mFenceHandleAllocator.setBaseHandle(0);
44
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000045 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
daniel@transgaming.com092bd482010-05-12 03:39:36 +000046
daniel@transgaming.com428d1582010-05-04 03:35:25 +000047 mState.depthClearValue = 1.0f;
48 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000049
daniel@transgaming.com428d1582010-05-04 03:35:25 +000050 mState.cullFace = false;
51 mState.cullMode = GL_BACK;
52 mState.frontFace = GL_CCW;
53 mState.depthTest = false;
54 mState.depthFunc = GL_LESS;
55 mState.blend = false;
56 mState.sourceBlendRGB = GL_ONE;
57 mState.sourceBlendAlpha = GL_ONE;
58 mState.destBlendRGB = GL_ZERO;
59 mState.destBlendAlpha = GL_ZERO;
60 mState.blendEquationRGB = GL_FUNC_ADD;
61 mState.blendEquationAlpha = GL_FUNC_ADD;
62 mState.blendColor.red = 0;
63 mState.blendColor.green = 0;
64 mState.blendColor.blue = 0;
65 mState.blendColor.alpha = 0;
66 mState.stencilTest = false;
67 mState.stencilFunc = GL_ALWAYS;
68 mState.stencilRef = 0;
69 mState.stencilMask = -1;
70 mState.stencilWritemask = -1;
71 mState.stencilBackFunc = GL_ALWAYS;
72 mState.stencilBackRef = 0;
73 mState.stencilBackMask = - 1;
74 mState.stencilBackWritemask = -1;
75 mState.stencilFail = GL_KEEP;
76 mState.stencilPassDepthFail = GL_KEEP;
77 mState.stencilPassDepthPass = GL_KEEP;
78 mState.stencilBackFail = GL_KEEP;
79 mState.stencilBackPassDepthFail = GL_KEEP;
80 mState.stencilBackPassDepthPass = GL_KEEP;
81 mState.polygonOffsetFill = false;
82 mState.polygonOffsetFactor = 0.0f;
83 mState.polygonOffsetUnits = 0.0f;
84 mState.sampleAlphaToCoverage = false;
85 mState.sampleCoverage = false;
86 mState.sampleCoverageValue = 1.0f;
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +000087 mState.sampleCoverageInvert = false;
daniel@transgaming.com428d1582010-05-04 03:35:25 +000088 mState.scissorTest = false;
89 mState.dither = true;
90 mState.generateMipmapHint = GL_DONT_CARE;
alokp@chromium.orgd303ef92010-09-09 17:30:15 +000091 mState.fragmentShaderDerivativeHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092
daniel@transgaming.com428d1582010-05-04 03:35:25 +000093 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000094
daniel@transgaming.com428d1582010-05-04 03:35:25 +000095 mState.viewportX = 0;
96 mState.viewportY = 0;
97 mState.viewportWidth = config->mDisplayMode.Width;
98 mState.viewportHeight = config->mDisplayMode.Height;
99 mState.zNear = 0.0f;
100 mState.zFar = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000102 mState.scissorX = 0;
103 mState.scissorY = 0;
104 mState.scissorWidth = config->mDisplayMode.Width;
105 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000107 mState.colorMaskRed = true;
108 mState.colorMaskGreen = true;
109 mState.colorMaskBlue = true;
110 mState.colorMaskAlpha = true;
111 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000112
daniel@transgaming.com0d25b002010-07-28 19:21:07 +0000113 if (shareContext != NULL)
114 {
115 mResourceManager = shareContext->mResourceManager;
116 mResourceManager->addRef();
117 }
118 else
119 {
120 mResourceManager = new ResourceManager();
121 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000122
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123 // [OpenGL ES 2.0.24] section 3.7 page 83:
124 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
125 // and cube map texture state vectors respectively associated with them.
126 // In order that access to these initial textures not be lost, they are treated as texture
127 // objects all of whose names are 0.
128
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +0000129 mTexture2DZero.set(new Texture2D(0));
130 mTextureCubeMapZero.set(new TextureCubeMap(0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000132 mState.activeSampler = 0;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000133 bindArrayBuffer(0);
134 bindElementArrayBuffer(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000135 bindTextureCubeMap(0);
136 bindTexture2D(0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000137 bindReadFramebuffer(0);
138 bindDrawFramebuffer(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000139 bindRenderbuffer(0);
140
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000141 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000142
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000143 mState.packAlignment = 4;
144 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000145
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000146 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000147 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000148 mBlit = NULL;
jbauman@chromium.org399c35f2011-04-28 23:19:51 +0000149 mClosingIB = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000150
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151 mInvalidEnum = false;
152 mInvalidValue = false;
153 mInvalidOperation = false;
154 mOutOfMemory = false;
155 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000156
157 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000158
gman@chromium.org50c526d2011-08-10 05:19:44 +0000159 mSupportsDXT1Textures = false;
160 mSupportsDXT3Textures = false;
161 mSupportsDXT5Textures = false;
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000162 mSupportsEventQueries = false;
gman@chromium.org50c526d2011-08-10 05:19:44 +0000163 mNumCompressedTextureFormats = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000164 mMaxSupportedSamples = 0;
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000165 mMaskedClearSavedState = NULL;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000166 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167}
168
169Context::~Context()
170{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000171 if (mState.currentProgram != 0)
172 {
173 Program *programObject = mResourceManager->getProgram(mState.currentProgram);
174 if (programObject)
175 {
176 programObject->release();
177 }
178 mState.currentProgram = 0;
179 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000180
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000181 while (!mFramebufferMap.empty())
182 {
183 deleteFramebuffer(mFramebufferMap.begin()->first);
184 }
185
daniel@transgaming.comfe208882010-09-01 15:47:57 +0000186 while (!mFenceMap.empty())
187 {
188 deleteFence(mFenceMap.begin()->first);
189 }
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000190
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000191 while (!mMultiSampleSupport.empty())
192 {
193 delete [] mMultiSampleSupport.begin()->second;
194 mMultiSampleSupport.erase(mMultiSampleSupport.begin());
195 }
196
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +0000197 for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000198 {
daniel@transgaming.com3f74c7a2011-05-11 15:36:51 +0000199 for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000200 {
201 mState.samplerTexture[type][sampler].set(NULL);
202 }
203 }
204
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +0000205 for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000206 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +0000207 mIncompleteTextures[type].set(NULL);
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000208 }
209
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000210 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
211 {
212 mState.vertexAttribute[i].mBoundBuffer.set(NULL);
213 }
214
215 mState.arrayBuffer.set(NULL);
216 mState.elementArrayBuffer.set(NULL);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000217 mState.renderbuffer.set(NULL);
218
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +0000219 mTexture2DZero.set(NULL);
220 mTextureCubeMapZero.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000222 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000223 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000224 delete mBlit;
jbauman@chromium.org399c35f2011-04-28 23:19:51 +0000225 delete mClosingIB;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000226
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000227 if (mMaskedClearSavedState)
228 {
229 mMaskedClearSavedState->Release();
230 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000231
daniel@transgaming.com0d25b002010-07-28 19:21:07 +0000232 mResourceManager->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233}
234
235void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
236{
237 IDirect3DDevice9 *device = display->getDevice();
238
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000239 if (!mHasBeenCurrent)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000240 {
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000241 mDeviceCaps = display->getDeviceCaps();
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000242
daniel@transgaming.com83921382011-01-08 05:46:00 +0000243 mVertexDataManager = new VertexDataManager(this, device);
244 mIndexDataManager = new IndexDataManager(this, device);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000245 mBlit = new Blit(this);
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000246
daniel@transgaming.com5d752f22010-10-07 13:37:20 +0000247 mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
daniel@transgaming.comaf29cac2011-05-11 15:36:31 +0000248 mSupportsVertexTexture = display->getVertexTextureSupport();
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +0000249 mSupportsNonPower2Texture = display->getNonPower2TextureSupport();
daniel@transgaming.com5d752f22010-10-07 13:37:20 +0000250
251 mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight),
252 (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
253 mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
254 mMaxRenderbufferDimension = mMaxTextureDimension;
255 mMaxTextureLevel = log2(mMaxTextureDimension) + 1;
256 TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d",
257 mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel);
258
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000259 const D3DFORMAT renderBufferFormats[] =
260 {
261 D3DFMT_A8R8G8B8,
daniel@transgaming.com63977542010-08-24 19:21:02 +0000262 D3DFMT_X8R8G8B8,
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000263 D3DFMT_R5G6B5,
264 D3DFMT_D24S8
265 };
266
267 int max = 0;
268 for (int i = 0; i < sizeof(renderBufferFormats) / sizeof(D3DFORMAT); ++i)
269 {
270 bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
271 display->getMultiSampleSupport(renderBufferFormats[i], multisampleArray);
272 mMultiSampleSupport[renderBufferFormats[i]] = multisampleArray;
273
274 for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
275 {
276 if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
277 {
278 max = j;
279 }
280 }
281 }
282
283 mMaxSupportedSamples = max;
284
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000285 mSupportsEventQueries = display->getEventQuerySupport();
gman@chromium.org50c526d2011-08-10 05:19:44 +0000286 mSupportsDXT1Textures = display->getDXT1TextureSupport();
287 mSupportsDXT3Textures = display->getDXT3TextureSupport();
288 mSupportsDXT5Textures = display->getDXT5TextureSupport();
daniel@transgaming.com1297d922010-09-01 15:47:47 +0000289 mSupportsFloatTextures = display->getFloatTextureSupport(&mSupportsFloatLinearFilter, &mSupportsFloatRenderableTextures);
290 mSupportsHalfFloatTextures = display->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter, &mSupportsHalfFloatRenderableTextures);
daniel@transgaming.comed828e52010-10-15 17:57:30 +0000291 mSupportsLuminanceTextures = display->getLuminanceTextureSupport();
292 mSupportsLuminanceAlphaTextures = display->getLuminanceAlphaTextureSupport();
daniel@transgaming.com01868132010-08-24 19:21:17 +0000293
daniel@transgaming.com83921382011-01-08 05:46:00 +0000294 mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16);
295
gman@chromium.org50c526d2011-08-10 05:19:44 +0000296 mNumCompressedTextureFormats = 0;
297 if (supportsDXT1Textures())
298 {
299 mNumCompressedTextureFormats += 2;
300 }
301 if (supportsDXT3Textures())
302 {
303 mNumCompressedTextureFormats += 1;
304 }
305 if (supportsDXT5Textures())
306 {
307 mNumCompressedTextureFormats += 1;
308 }
309
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000310 initExtensionString();
311
312 mState.viewportX = 0;
313 mState.viewportY = 0;
314 mState.viewportWidth = surface->getWidth();
315 mState.viewportHeight = surface->getHeight();
316
317 mState.scissorX = 0;
318 mState.scissorY = 0;
319 mState.scissorWidth = surface->getWidth();
320 mState.scissorHeight = surface->getHeight();
321
322 mHasBeenCurrent = true;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000323 }
324
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000325 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
326 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000327 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000328
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000329 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000330 DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000331 Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332
333 setFramebufferZero(framebufferZero);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000334
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000335 if (defaultRenderTarget)
336 {
337 defaultRenderTarget->Release();
338 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000340 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000342 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000343 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000344
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000345 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000346}
347
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000348// 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 +0000349void Context::markAllStateDirty()
350{
daniel@transgaming.com38e76e52011-03-21 16:39:10 +0000351 for (int t = 0; t < MAX_TEXTURE_IMAGE_UNITS; t++)
352 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +0000353 mAppliedTextureSerialPS[t] = 0;
354 }
355
356 for (int t = 0; t < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; t++)
357 {
358 mAppliedTextureSerialVS[t] = 0;
daniel@transgaming.com38e76e52011-03-21 16:39:10 +0000359 }
360
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +0000361 mAppliedProgramSerial = 0;
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000362 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000363 mAppliedDepthbufferSerial = 0;
apatrick@chromium.org85dc42b2010-09-14 03:10:08 +0000364 mAppliedStencilbufferSerial = 0;
vangelis@chromium.orgcf66ebb2010-09-14 22:15:43 +0000365 mDepthStencilInitialized = false;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000366
367 mClearStateDirty = true;
368 mCullStateDirty = true;
369 mDepthStateDirty = true;
370 mMaskStateDirty = true;
371 mBlendStateDirty = true;
372 mStencilStateDirty = true;
373 mPolygonOffsetStateDirty = true;
374 mScissorStateDirty = true;
375 mSampleStateDirty = true;
376 mDitherStateDirty = true;
daniel@transgaming.com0d25b002010-07-28 19:21:07 +0000377 mFrontFaceDirty = true;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000378}
379
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000380void Context::setClearColor(float red, float green, float blue, float alpha)
381{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000382 mState.colorClearValue.red = red;
383 mState.colorClearValue.green = green;
384 mState.colorClearValue.blue = blue;
385 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000386}
387
388void Context::setClearDepth(float depth)
389{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000390 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391}
392
393void Context::setClearStencil(int stencil)
394{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000395 mState.stencilClearValue = stencil;
396}
397
398void Context::setCullFace(bool enabled)
399{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000400 if (mState.cullFace != enabled)
401 {
402 mState.cullFace = enabled;
403 mCullStateDirty = true;
404 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000405}
406
407bool Context::isCullFaceEnabled() const
408{
409 return mState.cullFace;
410}
411
412void Context::setCullMode(GLenum mode)
413{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000414 if (mState.cullMode != mode)
415 {
416 mState.cullMode = mode;
417 mCullStateDirty = true;
418 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000419}
420
421void Context::setFrontFace(GLenum front)
422{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000423 if (mState.frontFace != front)
424 {
425 mState.frontFace = front;
426 mFrontFaceDirty = true;
427 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000428}
429
430void Context::setDepthTest(bool enabled)
431{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000432 if (mState.depthTest != enabled)
433 {
434 mState.depthTest = enabled;
435 mDepthStateDirty = true;
436 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000437}
438
439bool Context::isDepthTestEnabled() const
440{
441 return mState.depthTest;
442}
443
444void Context::setDepthFunc(GLenum depthFunc)
445{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000446 if (mState.depthFunc != depthFunc)
447 {
448 mState.depthFunc = depthFunc;
449 mDepthStateDirty = true;
450 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000451}
452
453void Context::setDepthRange(float zNear, float zFar)
454{
455 mState.zNear = zNear;
456 mState.zFar = zFar;
457}
458
459void Context::setBlend(bool enabled)
460{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000461 if (mState.blend != enabled)
462 {
463 mState.blend = enabled;
464 mBlendStateDirty = true;
465 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000466}
467
468bool Context::isBlendEnabled() const
469{
470 return mState.blend;
471}
472
473void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
474{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000475 if (mState.sourceBlendRGB != sourceRGB ||
476 mState.sourceBlendAlpha != sourceAlpha ||
477 mState.destBlendRGB != destRGB ||
478 mState.destBlendAlpha != destAlpha)
479 {
480 mState.sourceBlendRGB = sourceRGB;
481 mState.destBlendRGB = destRGB;
482 mState.sourceBlendAlpha = sourceAlpha;
483 mState.destBlendAlpha = destAlpha;
484 mBlendStateDirty = true;
485 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000486}
487
488void Context::setBlendColor(float red, float green, float blue, float alpha)
489{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000490 if (mState.blendColor.red != red ||
491 mState.blendColor.green != green ||
492 mState.blendColor.blue != blue ||
493 mState.blendColor.alpha != alpha)
494 {
495 mState.blendColor.red = red;
496 mState.blendColor.green = green;
497 mState.blendColor.blue = blue;
498 mState.blendColor.alpha = alpha;
499 mBlendStateDirty = true;
500 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000501}
502
503void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
504{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000505 if (mState.blendEquationRGB != rgbEquation ||
506 mState.blendEquationAlpha != alphaEquation)
507 {
508 mState.blendEquationRGB = rgbEquation;
509 mState.blendEquationAlpha = alphaEquation;
510 mBlendStateDirty = true;
511 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000512}
513
514void Context::setStencilTest(bool enabled)
515{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000516 if (mState.stencilTest != enabled)
517 {
518 mState.stencilTest = enabled;
519 mStencilStateDirty = true;
520 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000521}
522
523bool Context::isStencilTestEnabled() const
524{
525 return mState.stencilTest;
526}
527
528void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
529{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000530 if (mState.stencilFunc != stencilFunc ||
531 mState.stencilRef != stencilRef ||
532 mState.stencilMask != stencilMask)
533 {
534 mState.stencilFunc = stencilFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000535 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000536 mState.stencilMask = stencilMask;
537 mStencilStateDirty = true;
538 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000539}
540
541void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
542{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000543 if (mState.stencilBackFunc != stencilBackFunc ||
544 mState.stencilBackRef != stencilBackRef ||
545 mState.stencilBackMask != stencilBackMask)
546 {
547 mState.stencilBackFunc = stencilBackFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000548 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000549 mState.stencilBackMask = stencilBackMask;
550 mStencilStateDirty = true;
551 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000552}
553
554void Context::setStencilWritemask(GLuint stencilWritemask)
555{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000556 if (mState.stencilWritemask != stencilWritemask)
557 {
558 mState.stencilWritemask = stencilWritemask;
559 mStencilStateDirty = true;
560 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000561}
562
563void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
564{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000565 if (mState.stencilBackWritemask != stencilBackWritemask)
566 {
567 mState.stencilBackWritemask = stencilBackWritemask;
568 mStencilStateDirty = true;
569 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000570}
571
572void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
573{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000574 if (mState.stencilFail != stencilFail ||
575 mState.stencilPassDepthFail != stencilPassDepthFail ||
576 mState.stencilPassDepthPass != stencilPassDepthPass)
577 {
578 mState.stencilFail = stencilFail;
579 mState.stencilPassDepthFail = stencilPassDepthFail;
580 mState.stencilPassDepthPass = stencilPassDepthPass;
581 mStencilStateDirty = true;
582 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000583}
584
585void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
586{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000587 if (mState.stencilBackFail != stencilBackFail ||
588 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
589 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
590 {
591 mState.stencilBackFail = stencilBackFail;
592 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
593 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
594 mStencilStateDirty = true;
595 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000596}
597
598void Context::setPolygonOffsetFill(bool enabled)
599{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000600 if (mState.polygonOffsetFill != enabled)
601 {
602 mState.polygonOffsetFill = enabled;
603 mPolygonOffsetStateDirty = true;
604 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000605}
606
607bool Context::isPolygonOffsetFillEnabled() const
608{
609 return mState.polygonOffsetFill;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000610
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000611}
612
613void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
614{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000615 if (mState.polygonOffsetFactor != factor ||
616 mState.polygonOffsetUnits != units)
617 {
618 mState.polygonOffsetFactor = factor;
619 mState.polygonOffsetUnits = units;
620 mPolygonOffsetStateDirty = true;
621 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000622}
623
624void Context::setSampleAlphaToCoverage(bool enabled)
625{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000626 if (mState.sampleAlphaToCoverage != enabled)
627 {
628 mState.sampleAlphaToCoverage = enabled;
629 mSampleStateDirty = true;
630 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000631}
632
633bool Context::isSampleAlphaToCoverageEnabled() const
634{
635 return mState.sampleAlphaToCoverage;
636}
637
638void Context::setSampleCoverage(bool enabled)
639{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000640 if (mState.sampleCoverage != enabled)
641 {
642 mState.sampleCoverage = enabled;
643 mSampleStateDirty = true;
644 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000645}
646
647bool Context::isSampleCoverageEnabled() const
648{
649 return mState.sampleCoverage;
650}
651
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +0000652void Context::setSampleCoverageParams(GLclampf value, bool invert)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000653{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000654 if (mState.sampleCoverageValue != value ||
655 mState.sampleCoverageInvert != invert)
656 {
657 mState.sampleCoverageValue = value;
658 mState.sampleCoverageInvert = invert;
659 mSampleStateDirty = true;
660 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000661}
662
663void Context::setScissorTest(bool enabled)
664{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000665 if (mState.scissorTest != enabled)
666 {
667 mState.scissorTest = enabled;
668 mScissorStateDirty = true;
669 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000670}
671
672bool Context::isScissorTestEnabled() const
673{
674 return mState.scissorTest;
675}
676
677void Context::setDither(bool enabled)
678{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000679 if (mState.dither != enabled)
680 {
681 mState.dither = enabled;
682 mDitherStateDirty = true;
683 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000684}
685
686bool Context::isDitherEnabled() const
687{
688 return mState.dither;
689}
690
691void Context::setLineWidth(GLfloat width)
692{
693 mState.lineWidth = width;
694}
695
696void Context::setGenerateMipmapHint(GLenum hint)
697{
698 mState.generateMipmapHint = hint;
699}
700
alokp@chromium.orgd303ef92010-09-09 17:30:15 +0000701void Context::setFragmentShaderDerivativeHint(GLenum hint)
702{
703 mState.fragmentShaderDerivativeHint = hint;
704 // TODO: Propagate the hint to shader translator so we can write
705 // ddx, ddx_coarse, or ddx_fine depending on the hint.
706 // Ignore for now. It is valid for implementations to ignore hint.
707}
708
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000709void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
710{
711 mState.viewportX = x;
712 mState.viewportY = y;
713 mState.viewportWidth = width;
714 mState.viewportHeight = height;
715}
716
717void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
718{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000719 if (mState.scissorX != x || mState.scissorY != y ||
720 mState.scissorWidth != width || mState.scissorHeight != height)
721 {
722 mState.scissorX = x;
723 mState.scissorY = y;
724 mState.scissorWidth = width;
725 mState.scissorHeight = height;
726 mScissorStateDirty = true;
727 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000728}
729
730void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
731{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000732 if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
733 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
734 {
735 mState.colorMaskRed = red;
736 mState.colorMaskGreen = green;
737 mState.colorMaskBlue = blue;
738 mState.colorMaskAlpha = alpha;
739 mMaskStateDirty = true;
740 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000741}
742
743void Context::setDepthMask(bool mask)
744{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000745 if (mState.depthMask != mask)
746 {
747 mState.depthMask = mask;
748 mMaskStateDirty = true;
749 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000750}
751
daniel@transgaming.comdfd57022011-05-11 15:37:25 +0000752void Context::setActiveSampler(unsigned int active)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000753{
754 mState.activeSampler = active;
755}
756
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000757GLuint Context::getReadFramebufferHandle() const
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000758{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000759 return mState.readFramebuffer;
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000760}
761
762GLuint Context::getDrawFramebufferHandle() const
763{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000764 return mState.drawFramebuffer;
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000765}
766
767GLuint Context::getRenderbufferHandle() const
768{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000769 return mState.renderbuffer.id();
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000770}
771
772GLuint Context::getArrayBufferHandle() const
773{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000774 return mState.arrayBuffer.id();
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000775}
776
daniel@transgaming.com83921382011-01-08 05:46:00 +0000777void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000778{
daniel@transgaming.com83921382011-01-08 05:46:00 +0000779 mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000780}
781
daniel@transgaming.com83921382011-01-08 05:46:00 +0000782const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000783{
784 return mState.vertexAttribute[attribNum];
785}
786
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000787void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000788 GLsizei stride, const void *pointer)
789{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000790 mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000791 mState.vertexAttribute[attribNum].mSize = size;
792 mState.vertexAttribute[attribNum].mType = type;
793 mState.vertexAttribute[attribNum].mNormalized = normalized;
794 mState.vertexAttribute[attribNum].mStride = stride;
795 mState.vertexAttribute[attribNum].mPointer = pointer;
796}
797
798const void *Context::getVertexAttribPointer(unsigned int attribNum) const
799{
800 return mState.vertexAttribute[attribNum].mPointer;
801}
802
daniel@transgaming.com83921382011-01-08 05:46:00 +0000803const VertexAttributeArray &Context::getVertexAttributes()
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000804{
805 return mState.vertexAttribute;
806}
807
808void Context::setPackAlignment(GLint alignment)
809{
810 mState.packAlignment = alignment;
811}
812
813GLint Context::getPackAlignment() const
814{
815 return mState.packAlignment;
816}
817
818void Context::setUnpackAlignment(GLint alignment)
819{
820 mState.unpackAlignment = alignment;
821}
822
823GLint Context::getUnpackAlignment() const
824{
825 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000826}
827
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000828GLuint Context::createBuffer()
829{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000830 return mResourceManager->createBuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000831}
832
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000833GLuint Context::createProgram()
834{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000835 return mResourceManager->createProgram();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000836}
837
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000838GLuint Context::createShader(GLenum type)
839{
840 return mResourceManager->createShader(type);
841}
842
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000843GLuint Context::createTexture()
844{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000845 return mResourceManager->createTexture();
846}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000847
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000848GLuint Context::createRenderbuffer()
849{
850 return mResourceManager->createRenderbuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000851}
852
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000853// Returns an unused framebuffer name
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000854GLuint Context::createFramebuffer()
855{
benvanik@google.com1a233342011-04-28 19:44:39 +0000856 GLuint handle = mFramebufferHandleAllocator.allocate();
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000857
858 mFramebufferMap[handle] = NULL;
859
860 return handle;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000861}
862
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000863GLuint Context::createFence()
864{
benvanik@google.com1a233342011-04-28 19:44:39 +0000865 GLuint handle = mFenceHandleAllocator.allocate();
daniel@transgaming.comfe208882010-09-01 15:47:57 +0000866
867 mFenceMap[handle] = new Fence;
868
869 return handle;
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000870}
871
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000872void Context::deleteBuffer(GLuint buffer)
873{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000874 if (mResourceManager->getBuffer(buffer))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000875 {
876 detachBuffer(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000877 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000878
879 mResourceManager->deleteBuffer(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000880}
881
882void Context::deleteShader(GLuint shader)
883{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000884 mResourceManager->deleteShader(shader);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000885}
886
887void Context::deleteProgram(GLuint program)
888{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000889 mResourceManager->deleteProgram(program);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000890}
891
892void Context::deleteTexture(GLuint texture)
893{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000894 if (mResourceManager->getTexture(texture))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000895 {
896 detachTexture(texture);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000897 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000898
899 mResourceManager->deleteTexture(texture);
900}
901
902void Context::deleteRenderbuffer(GLuint renderbuffer)
903{
904 if (mResourceManager->getRenderbuffer(renderbuffer))
905 {
906 detachRenderbuffer(renderbuffer);
907 }
908
909 mResourceManager->deleteRenderbuffer(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000910}
911
912void Context::deleteFramebuffer(GLuint framebuffer)
913{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000914 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
915
916 if (framebufferObject != mFramebufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000917 {
918 detachFramebuffer(framebuffer);
apatrick@chromium.org55255022010-09-11 02:12:47 +0000919
benvanik@google.com1a233342011-04-28 19:44:39 +0000920 mFramebufferHandleAllocator.release(framebufferObject->first);
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000921 delete framebufferObject->second;
922 mFramebufferMap.erase(framebufferObject);
923 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000924}
daniel@transgaming.comfe208882010-09-01 15:47:57 +0000925
926void Context::deleteFence(GLuint fence)
927{
928 FenceMap::iterator fenceObject = mFenceMap.find(fence);
929
930 if (fenceObject != mFenceMap.end())
931 {
benvanik@google.com1a233342011-04-28 19:44:39 +0000932 mFenceHandleAllocator.release(fenceObject->first);
daniel@transgaming.comfe208882010-09-01 15:47:57 +0000933 delete fenceObject->second;
934 mFenceMap.erase(fenceObject);
935 }
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000936}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000937
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000938Buffer *Context::getBuffer(GLuint handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000939{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000940 return mResourceManager->getBuffer(handle);
941}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000942
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000943Shader *Context::getShader(GLuint handle)
944{
945 return mResourceManager->getShader(handle);
946}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000947
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000948Program *Context::getProgram(GLuint handle)
949{
950 return mResourceManager->getProgram(handle);
951}
952
953Texture *Context::getTexture(GLuint handle)
954{
955 return mResourceManager->getTexture(handle);
956}
957
958Renderbuffer *Context::getRenderbuffer(GLuint handle)
959{
960 return mResourceManager->getRenderbuffer(handle);
961}
962
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000963Framebuffer *Context::getReadFramebuffer()
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000964{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000965 return getFramebuffer(mState.readFramebuffer);
966}
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000967
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000968Framebuffer *Context::getDrawFramebuffer()
969{
970 return getFramebuffer(mState.drawFramebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000971}
972
973void Context::bindArrayBuffer(unsigned int buffer)
974{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000975 mResourceManager->checkBufferAllocation(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000976
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000977 mState.arrayBuffer.set(getBuffer(buffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000978}
979
980void Context::bindElementArrayBuffer(unsigned int buffer)
981{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000982 mResourceManager->checkBufferAllocation(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000983
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000984 mState.elementArrayBuffer.set(getBuffer(buffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000985}
986
987void Context::bindTexture2D(GLuint texture)
988{
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +0000989 mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000990
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +0000991 mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000992}
993
994void Context::bindTextureCubeMap(GLuint texture)
995{
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +0000996 mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000997
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +0000998 mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000999}
1000
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001001void Context::bindReadFramebuffer(GLuint framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001002{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +00001003 if (!getFramebuffer(framebuffer))
1004 {
1005 mFramebufferMap[framebuffer] = new Framebuffer();
1006 }
1007
1008 mState.readFramebuffer = framebuffer;
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001009}
1010
1011void Context::bindDrawFramebuffer(GLuint framebuffer)
1012{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +00001013 if (!getFramebuffer(framebuffer))
1014 {
1015 mFramebufferMap[framebuffer] = new Framebuffer();
1016 }
1017
1018 mState.drawFramebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001019}
1020
1021void Context::bindRenderbuffer(GLuint renderbuffer)
1022{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001023 mResourceManager->checkRenderbufferAllocation(renderbuffer);
1024
1025 mState.renderbuffer.set(getRenderbuffer(renderbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001026}
1027
1028void Context::useProgram(GLuint program)
1029{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001030 GLuint priorProgram = mState.currentProgram;
1031 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +00001032
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001033 if (priorProgram != program)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001034 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001035 Program *newProgram = mResourceManager->getProgram(program);
1036 Program *oldProgram = mResourceManager->getProgram(priorProgram);
1037
1038 if (newProgram)
1039 {
1040 newProgram->addRef();
1041 }
1042
1043 if (oldProgram)
1044 {
1045 oldProgram->release();
1046 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001047 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001048}
1049
1050void Context::setFramebufferZero(Framebuffer *buffer)
1051{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +00001052 delete mFramebufferMap[0];
1053 mFramebufferMap[0] = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001054}
1055
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001056void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001057{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001058 Renderbuffer *renderbufferObject = mState.renderbuffer.get();
1059 renderbufferObject->setStorage(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001060}
1061
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +00001062Framebuffer *Context::getFramebuffer(unsigned int handle)
1063{
1064 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
1065
1066 if (framebuffer == mFramebufferMap.end())
1067 {
1068 return NULL;
1069 }
1070 else
1071 {
1072 return framebuffer->second;
1073 }
1074}
1075
daniel@transgaming.comfe208882010-09-01 15:47:57 +00001076Fence *Context::getFence(unsigned int handle)
1077{
1078 FenceMap::iterator fence = mFenceMap.find(handle);
1079
1080 if (fence == mFenceMap.end())
1081 {
1082 return NULL;
1083 }
1084 else
1085 {
1086 return fence->second;
1087 }
1088}
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +00001089
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001090Buffer *Context::getArrayBuffer()
1091{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001092 return mState.arrayBuffer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001093}
1094
1095Buffer *Context::getElementArrayBuffer()
1096{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001097 return mState.elementArrayBuffer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001098}
1099
1100Program *Context::getCurrentProgram()
1101{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001102 return mResourceManager->getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001103}
1104
1105Texture2D *Context::getTexture2D()
1106{
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +00001107 return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001108}
1109
1110TextureCubeMap *Context::getTextureCubeMap()
1111{
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +00001112 return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001113}
1114
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +00001115Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001116{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001117 GLuint texid = mState.samplerTexture[type][sampler].id();
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001118
daniel@transgaming.coma5a8a0a2010-11-19 14:55:32 +00001119 if (texid == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001120 {
1121 switch (type)
1122 {
1123 default: UNREACHABLE();
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +00001124 case TEXTURE_2D: return mTexture2DZero.get();
1125 case TEXTURE_CUBE: return mTextureCubeMapZero.get();
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001126 }
1127 }
1128
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001129 return mState.samplerTexture[type][sampler].get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001130}
1131
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001132bool Context::getBooleanv(GLenum pname, GLboolean *params)
1133{
1134 switch (pname)
1135 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001136 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1137 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1138 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001139 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001140 params[0] = mState.colorMaskRed;
1141 params[1] = mState.colorMaskGreen;
1142 params[2] = mState.colorMaskBlue;
1143 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001144 break;
daniel@transgaming.com9d7fc1d2010-10-27 15:49:42 +00001145 case GL_CULL_FACE: *params = mState.cullFace; break;
1146 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; break;
1147 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; break;
1148 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break;
1149 case GL_SCISSOR_TEST: *params = mState.scissorTest; break;
1150 case GL_STENCIL_TEST: *params = mState.stencilTest; break;
1151 case GL_DEPTH_TEST: *params = mState.depthTest; break;
1152 case GL_BLEND: *params = mState.blend; break;
1153 case GL_DITHER: *params = mState.dither; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001154 default:
1155 return false;
1156 }
1157
1158 return true;
1159}
1160
1161bool Context::getFloatv(GLenum pname, GLfloat *params)
1162{
1163 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1164 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1165 // GetIntegerv as its native query function. As it would require conversion in any
1166 // case, this should make no difference to the calling application.
1167 switch (pname)
1168 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001169 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1170 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1171 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1172 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1173 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001174 case GL_ALIASED_LINE_WIDTH_RANGE:
1175 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1176 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1177 break;
1178 case GL_ALIASED_POINT_SIZE_RANGE:
1179 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001180 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 +00001181 break;
1182 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001183 params[0] = mState.zNear;
1184 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001185 break;
1186 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001187 params[0] = mState.colorClearValue.red;
1188 params[1] = mState.colorClearValue.green;
1189 params[2] = mState.colorClearValue.blue;
1190 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001191 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001192 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001193 params[0] = mState.blendColor.red;
1194 params[1] = mState.blendColor.green;
1195 params[2] = mState.blendColor.blue;
1196 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001197 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001198 default:
1199 return false;
1200 }
1201
1202 return true;
1203}
1204
1205bool Context::getIntegerv(GLenum pname, GLint *params)
1206{
1207 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1208 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1209 // GetIntegerv as its native query function. As it would require conversion in any
1210 // case, this should make no difference to the calling application. You may find it in
1211 // Context::getFloatv.
1212 switch (pname)
1213 {
1214 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1215 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001216 case GL_MAX_VARYING_VECTORS: *params = getMaximumVaryingVectors(); break;
daniel@transgaming.comaf29cac2011-05-11 15:36:31 +00001217 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = getMaximumCombinedTextureImageUnits(); break;
1218 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = getMaximumVertexTextureImageUnits(); break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001219 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
daniel@transgaming.com458da142010-11-28 02:03:02 +00001220 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = getMaximumFragmentUniformVectors(); break;
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00001221 case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001222 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001223 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001224 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break;
1225 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break;
daniel@transgaming.com9d7fc1d2010-10-27 15:49:42 +00001226 //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
1227 case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break;
1228 case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001229 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001230 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1231 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1232 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1233 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
alokp@chromium.orgd303ef92010-09-09 17:30:15 +00001234 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001235 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
1236 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1237 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1238 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1239 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1240 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1241 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1242 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1243 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1244 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1245 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1246 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1247 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1248 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1249 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1250 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1251 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1252 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1253 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1254 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1255 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1256 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1257 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
1258 case GL_SUBPIXEL_BITS: *params = 4; break;
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00001259 case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break;
1260 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break;
daniel@transgaming.com01868132010-08-24 19:21:17 +00001261 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
gman@chromium.org50c526d2011-08-10 05:19:44 +00001262 params[0] = mNumCompressedTextureFormats;
daniel@transgaming.com01868132010-08-24 19:21:17 +00001263 break;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001264 case GL_MAX_SAMPLES_ANGLE:
1265 {
1266 GLsizei maxSamples = getMaxSupportedSamples();
1267 if (maxSamples != 0)
1268 {
1269 *params = maxSamples;
1270 }
1271 else
1272 {
1273 return false;
1274 }
1275
1276 break;
1277 }
1278 case GL_SAMPLE_BUFFERS:
1279 case GL_SAMPLES:
1280 {
1281 gl::Framebuffer *framebuffer = getDrawFramebuffer();
1282 if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
1283 {
1284 switch (pname)
1285 {
1286 case GL_SAMPLE_BUFFERS:
1287 if (framebuffer->getSamples() != 0)
1288 {
1289 *params = 1;
1290 }
1291 else
1292 {
1293 *params = 0;
1294 }
1295 break;
1296 case GL_SAMPLES:
1297 *params = framebuffer->getSamples();
1298 break;
1299 }
1300 }
1301 else
1302 {
1303 *params = 0;
1304 }
1305 }
1306 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001307 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1308 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1309 case GL_MAX_VIEWPORT_DIMS:
1310 {
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00001311 int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension());
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001312 params[0] = maxDimension;
1313 params[1] = maxDimension;
1314 }
1315 break;
daniel@transgaming.com01868132010-08-24 19:21:17 +00001316 case GL_COMPRESSED_TEXTURE_FORMATS:
1317 {
gman@chromium.org50c526d2011-08-10 05:19:44 +00001318 if (supportsDXT1Textures())
daniel@transgaming.com01868132010-08-24 19:21:17 +00001319 {
gman@chromium.org50c526d2011-08-10 05:19:44 +00001320 *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
1321 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
1322 }
1323 if (supportsDXT3Textures())
1324 {
1325 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
1326 }
1327 if (supportsDXT5Textures())
1328 {
1329 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
daniel@transgaming.com01868132010-08-24 19:21:17 +00001330 }
1331 }
1332 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001333 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001334 params[0] = mState.viewportX;
1335 params[1] = mState.viewportY;
1336 params[2] = mState.viewportWidth;
1337 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001338 break;
1339 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001340 params[0] = mState.scissorX;
1341 params[1] = mState.scissorY;
1342 params[2] = mState.scissorWidth;
1343 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001344 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001345 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1346 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001347 case GL_RED_BITS:
1348 case GL_GREEN_BITS:
1349 case GL_BLUE_BITS:
1350 case GL_ALPHA_BITS:
1351 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001352 gl::Framebuffer *framebuffer = getDrawFramebuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001353 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1354
1355 if (colorbuffer)
1356 {
1357 switch (pname)
1358 {
1359 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1360 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1361 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1362 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1363 }
1364 }
1365 else
1366 {
1367 *params = 0;
1368 }
1369 }
1370 break;
1371 case GL_DEPTH_BITS:
1372 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001373 gl::Framebuffer *framebuffer = getDrawFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001374 gl::DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001375
1376 if (depthbuffer)
1377 {
1378 *params = depthbuffer->getDepthSize();
1379 }
1380 else
1381 {
1382 *params = 0;
1383 }
1384 }
1385 break;
1386 case GL_STENCIL_BITS:
1387 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001388 gl::Framebuffer *framebuffer = getDrawFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001389 gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001390
1391 if (stencilbuffer)
1392 {
1393 *params = stencilbuffer->getStencilSize();
1394 }
1395 else
1396 {
1397 *params = 0;
1398 }
1399 }
1400 break;
1401 case GL_TEXTURE_BINDING_2D:
1402 {
daniel@transgaming.com3f74c7a2011-05-11 15:36:51 +00001403 if (mState.activeSampler < 0 || mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001404 {
1405 error(GL_INVALID_OPERATION);
1406 return false;
1407 }
1408
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +00001409 *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001410 }
1411 break;
1412 case GL_TEXTURE_BINDING_CUBE_MAP:
1413 {
daniel@transgaming.com3f74c7a2011-05-11 15:36:51 +00001414 if (mState.activeSampler < 0 || mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001415 {
1416 error(GL_INVALID_OPERATION);
1417 return false;
1418 }
1419
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +00001420 *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001421 }
1422 break;
1423 default:
1424 return false;
1425 }
1426
1427 return true;
1428}
1429
1430bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1431{
1432 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1433 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1434 // to the fact that it is stored internally as a float, and so would require conversion
1435 // if returned from Context::getIntegerv. Since this conversion is already implemented
1436 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1437 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1438 // application.
1439 switch (pname)
1440 {
gman@chromium.org50c526d2011-08-10 05:19:44 +00001441 case GL_COMPRESSED_TEXTURE_FORMATS:
1442 {
1443 *type = GL_INT;
1444 *numParams = mNumCompressedTextureFormats;
1445 }
1446 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001447 case GL_SHADER_BINARY_FORMATS:
1448 {
1449 *type = GL_INT;
1450 *numParams = 0;
1451 }
1452 break;
1453 case GL_MAX_VERTEX_ATTRIBS:
1454 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1455 case GL_MAX_VARYING_VECTORS:
1456 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1457 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1458 case GL_MAX_TEXTURE_IMAGE_UNITS:
1459 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1460 case GL_MAX_RENDERBUFFER_SIZE:
1461 case GL_NUM_SHADER_BINARY_FORMATS:
1462 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1463 case GL_ARRAY_BUFFER_BINDING:
1464 case GL_FRAMEBUFFER_BINDING:
1465 case GL_RENDERBUFFER_BINDING:
1466 case GL_CURRENT_PROGRAM:
1467 case GL_PACK_ALIGNMENT:
1468 case GL_UNPACK_ALIGNMENT:
1469 case GL_GENERATE_MIPMAP_HINT:
alokp@chromium.orgd303ef92010-09-09 17:30:15 +00001470 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001471 case GL_RED_BITS:
1472 case GL_GREEN_BITS:
1473 case GL_BLUE_BITS:
1474 case GL_ALPHA_BITS:
1475 case GL_DEPTH_BITS:
1476 case GL_STENCIL_BITS:
1477 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1478 case GL_CULL_FACE_MODE:
1479 case GL_FRONT_FACE:
1480 case GL_ACTIVE_TEXTURE:
1481 case GL_STENCIL_FUNC:
1482 case GL_STENCIL_VALUE_MASK:
1483 case GL_STENCIL_REF:
1484 case GL_STENCIL_FAIL:
1485 case GL_STENCIL_PASS_DEPTH_FAIL:
1486 case GL_STENCIL_PASS_DEPTH_PASS:
1487 case GL_STENCIL_BACK_FUNC:
1488 case GL_STENCIL_BACK_VALUE_MASK:
1489 case GL_STENCIL_BACK_REF:
1490 case GL_STENCIL_BACK_FAIL:
1491 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1492 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1493 case GL_DEPTH_FUNC:
1494 case GL_BLEND_SRC_RGB:
1495 case GL_BLEND_SRC_ALPHA:
1496 case GL_BLEND_DST_RGB:
1497 case GL_BLEND_DST_ALPHA:
1498 case GL_BLEND_EQUATION_RGB:
1499 case GL_BLEND_EQUATION_ALPHA:
1500 case GL_STENCIL_WRITEMASK:
1501 case GL_STENCIL_BACK_WRITEMASK:
1502 case GL_STENCIL_CLEAR_VALUE:
1503 case GL_SUBPIXEL_BITS:
1504 case GL_MAX_TEXTURE_SIZE:
1505 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1506 case GL_SAMPLE_BUFFERS:
1507 case GL_SAMPLES:
1508 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1509 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1510 case GL_TEXTURE_BINDING_2D:
1511 case GL_TEXTURE_BINDING_CUBE_MAP:
1512 {
1513 *type = GL_INT;
1514 *numParams = 1;
1515 }
1516 break;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001517 case GL_MAX_SAMPLES_ANGLE:
1518 {
1519 if (getMaxSupportedSamples() != 0)
1520 {
1521 *type = GL_INT;
1522 *numParams = 1;
1523 }
1524 else
1525 {
1526 return false;
1527 }
1528 }
1529 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001530 case GL_MAX_VIEWPORT_DIMS:
1531 {
1532 *type = GL_INT;
1533 *numParams = 2;
1534 }
1535 break;
1536 case GL_VIEWPORT:
1537 case GL_SCISSOR_BOX:
1538 {
1539 *type = GL_INT;
1540 *numParams = 4;
1541 }
1542 break;
1543 case GL_SHADER_COMPILER:
1544 case GL_SAMPLE_COVERAGE_INVERT:
1545 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001546 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1547 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1548 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1549 case GL_SAMPLE_COVERAGE:
1550 case GL_SCISSOR_TEST:
1551 case GL_STENCIL_TEST:
1552 case GL_DEPTH_TEST:
1553 case GL_BLEND:
1554 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001555 {
1556 *type = GL_BOOL;
1557 *numParams = 1;
1558 }
1559 break;
1560 case GL_COLOR_WRITEMASK:
1561 {
1562 *type = GL_BOOL;
1563 *numParams = 4;
1564 }
1565 break;
1566 case GL_POLYGON_OFFSET_FACTOR:
1567 case GL_POLYGON_OFFSET_UNITS:
1568 case GL_SAMPLE_COVERAGE_VALUE:
1569 case GL_DEPTH_CLEAR_VALUE:
1570 case GL_LINE_WIDTH:
1571 {
1572 *type = GL_FLOAT;
1573 *numParams = 1;
1574 }
1575 break;
1576 case GL_ALIASED_LINE_WIDTH_RANGE:
1577 case GL_ALIASED_POINT_SIZE_RANGE:
1578 case GL_DEPTH_RANGE:
1579 {
1580 *type = GL_FLOAT;
1581 *numParams = 2;
1582 }
1583 break;
1584 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001585 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001586 {
1587 *type = GL_FLOAT;
1588 *numParams = 4;
1589 }
1590 break;
1591 default:
1592 return false;
1593 }
1594
1595 return true;
1596}
1597
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001598// Applies the render target surface, depth stencil surface, viewport rectangle and
1599// scissor rectangle to the Direct3D 9 device
1600bool Context::applyRenderTarget(bool ignoreViewport)
1601{
1602 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001603
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001604 Framebuffer *framebufferObject = getDrawFramebuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001605
1606 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1607 {
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00001608 return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001609 }
1610
1611 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +00001612
1613 if (!renderTarget)
1614 {
1615 return false; // Context must be lost
1616 }
1617
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001618 IDirect3DSurface9 *depthStencil = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001619
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001620 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
1621 if (renderTargetSerial != mAppliedRenderTargetSerial)
1622 {
1623 device->SetRenderTarget(0, renderTarget);
1624 mAppliedRenderTargetSerial = renderTargetSerial;
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001625 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 +00001626 }
1627
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001628 unsigned int depthbufferSerial = 0;
1629 unsigned int stencilbufferSerial = 0;
1630 if (framebufferObject->getDepthbufferType() != GL_NONE)
1631 {
1632 depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil();
apatrick@chromium.orgb2bdd062010-10-05 02:24:30 +00001633 if (!depthStencil)
1634 {
1635 ERR("Depth stencil pointer unexpectedly null.");
1636 return false;
1637 }
1638
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001639 depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial();
1640 }
1641 else if (framebufferObject->getStencilbufferType() != GL_NONE)
1642 {
1643 depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
apatrick@chromium.orgb2bdd062010-10-05 02:24:30 +00001644 if (!depthStencil)
1645 {
1646 ERR("Depth stencil pointer unexpectedly null.");
1647 return false;
1648 }
1649
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001650 stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial();
1651 }
1652
1653 if (depthbufferSerial != mAppliedDepthbufferSerial ||
apatrick@chromium.org85dc42b2010-09-14 03:10:08 +00001654 stencilbufferSerial != mAppliedStencilbufferSerial ||
vangelis@chromium.orgcf66ebb2010-09-14 22:15:43 +00001655 !mDepthStencilInitialized)
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001656 {
1657 device->SetDepthStencilSurface(depthStencil);
1658 mAppliedDepthbufferSerial = depthbufferSerial;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001659 mAppliedStencilbufferSerial = stencilbufferSerial;
vangelis@chromium.orgcf66ebb2010-09-14 22:15:43 +00001660 mDepthStencilInitialized = true;
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001661 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001662
1663 D3DVIEWPORT9 viewport;
1664 D3DSURFACE_DESC desc;
1665 renderTarget->GetDesc(&desc);
1666
daniel@transgaming.com996675c2010-11-17 13:06:29 +00001667 float zNear = clamp01(mState.zNear);
1668 float zFar = clamp01(mState.zFar);
1669
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001670 if (ignoreViewport)
1671 {
1672 viewport.X = 0;
1673 viewport.Y = 0;
1674 viewport.Width = desc.Width;
1675 viewport.Height = desc.Height;
1676 viewport.MinZ = 0.0f;
1677 viewport.MaxZ = 1.0f;
1678 }
1679 else
1680 {
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001681 RECT rect = transformPixelRect(mState.viewportX, mState.viewportY, mState.viewportWidth, mState.viewportHeight, desc.Height);
1682 viewport.X = clamp(rect.left, 0L, static_cast<LONG>(desc.Width));
1683 viewport.Y = clamp(rect.top, 0L, static_cast<LONG>(desc.Height));
1684 viewport.Width = clamp(rect.right - rect.left, 0L, static_cast<LONG>(desc.Width) - static_cast<LONG>(viewport.X));
1685 viewport.Height = clamp(rect.bottom - rect.top, 0L, static_cast<LONG>(desc.Height) - static_cast<LONG>(viewport.Y));
daniel@transgaming.com996675c2010-11-17 13:06:29 +00001686 viewport.MinZ = zNear;
1687 viewport.MaxZ = zFar;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001688 }
1689
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001690 if (viewport.Width <= 0 || viewport.Height <= 0)
1691 {
1692 return false; // Nothing to render
1693 }
1694
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001695 device->SetViewport(&viewport);
1696
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001697 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001698 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001699 if (mState.scissorTest)
1700 {
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001701 RECT rect = transformPixelRect(mState.scissorX, mState.scissorY, mState.scissorWidth, mState.scissorHeight, desc.Height);
1702 rect.left = clamp(rect.left, 0L, static_cast<LONG>(desc.Width));
1703 rect.top = clamp(rect.top, 0L, static_cast<LONG>(desc.Height));
1704 rect.right = clamp(rect.right, 0L, static_cast<LONG>(desc.Width));
1705 rect.bottom = clamp(rect.bottom, 0L, static_cast<LONG>(desc.Height));
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001706 device->SetScissorRect(&rect);
1707 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1708 }
1709 else
1710 {
1711 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1712 }
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001713
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001714 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001715 }
1716
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001717 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001718 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001719 Program *programObject = getCurrentProgram();
1720
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001721 GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001722 GLfloat xy[2] = {1.0f / viewport.Width, -1.0f / viewport.Height};
daniel@transgaming.com31754962010-11-28 02:02:52 +00001723 programObject->setUniform2fv(halfPixelSize, 1, xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001724
daniel@transgaming.com31754962010-11-28 02:02:52 +00001725 GLint viewport = programObject->getDxViewportLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001726 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1727 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1728 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com31754962010-11-28 02:02:52 +00001729 programObject->setUniform4fv(viewport, 1, whxy);
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001730
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001731 GLint depth = programObject->getDxDepthLocation();
daniel@transgaming.com996675c2010-11-17 13:06:29 +00001732 GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
daniel@transgaming.com31754962010-11-28 02:02:52 +00001733 programObject->setUniform2fv(depth, 1, dz);
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001734
daniel@transgaming.com31754962010-11-28 02:02:52 +00001735 GLint depthRange = programObject->getDxDepthRangeLocation();
1736 GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear};
1737 programObject->setUniform3fv(depthRange, 1, nearFarDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001738 }
1739
1740 return true;
1741}
1742
1743// 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 +00001744void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001745{
1746 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001747 Program *programObject = getCurrentProgram();
1748
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001749 Framebuffer *framebufferObject = getDrawFramebuffer();
1750
1751 GLenum adjustedFrontFace = adjustWinding(mState.frontFace);
1752
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001753 GLint frontCCW = programObject->getDxFrontCCWLocation();
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001754 GLint ccw = (adjustedFrontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001755 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001756
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001757 GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001758 GLint alwaysFront = !isTriangleMode(drawMode);
1759 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1760
jbauman@chromium.org03208d52011-06-15 01:15:24 +00001761 egl::Display *display = getDisplay();
1762 D3DADAPTER_IDENTIFIER9 *identifier = display->getAdapterIdentifier();
1763 bool zeroColorMaskAllowed = identifier->VendorId != 0x1002;
1764 // Apparently some ATI cards have a bug where a draw with a zero color
1765 // write mask can cause later draws to have incorrect results. Instead,
1766 // set a nonzero color write mask but modify the blend state so that no
1767 // drawing is done.
1768 // http://code.google.com/p/angleproject/issues/detail?id=169
1769
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001770 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001771 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001772 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001773 {
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001774 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, adjustedFrontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001775 }
1776 else
1777 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001778 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001779 }
1780
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001781 mCullStateDirty = false;
1782 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001783
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001784 if (mDepthStateDirty)
1785 {
daniel@transgaming.com317887f2011-05-11 15:26:12 +00001786 if (mState.depthTest)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001787 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001788 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1789 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001790 }
1791 else
1792 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001793 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001794 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001795
1796 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001797 }
1798
jbauman@chromium.org03208d52011-06-15 01:15:24 +00001799 if (!zeroColorMaskAllowed && (mMaskStateDirty || mBlendStateDirty))
1800 {
1801 mBlendStateDirty = true;
1802 mMaskStateDirty = true;
1803 }
1804
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001805 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001806 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001807 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001808 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001809 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1810
1811 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1812 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1813 {
1814 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1815 }
1816 else
1817 {
1818 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1819 unorm<8>(mState.blendColor.alpha),
1820 unorm<8>(mState.blendColor.alpha),
1821 unorm<8>(mState.blendColor.alpha)));
1822 }
1823
1824 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1825 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1826 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1827
1828 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1829 mState.destBlendRGB != mState.destBlendAlpha ||
1830 mState.blendEquationRGB != mState.blendEquationAlpha)
1831 {
1832 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1833
1834 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1835 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1836 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001837 }
1838 else
1839 {
1840 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1841 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001842 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001843 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001844 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001845 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001846 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001847
1848 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001849 }
1850
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001851 if (mStencilStateDirty || mFrontFaceDirty)
1852 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001853 if (mState.stencilTest && framebufferObject->hasStencil())
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001854 {
1855 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1856 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1857
1858 // FIXME: Unsupported by D3D9
1859 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1860 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1861 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1862 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1863 mState.stencilRef != mState.stencilBackRef ||
1864 mState.stencilMask != mState.stencilBackMask)
1865 {
1866 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1867 return error(GL_INVALID_OPERATION);
1868 }
1869
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001870 // get the maximum size of the stencil ref
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001871 gl::DepthStencilbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001872 GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
1873
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001874 device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1875 device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001876 es2dx::ConvertComparison(mState.stencilFunc));
1877
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001878 device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
1879 device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001880
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001881 device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001882 es2dx::ConvertStencilOp(mState.stencilFail));
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001883 device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001884 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001885 device->SetRenderState(adjustedFrontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001886 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1887
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001888 device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1889 device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001890 es2dx::ConvertComparison(mState.stencilBackFunc));
1891
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001892 device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
1893 device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001894
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001895 device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001896 es2dx::ConvertStencilOp(mState.stencilBackFail));
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001897 device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001898 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00001899 device->SetRenderState(adjustedFrontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001900 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1901 }
1902 else
1903 {
1904 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1905 }
1906
1907 mStencilStateDirty = false;
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001908 mFrontFaceDirty = false;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001909 }
1910
1911 if (mMaskStateDirty)
1912 {
jbauman@chromium.org03208d52011-06-15 01:15:24 +00001913 int colorMask = es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1914 mState.colorMaskBlue, mState.colorMaskAlpha);
1915 if (colorMask == 0 && !zeroColorMaskAllowed)
1916 {
1917 // Enable green channel, but set blending so nothing will be drawn.
1918 device->SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_GREEN);
1919 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1920
1921 device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ZERO);
1922 device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
1923 device->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
1924 }
1925 else
1926 {
1927 device->SetRenderState(D3DRS_COLORWRITEENABLE, colorMask);
1928 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001929 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1930
1931 mMaskStateDirty = false;
1932 }
1933
1934 if (mPolygonOffsetStateDirty)
1935 {
1936 if (mState.polygonOffsetFill)
1937 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001938 gl::DepthStencilbuffer *depthbuffer = framebufferObject->getDepthbuffer();
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001939 if (depthbuffer)
1940 {
1941 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1942 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1943 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1944 }
1945 }
1946 else
1947 {
1948 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1949 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1950 }
1951
1952 mPolygonOffsetStateDirty = false;
1953 }
1954
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001955 if (mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001956 {
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001957 if (mState.sampleAlphaToCoverage)
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001958 {
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001959 FIXME("Sample alpha to coverage is unimplemented.");
1960 }
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001961
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001962 device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
1963 if (mState.sampleCoverage)
1964 {
1965 unsigned int mask = 0;
1966 if (mState.sampleCoverageValue != 0)
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001967 {
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001968 float threshold = 0.5f;
1969
1970 for (int i = 0; i < framebufferObject->getSamples(); ++i)
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001971 {
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001972 mask <<= 1;
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001973
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001974 if ((i + 1) * mState.sampleCoverageValue >= threshold)
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001975 {
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001976 threshold += 1.0f;
1977 mask |= 1;
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001978 }
1979 }
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001980 }
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001981
1982 if (mState.sampleCoverageInvert)
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001983 {
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001984 mask = ~mask;
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001985 }
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001986
1987 device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask);
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001988 }
1989 else
1990 {
daniel@transgaming.com3203c102011-06-08 12:41:32 +00001991 device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001992 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001993
1994 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001995 }
1996
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001997 if (mDitherStateDirty)
1998 {
1999 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
2000
2001 mDitherStateDirty = false;
2002 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002003}
2004
daniel@transgaming.com83921382011-01-08 05:46:00 +00002005GLenum Context::applyVertexBuffer(GLint first, GLsizei count)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002006{
daniel@transgaming.combaa74512011-04-13 14:56:47 +00002007 TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS];
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002008
daniel@transgaming.combaa74512011-04-13 14:56:47 +00002009 GLenum err = mVertexDataManager->prepareVertexData(first, count, attributes);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002010 if (err != GL_NO_ERROR)
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002011 {
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002012 return err;
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002013 }
2014
daniel@transgaming.com09c2c1a2011-04-13 14:57:16 +00002015 return mVertexDeclarationCache.applyDeclaration(attributes, getCurrentProgram());
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002016}
2017
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002018// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002019GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00002020{
daniel@transgaming.com83921382011-01-08 05:46:00 +00002021 IDirect3DDevice9 *device = getDevice();
2022 GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002023
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002024 if (err == GL_NO_ERROR)
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002025 {
daniel@transgaming.com83921382011-01-08 05:46:00 +00002026 device->SetIndices(indexInfo->indexBuffer);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002027 }
2028
daniel@transgaming.com81655a72010-05-20 19:18:17 +00002029 return err;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002030}
2031
2032// Applies the shaders and shader constants to the Direct3D 9 device
2033void Context::applyShaders()
2034{
2035 IDirect3DDevice9 *device = getDevice();
2036 Program *programObject = getCurrentProgram();
2037 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
2038 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
2039
2040 device->SetVertexShader(vertexShader);
2041 device->SetPixelShader(pixelShader);
2042
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +00002043 if (programObject->getSerial() != mAppliedProgramSerial)
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002044 {
2045 programObject->dirtyAllUniforms();
daniel@transgaming.coma9eb5da2011-03-21 16:39:16 +00002046 mAppliedProgramSerial = programObject->getSerial();
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002047 }
2048
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002049 programObject->applyUniforms();
2050}
2051
2052// Applies the textures and sampler states to the Direct3D 9 device
2053void Context::applyTextures()
2054{
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002055 applyTextures(SAMPLER_PIXEL);
2056
2057 if (mSupportsVertexTexture)
2058 {
2059 applyTextures(SAMPLER_VERTEX);
2060 }
2061}
2062
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +00002063// For each Direct3D 9 sampler of either the pixel or vertex stage,
2064// looks up the corresponding OpenGL texture image unit and texture type,
2065// and sets the texture and its addressing/filtering state (or NULL when inactive).
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002066void Context::applyTextures(SamplerType type)
2067{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002068 IDirect3DDevice9 *device = getDevice();
2069 Program *programObject = getCurrentProgram();
2070
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +00002071 int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; // Range of Direct3D 9 samplers of given sampler type
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002072
2073 for (int samplerIndex = 0; samplerIndex < samplerCount; samplerIndex++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002074 {
daniel@transgaming.com9ba680a2011-05-11 15:37:11 +00002075 int textureUnit = programObject->getSamplerMapping(type, samplerIndex); // OpenGL texture image unit index
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002076 int d3dSampler = (type == SAMPLER_PIXEL) ? samplerIndex : D3DVERTEXTEXTURESAMPLER0 + samplerIndex;
2077 unsigned int *appliedTextureSerial = (type == SAMPLER_PIXEL) ? mAppliedTextureSerialPS : mAppliedTextureSerialVS;
2078
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002079 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002080 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002081 TextureType textureType = programObject->getSamplerTextureType(type, samplerIndex);
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002082
2083 Texture *texture = getSamplerTexture(textureUnit, textureType);
2084
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002085 if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyParameter() || texture->isDirtyImage())
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002086 {
daniel@transgaming.com38e76e52011-03-21 16:39:10 +00002087 IDirect3DBaseTexture9 *d3dTexture = texture->getTexture();
2088
2089 if (d3dTexture)
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002090 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002091 if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyParameter())
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00002092 {
2093 GLenum wrapS = texture->getWrapS();
2094 GLenum wrapT = texture->getWrapT();
2095 GLenum minFilter = texture->getMinFilter();
2096 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002097
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002098 device->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
2099 device->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002100
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002101 device->SetSamplerState(d3dSampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00002102 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
2103 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002104 device->SetSamplerState(d3dSampler, D3DSAMP_MINFILTER, d3dMinFilter);
2105 device->SetSamplerState(d3dSampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00002106 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002107
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002108 if (appliedTextureSerial[samplerIndex] != texture->getSerial() || texture->isDirtyImage())
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00002109 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002110 device->SetTexture(d3dSampler, d3dTexture);
daniel@transgaming.coma06aa872011-03-21 17:22:21 +00002111 }
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002112 }
2113 else
2114 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002115 device->SetTexture(d3dSampler, getIncompleteTexture(textureType)->getTexture());
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002116 }
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002117
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002118 appliedTextureSerial[samplerIndex] = texture->getSerial();
daniel@transgaming.com38e76e52011-03-21 16:39:10 +00002119 texture->resetDirty();
2120 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002121 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002122 else
2123 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002124 if (appliedTextureSerial[samplerIndex] != 0)
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002125 {
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002126 device->SetTexture(d3dSampler, NULL);
2127 appliedTextureSerial[samplerIndex] = 0;
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002128 }
daniel@transgaming.comd4a35172011-05-11 15:36:45 +00002129 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002130 }
2131}
2132
2133void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
2134{
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00002135 Framebuffer *framebuffer = getReadFramebuffer();
daniel@transgaming.combbc57792010-07-28 19:21:05 +00002136
2137 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
2138 {
2139 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
2140 }
2141
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00002142 if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
2143 {
2144 return error(GL_INVALID_OPERATION);
2145 }
2146
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002147 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +00002148
2149 if (!renderTarget)
2150 {
2151 return; // Context must be lost, return silently
2152 }
2153
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002154 IDirect3DDevice9 *device = getDevice();
2155
2156 D3DSURFACE_DESC desc;
2157 renderTarget->GetDesc(&desc);
2158
2159 IDirect3DSurface9 *systemSurface;
2160 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
2161
daniel@transgaming.com97b12412011-08-09 13:40:28 +00002162 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002163 {
daniel@transgaming.com97b12412011-08-09 13:40:28 +00002164 ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002165 return error(GL_OUT_OF_MEMORY);
2166 }
2167
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002168 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
2169 {
2170 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
daniel@transgaming.com97b12412011-08-09 13:40:28 +00002171 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002172 }
2173
2174 result = device->GetRenderTargetData(renderTarget, systemSurface);
2175
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002176 if (FAILED(result))
2177 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002178 systemSurface->Release();
2179
apatrick@chromium.org6db8cab2010-07-22 20:39:50 +00002180 switch (result)
2181 {
kbr@chromium.org1a2cd262011-07-08 17:30:18 +00002182 // It turns out that D3D will sometimes produce more error
2183 // codes than those documented.
daniel@transgaming.com1615be22011-02-09 16:30:06 +00002184 case D3DERR_DRIVERINTERNALERROR:
2185 case D3DERR_DEVICELOST:
kbr@chromium.org1a2cd262011-07-08 17:30:18 +00002186 case D3DERR_DEVICEHUNG:
daniel@transgaming.com1615be22011-02-09 16:30:06 +00002187 return error(GL_OUT_OF_MEMORY);
2188 default:
2189 UNREACHABLE();
2190 return; // No sensible error to generate
apatrick@chromium.org6db8cab2010-07-22 20:39:50 +00002191 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002192 }
2193
2194 D3DLOCKED_RECT lock;
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00002195 RECT rect = transformPixelRect(x, y, width, height, desc.Height);
2196 rect.left = clamp(rect.left, 0L, static_cast<LONG>(desc.Width));
2197 rect.top = clamp(rect.top, 0L, static_cast<LONG>(desc.Height));
2198 rect.right = clamp(rect.right, 0L, static_cast<LONG>(desc.Width));
2199 rect.bottom = clamp(rect.bottom, 0L, static_cast<LONG>(desc.Height));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002200
2201 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
2202
2203 if (FAILED(result))
2204 {
2205 UNREACHABLE();
2206 systemSurface->Release();
2207
2208 return; // No sensible error to generate
2209 }
2210
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00002211 unsigned char *source = ((unsigned char*)lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002212 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002213 unsigned short *dest16 = (unsigned short*)pixels;
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00002214 int inputPitch = -lock.Pitch;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002215 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002216
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002217 for (int j = 0; j < rect.bottom - rect.top; j++)
2218 {
daniel@transgaming.coma9198d92010-08-08 04:49:56 +00002219 if (desc.Format == D3DFMT_A8R8G8B8 &&
2220 format == GL_BGRA_EXT &&
2221 type == GL_UNSIGNED_BYTE)
2222 {
2223 // Fast path for EXT_read_format_bgra, given
2224 // an RGBA source buffer. Note that buffers with no
2225 // alpha go through the slow path below.
2226 memcpy(dest + j * outputPitch,
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00002227 source + j * inputPitch,
daniel@transgaming.coma9198d92010-08-08 04:49:56 +00002228 (rect.right - rect.left) * 4);
2229 continue;
2230 }
2231
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002232 for (int i = 0; i < rect.right - rect.left; i++)
2233 {
2234 float r;
2235 float g;
2236 float b;
2237 float a;
2238
2239 switch (desc.Format)
2240 {
2241 case D3DFMT_R5G6B5:
2242 {
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00002243 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * inputPitch);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002244
2245 a = 1.0f;
2246 b = (rgb & 0x001F) * (1.0f / 0x001F);
2247 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2248 r = (rgb & 0xF800) * (1.0f / 0xF800);
2249 }
2250 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002251 case D3DFMT_A1R5G5B5:
2252 {
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00002253 unsigned short argb = *(unsigned short*)(source + 2 * i + j * inputPitch);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002254
2255 a = (argb & 0x8000) ? 1.0f : 0.0f;
2256 b = (argb & 0x001F) * (1.0f / 0x001F);
2257 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2258 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2259 }
2260 break;
2261 case D3DFMT_A8R8G8B8:
2262 {
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00002263 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002264
2265 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2266 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2267 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2268 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2269 }
2270 break;
2271 case D3DFMT_X8R8G8B8:
2272 {
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00002273 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * inputPitch);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002274
2275 a = 1.0f;
2276 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2277 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2278 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2279 }
2280 break;
2281 case D3DFMT_A2R10G10B10:
2282 {
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00002283 unsigned int argb = *(unsigned int*)(source + 4 * i + j * inputPitch);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002284
2285 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2286 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2287 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2288 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2289 }
2290 break;
daniel@transgaming.com1297d922010-09-01 15:47:47 +00002291 case D3DFMT_A32B32G32R32F:
2292 {
2293 // float formats in D3D are stored rgba, rather than the other way round
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00002294 r = *((float*)(source + 16 * i + j * inputPitch) + 0);
2295 g = *((float*)(source + 16 * i + j * inputPitch) + 1);
2296 b = *((float*)(source + 16 * i + j * inputPitch) + 2);
2297 a = *((float*)(source + 16 * i + j * inputPitch) + 3);
daniel@transgaming.com1297d922010-09-01 15:47:47 +00002298 }
2299 break;
2300 case D3DFMT_A16B16G16R16F:
2301 {
2302 // float formats in D3D are stored rgba, rather than the other way round
2303 float abgr[4];
2304
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00002305 D3DXFloat16To32Array(abgr, (D3DXFLOAT16*)(source + 8 * i + j * inputPitch), 4);
daniel@transgaming.com1297d922010-09-01 15:47:47 +00002306
2307 a = abgr[3];
2308 b = abgr[2];
2309 g = abgr[1];
2310 r = abgr[0];
2311 }
2312 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002313 default:
2314 UNIMPLEMENTED(); // FIXME
2315 UNREACHABLE();
2316 }
2317
2318 switch (format)
2319 {
2320 case GL_RGBA:
2321 switch (type)
2322 {
2323 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002324 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2325 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2326 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2327 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002328 break;
2329 default: UNREACHABLE();
2330 }
2331 break;
daniel@transgaming.coma9198d92010-08-08 04:49:56 +00002332 case GL_BGRA_EXT:
2333 switch (type)
2334 {
2335 case GL_UNSIGNED_BYTE:
2336 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
2337 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2338 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
2339 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
2340 break;
2341 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
2342 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
2343 // this type is packed as follows:
2344 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
2345 // --------------------------------------------------------------------------------
2346 // | 4th | 3rd | 2nd | 1st component |
2347 // --------------------------------------------------------------------------------
2348 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
2349 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2350 ((unsigned short)(15 * a + 0.5f) << 12)|
2351 ((unsigned short)(15 * r + 0.5f) << 8) |
2352 ((unsigned short)(15 * g + 0.5f) << 4) |
2353 ((unsigned short)(15 * b + 0.5f) << 0);
2354 break;
2355 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
2356 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
2357 // this type is packed as follows:
2358 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
2359 // --------------------------------------------------------------------------------
2360 // | 4th | 3rd | 2nd | 1st component |
2361 // --------------------------------------------------------------------------------
2362 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
2363 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2364 ((unsigned short)( a + 0.5f) << 15) |
2365 ((unsigned short)(31 * r + 0.5f) << 10) |
2366 ((unsigned short)(31 * g + 0.5f) << 5) |
2367 ((unsigned short)(31 * b + 0.5f) << 0);
2368 break;
2369 default: UNREACHABLE();
2370 }
2371 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002372 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002373 switch (type)
2374 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002375 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002376 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2377 ((unsigned short)(31 * b + 0.5f) << 0) |
2378 ((unsigned short)(63 * g + 0.5f) << 5) |
2379 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002380 break;
2381 default: UNREACHABLE();
2382 }
2383 break;
2384 default: UNREACHABLE();
2385 }
2386 }
2387 }
2388
2389 systemSurface->UnlockRect();
2390
2391 systemSurface->Release();
2392}
2393
2394void Context::clear(GLbitfield mask)
2395{
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00002396 Framebuffer *framebufferObject = getDrawFramebuffer();
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002397
2398 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2399 {
daniel@transgaming.comb5a3a6b2011-03-21 16:38:46 +00002400 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002401 }
2402
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002403 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002404 IDirect3DDevice9 *device = getDevice();
2405 DWORD flags = 0;
2406
2407 if (mask & GL_COLOR_BUFFER_BIT)
2408 {
2409 mask &= ~GL_COLOR_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002410
2411 if (framebufferObject->getColorbufferType() != GL_NONE)
2412 {
2413 flags |= D3DCLEAR_TARGET;
2414 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002415 }
2416
2417 if (mask & GL_DEPTH_BUFFER_BIT)
2418 {
2419 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002420 if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002421 {
2422 flags |= D3DCLEAR_ZBUFFER;
2423 }
2424 }
2425
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002426 GLuint stencilUnmasked = 0x0;
2427
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002428 if (mask & GL_STENCIL_BUFFER_BIT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002429 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002430 mask &= ~GL_STENCIL_BUFFER_BIT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002431 if (framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002432 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002433 IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
apatrick@chromium.orgb2bdd062010-10-05 02:24:30 +00002434 if (!depthStencil)
2435 {
2436 ERR("Depth stencil pointer unexpectedly null.");
2437 return;
2438 }
2439
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002440 D3DSURFACE_DESC desc;
2441 depthStencil->GetDesc(&desc);
2442
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002443 unsigned int stencilSize = dx2es::GetStencilSize(desc.Format);
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002444 stencilUnmasked = (0x1 << stencilSize) - 1;
2445
2446 if (stencilUnmasked != 0x0)
2447 {
2448 flags |= D3DCLEAR_STENCIL;
2449 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002450 }
2451 }
2452
2453 if (mask != 0)
2454 {
2455 return error(GL_INVALID_VALUE);
2456 }
2457
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002458 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2459 {
2460 return;
2461 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002462
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002463 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
daniel@transgaming.com1615be22011-02-09 16:30:06 +00002464 unorm<8>(mState.colorClearValue.red),
2465 unorm<8>(mState.colorClearValue.green),
2466 unorm<8>(mState.colorClearValue.blue));
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002467 float depth = clamp01(mState.depthClearValue);
2468 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002469
2470 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2471
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +00002472 if (!renderTarget)
2473 {
2474 return; // Context must be lost, return silently
2475 }
2476
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002477 D3DSURFACE_DESC desc;
2478 renderTarget->GetDesc(&desc);
2479
daniel@transgaming.comd2fd4f22011-02-01 18:49:11 +00002480 bool alphaUnmasked = (dx2es::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002481
2482 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002483 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002484 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002485 !(mState.colorMaskRed && mState.colorMaskGreen &&
2486 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002487
2488 if (needMaskedColorClear || needMaskedStencilClear)
2489 {
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002490 // State which is altered in all paths from this point to the clear call is saved.
2491 // State which is altered in only some paths will be flagged dirty in the case that
2492 // that path is taken.
2493 HRESULT hr;
2494 if (mMaskedClearSavedState == NULL)
2495 {
2496 hr = device->BeginStateBlock();
2497 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2498
2499 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2500 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2501 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2502 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2503 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2504 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2505 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2506 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2507 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2508 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2509 device->SetPixelShader(NULL);
2510 device->SetVertexShader(NULL);
2511 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
daniel@transgaming.com1615be22011-02-09 16:30:06 +00002512 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
2513 device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
2514 device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
2515 device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
2516 device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
2517 device->SetRenderState(D3DRS_TEXTUREFACTOR, color);
2518 device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002519
2520 hr = device->EndStateBlock(&mMaskedClearSavedState);
2521 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2522 }
2523
2524 ASSERT(mMaskedClearSavedState != NULL);
2525
2526 if (mMaskedClearSavedState != NULL)
2527 {
2528 hr = mMaskedClearSavedState->Capture();
2529 ASSERT(SUCCEEDED(hr));
2530 }
2531
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002532 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2533 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2534 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2535 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2536 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2537 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2538 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2539 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2540
2541 if (flags & D3DCLEAR_TARGET)
2542 {
daniel@transgaming.com1615be22011-02-09 16:30:06 +00002543 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen, mState.colorMaskBlue, mState.colorMaskAlpha));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002544 }
2545 else
2546 {
2547 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2548 }
2549
2550 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2551 {
2552 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2553 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2554 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2555 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002556 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002557 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002558 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2559 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002560 mStencilStateDirty = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002561 }
2562 else
2563 {
2564 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2565 }
2566
2567 device->SetPixelShader(NULL);
2568 device->SetVertexShader(NULL);
daniel@transgaming.com1615be22011-02-09 16:30:06 +00002569 device->SetFVF(D3DFVF_XYZRHW);
2570 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
2571 device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
2572 device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TFACTOR);
2573 device->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
2574 device->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TFACTOR);
2575 device->SetRenderState(D3DRS_TEXTUREFACTOR, color);
2576 device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002577
daniel@transgaming.com1615be22011-02-09 16:30:06 +00002578 float quad[4][4]; // A quadrilateral covering the target, aligned to match the edges
2579 quad[0][0] = -0.5f;
2580 quad[0][1] = desc.Height - 0.5f;
2581 quad[0][2] = 0.0f;
2582 quad[0][3] = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002583
daniel@transgaming.com1615be22011-02-09 16:30:06 +00002584 quad[1][0] = desc.Width - 0.5f;
2585 quad[1][1] = desc.Height - 0.5f;
2586 quad[1][2] = 0.0f;
2587 quad[1][3] = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002588
daniel@transgaming.com1615be22011-02-09 16:30:06 +00002589 quad[2][0] = -0.5f;
2590 quad[2][1] = -0.5f;
2591 quad[2][2] = 0.0f;
2592 quad[2][3] = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002593
daniel@transgaming.com1615be22011-02-09 16:30:06 +00002594 quad[3][0] = desc.Width - 0.5f;
2595 quad[3][1] = -0.5f;
2596 quad[3][2] = 0.0f;
2597 quad[3][3] = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002598
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002599 display->startScene();
daniel@transgaming.com1615be22011-02-09 16:30:06 +00002600 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(float[4]));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002601
2602 if (flags & D3DCLEAR_ZBUFFER)
2603 {
2604 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2605 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2606 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2607 }
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002608
2609 if (mMaskedClearSavedState != NULL)
2610 {
2611 mMaskedClearSavedState->Apply();
2612 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002613 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002614 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002615 {
2616 device->Clear(0, NULL, flags, color, depth, stencil);
2617 }
2618}
2619
2620void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2621{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002622 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002623 {
2624 return error(GL_INVALID_OPERATION);
2625 }
2626
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002627 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002628 IDirect3DDevice9 *device = getDevice();
2629 D3DPRIMITIVETYPE primitiveType;
2630 int primitiveCount;
2631
2632 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2633 return error(GL_INVALID_ENUM);
2634
2635 if (primitiveCount <= 0)
2636 {
2637 return;
2638 }
2639
2640 if (!applyRenderTarget(false))
2641 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002642 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002643 }
2644
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002645 applyState(mode);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002646
daniel@transgaming.com83921382011-01-08 05:46:00 +00002647 GLenum err = applyVertexBuffer(first, count);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002648 if (err != GL_NO_ERROR)
2649 {
2650 return error(err);
2651 }
2652
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002653 applyShaders();
2654 applyTextures();
2655
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002656 if (!getCurrentProgram()->validateSamplers(false))
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002657 {
2658 return error(GL_INVALID_OPERATION);
2659 }
2660
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002661 if (!cullSkipsDraw(mode))
2662 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002663 display->startScene();
daniel@transgaming.com83921382011-01-08 05:46:00 +00002664
2665 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002666
2667 if (mode == GL_LINE_LOOP) // Draw the last segment separately
2668 {
2669 drawClosingLine(first, first + count - 1);
2670 }
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002671 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002672}
2673
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002674void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002675{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002676 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002677 {
2678 return error(GL_INVALID_OPERATION);
2679 }
2680
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002681 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002682 {
2683 return error(GL_INVALID_OPERATION);
2684 }
2685
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002686 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002687 IDirect3DDevice9 *device = getDevice();
2688 D3DPRIMITIVETYPE primitiveType;
2689 int primitiveCount;
2690
2691 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2692 return error(GL_INVALID_ENUM);
2693
2694 if (primitiveCount <= 0)
2695 {
2696 return;
2697 }
2698
2699 if (!applyRenderTarget(false))
2700 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002701 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002702 }
2703
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002704 applyState(mode);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002705
2706 TranslatedIndexData indexInfo;
2707 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2708 if (err != GL_NO_ERROR)
2709 {
2710 return error(err);
2711 }
2712
daniel@transgaming.com83921382011-01-08 05:46:00 +00002713 GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
2714 err = applyVertexBuffer(indexInfo.minIndex, vertexCount);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002715 if (err != GL_NO_ERROR)
2716 {
2717 return error(err);
2718 }
2719
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002720 applyShaders();
2721 applyTextures();
2722
daniel@transgaming.comf494c9c2011-05-11 15:37:05 +00002723 if (!getCurrentProgram()->validateSamplers(false))
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002724 {
2725 return error(GL_INVALID_OPERATION);
2726 }
2727
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002728 if (!cullSkipsDraw(mode))
2729 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002730 display->startScene();
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002731
daniel@transgaming.com83921382011-01-08 05:46:00 +00002732 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount);
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002733
2734 if (mode == GL_LINE_LOOP) // Draw the last segment separately
2735 {
2736 drawClosingLine(count, type, indices);
2737 }
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002738 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002739}
2740
2741void Context::finish()
2742{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002743 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002744 IDirect3DDevice9 *device = getDevice();
2745 IDirect3DQuery9 *occlusionQuery = NULL;
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002746 HRESULT result;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002747
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002748 result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2749 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002750 {
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002751 ERR("CreateQuery failed hr=%x\n", result);
2752 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2753 {
2754 return error(GL_OUT_OF_MEMORY);
2755 }
2756 ASSERT(false);
2757 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002758 }
2759
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002760 IDirect3DStateBlock9 *savedState = NULL;
2761 result = device->CreateStateBlock(D3DSBT_ALL, &savedState);
2762 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002763 {
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002764 ERR("CreateStateBlock failed hr=%x\n", result);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002765 occlusionQuery->Release();
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002766
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002767 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002768 {
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002769 return error(GL_OUT_OF_MEMORY);
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002770 }
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002771 ASSERT(false);
2772 return;
2773 }
2774
2775 result = occlusionQuery->Issue(D3DISSUE_BEGIN);
2776 if (FAILED(result))
2777 {
2778 ERR("occlusionQuery->Issue(BEGIN) failed hr=%x\n", result);
2779 occlusionQuery->Release();
2780 savedState->Release();
2781 ASSERT(false);
2782 return;
2783 }
2784
2785 // Render something outside the render target
2786 device->SetPixelShader(NULL);
2787 device->SetVertexShader(NULL);
2788 device->SetFVF(D3DFVF_XYZRHW);
2789 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
2790 display->startScene();
2791 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
2792
2793 result = occlusionQuery->Issue(D3DISSUE_END);
2794 if (FAILED(result))
2795 {
2796 ERR("occlusionQuery->Issue(END) failed hr=%x\n", result);
2797 occlusionQuery->Release();
2798 savedState->Apply();
2799 savedState->Release();
2800 ASSERT(false);
2801 return;
2802 }
2803
2804 while ((result = occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH)) == S_FALSE)
2805 {
2806 // Keep polling, but allow other threads to do something useful first
2807 Sleep(0);
2808 }
2809
2810 occlusionQuery->Release();
2811 savedState->Apply();
2812 savedState->Release();
2813
2814 if (result == D3DERR_DEVICELOST)
2815 {
2816 error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002817 }
2818}
2819
2820void Context::flush()
2821{
2822 IDirect3DDevice9 *device = getDevice();
2823 IDirect3DQuery9 *eventQuery = NULL;
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002824 HRESULT result;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002825
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002826 result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2827 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002828 {
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002829 ERR("CreateQuery failed hr=%x\n", result);
2830 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2831 {
2832 return error(GL_OUT_OF_MEMORY);
2833 }
2834 ASSERT(false);
2835 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002836 }
2837
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002838 result = eventQuery->Issue(D3DISSUE_END);
2839 if (FAILED(result))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002840 {
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002841 ERR("eventQuery->Issue(END) failed hr=%x\n", result);
2842 ASSERT(false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002843 eventQuery->Release();
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002844 return;
2845 }
apatrick@chromium.org575e7912010-08-25 18:07:12 +00002846
daniel@transgaming.com18b7b5b2011-05-17 18:34:18 +00002847 result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
2848 eventQuery->Release();
2849
2850 if (result == D3DERR_DEVICELOST)
2851 {
2852 error(GL_OUT_OF_MEMORY);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002853 }
2854}
2855
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002856void Context::drawClosingLine(unsigned int first, unsigned int last)
2857{
2858 IDirect3DDevice9 *device = getDevice();
2859 IDirect3DIndexBuffer9 *indexBuffer = NULL;
jbauman@chromium.org399c35f2011-04-28 23:19:51 +00002860 bool succeeded = false;
2861 UINT offset;
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002862
2863 if (supports32bitIndices())
2864 {
jbauman@chromium.org399c35f2011-04-28 23:19:51 +00002865 const int spaceNeeded = 2 * sizeof(unsigned int);
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002866
jbauman@chromium.org399c35f2011-04-28 23:19:51 +00002867 if (!mClosingIB)
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002868 {
jbauman@chromium.org399c35f2011-04-28 23:19:51 +00002869 mClosingIB = new StreamingIndexBuffer(device, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX32);
2870 }
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002871
jbauman@chromium.org399c35f2011-04-28 23:19:51 +00002872 mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_INT);
2873
2874 unsigned int *data = static_cast<unsigned int*>(mClosingIB->map(spaceNeeded, &offset));
2875 if (data)
2876 {
2877 data[0] = last;
2878 data[1] = first;
2879 mClosingIB->unmap();
2880 offset /= 4;
2881 succeeded = true;
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002882 }
2883 }
2884 else
2885 {
jbauman@chromium.org399c35f2011-04-28 23:19:51 +00002886 const int spaceNeeded = 2 * sizeof(unsigned short);
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002887
jbauman@chromium.org399c35f2011-04-28 23:19:51 +00002888 if (!mClosingIB)
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002889 {
jbauman@chromium.org399c35f2011-04-28 23:19:51 +00002890 mClosingIB = new StreamingIndexBuffer(device, CLOSING_INDEX_BUFFER_SIZE, D3DFMT_INDEX16);
2891 }
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002892
jbauman@chromium.org399c35f2011-04-28 23:19:51 +00002893 mClosingIB->reserveSpace(spaceNeeded, GL_UNSIGNED_SHORT);
2894
2895 unsigned short *data = static_cast<unsigned short*>(mClosingIB->map(spaceNeeded, &offset));
2896 if (data)
2897 {
2898 data[0] = last;
2899 data[1] = first;
2900 mClosingIB->unmap();
2901 offset /= 2;
2902 succeeded = true;
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002903 }
2904 }
2905
jbauman@chromium.org399c35f2011-04-28 23:19:51 +00002906 if (succeeded)
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002907 {
jbauman@chromium.org399c35f2011-04-28 23:19:51 +00002908 device->SetIndices(mClosingIB->getBuffer());
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002909
jbauman@chromium.org2c199b12011-06-13 22:20:06 +00002910 device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, last, offset, 1);
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002911 }
2912 else
2913 {
2914 ERR("Could not create an index buffer for closing a line loop.");
2915 error(GL_OUT_OF_MEMORY);
2916 }
2917}
2918
2919void Context::drawClosingLine(GLsizei count, GLenum type, const void *indices)
2920{
2921 unsigned int first = 0;
2922 unsigned int last = 0;
2923
2924 if (mState.elementArrayBuffer.get())
2925 {
2926 Buffer *indexBuffer = mState.elementArrayBuffer.get();
2927 intptr_t offset = reinterpret_cast<intptr_t>(indices);
2928 indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset;
2929 }
2930
2931 switch (type)
2932 {
2933 case GL_UNSIGNED_BYTE:
2934 first = static_cast<const GLubyte*>(indices)[0];
2935 last = static_cast<const GLubyte*>(indices)[count - 1];
2936 break;
2937 case GL_UNSIGNED_SHORT:
2938 first = static_cast<const GLushort*>(indices)[0];
2939 last = static_cast<const GLushort*>(indices)[count - 1];
2940 break;
2941 case GL_UNSIGNED_INT:
2942 first = static_cast<const GLuint*>(indices)[0];
2943 last = static_cast<const GLuint*>(indices)[count - 1];
2944 break;
2945 default: UNREACHABLE();
2946 }
2947
2948 drawClosingLine(first, last);
2949}
2950
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002951void Context::recordInvalidEnum()
2952{
2953 mInvalidEnum = true;
2954}
2955
2956void Context::recordInvalidValue()
2957{
2958 mInvalidValue = true;
2959}
2960
2961void Context::recordInvalidOperation()
2962{
2963 mInvalidOperation = true;
2964}
2965
2966void Context::recordOutOfMemory()
2967{
2968 mOutOfMemory = true;
2969}
2970
2971void Context::recordInvalidFramebufferOperation()
2972{
2973 mInvalidFramebufferOperation = true;
2974}
2975
2976// Get one of the recorded errors and clear its flag, if any.
2977// [OpenGL ES 2.0.24] section 2.5 page 13.
2978GLenum Context::getError()
2979{
2980 if (mInvalidEnum)
2981 {
2982 mInvalidEnum = false;
2983
2984 return GL_INVALID_ENUM;
2985 }
2986
2987 if (mInvalidValue)
2988 {
2989 mInvalidValue = false;
2990
2991 return GL_INVALID_VALUE;
2992 }
2993
2994 if (mInvalidOperation)
2995 {
2996 mInvalidOperation = false;
2997
2998 return GL_INVALID_OPERATION;
2999 }
3000
3001 if (mOutOfMemory)
3002 {
3003 mOutOfMemory = false;
3004
3005 return GL_OUT_OF_MEMORY;
3006 }
3007
3008 if (mInvalidFramebufferOperation)
3009 {
3010 mInvalidFramebufferOperation = false;
3011
3012 return GL_INVALID_FRAMEBUFFER_OPERATION;
3013 }
3014
3015 return GL_NO_ERROR;
3016}
3017
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00003018bool Context::supportsShaderModel3() const
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00003019{
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00003020 return mSupportsShaderModel3;
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00003021}
3022
daniel@transgaming.com396c6432010-11-26 16:26:12 +00003023int Context::getMaximumVaryingVectors() const
3024{
3025 return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
3026}
3027
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00003028unsigned int Context::getMaximumVertexTextureImageUnits() const
daniel@transgaming.comaf29cac2011-05-11 15:36:31 +00003029{
3030 return mSupportsVertexTexture ? MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF : 0;
3031}
3032
daniel@transgaming.comdfd57022011-05-11 15:37:25 +00003033unsigned int Context::getMaximumCombinedTextureImageUnits() const
daniel@transgaming.comaf29cac2011-05-11 15:36:31 +00003034{
3035 return MAX_TEXTURE_IMAGE_UNITS + getMaximumVertexTextureImageUnits();
3036}
3037
daniel@transgaming.com458da142010-11-28 02:03:02 +00003038int Context::getMaximumFragmentUniformVectors() const
3039{
3040 return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2;
3041}
3042
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003043int Context::getMaxSupportedSamples() const
3044{
3045 return mMaxSupportedSamples;
3046}
3047
3048int Context::getNearestSupportedSamples(D3DFORMAT format, int requested) const
3049{
3050 if (requested == 0)
3051 {
3052 return requested;
3053 }
3054
3055 std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
3056 if (itr == mMultiSampleSupport.end())
3057 {
3058 return -1;
3059 }
3060
3061 for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
3062 {
3063 if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
3064 {
3065 return i;
3066 }
3067 }
3068
3069 return -1;
3070}
3071
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +00003072bool Context::supportsEventQueries() const
3073{
3074 return mSupportsEventQueries;
3075}
3076
gman@chromium.org50c526d2011-08-10 05:19:44 +00003077bool Context::supportsDXT1Textures() const
daniel@transgaming.com01868132010-08-24 19:21:17 +00003078{
gman@chromium.org50c526d2011-08-10 05:19:44 +00003079 return mSupportsDXT1Textures;
3080}
3081
3082bool Context::supportsDXT3Textures() const
3083{
3084 return mSupportsDXT3Textures;
3085}
3086
3087bool Context::supportsDXT5Textures() const
3088{
3089 return mSupportsDXT5Textures;
daniel@transgaming.com01868132010-08-24 19:21:17 +00003090}
3091
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00003092bool Context::supportsFloatTextures() const
3093{
3094 return mSupportsFloatTextures;
3095}
3096
3097bool Context::supportsFloatLinearFilter() const
3098{
3099 return mSupportsFloatLinearFilter;
3100}
3101
daniel@transgaming.com1297d922010-09-01 15:47:47 +00003102bool Context::supportsFloatRenderableTextures() const
3103{
3104 return mSupportsFloatRenderableTextures;
3105}
3106
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00003107bool Context::supportsHalfFloatTextures() const
3108{
3109 return mSupportsHalfFloatTextures;
3110}
3111
3112bool Context::supportsHalfFloatLinearFilter() const
3113{
3114 return mSupportsHalfFloatLinearFilter;
3115}
3116
daniel@transgaming.com1297d922010-09-01 15:47:47 +00003117bool Context::supportsHalfFloatRenderableTextures() const
3118{
3119 return mSupportsHalfFloatRenderableTextures;
3120}
3121
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00003122int Context::getMaximumRenderbufferDimension() const
3123{
3124 return mMaxRenderbufferDimension;
3125}
3126
3127int Context::getMaximumTextureDimension() const
3128{
3129 return mMaxTextureDimension;
3130}
3131
3132int Context::getMaximumCubeTextureDimension() const
3133{
3134 return mMaxCubeTextureDimension;
3135}
3136
3137int Context::getMaximumTextureLevel() const
3138{
3139 return mMaxTextureLevel;
3140}
3141
daniel@transgaming.comed828e52010-10-15 17:57:30 +00003142bool Context::supportsLuminanceTextures() const
3143{
3144 return mSupportsLuminanceTextures;
3145}
3146
3147bool Context::supportsLuminanceAlphaTextures() const
3148{
3149 return mSupportsLuminanceAlphaTextures;
3150}
3151
daniel@transgaming.com83921382011-01-08 05:46:00 +00003152bool Context::supports32bitIndices() const
3153{
3154 return mSupports32bitIndices;
3155}
3156
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00003157bool Context::supportsNonPower2Texture() const
3158{
3159 return mSupportsNonPower2Texture;
3160}
3161
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003162void Context::detachBuffer(GLuint buffer)
3163{
3164 // [OpenGL ES 2.0.24] section 2.9 page 22:
3165 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
3166 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
3167
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003168 if (mState.arrayBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003169 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003170 mState.arrayBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003171 }
3172
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003173 if (mState.elementArrayBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003174 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003175 mState.elementArrayBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003176 }
3177
3178 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
3179 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003180 if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003181 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003182 mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003183 }
3184 }
3185}
3186
3187void Context::detachTexture(GLuint texture)
3188{
3189 // [OpenGL ES 2.0.24] section 3.8 page 84:
3190 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
3191 // rebound to texture object zero
3192
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +00003193 for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003194 {
daniel@transgaming.com3f74c7a2011-05-11 15:36:51 +00003195 for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003196 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003197 if (mState.samplerTexture[type][sampler].id() == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00003198 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003199 mState.samplerTexture[type][sampler].set(NULL);
daniel@transgaming.com416485f2010-03-16 06:23:23 +00003200 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003201 }
3202 }
3203
3204 // [OpenGL ES 2.0.24] section 4.4 page 112:
3205 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
3206 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
3207 // image was attached in the currently bound framebuffer.
3208
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003209 Framebuffer *readFramebuffer = getReadFramebuffer();
3210 Framebuffer *drawFramebuffer = getDrawFramebuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003211
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003212 if (readFramebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003213 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003214 readFramebuffer->detachTexture(texture);
3215 }
3216
3217 if (drawFramebuffer && drawFramebuffer != readFramebuffer)
3218 {
3219 drawFramebuffer->detachTexture(texture);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003220 }
3221}
3222
3223void Context::detachFramebuffer(GLuint framebuffer)
3224{
3225 // [OpenGL ES 2.0.24] section 4.4 page 107:
3226 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
3227 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
3228
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +00003229 if (mState.readFramebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003230 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003231 bindReadFramebuffer(0);
3232 }
3233
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +00003234 if (mState.drawFramebuffer == framebuffer)
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003235 {
3236 bindDrawFramebuffer(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003237 }
3238}
3239
3240void Context::detachRenderbuffer(GLuint renderbuffer)
3241{
3242 // [OpenGL ES 2.0.24] section 4.4 page 109:
3243 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
3244 // had been executed with the target RENDERBUFFER and name of zero.
3245
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003246 if (mState.renderbuffer.id() == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003247 {
3248 bindRenderbuffer(0);
3249 }
3250
3251 // [OpenGL ES 2.0.24] section 4.4 page 111:
3252 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
3253 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
3254 // point to which this image was attached in the currently bound framebuffer.
3255
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003256 Framebuffer *readFramebuffer = getReadFramebuffer();
3257 Framebuffer *drawFramebuffer = getDrawFramebuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003258
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003259 if (readFramebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003260 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003261 readFramebuffer->detachRenderbuffer(renderbuffer);
3262 }
3263
3264 if (drawFramebuffer && drawFramebuffer != readFramebuffer)
3265 {
3266 drawFramebuffer->detachRenderbuffer(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003267 }
3268}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003269
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +00003270Texture *Context::getIncompleteTexture(TextureType type)
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003271{
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00003272 Texture *t = mIncompleteTextures[type].get();
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003273
3274 if (t == NULL)
3275 {
3276 static const GLubyte color[] = { 0, 0, 0, 255 };
3277
3278 switch (type)
3279 {
3280 default:
3281 UNREACHABLE();
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +00003282 // default falls through to TEXTURE_2D
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003283
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +00003284 case TEXTURE_2D:
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003285 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003286 Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID);
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00003287 incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003288 t = incomplete2d;
3289 }
3290 break;
3291
daniel@transgaming.com0e64dd62011-05-11 15:36:37 +00003292 case TEXTURE_CUBE:
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003293 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003294 TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003295
daniel@transgaming.com8a0a2db2011-03-21 16:38:20 +00003296 incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
3297 incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
3298 incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
3299 incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
3300 incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
3301 incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003302
3303 t = incompleteCube;
3304 }
3305 break;
3306 }
3307
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00003308 mIncompleteTextures[type].set(t);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003309 }
3310
3311 return t;
3312}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00003313
daniel@transgaming.com5af64272010-04-15 20:45:12 +00003314bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00003315{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00003316 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00003317}
3318
daniel@transgaming.com5af64272010-04-15 20:45:12 +00003319bool Context::isTriangleMode(GLenum drawMode)
3320{
3321 switch (drawMode)
3322 {
3323 case GL_TRIANGLES:
3324 case GL_TRIANGLE_FAN:
3325 case GL_TRIANGLE_STRIP:
3326 return true;
3327 case GL_POINTS:
3328 case GL_LINES:
3329 case GL_LINE_LOOP:
3330 case GL_LINE_STRIP:
3331 return false;
3332 default: UNREACHABLE();
3333 }
3334
3335 return false;
3336}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00003337
3338void Context::setVertexAttrib(GLuint index, const GLfloat *values)
3339{
3340 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
3341
daniel@transgaming.com428d1582010-05-04 03:35:25 +00003342 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
3343 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
3344 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
3345 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00003346
daniel@transgaming.com83921382011-01-08 05:46:00 +00003347 mVertexDataManager->dirtyCurrentValue(index);
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00003348}
3349
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00003350void Context::initExtensionString()
3351{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00003352 mExtensionString += "GL_OES_packed_depth_stencil ";
daniel@transgaming.coma9198d92010-08-08 04:49:56 +00003353 mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
3354 mExtensionString += "GL_EXT_read_format_bgra ";
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003355 mExtensionString += "GL_ANGLE_framebuffer_blit ";
daniel@transgaming.comd36c2972010-08-24 19:21:07 +00003356 mExtensionString += "GL_OES_rgb8_rgba8 ";
alokp@chromium.orgd303ef92010-09-09 17:30:15 +00003357 mExtensionString += "GL_OES_standard_derivatives ";
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00003358
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +00003359 if (supportsEventQueries())
3360 {
3361 mExtensionString += "GL_NV_fence ";
3362 }
3363
gman@chromium.org50c526d2011-08-10 05:19:44 +00003364 if (supportsDXT1Textures())
daniel@transgaming.com01868132010-08-24 19:21:17 +00003365 {
3366 mExtensionString += "GL_EXT_texture_compression_dxt1 ";
3367 }
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00003368
gman@chromium.org50c526d2011-08-10 05:19:44 +00003369 if (supportsDXT3Textures())
3370 {
3371 mExtensionString += "GL_ANGLE_texture_compression_dxt3 ";
3372 }
3373
3374 if (supportsDXT5Textures())
3375 {
3376 mExtensionString += "GL_ANGLE_texture_compression_dxt5 ";
3377 }
3378
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00003379 if (supportsFloatTextures())
3380 {
3381 mExtensionString += "GL_OES_texture_float ";
3382 }
3383
3384 if (supportsHalfFloatTextures())
3385 {
3386 mExtensionString += "GL_OES_texture_half_float ";
3387 }
3388
3389 if (supportsFloatLinearFilter())
3390 {
3391 mExtensionString += "GL_OES_texture_float_linear ";
3392 }
3393
3394 if (supportsHalfFloatLinearFilter())
3395 {
3396 mExtensionString += "GL_OES_texture_half_float_linear ";
3397 }
3398
daniel@transgaming.com3ea20e72010-08-24 19:20:58 +00003399 if (getMaxSupportedSamples() != 0)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003400 {
3401 mExtensionString += "GL_ANGLE_framebuffer_multisample ";
3402 }
3403
daniel@transgaming.com83921382011-01-08 05:46:00 +00003404 if (supports32bitIndices())
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00003405 {
3406 mExtensionString += "GL_OES_element_index_uint ";
3407 }
3408
daniel@transgaming.com4f9ef0d2011-05-30 23:51:19 +00003409 if (supportsNonPower2Texture())
3410 {
3411 mExtensionString += "GL_OES_texture_npot ";
3412 }
3413
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00003414 std::string::size_type end = mExtensionString.find_last_not_of(' ');
3415 if (end != std::string::npos)
3416 {
3417 mExtensionString.resize(end+1);
3418 }
3419}
3420
3421const char *Context::getExtensionString() const
3422{
3423 return mExtensionString.c_str();
3424}
3425
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003426void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3427 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3428 GLbitfield mask)
3429{
3430 IDirect3DDevice9 *device = getDevice();
3431
3432 Framebuffer *readFramebuffer = getReadFramebuffer();
3433 Framebuffer *drawFramebuffer = getDrawFramebuffer();
3434
3435 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
3436 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
3437 {
3438 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
3439 }
3440
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003441 if (drawFramebuffer->getSamples() != 0)
3442 {
3443 return error(GL_INVALID_OPERATION);
3444 }
3445
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00003446 int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth();
3447 int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight();
3448 int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth();
3449 int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight();
3450
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003451 RECT sourceRect;
3452 RECT destRect;
3453
3454 if (srcX0 < srcX1)
3455 {
3456 sourceRect.left = srcX0;
3457 sourceRect.right = srcX1;
3458 destRect.left = dstX0;
3459 destRect.right = dstX1;
3460 }
3461 else
3462 {
3463 sourceRect.left = srcX1;
3464 destRect.left = dstX1;
3465 sourceRect.right = srcX0;
3466 destRect.right = dstX0;
3467 }
3468
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003469 if (srcY0 < srcY1)
3470 {
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00003471 sourceRect.top = readBufferHeight - srcY1;
3472 destRect.top = drawBufferHeight - dstY1;
3473 sourceRect.bottom = readBufferHeight - srcY0;
3474 destRect.bottom = drawBufferHeight - dstY0;
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003475 }
3476 else
3477 {
apatrick@chromium.orgb31f5322011-01-19 19:02:52 +00003478 sourceRect.top = readBufferHeight - srcY0;
3479 destRect.top = drawBufferHeight - dstY0;
3480 sourceRect.bottom = readBufferHeight - srcY1;
3481 destRect.bottom = drawBufferHeight - dstY1;
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003482 }
3483
3484 RECT sourceScissoredRect = sourceRect;
3485 RECT destScissoredRect = destRect;
3486
3487 if (mState.scissorTest)
3488 {
3489 // Only write to parts of the destination framebuffer which pass the scissor test
3490 // Please note: the destRect is now in D3D-style coordinates, so the *top* of the
3491 // rect will be checked against scissorY, rather than the bottom.
3492 if (destRect.left < mState.scissorX)
3493 {
3494 int xDiff = mState.scissorX - destRect.left;
3495 destScissoredRect.left = mState.scissorX;
3496 sourceScissoredRect.left += xDiff;
3497 }
3498
3499 if (destRect.right > mState.scissorX + mState.scissorWidth)
3500 {
3501 int xDiff = destRect.right - (mState.scissorX + mState.scissorWidth);
3502 destScissoredRect.right = mState.scissorX + mState.scissorWidth;
3503 sourceScissoredRect.right -= xDiff;
3504 }
3505
3506 if (destRect.top < mState.scissorY)
3507 {
3508 int yDiff = mState.scissorY - destRect.top;
3509 destScissoredRect.top = mState.scissorY;
3510 sourceScissoredRect.top += yDiff;
3511 }
3512
3513 if (destRect.bottom > mState.scissorY + mState.scissorHeight)
3514 {
3515 int yDiff = destRect.bottom - (mState.scissorY + mState.scissorHeight);
3516 destScissoredRect.bottom = mState.scissorY + mState.scissorHeight;
3517 sourceScissoredRect.bottom -= yDiff;
3518 }
3519 }
3520
3521 bool blitRenderTarget = false;
3522 bool blitDepthStencil = false;
3523
3524 RECT sourceTrimmedRect = sourceScissoredRect;
3525 RECT destTrimmedRect = destScissoredRect;
3526
3527 // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of
3528 // the actual draw and read surfaces.
3529 if (sourceTrimmedRect.left < 0)
3530 {
3531 int xDiff = 0 - sourceTrimmedRect.left;
3532 sourceTrimmedRect.left = 0;
3533 destTrimmedRect.left += xDiff;
3534 }
3535
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003536 if (sourceTrimmedRect.right > readBufferWidth)
3537 {
3538 int xDiff = sourceTrimmedRect.right - readBufferWidth;
3539 sourceTrimmedRect.right = readBufferWidth;
3540 destTrimmedRect.right -= xDiff;
3541 }
3542
3543 if (sourceTrimmedRect.top < 0)
3544 {
3545 int yDiff = 0 - sourceTrimmedRect.top;
3546 sourceTrimmedRect.top = 0;
3547 destTrimmedRect.top += yDiff;
3548 }
3549
3550 if (sourceTrimmedRect.bottom > readBufferHeight)
3551 {
3552 int yDiff = sourceTrimmedRect.bottom - readBufferHeight;
3553 sourceTrimmedRect.bottom = readBufferHeight;
3554 destTrimmedRect.bottom -= yDiff;
3555 }
3556
3557 if (destTrimmedRect.left < 0)
3558 {
3559 int xDiff = 0 - destTrimmedRect.left;
3560 destTrimmedRect.left = 0;
3561 sourceTrimmedRect.left += xDiff;
3562 }
3563
3564 if (destTrimmedRect.right > drawBufferWidth)
3565 {
3566 int xDiff = destTrimmedRect.right - drawBufferWidth;
3567 destTrimmedRect.right = drawBufferWidth;
3568 sourceTrimmedRect.right -= xDiff;
3569 }
3570
3571 if (destTrimmedRect.top < 0)
3572 {
3573 int yDiff = 0 - destTrimmedRect.top;
3574 destTrimmedRect.top = 0;
3575 sourceTrimmedRect.top += yDiff;
3576 }
3577
3578 if (destTrimmedRect.bottom > drawBufferHeight)
3579 {
3580 int yDiff = destTrimmedRect.bottom - drawBufferHeight;
3581 destTrimmedRect.bottom = drawBufferHeight;
3582 sourceTrimmedRect.bottom -= yDiff;
3583 }
3584
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003585 bool partialBufferCopy = false;
daniel@transgaming.com3aba7332011-01-14 15:08:35 +00003586 if (sourceTrimmedRect.bottom - sourceTrimmedRect.top < readBufferHeight ||
3587 sourceTrimmedRect.right - sourceTrimmedRect.left < readBufferWidth ||
3588 destTrimmedRect.bottom - destTrimmedRect.top < drawBufferHeight ||
3589 destTrimmedRect.right - destTrimmedRect.left < drawBufferWidth ||
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003590 sourceTrimmedRect.top != 0 || destTrimmedRect.top != 0 || sourceTrimmedRect.left != 0 || destTrimmedRect.left != 0)
3591 {
3592 partialBufferCopy = true;
3593 }
3594
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003595 if (mask & GL_COLOR_BUFFER_BIT)
3596 {
enne@chromium.org0fa74632010-09-21 16:18:52 +00003597 const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
3598 readFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
3599 const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
3600 drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
3601 if (!validReadType || !validDrawType ||
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003602 readFramebuffer->getColorbuffer()->getD3DFormat() != drawFramebuffer->getColorbuffer()->getD3DFormat())
3603 {
3604 ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
3605 return error(GL_INVALID_OPERATION);
3606 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003607
3608 if (partialBufferCopy && readFramebuffer->getSamples() != 0)
3609 {
3610 return error(GL_INVALID_OPERATION);
3611 }
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003612
3613 blitRenderTarget = true;
3614
3615 }
3616
3617 if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
3618 {
3619 DepthStencilbuffer *readDSBuffer = NULL;
3620 DepthStencilbuffer *drawDSBuffer = NULL;
3621
3622 // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
3623 // both a depth and stencil buffer, it will be the same buffer.
3624
3625 if (mask & GL_DEPTH_BUFFER_BIT)
3626 {
3627 if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
3628 {
3629 if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
3630 readFramebuffer->getDepthbuffer()->getD3DFormat() != drawFramebuffer->getDepthbuffer()->getD3DFormat())
3631 {
3632 return error(GL_INVALID_OPERATION);
3633 }
3634
3635 blitDepthStencil = true;
3636 readDSBuffer = readFramebuffer->getDepthbuffer();
3637 drawDSBuffer = drawFramebuffer->getDepthbuffer();
3638 }
3639 }
3640
3641 if (mask & GL_STENCIL_BUFFER_BIT)
3642 {
3643 if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
3644 {
3645 if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
3646 readFramebuffer->getStencilbuffer()->getD3DFormat() != drawFramebuffer->getStencilbuffer()->getD3DFormat())
3647 {
3648 return error(GL_INVALID_OPERATION);
3649 }
3650
3651 blitDepthStencil = true;
3652 readDSBuffer = readFramebuffer->getStencilbuffer();
3653 drawDSBuffer = drawFramebuffer->getStencilbuffer();
3654 }
3655 }
3656
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003657 if (partialBufferCopy)
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003658 {
3659 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
3660 return error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted
3661 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003662
daniel@transgaming.com97446d22010-08-24 19:20:54 +00003663 if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) ||
3664 (readDSBuffer && readDSBuffer->getSamples() != 0))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003665 {
3666 return error(GL_INVALID_OPERATION);
3667 }
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003668 }
3669
3670 if (blitRenderTarget || blitDepthStencil)
3671 {
3672 egl::Display *display = getDisplay();
3673 display->endScene();
3674
3675 if (blitRenderTarget)
3676 {
3677 HRESULT result = device->StretchRect(readFramebuffer->getRenderTarget(), &sourceTrimmedRect,
3678 drawFramebuffer->getRenderTarget(), &destTrimmedRect, D3DTEXF_NONE);
3679
3680 if (FAILED(result))
3681 {
3682 ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
3683 return;
3684 }
3685 }
3686
3687 if (blitDepthStencil)
3688 {
3689 HRESULT result = device->StretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, D3DTEXF_NONE);
3690
3691 if (FAILED(result))
3692 {
3693 ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
3694 return;
3695 }
3696 }
3697 }
3698}
3699
daniel@transgaming.com09c2c1a2011-04-13 14:57:16 +00003700VertexDeclarationCache::VertexDeclarationCache() : mMaxLru(0)
3701{
3702 for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
3703 {
3704 mVertexDeclCache[i].vertexDeclaration = NULL;
3705 mVertexDeclCache[i].lruCount = 0;
3706 }
3707}
3708
3709VertexDeclarationCache::~VertexDeclarationCache()
3710{
3711 for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
3712 {
3713 if (mVertexDeclCache[i].vertexDeclaration)
3714 {
3715 mVertexDeclCache[i].vertexDeclaration->Release();
3716 }
3717 }
3718}
3719
3720GLenum VertexDeclarationCache::applyDeclaration(TranslatedAttribute attributes[], Program *program)
3721{
3722 IDirect3DDevice9 *device = getDevice();
3723
3724 D3DVERTEXELEMENT9 elements[MAX_VERTEX_ATTRIBS + 1];
3725 D3DVERTEXELEMENT9 *element = &elements[0];
3726
3727 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
3728 {
3729 if (attributes[i].active)
3730 {
3731 device->SetStreamSource(i, attributes[i].vertexBuffer, attributes[i].offset, attributes[i].stride);
3732
3733 element->Stream = i;
3734 element->Offset = 0;
3735 element->Type = attributes[i].type;
3736 element->Method = D3DDECLMETHOD_DEFAULT;
3737 element->Usage = D3DDECLUSAGE_TEXCOORD;
3738 element->UsageIndex = program->getSemanticIndex(i);
3739 element++;
3740 }
3741 }
3742
3743 static const D3DVERTEXELEMENT9 end = D3DDECL_END();
3744 *(element++) = end;
3745
3746 for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
3747 {
3748 VertexDeclCacheEntry *entry = &mVertexDeclCache[i];
3749 if (memcmp(entry->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9)) == 0 && entry->vertexDeclaration)
3750 {
3751 entry->lruCount = ++mMaxLru;
3752 device->SetVertexDeclaration(entry->vertexDeclaration);
3753
3754 return GL_NO_ERROR;
3755 }
3756 }
3757
3758 VertexDeclCacheEntry *lastCache = mVertexDeclCache;
3759
3760 for (int i = 0; i < NUM_VERTEX_DECL_CACHE_ENTRIES; i++)
3761 {
3762 if (mVertexDeclCache[i].lruCount < lastCache->lruCount)
3763 {
3764 lastCache = &mVertexDeclCache[i];
3765 }
3766 }
3767
3768 if (lastCache->vertexDeclaration != NULL)
3769 {
3770 lastCache->vertexDeclaration->Release();
3771 lastCache->vertexDeclaration = NULL;
3772 }
3773
3774 memcpy(lastCache->cachedElements, elements, (element - elements) * sizeof(D3DVERTEXELEMENT9));
3775 device->CreateVertexDeclaration(elements, &lastCache->vertexDeclaration);
3776 device->SetVertexDeclaration(lastCache->vertexDeclaration);
3777 lastCache->lruCount = ++mMaxLru;
3778
3779 return GL_NO_ERROR;
3780}
3781
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003782}
3783
3784extern "C"
3785{
daniel@transgaming.com0d25b002010-07-28 19:21:07 +00003786gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003787{
daniel@transgaming.com0d25b002010-07-28 19:21:07 +00003788 return new gl::Context(config, shareContext);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003789}
3790
3791void glDestroyContext(gl::Context *context)
3792{
3793 delete context;
3794
3795 if (context == gl::getContext())
3796 {
3797 gl::makeCurrent(NULL, NULL, NULL);
3798 }
3799}
3800
3801void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
3802{
3803 gl::makeCurrent(context, display, surface);
3804}
3805
3806gl::Context *glGetCurrentContext()
3807{
3808 return gl::getContext();
3809}
3810}