blob: 9be59c4bb5f8f38699e025f91f75b5a7fd729427 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
2// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Context.cpp: Implements the gl::Context class, managing all GL state and performing
8// rendering operations. It is the GLES2 specific implementation of EGLContext.
9
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/Context.h"
daniel@transgaming.com16973022010-03-11 19:22:19 +000011
12#include <algorithm>
13
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000014#include "libEGL/Display.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000015
16#include "libGLESv2/main.h"
17#include "libGLESv2/mathutil.h"
18#include "libGLESv2/utilities.h"
19#include "libGLESv2/Blit.h"
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000020#include "libGLESv2/ResourceManager.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000021#include "libGLESv2/Buffer.h"
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.combbf56f72010-04-20 18:52:13 +000028#include "libGLESv2/geometry/VertexDataManager.h"
29#include "libGLESv2/geometry/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
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034namespace gl
35{
daniel@transgaming.com0d25b002010-07-28 19:21:07 +000036Context::Context(const egl::Config *config, const gl::Context *shareContext)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +000037 : mConfig(config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000038{
39 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
daniel@transgaming.com092bd482010-05-12 03:39:36 +000040
daniel@transgaming.com428d1582010-05-04 03:35:25 +000041 mState.depthClearValue = 1.0f;
42 mState.stencilClearValue = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043
daniel@transgaming.com428d1582010-05-04 03:35:25 +000044 mState.cullFace = false;
45 mState.cullMode = GL_BACK;
46 mState.frontFace = GL_CCW;
47 mState.depthTest = false;
48 mState.depthFunc = GL_LESS;
49 mState.blend = false;
50 mState.sourceBlendRGB = GL_ONE;
51 mState.sourceBlendAlpha = GL_ONE;
52 mState.destBlendRGB = GL_ZERO;
53 mState.destBlendAlpha = GL_ZERO;
54 mState.blendEquationRGB = GL_FUNC_ADD;
55 mState.blendEquationAlpha = GL_FUNC_ADD;
56 mState.blendColor.red = 0;
57 mState.blendColor.green = 0;
58 mState.blendColor.blue = 0;
59 mState.blendColor.alpha = 0;
60 mState.stencilTest = false;
61 mState.stencilFunc = GL_ALWAYS;
62 mState.stencilRef = 0;
63 mState.stencilMask = -1;
64 mState.stencilWritemask = -1;
65 mState.stencilBackFunc = GL_ALWAYS;
66 mState.stencilBackRef = 0;
67 mState.stencilBackMask = - 1;
68 mState.stencilBackWritemask = -1;
69 mState.stencilFail = GL_KEEP;
70 mState.stencilPassDepthFail = GL_KEEP;
71 mState.stencilPassDepthPass = GL_KEEP;
72 mState.stencilBackFail = GL_KEEP;
73 mState.stencilBackPassDepthFail = GL_KEEP;
74 mState.stencilBackPassDepthPass = GL_KEEP;
75 mState.polygonOffsetFill = false;
76 mState.polygonOffsetFactor = 0.0f;
77 mState.polygonOffsetUnits = 0.0f;
78 mState.sampleAlphaToCoverage = false;
79 mState.sampleCoverage = false;
80 mState.sampleCoverageValue = 1.0f;
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +000081 mState.sampleCoverageInvert = false;
daniel@transgaming.com428d1582010-05-04 03:35:25 +000082 mState.scissorTest = false;
83 mState.dither = true;
84 mState.generateMipmapHint = GL_DONT_CARE;
alokp@chromium.orgd303ef92010-09-09 17:30:15 +000085 mState.fragmentShaderDerivativeHint = GL_DONT_CARE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000086
daniel@transgaming.com428d1582010-05-04 03:35:25 +000087 mState.lineWidth = 1.0f;
daniel@transgaming.com32e58cd2010-03-24 09:44:10 +000088
daniel@transgaming.com428d1582010-05-04 03:35:25 +000089 mState.viewportX = 0;
90 mState.viewportY = 0;
91 mState.viewportWidth = config->mDisplayMode.Width;
92 mState.viewportHeight = config->mDisplayMode.Height;
93 mState.zNear = 0.0f;
94 mState.zFar = 1.0f;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095
daniel@transgaming.com428d1582010-05-04 03:35:25 +000096 mState.scissorX = 0;
97 mState.scissorY = 0;
98 mState.scissorWidth = config->mDisplayMode.Width;
99 mState.scissorHeight = config->mDisplayMode.Height;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000101 mState.colorMaskRed = true;
102 mState.colorMaskGreen = true;
103 mState.colorMaskBlue = true;
104 mState.colorMaskAlpha = true;
105 mState.depthMask = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106
daniel@transgaming.com0d25b002010-07-28 19:21:07 +0000107 if (shareContext != NULL)
108 {
109 mResourceManager = shareContext->mResourceManager;
110 mResourceManager->addRef();
111 }
112 else
113 {
114 mResourceManager = new ResourceManager();
115 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000116
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000117 // [OpenGL ES 2.0.24] section 3.7 page 83:
118 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
119 // and cube map texture state vectors respectively associated with them.
120 // In order that access to these initial textures not be lost, they are treated as texture
121 // objects all of whose names are 0.
122
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +0000123 mTexture2DZero.set(new Texture2D(0));
124 mTextureCubeMapZero.set(new TextureCubeMap(0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000126 mState.activeSampler = 0;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000127 bindArrayBuffer(0);
128 bindElementArrayBuffer(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129 bindTextureCubeMap(0);
130 bindTexture2D(0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000131 bindReadFramebuffer(0);
132 bindDrawFramebuffer(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133 bindRenderbuffer(0);
134
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000135 mState.currentProgram = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000136
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000137 mState.packAlignment = 4;
138 mState.unpackAlignment = 4;
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +0000139
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000140 mVertexDataManager = NULL;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000141 mIndexDataManager = NULL;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000142 mBlit = NULL;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000143
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000144 mInvalidEnum = false;
145 mInvalidValue = false;
146 mInvalidOperation = false;
147 mOutOfMemory = false;
148 mInvalidFramebufferOperation = false;
daniel@transgaming.com159acdf2010-03-21 04:31:24 +0000149
150 mHasBeenCurrent = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000151
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000152 mSupportsCompressedTextures = false;
153 mSupportsEventQueries = false;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000154 mMaxSupportedSamples = 0;
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000155 mMaskedClearSavedState = NULL;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000156 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157}
158
159Context::~Context()
160{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000161 if (mState.currentProgram != 0)
162 {
163 Program *programObject = mResourceManager->getProgram(mState.currentProgram);
164 if (programObject)
165 {
166 programObject->release();
167 }
168 mState.currentProgram = 0;
169 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000170
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000171 while (!mFramebufferMap.empty())
172 {
173 deleteFramebuffer(mFramebufferMap.begin()->first);
174 }
175
daniel@transgaming.comfe208882010-09-01 15:47:57 +0000176 while (!mFenceMap.empty())
177 {
178 deleteFence(mFenceMap.begin()->first);
179 }
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000180
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000181 while (!mMultiSampleSupport.empty())
182 {
183 delete [] mMultiSampleSupport.begin()->second;
184 mMultiSampleSupport.erase(mMultiSampleSupport.begin());
185 }
186
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000187 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
188 {
189 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
190 {
191 mState.samplerTexture[type][sampler].set(NULL);
192 }
193 }
194
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000195 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
196 {
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +0000197 mIncompleteTextures[type].set(NULL);
daniel@transgaming.com12d54072010-03-16 06:23:26 +0000198 }
199
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000200 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
201 {
202 mState.vertexAttribute[i].mBoundBuffer.set(NULL);
203 }
204
205 mState.arrayBuffer.set(NULL);
206 mState.elementArrayBuffer.set(NULL);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000207 mState.renderbuffer.set(NULL);
208
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +0000209 mTexture2DZero.set(NULL);
210 mTextureCubeMapZero.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000211
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000212 delete mVertexDataManager;
daniel@transgaming.comf8b58a02010-03-26 04:08:45 +0000213 delete mIndexDataManager;
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000214 delete mBlit;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000215
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +0000216 if (mMaskedClearSavedState)
217 {
218 mMaskedClearSavedState->Release();
219 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000220
daniel@transgaming.com0d25b002010-07-28 19:21:07 +0000221 mResourceManager->release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222}
223
224void Context::makeCurrent(egl::Display *display, egl::Surface *surface)
225{
226 IDirect3DDevice9 *device = display->getDevice();
227
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000228 if (!mHasBeenCurrent)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000229 {
daniel@transgaming.com353569a2010-06-24 13:02:12 +0000230 mDeviceCaps = display->getDeviceCaps();
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000231
daniel@transgaming.com83921382011-01-08 05:46:00 +0000232 mVertexDataManager = new VertexDataManager(this, device);
233 mIndexDataManager = new IndexDataManager(this, device);
daniel@transgaming.comb8c28ed2010-04-13 03:26:32 +0000234 mBlit = new Blit(this);
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000235
daniel@transgaming.com5d752f22010-10-07 13:37:20 +0000236 mSupportsShaderModel3 = mDeviceCaps.PixelShaderVersion == D3DPS_VERSION(3, 0);
237
238 mMaxTextureDimension = std::min(std::min((int)mDeviceCaps.MaxTextureWidth, (int)mDeviceCaps.MaxTextureHeight),
239 (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
240 mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
241 mMaxRenderbufferDimension = mMaxTextureDimension;
242 mMaxTextureLevel = log2(mMaxTextureDimension) + 1;
243 TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d",
244 mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel);
245
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000246 const D3DFORMAT renderBufferFormats[] =
247 {
248 D3DFMT_A8R8G8B8,
daniel@transgaming.com63977542010-08-24 19:21:02 +0000249 D3DFMT_X8R8G8B8,
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000250 D3DFMT_R5G6B5,
251 D3DFMT_D24S8
252 };
253
254 int max = 0;
255 for (int i = 0; i < sizeof(renderBufferFormats) / sizeof(D3DFORMAT); ++i)
256 {
257 bool *multisampleArray = new bool[D3DMULTISAMPLE_16_SAMPLES + 1];
258 display->getMultiSampleSupport(renderBufferFormats[i], multisampleArray);
259 mMultiSampleSupport[renderBufferFormats[i]] = multisampleArray;
260
261 for (int j = D3DMULTISAMPLE_16_SAMPLES; j >= 0; --j)
262 {
263 if (multisampleArray[j] && j != D3DMULTISAMPLE_NONMASKABLE && j > max)
264 {
265 max = j;
266 }
267 }
268 }
269
270 mMaxSupportedSamples = max;
271
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000272 mSupportsEventQueries = display->getEventQuerySupport();
daniel@transgaming.com01868132010-08-24 19:21:17 +0000273 mSupportsCompressedTextures = display->getCompressedTextureSupport();
daniel@transgaming.com1297d922010-09-01 15:47:47 +0000274 mSupportsFloatTextures = display->getFloatTextureSupport(&mSupportsFloatLinearFilter, &mSupportsFloatRenderableTextures);
275 mSupportsHalfFloatTextures = display->getHalfFloatTextureSupport(&mSupportsHalfFloatLinearFilter, &mSupportsHalfFloatRenderableTextures);
daniel@transgaming.comed828e52010-10-15 17:57:30 +0000276 mSupportsLuminanceTextures = display->getLuminanceTextureSupport();
277 mSupportsLuminanceAlphaTextures = display->getLuminanceAlphaTextureSupport();
daniel@transgaming.com01868132010-08-24 19:21:17 +0000278
daniel@transgaming.com83921382011-01-08 05:46:00 +0000279 mSupports32bitIndices = mDeviceCaps.MaxVertexIndex >= (1 << 16);
280
daniel@transgaming.comc808c5a2010-05-14 17:31:01 +0000281 initExtensionString();
282
283 mState.viewportX = 0;
284 mState.viewportY = 0;
285 mState.viewportWidth = surface->getWidth();
286 mState.viewportHeight = surface->getHeight();
287
288 mState.scissorX = 0;
289 mState.scissorY = 0;
290 mState.scissorWidth = surface->getWidth();
291 mState.scissorHeight = surface->getHeight();
292
293 mHasBeenCurrent = true;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +0000294 }
295
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000296 // Wrap the existing Direct3D 9 resources into GL objects and assign them to the '0' names
297 IDirect3DSurface9 *defaultRenderTarget = surface->getRenderTarget();
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000298 IDirect3DSurface9 *depthStencil = surface->getDepthStencil();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000300 Colorbuffer *colorbufferZero = new Colorbuffer(defaultRenderTarget);
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000301 DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(depthStencil);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000302 Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303
304 setFramebufferZero(framebufferZero);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +0000306 if (defaultRenderTarget)
307 {
308 defaultRenderTarget->Release();
309 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000311 if (depthStencil)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312 {
daniel@transgaming.com0009d622010-03-16 06:23:31 +0000313 depthStencil->Release();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314 }
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +0000315
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000316 markAllStateDirty();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317}
318
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000319// 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 +0000320void Context::markAllStateDirty()
321{
daniel@transgaming.com092bd482010-05-12 03:39:36 +0000322 mAppliedRenderTargetSerial = 0;
daniel@transgaming.com339ae702010-05-12 03:40:20 +0000323 mAppliedDepthbufferSerial = 0;
apatrick@chromium.org85dc42b2010-09-14 03:10:08 +0000324 mAppliedStencilbufferSerial = 0;
vangelis@chromium.orgcf66ebb2010-09-14 22:15:43 +0000325 mDepthStencilInitialized = false;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000326 mAppliedProgram = 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000327
328 mClearStateDirty = true;
329 mCullStateDirty = true;
330 mDepthStateDirty = true;
331 mMaskStateDirty = true;
332 mBlendStateDirty = true;
333 mStencilStateDirty = true;
334 mPolygonOffsetStateDirty = true;
335 mScissorStateDirty = true;
336 mSampleStateDirty = true;
337 mDitherStateDirty = true;
daniel@transgaming.com0d25b002010-07-28 19:21:07 +0000338 mFrontFaceDirty = true;
daniel@transgaming.com4fa08332010-05-11 02:29:27 +0000339}
340
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341void Context::setClearColor(float red, float green, float blue, float alpha)
342{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000343 mState.colorClearValue.red = red;
344 mState.colorClearValue.green = green;
345 mState.colorClearValue.blue = blue;
346 mState.colorClearValue.alpha = alpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000347}
348
349void Context::setClearDepth(float depth)
350{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000351 mState.depthClearValue = depth;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352}
353
354void Context::setClearStencil(int stencil)
355{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000356 mState.stencilClearValue = stencil;
357}
358
359void Context::setCullFace(bool enabled)
360{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000361 if (mState.cullFace != enabled)
362 {
363 mState.cullFace = enabled;
364 mCullStateDirty = true;
365 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000366}
367
368bool Context::isCullFaceEnabled() const
369{
370 return mState.cullFace;
371}
372
373void Context::setCullMode(GLenum mode)
374{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000375 if (mState.cullMode != mode)
376 {
377 mState.cullMode = mode;
378 mCullStateDirty = true;
379 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000380}
381
382void Context::setFrontFace(GLenum front)
383{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000384 if (mState.frontFace != front)
385 {
386 mState.frontFace = front;
387 mFrontFaceDirty = true;
388 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000389}
390
391void Context::setDepthTest(bool enabled)
392{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000393 if (mState.depthTest != enabled)
394 {
395 mState.depthTest = enabled;
396 mDepthStateDirty = true;
397 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000398}
399
400bool Context::isDepthTestEnabled() const
401{
402 return mState.depthTest;
403}
404
405void Context::setDepthFunc(GLenum depthFunc)
406{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000407 if (mState.depthFunc != depthFunc)
408 {
409 mState.depthFunc = depthFunc;
410 mDepthStateDirty = true;
411 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000412}
413
414void Context::setDepthRange(float zNear, float zFar)
415{
416 mState.zNear = zNear;
417 mState.zFar = zFar;
418}
419
420void Context::setBlend(bool enabled)
421{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000422 if (mState.blend != enabled)
423 {
424 mState.blend = enabled;
425 mBlendStateDirty = true;
426 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000427}
428
429bool Context::isBlendEnabled() const
430{
431 return mState.blend;
432}
433
434void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
435{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000436 if (mState.sourceBlendRGB != sourceRGB ||
437 mState.sourceBlendAlpha != sourceAlpha ||
438 mState.destBlendRGB != destRGB ||
439 mState.destBlendAlpha != destAlpha)
440 {
441 mState.sourceBlendRGB = sourceRGB;
442 mState.destBlendRGB = destRGB;
443 mState.sourceBlendAlpha = sourceAlpha;
444 mState.destBlendAlpha = destAlpha;
445 mBlendStateDirty = true;
446 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000447}
448
449void Context::setBlendColor(float red, float green, float blue, float alpha)
450{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000451 if (mState.blendColor.red != red ||
452 mState.blendColor.green != green ||
453 mState.blendColor.blue != blue ||
454 mState.blendColor.alpha != alpha)
455 {
456 mState.blendColor.red = red;
457 mState.blendColor.green = green;
458 mState.blendColor.blue = blue;
459 mState.blendColor.alpha = alpha;
460 mBlendStateDirty = true;
461 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000462}
463
464void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
465{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000466 if (mState.blendEquationRGB != rgbEquation ||
467 mState.blendEquationAlpha != alphaEquation)
468 {
469 mState.blendEquationRGB = rgbEquation;
470 mState.blendEquationAlpha = alphaEquation;
471 mBlendStateDirty = true;
472 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000473}
474
475void Context::setStencilTest(bool enabled)
476{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000477 if (mState.stencilTest != enabled)
478 {
479 mState.stencilTest = enabled;
480 mStencilStateDirty = true;
481 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000482}
483
484bool Context::isStencilTestEnabled() const
485{
486 return mState.stencilTest;
487}
488
489void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
490{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000491 if (mState.stencilFunc != stencilFunc ||
492 mState.stencilRef != stencilRef ||
493 mState.stencilMask != stencilMask)
494 {
495 mState.stencilFunc = stencilFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000496 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000497 mState.stencilMask = stencilMask;
498 mStencilStateDirty = true;
499 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000500}
501
502void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
503{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000504 if (mState.stencilBackFunc != stencilBackFunc ||
505 mState.stencilBackRef != stencilBackRef ||
506 mState.stencilBackMask != stencilBackMask)
507 {
508 mState.stencilBackFunc = stencilBackFunc;
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +0000509 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000510 mState.stencilBackMask = stencilBackMask;
511 mStencilStateDirty = true;
512 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000513}
514
515void Context::setStencilWritemask(GLuint stencilWritemask)
516{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000517 if (mState.stencilWritemask != stencilWritemask)
518 {
519 mState.stencilWritemask = stencilWritemask;
520 mStencilStateDirty = true;
521 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000522}
523
524void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
525{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000526 if (mState.stencilBackWritemask != stencilBackWritemask)
527 {
528 mState.stencilBackWritemask = stencilBackWritemask;
529 mStencilStateDirty = true;
530 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000531}
532
533void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
534{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000535 if (mState.stencilFail != stencilFail ||
536 mState.stencilPassDepthFail != stencilPassDepthFail ||
537 mState.stencilPassDepthPass != stencilPassDepthPass)
538 {
539 mState.stencilFail = stencilFail;
540 mState.stencilPassDepthFail = stencilPassDepthFail;
541 mState.stencilPassDepthPass = stencilPassDepthPass;
542 mStencilStateDirty = true;
543 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000544}
545
546void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
547{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000548 if (mState.stencilBackFail != stencilBackFail ||
549 mState.stencilBackPassDepthFail != stencilBackPassDepthFail ||
550 mState.stencilBackPassDepthPass != stencilBackPassDepthPass)
551 {
552 mState.stencilBackFail = stencilBackFail;
553 mState.stencilBackPassDepthFail = stencilBackPassDepthFail;
554 mState.stencilBackPassDepthPass = stencilBackPassDepthPass;
555 mStencilStateDirty = true;
556 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000557}
558
559void Context::setPolygonOffsetFill(bool enabled)
560{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000561 if (mState.polygonOffsetFill != enabled)
562 {
563 mState.polygonOffsetFill = enabled;
564 mPolygonOffsetStateDirty = true;
565 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000566}
567
568bool Context::isPolygonOffsetFillEnabled() const
569{
570 return mState.polygonOffsetFill;
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000571
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000572}
573
574void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
575{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000576 if (mState.polygonOffsetFactor != factor ||
577 mState.polygonOffsetUnits != units)
578 {
579 mState.polygonOffsetFactor = factor;
580 mState.polygonOffsetUnits = units;
581 mPolygonOffsetStateDirty = true;
582 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000583}
584
585void Context::setSampleAlphaToCoverage(bool enabled)
586{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000587 if (mState.sampleAlphaToCoverage != enabled)
588 {
589 mState.sampleAlphaToCoverage = enabled;
590 mSampleStateDirty = true;
591 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000592}
593
594bool Context::isSampleAlphaToCoverageEnabled() const
595{
596 return mState.sampleAlphaToCoverage;
597}
598
599void Context::setSampleCoverage(bool enabled)
600{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000601 if (mState.sampleCoverage != enabled)
602 {
603 mState.sampleCoverage = enabled;
604 mSampleStateDirty = true;
605 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000606}
607
608bool Context::isSampleCoverageEnabled() const
609{
610 return mState.sampleCoverage;
611}
612
daniel@transgaming.coma36f98e2010-05-18 18:51:09 +0000613void Context::setSampleCoverageParams(GLclampf value, bool invert)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000614{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000615 if (mState.sampleCoverageValue != value ||
616 mState.sampleCoverageInvert != invert)
617 {
618 mState.sampleCoverageValue = value;
619 mState.sampleCoverageInvert = invert;
620 mSampleStateDirty = true;
621 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000622}
623
624void Context::setScissorTest(bool enabled)
625{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000626 if (mState.scissorTest != enabled)
627 {
628 mState.scissorTest = enabled;
629 mScissorStateDirty = true;
630 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000631}
632
633bool Context::isScissorTestEnabled() const
634{
635 return mState.scissorTest;
636}
637
638void Context::setDither(bool enabled)
639{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000640 if (mState.dither != enabled)
641 {
642 mState.dither = enabled;
643 mDitherStateDirty = true;
644 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000645}
646
647bool Context::isDitherEnabled() const
648{
649 return mState.dither;
650}
651
652void Context::setLineWidth(GLfloat width)
653{
654 mState.lineWidth = width;
655}
656
657void Context::setGenerateMipmapHint(GLenum hint)
658{
659 mState.generateMipmapHint = hint;
660}
661
alokp@chromium.orgd303ef92010-09-09 17:30:15 +0000662void Context::setFragmentShaderDerivativeHint(GLenum hint)
663{
664 mState.fragmentShaderDerivativeHint = hint;
665 // TODO: Propagate the hint to shader translator so we can write
666 // ddx, ddx_coarse, or ddx_fine depending on the hint.
667 // Ignore for now. It is valid for implementations to ignore hint.
668}
669
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000670void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
671{
672 mState.viewportX = x;
673 mState.viewportY = y;
674 mState.viewportWidth = width;
675 mState.viewportHeight = height;
676}
677
678void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
679{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000680 if (mState.scissorX != x || mState.scissorY != y ||
681 mState.scissorWidth != width || mState.scissorHeight != height)
682 {
683 mState.scissorX = x;
684 mState.scissorY = y;
685 mState.scissorWidth = width;
686 mState.scissorHeight = height;
687 mScissorStateDirty = true;
688 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000689}
690
691void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
692{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000693 if (mState.colorMaskRed != red || mState.colorMaskGreen != green ||
694 mState.colorMaskBlue != blue || mState.colorMaskAlpha != alpha)
695 {
696 mState.colorMaskRed = red;
697 mState.colorMaskGreen = green;
698 mState.colorMaskBlue = blue;
699 mState.colorMaskAlpha = alpha;
700 mMaskStateDirty = true;
701 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000702}
703
704void Context::setDepthMask(bool mask)
705{
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +0000706 if (mState.depthMask != mask)
707 {
708 mState.depthMask = mask;
709 mMaskStateDirty = true;
710 }
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000711}
712
713void Context::setActiveSampler(int active)
714{
715 mState.activeSampler = active;
716}
717
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000718GLuint Context::getReadFramebufferHandle() const
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000719{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000720 return mState.readFramebuffer;
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000721}
722
723GLuint Context::getDrawFramebufferHandle() const
724{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000725 return mState.drawFramebuffer;
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000726}
727
728GLuint Context::getRenderbufferHandle() const
729{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000730 return mState.renderbuffer.id();
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000731}
732
733GLuint Context::getArrayBufferHandle() const
734{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000735 return mState.arrayBuffer.id();
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000736}
737
daniel@transgaming.com83921382011-01-08 05:46:00 +0000738void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000739{
daniel@transgaming.com83921382011-01-08 05:46:00 +0000740 mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000741}
742
daniel@transgaming.com83921382011-01-08 05:46:00 +0000743const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000744{
745 return mState.vertexAttribute[attribNum];
746}
747
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000748void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000749 GLsizei stride, const void *pointer)
750{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000751 mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000752 mState.vertexAttribute[attribNum].mSize = size;
753 mState.vertexAttribute[attribNum].mType = type;
754 mState.vertexAttribute[attribNum].mNormalized = normalized;
755 mState.vertexAttribute[attribNum].mStride = stride;
756 mState.vertexAttribute[attribNum].mPointer = pointer;
757}
758
759const void *Context::getVertexAttribPointer(unsigned int attribNum) const
760{
761 return mState.vertexAttribute[attribNum].mPointer;
762}
763
daniel@transgaming.com83921382011-01-08 05:46:00 +0000764const VertexAttributeArray &Context::getVertexAttributes()
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000765{
766 return mState.vertexAttribute;
767}
768
769void Context::setPackAlignment(GLint alignment)
770{
771 mState.packAlignment = alignment;
772}
773
774GLint Context::getPackAlignment() const
775{
776 return mState.packAlignment;
777}
778
779void Context::setUnpackAlignment(GLint alignment)
780{
781 mState.unpackAlignment = alignment;
782}
783
784GLint Context::getUnpackAlignment() const
785{
786 return mState.unpackAlignment;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000787}
788
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000789GLuint Context::createBuffer()
790{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000791 return mResourceManager->createBuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000792}
793
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000794GLuint Context::createProgram()
795{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000796 return mResourceManager->createProgram();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000797}
798
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000799GLuint Context::createShader(GLenum type)
800{
801 return mResourceManager->createShader(type);
802}
803
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000804GLuint Context::createTexture()
805{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000806 return mResourceManager->createTexture();
807}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000808
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000809GLuint Context::createRenderbuffer()
810{
811 return mResourceManager->createRenderbuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000812}
813
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000814// Returns an unused framebuffer name
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000815GLuint Context::createFramebuffer()
816{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000817 unsigned int handle = 1;
818
819 while (mFramebufferMap.find(handle) != mFramebufferMap.end())
820 {
821 handle++;
822 }
823
824 mFramebufferMap[handle] = NULL;
825
826 return handle;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000827}
828
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000829GLuint Context::createFence()
830{
daniel@transgaming.comfe208882010-09-01 15:47:57 +0000831 unsigned int handle = 0;
832
833 while (mFenceMap.find(handle) != mFenceMap.end())
834 {
835 handle++;
836 }
837
838 mFenceMap[handle] = new Fence;
839
840 return handle;
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000841}
842
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000843void Context::deleteBuffer(GLuint buffer)
844{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000845 if (mResourceManager->getBuffer(buffer))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000846 {
847 detachBuffer(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000848 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000849
850 mResourceManager->deleteBuffer(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000851}
852
853void Context::deleteShader(GLuint shader)
854{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000855 mResourceManager->deleteShader(shader);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000856}
857
858void Context::deleteProgram(GLuint program)
859{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000860 mResourceManager->deleteProgram(program);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000861}
862
863void Context::deleteTexture(GLuint texture)
864{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000865 if (mResourceManager->getTexture(texture))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000866 {
867 detachTexture(texture);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000868 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000869
870 mResourceManager->deleteTexture(texture);
871}
872
873void Context::deleteRenderbuffer(GLuint renderbuffer)
874{
875 if (mResourceManager->getRenderbuffer(renderbuffer))
876 {
877 detachRenderbuffer(renderbuffer);
878 }
879
880 mResourceManager->deleteRenderbuffer(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000881}
882
883void Context::deleteFramebuffer(GLuint framebuffer)
884{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000885 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
886
887 if (framebufferObject != mFramebufferMap.end())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000888 {
889 detachFramebuffer(framebuffer);
apatrick@chromium.org55255022010-09-11 02:12:47 +0000890
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000891 delete framebufferObject->second;
892 mFramebufferMap.erase(framebufferObject);
893 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000894}
daniel@transgaming.comfe208882010-09-01 15:47:57 +0000895
896void Context::deleteFence(GLuint fence)
897{
898 FenceMap::iterator fenceObject = mFenceMap.find(fence);
899
900 if (fenceObject != mFenceMap.end())
901 {
902 delete fenceObject->second;
903 mFenceMap.erase(fenceObject);
904 }
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +0000905}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000906
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000907Buffer *Context::getBuffer(GLuint handle)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000908{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000909 return mResourceManager->getBuffer(handle);
910}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000911
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000912Shader *Context::getShader(GLuint handle)
913{
914 return mResourceManager->getShader(handle);
915}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000916
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000917Program *Context::getProgram(GLuint handle)
918{
919 return mResourceManager->getProgram(handle);
920}
921
922Texture *Context::getTexture(GLuint handle)
923{
924 return mResourceManager->getTexture(handle);
925}
926
927Renderbuffer *Context::getRenderbuffer(GLuint handle)
928{
929 return mResourceManager->getRenderbuffer(handle);
930}
931
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000932Framebuffer *Context::getReadFramebuffer()
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000933{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000934 return getFramebuffer(mState.readFramebuffer);
935}
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000936
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000937Framebuffer *Context::getDrawFramebuffer()
938{
939 return getFramebuffer(mState.drawFramebuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000940}
941
942void Context::bindArrayBuffer(unsigned int buffer)
943{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000944 mResourceManager->checkBufferAllocation(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000945
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000946 mState.arrayBuffer.set(getBuffer(buffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000947}
948
949void Context::bindElementArrayBuffer(unsigned int buffer)
950{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000951 mResourceManager->checkBufferAllocation(buffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000952
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000953 mState.elementArrayBuffer.set(getBuffer(buffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000954}
955
956void Context::bindTexture2D(GLuint texture)
957{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000958 mResourceManager->checkTextureAllocation(texture, SAMPLER_2D);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000959
daniel@transgaming.coma5a8a0a2010-11-19 14:55:32 +0000960 mState.samplerTexture[SAMPLER_2D][mState.activeSampler].set(getTexture(texture));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000961}
962
963void Context::bindTextureCubeMap(GLuint texture)
964{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000965 mResourceManager->checkTextureAllocation(texture, SAMPLER_CUBE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000966
daniel@transgaming.coma5a8a0a2010-11-19 14:55:32 +0000967 mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].set(getTexture(texture));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968}
969
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000970void Context::bindReadFramebuffer(GLuint framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000971{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000972 if (!getFramebuffer(framebuffer))
973 {
974 mFramebufferMap[framebuffer] = new Framebuffer();
975 }
976
977 mState.readFramebuffer = framebuffer;
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000978}
979
980void Context::bindDrawFramebuffer(GLuint framebuffer)
981{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +0000982 if (!getFramebuffer(framebuffer))
983 {
984 mFramebufferMap[framebuffer] = new Framebuffer();
985 }
986
987 mState.drawFramebuffer = framebuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000988}
989
990void Context::bindRenderbuffer(GLuint renderbuffer)
991{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000992 mResourceManager->checkRenderbufferAllocation(renderbuffer);
993
994 mState.renderbuffer.set(getRenderbuffer(renderbuffer));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000995}
996
997void Context::useProgram(GLuint program)
998{
daniel@transgaming.com428d1582010-05-04 03:35:25 +0000999 GLuint priorProgram = mState.currentProgram;
1000 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
daniel@transgaming.com71cd8682010-04-29 03:35:25 +00001001
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001002 if (priorProgram != program)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001003 {
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001004 Program *newProgram = mResourceManager->getProgram(program);
1005 Program *oldProgram = mResourceManager->getProgram(priorProgram);
1006
1007 if (newProgram)
1008 {
1009 newProgram->addRef();
1010 }
1011
1012 if (oldProgram)
1013 {
1014 oldProgram->release();
1015 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001016 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001017}
1018
1019void Context::setFramebufferZero(Framebuffer *buffer)
1020{
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +00001021 delete mFramebufferMap[0];
1022 mFramebufferMap[0] = buffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001023}
1024
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001025void Context::setRenderbufferStorage(RenderbufferStorage *renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001026{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001027 Renderbuffer *renderbufferObject = mState.renderbuffer.get();
1028 renderbufferObject->setStorage(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001029}
1030
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +00001031Framebuffer *Context::getFramebuffer(unsigned int handle)
1032{
1033 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
1034
1035 if (framebuffer == mFramebufferMap.end())
1036 {
1037 return NULL;
1038 }
1039 else
1040 {
1041 return framebuffer->second;
1042 }
1043}
1044
daniel@transgaming.comfe208882010-09-01 15:47:57 +00001045Fence *Context::getFence(unsigned int handle)
1046{
1047 FenceMap::iterator fence = mFenceMap.find(handle);
1048
1049 if (fence == mFenceMap.end())
1050 {
1051 return NULL;
1052 }
1053 else
1054 {
1055 return fence->second;
1056 }
1057}
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +00001058
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001059Buffer *Context::getArrayBuffer()
1060{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001061 return mState.arrayBuffer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001062}
1063
1064Buffer *Context::getElementArrayBuffer()
1065{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001066 return mState.elementArrayBuffer.get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001067}
1068
1069Program *Context::getCurrentProgram()
1070{
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001071 return mResourceManager->getProgram(mState.currentProgram);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001072}
1073
1074Texture2D *Context::getTexture2D()
1075{
daniel@transgaming.coma5a8a0a2010-11-19 14:55:32 +00001076 return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, SAMPLER_2D));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001077}
1078
1079TextureCubeMap *Context::getTextureCubeMap()
1080{
daniel@transgaming.coma5a8a0a2010-11-19 14:55:32 +00001081 return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, SAMPLER_CUBE));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001082}
1083
daniel@transgaming.com416485f2010-03-16 06:23:23 +00001084Texture *Context::getSamplerTexture(unsigned int sampler, SamplerType type)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001085{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001086 GLuint texid = mState.samplerTexture[type][sampler].id();
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001087
daniel@transgaming.coma5a8a0a2010-11-19 14:55:32 +00001088 if (texid == 0) // Special case: 0 refers to different initial textures based on the target
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001089 {
1090 switch (type)
1091 {
1092 default: UNREACHABLE();
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00001093 case SAMPLER_2D: return mTexture2DZero.get();
1094 case SAMPLER_CUBE: return mTextureCubeMapZero.get();
daniel@transgaming.com4195fc42010-04-08 03:51:09 +00001095 }
1096 }
1097
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001098 return mState.samplerTexture[type][sampler].get();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001099}
1100
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001101bool Context::getBooleanv(GLenum pname, GLboolean *params)
1102{
1103 switch (pname)
1104 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001105 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1106 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1107 case GL_DEPTH_WRITEMASK: *params = mState.depthMask; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001108 case GL_COLOR_WRITEMASK:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001109 params[0] = mState.colorMaskRed;
1110 params[1] = mState.colorMaskGreen;
1111 params[2] = mState.colorMaskBlue;
1112 params[3] = mState.colorMaskAlpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001113 break;
daniel@transgaming.com9d7fc1d2010-10-27 15:49:42 +00001114 case GL_CULL_FACE: *params = mState.cullFace; break;
1115 case GL_POLYGON_OFFSET_FILL: *params = mState.polygonOffsetFill; break;
1116 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.sampleAlphaToCoverage; break;
1117 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break;
1118 case GL_SCISSOR_TEST: *params = mState.scissorTest; break;
1119 case GL_STENCIL_TEST: *params = mState.stencilTest; break;
1120 case GL_DEPTH_TEST: *params = mState.depthTest; break;
1121 case GL_BLEND: *params = mState.blend; break;
1122 case GL_DITHER: *params = mState.dither; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001123 default:
1124 return false;
1125 }
1126
1127 return true;
1128}
1129
1130bool Context::getFloatv(GLenum pname, GLfloat *params)
1131{
1132 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1133 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1134 // GetIntegerv as its native query function. As it would require conversion in any
1135 // case, this should make no difference to the calling application.
1136 switch (pname)
1137 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001138 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1139 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1140 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1141 case GL_POLYGON_OFFSET_FACTOR: *params = mState.polygonOffsetFactor; break;
1142 case GL_POLYGON_OFFSET_UNITS: *params = mState.polygonOffsetUnits; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001143 case GL_ALIASED_LINE_WIDTH_RANGE:
1144 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1145 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1146 break;
1147 case GL_ALIASED_POINT_SIZE_RANGE:
1148 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00001149 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 +00001150 break;
1151 case GL_DEPTH_RANGE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001152 params[0] = mState.zNear;
1153 params[1] = mState.zFar;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001154 break;
1155 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001156 params[0] = mState.colorClearValue.red;
1157 params[1] = mState.colorClearValue.green;
1158 params[2] = mState.colorClearValue.blue;
1159 params[3] = mState.colorClearValue.alpha;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001160 break;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001161 case GL_BLEND_COLOR:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001162 params[0] = mState.blendColor.red;
1163 params[1] = mState.blendColor.green;
1164 params[2] = mState.blendColor.blue;
1165 params[3] = mState.blendColor.alpha;
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001166 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001167 default:
1168 return false;
1169 }
1170
1171 return true;
1172}
1173
1174bool Context::getIntegerv(GLenum pname, GLint *params)
1175{
1176 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1177 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1178 // GetIntegerv as its native query function. As it would require conversion in any
1179 // case, this should make no difference to the calling application. You may find it in
1180 // Context::getFloatv.
1181 switch (pname)
1182 {
1183 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1184 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
daniel@transgaming.com396c6432010-11-26 16:26:12 +00001185 case GL_MAX_VARYING_VECTORS: *params = getMaximumVaryingVectors(); break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001186 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS; break;
1187 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS; break;
1188 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
daniel@transgaming.com458da142010-11-28 02:03:02 +00001189 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = getMaximumFragmentUniformVectors(); break;
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00001190 case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001191 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001192 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001193 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break;
1194 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break;
daniel@transgaming.com9d7fc1d2010-10-27 15:49:42 +00001195 //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
1196 case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break;
1197 case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001198 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001199 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1200 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1201 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1202 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
alokp@chromium.orgd303ef92010-09-09 17:30:15 +00001203 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;
daniel@transgaming.comb28a23b2010-05-20 19:18:06 +00001204 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
1205 case GL_STENCIL_FUNC: *params = mState.stencilFunc; break;
1206 case GL_STENCIL_REF: *params = mState.stencilRef; break;
1207 case GL_STENCIL_VALUE_MASK: *params = mState.stencilMask; break;
1208 case GL_STENCIL_BACK_FUNC: *params = mState.stencilBackFunc; break;
1209 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
1210 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.stencilBackMask; break;
1211 case GL_STENCIL_FAIL: *params = mState.stencilFail; break;
1212 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.stencilPassDepthFail; break;
1213 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.stencilPassDepthPass; break;
1214 case GL_STENCIL_BACK_FAIL: *params = mState.stencilBackFail; break;
1215 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.stencilBackPassDepthFail; break;
1216 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.stencilBackPassDepthPass; break;
1217 case GL_DEPTH_FUNC: *params = mState.depthFunc; break;
1218 case GL_BLEND_SRC_RGB: *params = mState.sourceBlendRGB; break;
1219 case GL_BLEND_SRC_ALPHA: *params = mState.sourceBlendAlpha; break;
1220 case GL_BLEND_DST_RGB: *params = mState.destBlendRGB; break;
1221 case GL_BLEND_DST_ALPHA: *params = mState.destBlendAlpha; break;
1222 case GL_BLEND_EQUATION_RGB: *params = mState.blendEquationRGB; break;
1223 case GL_BLEND_EQUATION_ALPHA: *params = mState.blendEquationAlpha; break;
1224 case GL_STENCIL_WRITEMASK: *params = mState.stencilWritemask; break;
1225 case GL_STENCIL_BACK_WRITEMASK: *params = mState.stencilBackWritemask; break;
1226 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
1227 case GL_SUBPIXEL_BITS: *params = 4; break;
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00001228 case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break;
1229 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break;
daniel@transgaming.com01868132010-08-24 19:21:17 +00001230 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1231 {
1232 if (supportsCompressedTextures())
1233 {
1234 // at current, only GL_COMPRESSED_RGB_S3TC_DXT1_EXT and
1235 // GL_COMPRESSED_RGBA_S3TC_DXT1_EXT are supported
1236 *params = 2;
1237 }
1238 else
1239 {
1240 *params = 0;
1241 }
1242 }
1243 break;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001244 case GL_MAX_SAMPLES_ANGLE:
1245 {
1246 GLsizei maxSamples = getMaxSupportedSamples();
1247 if (maxSamples != 0)
1248 {
1249 *params = maxSamples;
1250 }
1251 else
1252 {
1253 return false;
1254 }
1255
1256 break;
1257 }
1258 case GL_SAMPLE_BUFFERS:
1259 case GL_SAMPLES:
1260 {
1261 gl::Framebuffer *framebuffer = getDrawFramebuffer();
1262 if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
1263 {
1264 switch (pname)
1265 {
1266 case GL_SAMPLE_BUFFERS:
1267 if (framebuffer->getSamples() != 0)
1268 {
1269 *params = 1;
1270 }
1271 else
1272 {
1273 *params = 0;
1274 }
1275 break;
1276 case GL_SAMPLES:
1277 *params = framebuffer->getSamples();
1278 break;
1279 }
1280 }
1281 else
1282 {
1283 *params = 0;
1284 }
1285 }
1286 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001287 case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = gl::IMPLEMENTATION_COLOR_READ_TYPE; break;
1288 case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = gl::IMPLEMENTATION_COLOR_READ_FORMAT; break;
1289 case GL_MAX_VIEWPORT_DIMS:
1290 {
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00001291 int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension());
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001292 params[0] = maxDimension;
1293 params[1] = maxDimension;
1294 }
1295 break;
daniel@transgaming.com01868132010-08-24 19:21:17 +00001296 case GL_COMPRESSED_TEXTURE_FORMATS:
1297 {
1298 if (supportsCompressedTextures())
1299 {
1300 params[0] = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
1301 params[1] = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
1302 }
1303 }
1304 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001305 case GL_VIEWPORT:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001306 params[0] = mState.viewportX;
1307 params[1] = mState.viewportY;
1308 params[2] = mState.viewportWidth;
1309 params[3] = mState.viewportHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001310 break;
1311 case GL_SCISSOR_BOX:
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001312 params[0] = mState.scissorX;
1313 params[1] = mState.scissorY;
1314 params[2] = mState.scissorWidth;
1315 params[3] = mState.scissorHeight;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001316 break;
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001317 case GL_CULL_FACE_MODE: *params = mState.cullMode; break;
1318 case GL_FRONT_FACE: *params = mState.frontFace; break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001319 case GL_RED_BITS:
1320 case GL_GREEN_BITS:
1321 case GL_BLUE_BITS:
1322 case GL_ALPHA_BITS:
1323 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001324 gl::Framebuffer *framebuffer = getDrawFramebuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001325 gl::Colorbuffer *colorbuffer = framebuffer->getColorbuffer();
1326
1327 if (colorbuffer)
1328 {
1329 switch (pname)
1330 {
1331 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1332 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1333 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1334 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
1335 }
1336 }
1337 else
1338 {
1339 *params = 0;
1340 }
1341 }
1342 break;
1343 case GL_DEPTH_BITS:
1344 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001345 gl::Framebuffer *framebuffer = getDrawFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001346 gl::DepthStencilbuffer *depthbuffer = framebuffer->getDepthbuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001347
1348 if (depthbuffer)
1349 {
1350 *params = depthbuffer->getDepthSize();
1351 }
1352 else
1353 {
1354 *params = 0;
1355 }
1356 }
1357 break;
1358 case GL_STENCIL_BITS:
1359 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001360 gl::Framebuffer *framebuffer = getDrawFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001361 gl::DepthStencilbuffer *stencilbuffer = framebuffer->getStencilbuffer();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001362
1363 if (stencilbuffer)
1364 {
1365 *params = stencilbuffer->getStencilSize();
1366 }
1367 else
1368 {
1369 *params = 0;
1370 }
1371 }
1372 break;
1373 case GL_TEXTURE_BINDING_2D:
1374 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001375 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001376 {
1377 error(GL_INVALID_OPERATION);
1378 return false;
1379 }
1380
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001381 *params = mState.samplerTexture[SAMPLER_2D][mState.activeSampler].id();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001382 }
1383 break;
1384 case GL_TEXTURE_BINDING_CUBE_MAP:
1385 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001386 if (mState.activeSampler < 0 || mState.activeSampler > gl::MAX_TEXTURE_IMAGE_UNITS - 1)
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001387 {
1388 error(GL_INVALID_OPERATION);
1389 return false;
1390 }
1391
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001392 *params = mState.samplerTexture[SAMPLER_CUBE][mState.activeSampler].id();
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001393 }
1394 break;
1395 default:
1396 return false;
1397 }
1398
1399 return true;
1400}
1401
1402bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1403{
1404 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1405 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1406 // to the fact that it is stored internally as a float, and so would require conversion
1407 // if returned from Context::getIntegerv. Since this conversion is already implemented
1408 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1409 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1410 // application.
1411 switch (pname)
1412 {
1413 case GL_COMPRESSED_TEXTURE_FORMATS: /* no compressed texture formats are supported */
1414 case GL_SHADER_BINARY_FORMATS:
1415 {
1416 *type = GL_INT;
1417 *numParams = 0;
1418 }
1419 break;
1420 case GL_MAX_VERTEX_ATTRIBS:
1421 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1422 case GL_MAX_VARYING_VECTORS:
1423 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1424 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1425 case GL_MAX_TEXTURE_IMAGE_UNITS:
1426 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1427 case GL_MAX_RENDERBUFFER_SIZE:
1428 case GL_NUM_SHADER_BINARY_FORMATS:
1429 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1430 case GL_ARRAY_BUFFER_BINDING:
1431 case GL_FRAMEBUFFER_BINDING:
1432 case GL_RENDERBUFFER_BINDING:
1433 case GL_CURRENT_PROGRAM:
1434 case GL_PACK_ALIGNMENT:
1435 case GL_UNPACK_ALIGNMENT:
1436 case GL_GENERATE_MIPMAP_HINT:
alokp@chromium.orgd303ef92010-09-09 17:30:15 +00001437 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001438 case GL_RED_BITS:
1439 case GL_GREEN_BITS:
1440 case GL_BLUE_BITS:
1441 case GL_ALPHA_BITS:
1442 case GL_DEPTH_BITS:
1443 case GL_STENCIL_BITS:
1444 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1445 case GL_CULL_FACE_MODE:
1446 case GL_FRONT_FACE:
1447 case GL_ACTIVE_TEXTURE:
1448 case GL_STENCIL_FUNC:
1449 case GL_STENCIL_VALUE_MASK:
1450 case GL_STENCIL_REF:
1451 case GL_STENCIL_FAIL:
1452 case GL_STENCIL_PASS_DEPTH_FAIL:
1453 case GL_STENCIL_PASS_DEPTH_PASS:
1454 case GL_STENCIL_BACK_FUNC:
1455 case GL_STENCIL_BACK_VALUE_MASK:
1456 case GL_STENCIL_BACK_REF:
1457 case GL_STENCIL_BACK_FAIL:
1458 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1459 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1460 case GL_DEPTH_FUNC:
1461 case GL_BLEND_SRC_RGB:
1462 case GL_BLEND_SRC_ALPHA:
1463 case GL_BLEND_DST_RGB:
1464 case GL_BLEND_DST_ALPHA:
1465 case GL_BLEND_EQUATION_RGB:
1466 case GL_BLEND_EQUATION_ALPHA:
1467 case GL_STENCIL_WRITEMASK:
1468 case GL_STENCIL_BACK_WRITEMASK:
1469 case GL_STENCIL_CLEAR_VALUE:
1470 case GL_SUBPIXEL_BITS:
1471 case GL_MAX_TEXTURE_SIZE:
1472 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1473 case GL_SAMPLE_BUFFERS:
1474 case GL_SAMPLES:
1475 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1476 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1477 case GL_TEXTURE_BINDING_2D:
1478 case GL_TEXTURE_BINDING_CUBE_MAP:
1479 {
1480 *type = GL_INT;
1481 *numParams = 1;
1482 }
1483 break;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001484 case GL_MAX_SAMPLES_ANGLE:
1485 {
1486 if (getMaxSupportedSamples() != 0)
1487 {
1488 *type = GL_INT;
1489 *numParams = 1;
1490 }
1491 else
1492 {
1493 return false;
1494 }
1495 }
1496 break;
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001497 case GL_MAX_VIEWPORT_DIMS:
1498 {
1499 *type = GL_INT;
1500 *numParams = 2;
1501 }
1502 break;
1503 case GL_VIEWPORT:
1504 case GL_SCISSOR_BOX:
1505 {
1506 *type = GL_INT;
1507 *numParams = 4;
1508 }
1509 break;
1510 case GL_SHADER_COMPILER:
1511 case GL_SAMPLE_COVERAGE_INVERT:
1512 case GL_DEPTH_WRITEMASK:
daniel@transgaming.com79f66772010-04-13 03:26:09 +00001513 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1514 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1515 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1516 case GL_SAMPLE_COVERAGE:
1517 case GL_SCISSOR_TEST:
1518 case GL_STENCIL_TEST:
1519 case GL_DEPTH_TEST:
1520 case GL_BLEND:
1521 case GL_DITHER:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001522 {
1523 *type = GL_BOOL;
1524 *numParams = 1;
1525 }
1526 break;
1527 case GL_COLOR_WRITEMASK:
1528 {
1529 *type = GL_BOOL;
1530 *numParams = 4;
1531 }
1532 break;
1533 case GL_POLYGON_OFFSET_FACTOR:
1534 case GL_POLYGON_OFFSET_UNITS:
1535 case GL_SAMPLE_COVERAGE_VALUE:
1536 case GL_DEPTH_CLEAR_VALUE:
1537 case GL_LINE_WIDTH:
1538 {
1539 *type = GL_FLOAT;
1540 *numParams = 1;
1541 }
1542 break;
1543 case GL_ALIASED_LINE_WIDTH_RANGE:
1544 case GL_ALIASED_POINT_SIZE_RANGE:
1545 case GL_DEPTH_RANGE:
1546 {
1547 *type = GL_FLOAT;
1548 *numParams = 2;
1549 }
1550 break;
1551 case GL_COLOR_CLEAR_VALUE:
daniel@transgaming.comc1641352010-04-26 15:33:36 +00001552 case GL_BLEND_COLOR:
daniel@transgaming.com777f2672010-04-07 03:25:16 +00001553 {
1554 *type = GL_FLOAT;
1555 *numParams = 4;
1556 }
1557 break;
1558 default:
1559 return false;
1560 }
1561
1562 return true;
1563}
1564
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001565// Applies the render target surface, depth stencil surface, viewport rectangle and
1566// scissor rectangle to the Direct3D 9 device
1567bool Context::applyRenderTarget(bool ignoreViewport)
1568{
1569 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001570
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001571 Framebuffer *framebufferObject = getDrawFramebuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001572
1573 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1574 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001575 error(GL_INVALID_FRAMEBUFFER_OPERATION);
1576
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001577 return false;
1578 }
1579
1580 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +00001581
1582 if (!renderTarget)
1583 {
1584 return false; // Context must be lost
1585 }
1586
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001587 IDirect3DSurface9 *depthStencil = NULL;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001588
daniel@transgaming.com092bd482010-05-12 03:39:36 +00001589 unsigned int renderTargetSerial = framebufferObject->getRenderTargetSerial();
1590 if (renderTargetSerial != mAppliedRenderTargetSerial)
1591 {
1592 device->SetRenderTarget(0, renderTarget);
1593 mAppliedRenderTargetSerial = renderTargetSerial;
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001594 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 +00001595 }
1596
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001597 unsigned int depthbufferSerial = 0;
1598 unsigned int stencilbufferSerial = 0;
1599 if (framebufferObject->getDepthbufferType() != GL_NONE)
1600 {
1601 depthStencil = framebufferObject->getDepthbuffer()->getDepthStencil();
apatrick@chromium.orgb2bdd062010-10-05 02:24:30 +00001602 if (!depthStencil)
1603 {
1604 ERR("Depth stencil pointer unexpectedly null.");
1605 return false;
1606 }
1607
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001608 depthbufferSerial = framebufferObject->getDepthbuffer()->getSerial();
1609 }
1610 else if (framebufferObject->getStencilbufferType() != GL_NONE)
1611 {
1612 depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
apatrick@chromium.orgb2bdd062010-10-05 02:24:30 +00001613 if (!depthStencil)
1614 {
1615 ERR("Depth stencil pointer unexpectedly null.");
1616 return false;
1617 }
1618
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001619 stencilbufferSerial = framebufferObject->getStencilbuffer()->getSerial();
1620 }
1621
1622 if (depthbufferSerial != mAppliedDepthbufferSerial ||
apatrick@chromium.org85dc42b2010-09-14 03:10:08 +00001623 stencilbufferSerial != mAppliedStencilbufferSerial ||
vangelis@chromium.orgcf66ebb2010-09-14 22:15:43 +00001624 !mDepthStencilInitialized)
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001625 {
1626 device->SetDepthStencilSurface(depthStencil);
1627 mAppliedDepthbufferSerial = depthbufferSerial;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001628 mAppliedStencilbufferSerial = stencilbufferSerial;
vangelis@chromium.orgcf66ebb2010-09-14 22:15:43 +00001629 mDepthStencilInitialized = true;
daniel@transgaming.com339ae702010-05-12 03:40:20 +00001630 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001631
1632 D3DVIEWPORT9 viewport;
1633 D3DSURFACE_DESC desc;
1634 renderTarget->GetDesc(&desc);
1635
daniel@transgaming.com996675c2010-11-17 13:06:29 +00001636 float zNear = clamp01(mState.zNear);
1637 float zFar = clamp01(mState.zFar);
1638
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001639 if (ignoreViewport)
1640 {
1641 viewport.X = 0;
1642 viewport.Y = 0;
1643 viewport.Width = desc.Width;
1644 viewport.Height = desc.Height;
1645 viewport.MinZ = 0.0f;
1646 viewport.MaxZ = 1.0f;
1647 }
1648 else
1649 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001650 viewport.X = std::max(mState.viewportX, 0);
1651 viewport.Y = std::max(mState.viewportY, 0);
1652 viewport.Width = std::min(mState.viewportWidth, (int)desc.Width - (int)viewport.X);
1653 viewport.Height = std::min(mState.viewportHeight, (int)desc.Height - (int)viewport.Y);
daniel@transgaming.com996675c2010-11-17 13:06:29 +00001654 viewport.MinZ = zNear;
1655 viewport.MaxZ = zFar;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001656 }
1657
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00001658 if (viewport.Width <= 0 || viewport.Height <= 0)
1659 {
1660 return false; // Nothing to render
1661 }
1662
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001663 device->SetViewport(&viewport);
1664
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001665 if (mScissorStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001666 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001667 if (mState.scissorTest)
1668 {
1669 RECT rect = {mState.scissorX,
1670 mState.scissorY,
1671 mState.scissorX + mState.scissorWidth,
1672 mState.scissorY + mState.scissorHeight};
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001673 rect.right = std::min(static_cast<UINT>(rect.right), desc.Width);
1674 rect.bottom = std::min(static_cast<UINT>(rect.bottom), desc.Height);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001675 device->SetScissorRect(&rect);
1676 device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
1677 }
1678 else
1679 {
1680 device->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
1681 }
daniel@transgaming.combc3699d2010-08-05 14:48:49 +00001682
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001683 mScissorStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001684 }
1685
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001686 if (mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001687 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001688 Program *programObject = getCurrentProgram();
1689
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001690 GLint halfPixelSize = programObject->getDxHalfPixelSizeLocation();
daniel@transgaming.com8ee00ea2010-04-29 03:38:47 +00001691 GLfloat xy[2] = {1.0f / viewport.Width, 1.0f / viewport.Height};
daniel@transgaming.com31754962010-11-28 02:02:52 +00001692 programObject->setUniform2fv(halfPixelSize, 1, xy);
daniel@transgaming.com86487c22010-03-11 19:41:43 +00001693
daniel@transgaming.com31754962010-11-28 02:02:52 +00001694 GLint viewport = programObject->getDxViewportLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001695 GLfloat whxy[4] = {mState.viewportWidth / 2.0f, mState.viewportHeight / 2.0f,
1696 (float)mState.viewportX + mState.viewportWidth / 2.0f,
1697 (float)mState.viewportY + mState.viewportHeight / 2.0f};
daniel@transgaming.com31754962010-11-28 02:02:52 +00001698 programObject->setUniform4fv(viewport, 1, whxy);
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001699
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001700 GLint depth = programObject->getDxDepthLocation();
daniel@transgaming.com996675c2010-11-17 13:06:29 +00001701 GLfloat dz[2] = {(zFar - zNear) / 2.0f, (zNear + zFar) / 2.0f};
daniel@transgaming.com31754962010-11-28 02:02:52 +00001702 programObject->setUniform2fv(depth, 1, dz);
daniel@transgaming.com9b5f5442010-03-16 05:43:55 +00001703
daniel@transgaming.com31754962010-11-28 02:02:52 +00001704 GLint depthRange = programObject->getDxDepthRangeLocation();
1705 GLfloat nearFarDiff[3] = {zNear, zFar, zFar - zNear};
1706 programObject->setUniform3fv(depthRange, 1, nearFarDiff);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001707 }
1708
1709 return true;
1710}
1711
1712// 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 +00001713void Context::applyState(GLenum drawMode)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001714{
1715 IDirect3DDevice9 *device = getDevice();
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001716 Program *programObject = getCurrentProgram();
1717
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001718 GLint frontCCW = programObject->getDxFrontCCWLocation();
daniel@transgaming.com428d1582010-05-04 03:35:25 +00001719 GLint ccw = (mState.frontFace == GL_CCW);
daniel@transgaming.com79b820b2010-03-16 05:48:57 +00001720 programObject->setUniform1iv(frontCCW, 1, &ccw);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001721
daniel@transgaming.com91fd1de2010-05-18 18:51:40 +00001722 GLint pointsOrLines = programObject->getDxPointsOrLinesLocation();
daniel@transgaming.com5af64272010-04-15 20:45:12 +00001723 GLint alwaysFront = !isTriangleMode(drawMode);
1724 programObject->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1725
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001726 Framebuffer *framebufferObject = getDrawFramebuffer();
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001727
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001728 if (mCullStateDirty || mFrontFaceDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001729 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001730 if (mState.cullFace)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001731 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001732 device->SetRenderState(D3DRS_CULLMODE, es2dx::ConvertCullMode(mState.cullMode, mState.frontFace));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001733 }
1734 else
1735 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001736 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001737 }
1738
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001739 mCullStateDirty = false;
1740 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001741
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001742 if (mDepthStateDirty)
1743 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001744 if (mState.depthTest && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001745 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001746 device->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
1747 device->SetRenderState(D3DRS_ZFUNC, es2dx::ConvertComparison(mState.depthFunc));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001748 }
1749 else
1750 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001751 device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001752 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001753
1754 mDepthStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001755 }
1756
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001757 if (mBlendStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001758 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001759 if (mState.blend)
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001760 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001761 device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
1762
1763 if (mState.sourceBlendRGB != GL_CONSTANT_ALPHA && mState.sourceBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA &&
1764 mState.destBlendRGB != GL_CONSTANT_ALPHA && mState.destBlendRGB != GL_ONE_MINUS_CONSTANT_ALPHA)
1765 {
1766 device->SetRenderState(D3DRS_BLENDFACTOR, es2dx::ConvertColor(mState.blendColor));
1767 }
1768 else
1769 {
1770 device->SetRenderState(D3DRS_BLENDFACTOR, D3DCOLOR_RGBA(unorm<8>(mState.blendColor.alpha),
1771 unorm<8>(mState.blendColor.alpha),
1772 unorm<8>(mState.blendColor.alpha),
1773 unorm<8>(mState.blendColor.alpha)));
1774 }
1775
1776 device->SetRenderState(D3DRS_SRCBLEND, es2dx::ConvertBlendFunc(mState.sourceBlendRGB));
1777 device->SetRenderState(D3DRS_DESTBLEND, es2dx::ConvertBlendFunc(mState.destBlendRGB));
1778 device->SetRenderState(D3DRS_BLENDOP, es2dx::ConvertBlendOp(mState.blendEquationRGB));
1779
1780 if (mState.sourceBlendRGB != mState.sourceBlendAlpha ||
1781 mState.destBlendRGB != mState.destBlendAlpha ||
1782 mState.blendEquationRGB != mState.blendEquationAlpha)
1783 {
1784 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, TRUE);
1785
1786 device->SetRenderState(D3DRS_SRCBLENDALPHA, es2dx::ConvertBlendFunc(mState.sourceBlendAlpha));
1787 device->SetRenderState(D3DRS_DESTBLENDALPHA, es2dx::ConvertBlendFunc(mState.destBlendAlpha));
1788 device->SetRenderState(D3DRS_BLENDOPALPHA, es2dx::ConvertBlendOp(mState.blendEquationAlpha));
1789
1790 }
1791 else
1792 {
1793 device->SetRenderState(D3DRS_SEPARATEALPHABLENDENABLE, FALSE);
1794 }
daniel@transgaming.com1436e262010-03-17 03:58:56 +00001795 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001796 else
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001797 {
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001798 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
daniel@transgaming.comaede6302010-04-29 03:35:48 +00001799 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001800
1801 mBlendStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001802 }
1803
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001804 if (mStencilStateDirty || mFrontFaceDirty)
1805 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001806 if (mState.stencilTest && framebufferObject->hasStencil())
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001807 {
1808 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
1809 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, TRUE);
1810
1811 // FIXME: Unsupported by D3D9
1812 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILREF = D3DRS_STENCILREF;
1813 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILMASK = D3DRS_STENCILMASK;
1814 const D3DRENDERSTATETYPE D3DRS_CCW_STENCILWRITEMASK = D3DRS_STENCILWRITEMASK;
1815 if (mState.stencilWritemask != mState.stencilBackWritemask ||
1816 mState.stencilRef != mState.stencilBackRef ||
1817 mState.stencilMask != mState.stencilBackMask)
1818 {
1819 ERR("Separate front/back stencil writemasks, reference values, or stencil mask values are invalid under WebGL.");
1820 return error(GL_INVALID_OPERATION);
1821 }
1822
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001823 // get the maximum size of the stencil ref
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001824 gl::DepthStencilbuffer *stencilbuffer = framebufferObject->getStencilbuffer();
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001825 GLuint maxStencil = (1 << stencilbuffer->getStencilSize()) - 1;
1826
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001827 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilWritemask);
1828 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1829 es2dx::ConvertComparison(mState.stencilFunc));
1830
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001831 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilRef < (GLint)maxStencil) ? mState.stencilRef : maxStencil);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001832 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilMask);
1833
1834 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1835 es2dx::ConvertStencilOp(mState.stencilFail));
1836 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1837 es2dx::ConvertStencilOp(mState.stencilPassDepthFail));
1838 device->SetRenderState(mState.frontFace == GL_CCW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1839 es2dx::ConvertStencilOp(mState.stencilPassDepthPass));
1840
1841 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILWRITEMASK : D3DRS_CCW_STENCILWRITEMASK, mState.stencilBackWritemask);
1842 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFUNC : D3DRS_CCW_STENCILFUNC,
1843 es2dx::ConvertComparison(mState.stencilBackFunc));
1844
daniel@transgaming.comdd7948b2010-06-02 16:12:34 +00001845 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILREF : D3DRS_CCW_STENCILREF, (mState.stencilBackRef < (GLint)maxStencil) ? mState.stencilBackRef : maxStencil);
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001846 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILMASK : D3DRS_CCW_STENCILMASK, mState.stencilBackMask);
1847
1848 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILFAIL : D3DRS_CCW_STENCILFAIL,
1849 es2dx::ConvertStencilOp(mState.stencilBackFail));
1850 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILZFAIL : D3DRS_CCW_STENCILZFAIL,
1851 es2dx::ConvertStencilOp(mState.stencilBackPassDepthFail));
1852 device->SetRenderState(mState.frontFace == GL_CW ? D3DRS_STENCILPASS : D3DRS_CCW_STENCILPASS,
1853 es2dx::ConvertStencilOp(mState.stencilBackPassDepthPass));
1854 }
1855 else
1856 {
1857 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
1858 }
1859
1860 mStencilStateDirty = false;
1861 }
1862
1863 if (mMaskStateDirty)
1864 {
1865 device->SetRenderState(D3DRS_COLORWRITEENABLE, es2dx::ConvertColorMask(mState.colorMaskRed, mState.colorMaskGreen,
1866 mState.colorMaskBlue, mState.colorMaskAlpha));
1867 device->SetRenderState(D3DRS_ZWRITEENABLE, mState.depthMask ? TRUE : FALSE);
1868
1869 mMaskStateDirty = false;
1870 }
1871
1872 if (mPolygonOffsetStateDirty)
1873 {
1874 if (mState.polygonOffsetFill)
1875 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001876 gl::DepthStencilbuffer *depthbuffer = framebufferObject->getDepthbuffer();
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001877 if (depthbuffer)
1878 {
1879 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, *((DWORD*)&mState.polygonOffsetFactor));
1880 float depthBias = ldexp(mState.polygonOffsetUnits, -(int)(depthbuffer->getDepthSize()));
1881 device->SetRenderState(D3DRS_DEPTHBIAS, *((DWORD*)&depthBias));
1882 }
1883 }
1884 else
1885 {
1886 device->SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0);
1887 device->SetRenderState(D3DRS_DEPTHBIAS, 0);
1888 }
1889
1890 mPolygonOffsetStateDirty = false;
1891 }
1892
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001893 if (mSampleStateDirty)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001894 {
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001895 if (framebufferObject->isMultisample())
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001896 {
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001897 if (mState.sampleAlphaToCoverage)
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001898 {
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001899 FIXME("Sample alpha to coverage is unimplemented.");
1900 }
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001901
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001902 device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, TRUE);
1903 if (mState.sampleCoverage)
1904 {
1905 unsigned int mask = 0;
1906 if (mState.sampleCoverageValue != 0)
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001907 {
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001908 float threshold = 0.5f;
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001909
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001910 for (int i = 0; i < framebufferObject->getSamples(); ++i)
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001911 {
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001912 mask <<= 1;
1913
1914 if ((i + 1) * mState.sampleCoverageValue >= threshold)
1915 {
1916 threshold += 1.0f;
1917 mask |= 1;
1918 }
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001919 }
1920 }
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001921
1922 if (mState.sampleCoverageInvert)
1923 {
1924 mask = ~mask;
1925 }
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001926
enne@chromium.orgc5f8dea2010-09-21 16:40:30 +00001927 device->SetRenderState(D3DRS_MULTISAMPLEMASK, mask);
1928 }
1929 else
1930 {
1931 device->SetRenderState(D3DRS_MULTISAMPLEMASK, 0xFFFFFFFF);
1932 }
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00001933 }
1934 else
1935 {
1936 device->SetRenderState(D3DRS_MULTISAMPLEANTIALIAS, FALSE);
daniel@transgaming.coma87bdf52010-04-29 03:38:55 +00001937 }
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001938
1939 mSampleStateDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001940 }
1941
daniel@transgaming.coma79f9d12010-05-12 03:40:01 +00001942 if (mDitherStateDirty)
1943 {
1944 device->SetRenderState(D3DRS_DITHERENABLE, mState.dither ? TRUE : FALSE);
1945
1946 mDitherStateDirty = false;
1947 }
1948
1949 mFrontFaceDirty = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001950}
1951
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001952// Fill in the semanticIndex field of the array of TranslatedAttributes based on the active GLSL program.
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001953void Context::lookupAttributeMapping(TranslatedAttribute *attributes)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001954{
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001955 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001956 {
daniel@transgaming.com83921382011-01-08 05:46:00 +00001957 if (attributes[i].active)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001958 {
daniel@transgaming.comb4ff1f82010-04-22 13:35:18 +00001959 attributes[i].semanticIndex = getCurrentProgram()->getSemanticIndex(i);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001960 }
1961 }
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001962}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001963
daniel@transgaming.com83921382011-01-08 05:46:00 +00001964GLenum Context::applyVertexBuffer(GLint first, GLsizei count)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001965{
1966 TranslatedAttribute translated[MAX_VERTEX_ATTRIBS];
1967
daniel@transgaming.com83921382011-01-08 05:46:00 +00001968 GLenum err = mVertexDataManager->prepareVertexData(first, count, translated);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001969 if (err != GL_NO_ERROR)
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001970 {
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001971 return err;
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00001972 }
1973
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001974 lookupAttributeMapping(translated);
1975
daniel@transgaming.com83921382011-01-08 05:46:00 +00001976 mVertexDataManager->setupAttributes(translated);
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001977
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001978 return GL_NO_ERROR;
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001979}
1980
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001981// Applies the indices and element array bindings to the Direct3D 9 device
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001982GLenum Context::applyIndexBuffer(const void *indices, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
daniel@transgaming.com0f7aaf52010-03-11 19:41:38 +00001983{
daniel@transgaming.com83921382011-01-08 05:46:00 +00001984 IDirect3DDevice9 *device = getDevice();
1985 GLenum err = mIndexDataManager->prepareIndexData(type, count, mState.elementArrayBuffer.get(), indices, indexInfo);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001986
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001987 if (err == GL_NO_ERROR)
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001988 {
daniel@transgaming.com83921382011-01-08 05:46:00 +00001989 device->SetIndices(indexInfo->indexBuffer);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00001990 }
1991
daniel@transgaming.com81655a72010-05-20 19:18:17 +00001992 return err;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001993}
1994
1995// Applies the shaders and shader constants to the Direct3D 9 device
1996void Context::applyShaders()
1997{
1998 IDirect3DDevice9 *device = getDevice();
1999 Program *programObject = getCurrentProgram();
2000 IDirect3DVertexShader9 *vertexShader = programObject->getVertexShader();
2001 IDirect3DPixelShader9 *pixelShader = programObject->getPixelShader();
2002
2003 device->SetVertexShader(vertexShader);
2004 device->SetPixelShader(pixelShader);
2005
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002006 if (programObject->getSerial() != mAppliedProgram)
2007 {
2008 programObject->dirtyAllUniforms();
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002009 programObject->dirtyAllSamplers();
daniel@transgaming.com4fa08332010-05-11 02:29:27 +00002010 mAppliedProgram = programObject->getSerial();
2011 }
2012
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002013 programObject->applyUniforms();
2014}
2015
2016// Applies the textures and sampler states to the Direct3D 9 device
2017void Context::applyTextures()
2018{
2019 IDirect3DDevice9 *device = getDevice();
2020 Program *programObject = getCurrentProgram();
2021
2022 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
2023 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002024 int textureUnit = programObject->getSamplerMapping(sampler);
2025 if (textureUnit != -1)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002026 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002027 SamplerType textureType = programObject->getSamplerType(sampler);
2028
2029 Texture *texture = getSamplerTexture(textureUnit, textureType);
2030
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002031 if (programObject->isSamplerDirty(sampler) || texture->isDirty())
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002032 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002033 if (texture->isComplete())
2034 {
2035 GLenum wrapS = texture->getWrapS();
2036 GLenum wrapT = texture->getWrapT();
2037 GLenum minFilter = texture->getMinFilter();
2038 GLenum magFilter = texture->getMagFilter();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002039
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002040 device->SetSamplerState(sampler, D3DSAMP_ADDRESSU, es2dx::ConvertTextureWrap(wrapS));
2041 device->SetSamplerState(sampler, D3DSAMP_ADDRESSV, es2dx::ConvertTextureWrap(wrapT));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002042
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002043 device->SetSamplerState(sampler, D3DSAMP_MAGFILTER, es2dx::ConvertMagFilter(magFilter));
2044 D3DTEXTUREFILTERTYPE d3dMinFilter, d3dMipFilter;
2045 es2dx::ConvertMinFilter(minFilter, &d3dMinFilter, &d3dMipFilter);
2046 device->SetSamplerState(sampler, D3DSAMP_MINFILTER, d3dMinFilter);
2047 device->SetSamplerState(sampler, D3DSAMP_MIPFILTER, d3dMipFilter);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002048
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002049 device->SetTexture(sampler, texture->getTexture());
2050 }
2051 else
2052 {
2053 device->SetTexture(sampler, getIncompleteTexture(textureType)->getTexture());
2054 }
daniel@transgaming.com12d54072010-03-16 06:23:26 +00002055 }
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002056
2057 programObject->setSamplerDirty(sampler, false);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002058 }
daniel@transgaming.com416485f2010-03-16 06:23:23 +00002059 else
2060 {
daniel@transgaming.com5a0b0a82010-05-12 03:45:07 +00002061 if (programObject->isSamplerDirty(sampler))
2062 {
2063 device->SetTexture(sampler, NULL);
2064 programObject->setSamplerDirty(sampler, false);
2065 }
2066 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002067 }
2068}
2069
2070void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void* pixels)
2071{
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00002072 Framebuffer *framebuffer = getReadFramebuffer();
daniel@transgaming.combbc57792010-07-28 19:21:05 +00002073
2074 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
2075 {
2076 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
2077 }
2078
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00002079 if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
2080 {
2081 return error(GL_INVALID_OPERATION);
2082 }
2083
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002084 IDirect3DSurface9 *renderTarget = framebuffer->getRenderTarget();
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +00002085
2086 if (!renderTarget)
2087 {
2088 return; // Context must be lost, return silently
2089 }
2090
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002091 IDirect3DDevice9 *device = getDevice();
2092
2093 D3DSURFACE_DESC desc;
2094 renderTarget->GetDesc(&desc);
2095
2096 IDirect3DSurface9 *systemSurface;
2097 HRESULT result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
2098
2099 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2100 {
2101 return error(GL_OUT_OF_MEMORY);
2102 }
2103
2104 ASSERT(SUCCEEDED(result));
2105
2106 if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
2107 {
2108 UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
2109 }
2110
2111 result = device->GetRenderTargetData(renderTarget, systemSurface);
2112
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002113 if (FAILED(result))
2114 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002115 systemSurface->Release();
2116
apatrick@chromium.org6db8cab2010-07-22 20:39:50 +00002117 switch (result)
2118 {
2119 case D3DERR_DRIVERINTERNALERROR:
2120 case D3DERR_DEVICELOST:
2121 return error(GL_OUT_OF_MEMORY);
2122 default:
2123 UNREACHABLE();
2124 return; // No sensible error to generate
2125 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002126 }
2127
2128 D3DLOCKED_RECT lock;
daniel@transgaming.com16973022010-03-11 19:22:19 +00002129 RECT rect = {std::max(x, 0),
2130 std::max(y, 0),
2131 std::min(x + width, (int)desc.Width),
2132 std::min(y + height, (int)desc.Height)};
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002133
2134 result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
2135
2136 if (FAILED(result))
2137 {
2138 UNREACHABLE();
2139 systemSurface->Release();
2140
2141 return; // No sensible error to generate
2142 }
2143
2144 unsigned char *source = (unsigned char*)lock.pBits;
2145 unsigned char *dest = (unsigned char*)pixels;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002146 unsigned short *dest16 = (unsigned short*)pixels;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002147
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002148 GLsizei outputPitch = ComputePitch(width, format, type, mState.packAlignment);
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002149
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002150 for (int j = 0; j < rect.bottom - rect.top; j++)
2151 {
daniel@transgaming.coma9198d92010-08-08 04:49:56 +00002152 if (desc.Format == D3DFMT_A8R8G8B8 &&
2153 format == GL_BGRA_EXT &&
2154 type == GL_UNSIGNED_BYTE)
2155 {
2156 // Fast path for EXT_read_format_bgra, given
2157 // an RGBA source buffer. Note that buffers with no
2158 // alpha go through the slow path below.
2159 memcpy(dest + j * outputPitch,
2160 source + j * lock.Pitch,
2161 (rect.right - rect.left) * 4);
2162 continue;
2163 }
2164
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002165 for (int i = 0; i < rect.right - rect.left; i++)
2166 {
2167 float r;
2168 float g;
2169 float b;
2170 float a;
2171
2172 switch (desc.Format)
2173 {
2174 case D3DFMT_R5G6B5:
2175 {
2176 unsigned short rgb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2177
2178 a = 1.0f;
2179 b = (rgb & 0x001F) * (1.0f / 0x001F);
2180 g = (rgb & 0x07E0) * (1.0f / 0x07E0);
2181 r = (rgb & 0xF800) * (1.0f / 0xF800);
2182 }
2183 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002184 case D3DFMT_A1R5G5B5:
2185 {
2186 unsigned short argb = *(unsigned short*)(source + 2 * i + j * lock.Pitch);
2187
2188 a = (argb & 0x8000) ? 1.0f : 0.0f;
2189 b = (argb & 0x001F) * (1.0f / 0x001F);
2190 g = (argb & 0x03E0) * (1.0f / 0x03E0);
2191 r = (argb & 0x7C00) * (1.0f / 0x7C00);
2192 }
2193 break;
2194 case D3DFMT_A8R8G8B8:
2195 {
2196 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2197
2198 a = (argb & 0xFF000000) * (1.0f / 0xFF000000);
2199 b = (argb & 0x000000FF) * (1.0f / 0x000000FF);
2200 g = (argb & 0x0000FF00) * (1.0f / 0x0000FF00);
2201 r = (argb & 0x00FF0000) * (1.0f / 0x00FF0000);
2202 }
2203 break;
2204 case D3DFMT_X8R8G8B8:
2205 {
2206 unsigned int xrgb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2207
2208 a = 1.0f;
2209 b = (xrgb & 0x000000FF) * (1.0f / 0x000000FF);
2210 g = (xrgb & 0x0000FF00) * (1.0f / 0x0000FF00);
2211 r = (xrgb & 0x00FF0000) * (1.0f / 0x00FF0000);
2212 }
2213 break;
2214 case D3DFMT_A2R10G10B10:
2215 {
2216 unsigned int argb = *(unsigned int*)(source + 4 * i + j * lock.Pitch);
2217
2218 a = (argb & 0xC0000000) * (1.0f / 0xC0000000);
2219 b = (argb & 0x000003FF) * (1.0f / 0x000003FF);
2220 g = (argb & 0x000FFC00) * (1.0f / 0x000FFC00);
2221 r = (argb & 0x3FF00000) * (1.0f / 0x3FF00000);
2222 }
2223 break;
daniel@transgaming.com1297d922010-09-01 15:47:47 +00002224 case D3DFMT_A32B32G32R32F:
2225 {
2226 // float formats in D3D are stored rgba, rather than the other way round
2227 r = *((float*)(source + 16 * i + j * lock.Pitch) + 0);
2228 g = *((float*)(source + 16 * i + j * lock.Pitch) + 1);
2229 b = *((float*)(source + 16 * i + j * lock.Pitch) + 2);
2230 a = *((float*)(source + 16 * i + j * lock.Pitch) + 3);
2231 }
2232 break;
2233 case D3DFMT_A16B16G16R16F:
2234 {
2235 // float formats in D3D are stored rgba, rather than the other way round
2236 float abgr[4];
2237
2238 D3DXFloat16To32Array(abgr, (D3DXFLOAT16*)(source + 8 * i + j * lock.Pitch), 4);
2239
2240 a = abgr[3];
2241 b = abgr[2];
2242 g = abgr[1];
2243 r = abgr[0];
2244 }
2245 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002246 default:
2247 UNIMPLEMENTED(); // FIXME
2248 UNREACHABLE();
2249 }
2250
2251 switch (format)
2252 {
2253 case GL_RGBA:
2254 switch (type)
2255 {
2256 case GL_UNSIGNED_BYTE:
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002257 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * r + 0.5f);
2258 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2259 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * b + 0.5f);
2260 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002261 break;
2262 default: UNREACHABLE();
2263 }
2264 break;
daniel@transgaming.coma9198d92010-08-08 04:49:56 +00002265 case GL_BGRA_EXT:
2266 switch (type)
2267 {
2268 case GL_UNSIGNED_BYTE:
2269 dest[4 * i + j * outputPitch + 0] = (unsigned char)(255 * b + 0.5f);
2270 dest[4 * i + j * outputPitch + 1] = (unsigned char)(255 * g + 0.5f);
2271 dest[4 * i + j * outputPitch + 2] = (unsigned char)(255 * r + 0.5f);
2272 dest[4 * i + j * outputPitch + 3] = (unsigned char)(255 * a + 0.5f);
2273 break;
2274 case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
2275 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
2276 // this type is packed as follows:
2277 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
2278 // --------------------------------------------------------------------------------
2279 // | 4th | 3rd | 2nd | 1st component |
2280 // --------------------------------------------------------------------------------
2281 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
2282 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2283 ((unsigned short)(15 * a + 0.5f) << 12)|
2284 ((unsigned short)(15 * r + 0.5f) << 8) |
2285 ((unsigned short)(15 * g + 0.5f) << 4) |
2286 ((unsigned short)(15 * b + 0.5f) << 0);
2287 break;
2288 case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
2289 // According to the desktop GL spec in the "Transfer of Pixel Rectangles" section
2290 // this type is packed as follows:
2291 // 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
2292 // --------------------------------------------------------------------------------
2293 // | 4th | 3rd | 2nd | 1st component |
2294 // --------------------------------------------------------------------------------
2295 // in the case of BGRA_EXT, B is the first component, G the second, and so forth.
2296 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2297 ((unsigned short)( a + 0.5f) << 15) |
2298 ((unsigned short)(31 * r + 0.5f) << 10) |
2299 ((unsigned short)(31 * g + 0.5f) << 5) |
2300 ((unsigned short)(31 * b + 0.5f) << 0);
2301 break;
2302 default: UNREACHABLE();
2303 }
2304 break;
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002305 case GL_RGB: // IMPLEMENTATION_COLOR_READ_FORMAT
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002306 switch (type)
2307 {
daniel@transgaming.comafb23952010-04-13 03:25:54 +00002308 case GL_UNSIGNED_SHORT_5_6_5: // IMPLEMENTATION_COLOR_READ_TYPE
daniel@transgaming.com713914b2010-05-04 03:35:17 +00002309 dest16[i + j * outputPitch / sizeof(unsigned short)] =
2310 ((unsigned short)(31 * b + 0.5f) << 0) |
2311 ((unsigned short)(63 * g + 0.5f) << 5) |
2312 ((unsigned short)(31 * r + 0.5f) << 11);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002313 break;
2314 default: UNREACHABLE();
2315 }
2316 break;
2317 default: UNREACHABLE();
2318 }
2319 }
2320 }
2321
2322 systemSurface->UnlockRect();
2323
2324 systemSurface->Release();
2325}
2326
2327void Context::clear(GLbitfield mask)
2328{
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00002329 Framebuffer *framebufferObject = getDrawFramebuffer();
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002330
2331 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
2332 {
2333 error(GL_INVALID_FRAMEBUFFER_OPERATION);
2334
2335 return;
2336 }
2337
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002338 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002339 IDirect3DDevice9 *device = getDevice();
2340 DWORD flags = 0;
2341
2342 if (mask & GL_COLOR_BUFFER_BIT)
2343 {
2344 mask &= ~GL_COLOR_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002345
2346 if (framebufferObject->getColorbufferType() != GL_NONE)
2347 {
2348 flags |= D3DCLEAR_TARGET;
2349 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002350 }
2351
2352 if (mask & GL_DEPTH_BUFFER_BIT)
2353 {
2354 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.comc6f53402010-06-24 13:02:19 +00002355 if (mState.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002356 {
2357 flags |= D3DCLEAR_ZBUFFER;
2358 }
2359 }
2360
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002361 GLuint stencilUnmasked = 0x0;
2362
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002363 if (mask & GL_STENCIL_BUFFER_BIT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002364 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002365 mask &= ~GL_STENCIL_BUFFER_BIT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002366 if (framebufferObject->getStencilbufferType() != GL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002367 {
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002368 IDirect3DSurface9 *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
apatrick@chromium.orgb2bdd062010-10-05 02:24:30 +00002369 if (!depthStencil)
2370 {
2371 ERR("Depth stencil pointer unexpectedly null.");
2372 return;
2373 }
2374
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00002375 D3DSURFACE_DESC desc;
2376 depthStencil->GetDesc(&desc);
2377
2378 unsigned int stencilSize = es2dx::GetStencilSize(desc.Format);
2379 stencilUnmasked = (0x1 << stencilSize) - 1;
2380
2381 if (stencilUnmasked != 0x0)
2382 {
2383 flags |= D3DCLEAR_STENCIL;
2384 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002385 }
2386 }
2387
2388 if (mask != 0)
2389 {
2390 return error(GL_INVALID_VALUE);
2391 }
2392
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002393 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2394 {
2395 return;
2396 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002397
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002398 D3DCOLOR color = D3DCOLOR_ARGB(unorm<8>(mState.colorClearValue.alpha),
2399 unorm<8>(mState.colorClearValue.red),
2400 unorm<8>(mState.colorClearValue.green),
2401 unorm<8>(mState.colorClearValue.blue));
2402 float depth = clamp01(mState.depthClearValue);
2403 int stencil = mState.stencilClearValue & 0x000000FF;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002404
2405 IDirect3DSurface9 *renderTarget = framebufferObject->getRenderTarget();
2406
daniel@transgaming.comd36c6a02010-08-31 12:15:09 +00002407 if (!renderTarget)
2408 {
2409 return; // Context must be lost, return silently
2410 }
2411
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002412 D3DSURFACE_DESC desc;
2413 renderTarget->GetDesc(&desc);
2414
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002415 bool alphaUnmasked = (es2dx::GetAlphaSize(desc.Format) == 0) || mState.colorMaskAlpha;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002416
2417 const bool needMaskedStencilClear = (flags & D3DCLEAR_STENCIL) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002418 (mState.stencilWritemask & stencilUnmasked) != stencilUnmasked;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002419 const bool needMaskedColorClear = (flags & D3DCLEAR_TARGET) &&
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002420 !(mState.colorMaskRed && mState.colorMaskGreen &&
2421 mState.colorMaskBlue && alphaUnmasked);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002422
2423 if (needMaskedColorClear || needMaskedStencilClear)
2424 {
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002425 // State which is altered in all paths from this point to the clear call is saved.
2426 // State which is altered in only some paths will be flagged dirty in the case that
2427 // that path is taken.
2428 HRESULT hr;
2429 if (mMaskedClearSavedState == NULL)
2430 {
2431 hr = device->BeginStateBlock();
2432 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2433
2434 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2435 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2436 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2437 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2438 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2439 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2440 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2441 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2442 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2443 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2444 device->SetPixelShader(NULL);
2445 device->SetVertexShader(NULL);
2446 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
daniel@transgaming.comd10f8692010-09-16 19:56:52 +00002447 device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002448
2449 hr = device->EndStateBlock(&mMaskedClearSavedState);
2450 ASSERT(SUCCEEDED(hr) || hr == D3DERR_OUTOFVIDEOMEMORY || hr == E_OUTOFMEMORY);
2451 }
2452
2453 ASSERT(mMaskedClearSavedState != NULL);
2454
2455 if (mMaskedClearSavedState != NULL)
2456 {
2457 hr = mMaskedClearSavedState->Capture();
2458 ASSERT(SUCCEEDED(hr));
2459 }
2460
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002461 device->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
2462 device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS);
2463 device->SetRenderState(D3DRS_ZENABLE, FALSE);
2464 device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
2465 device->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
2466 device->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
2467 device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
2468 device->SetRenderState(D3DRS_CLIPPLANEENABLE, 0);
2469
2470 if (flags & D3DCLEAR_TARGET)
2471 {
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002472 device->SetRenderState(D3DRS_COLORWRITEENABLE, (mState.colorMaskRed ? D3DCOLORWRITEENABLE_RED : 0) |
2473 (mState.colorMaskGreen ? D3DCOLORWRITEENABLE_GREEN : 0) |
2474 (mState.colorMaskBlue ? D3DCOLORWRITEENABLE_BLUE : 0) |
2475 (mState.colorMaskAlpha ? D3DCOLORWRITEENABLE_ALPHA : 0));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002476 }
2477 else
2478 {
2479 device->SetRenderState(D3DRS_COLORWRITEENABLE, 0);
2480 }
2481
2482 if (stencilUnmasked != 0x0 && (flags & D3DCLEAR_STENCIL))
2483 {
2484 device->SetRenderState(D3DRS_STENCILENABLE, TRUE);
2485 device->SetRenderState(D3DRS_TWOSIDEDSTENCILMODE, FALSE);
2486 device->SetRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
2487 device->SetRenderState(D3DRS_STENCILREF, stencil);
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002488 device->SetRenderState(D3DRS_STENCILWRITEMASK, mState.stencilWritemask);
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002489 device->SetRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_REPLACE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002490 device->SetRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_REPLACE);
2491 device->SetRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002492 mStencilStateDirty = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002493 }
2494 else
2495 {
2496 device->SetRenderState(D3DRS_STENCILENABLE, FALSE);
2497 }
2498
2499 device->SetPixelShader(NULL);
2500 device->SetVertexShader(NULL);
2501 device->SetFVF(D3DFVF_XYZRHW | D3DFVF_DIFFUSE);
daniel@transgaming.comd10f8692010-09-16 19:56:52 +00002502 device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002503
daniel@transgaming.comfab5a1a2010-03-11 19:22:30 +00002504 struct Vertex
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002505 {
2506 float x, y, z, w;
2507 D3DCOLOR diffuse;
2508 };
2509
2510 Vertex quad[4];
2511 quad[0].x = 0.0f;
2512 quad[0].y = (float)desc.Height;
2513 quad[0].z = 0.0f;
2514 quad[0].w = 1.0f;
2515 quad[0].diffuse = color;
2516
2517 quad[1].x = (float)desc.Width;
2518 quad[1].y = (float)desc.Height;
2519 quad[1].z = 0.0f;
2520 quad[1].w = 1.0f;
2521 quad[1].diffuse = color;
2522
2523 quad[2].x = 0.0f;
2524 quad[2].y = 0.0f;
2525 quad[2].z = 0.0f;
2526 quad[2].w = 1.0f;
2527 quad[2].diffuse = color;
2528
2529 quad[3].x = (float)desc.Width;
2530 quad[3].y = 0.0f;
2531 quad[3].z = 0.0f;
2532 quad[3].w = 1.0f;
2533 quad[3].diffuse = color;
2534
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002535 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002536 device->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, quad, sizeof(Vertex));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002537
2538 if (flags & D3DCLEAR_ZBUFFER)
2539 {
2540 device->SetRenderState(D3DRS_ZENABLE, TRUE);
2541 device->SetRenderState(D3DRS_ZWRITEENABLE, TRUE);
2542 device->Clear(0, NULL, D3DCLEAR_ZBUFFER, color, depth, stencil);
2543 }
daniel@transgaming.com8f05d1a2010-06-07 02:06:03 +00002544
2545 if (mMaskedClearSavedState != NULL)
2546 {
2547 mMaskedClearSavedState->Apply();
2548 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002549 }
daniel@transgaming.com8ede24f2010-05-05 18:47:58 +00002550 else if (flags)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002551 {
2552 device->Clear(0, NULL, flags, color, depth, stencil);
2553 }
2554}
2555
2556void Context::drawArrays(GLenum mode, GLint first, GLsizei count)
2557{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002558 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002559 {
2560 return error(GL_INVALID_OPERATION);
2561 }
2562
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002563 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002564 IDirect3DDevice9 *device = getDevice();
2565 D3DPRIMITIVETYPE primitiveType;
2566 int primitiveCount;
2567
2568 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2569 return error(GL_INVALID_ENUM);
2570
2571 if (primitiveCount <= 0)
2572 {
2573 return;
2574 }
2575
2576 if (!applyRenderTarget(false))
2577 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002578 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002579 }
2580
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002581 applyState(mode);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002582
daniel@transgaming.com83921382011-01-08 05:46:00 +00002583 GLenum err = applyVertexBuffer(first, count);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002584 if (err != GL_NO_ERROR)
2585 {
2586 return error(err);
2587 }
2588
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002589 applyShaders();
2590 applyTextures();
2591
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002592 if (!getCurrentProgram()->validateSamplers())
2593 {
2594 return error(GL_INVALID_OPERATION);
2595 }
2596
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002597 if (!cullSkipsDraw(mode))
2598 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002599 display->startScene();
daniel@transgaming.com83921382011-01-08 05:46:00 +00002600
2601 device->DrawPrimitive(primitiveType, 0, primitiveCount);
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002602
2603 if (mode == GL_LINE_LOOP) // Draw the last segment separately
2604 {
2605 drawClosingLine(first, first + count - 1);
2606 }
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002607 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002608}
2609
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002610void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const void *indices)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002611{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002612 if (!mState.currentProgram)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002613 {
2614 return error(GL_INVALID_OPERATION);
2615 }
2616
daniel@transgaming.com428d1582010-05-04 03:35:25 +00002617 if (!indices && !mState.elementArrayBuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002618 {
2619 return error(GL_INVALID_OPERATION);
2620 }
2621
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002622 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002623 IDirect3DDevice9 *device = getDevice();
2624 D3DPRIMITIVETYPE primitiveType;
2625 int primitiveCount;
2626
2627 if(!es2dx::ConvertPrimitiveType(mode, count, &primitiveType, &primitiveCount))
2628 return error(GL_INVALID_ENUM);
2629
2630 if (primitiveCount <= 0)
2631 {
2632 return;
2633 }
2634
2635 if (!applyRenderTarget(false))
2636 {
daniel@transgaming.combaeb8c52010-05-05 18:50:39 +00002637 return;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002638 }
2639
daniel@transgaming.com5af64272010-04-15 20:45:12 +00002640 applyState(mode);
daniel@transgaming.com41d8dd82010-05-12 03:45:03 +00002641
2642 TranslatedIndexData indexInfo;
2643 GLenum err = applyIndexBuffer(indices, count, mode, type, &indexInfo);
2644 if (err != GL_NO_ERROR)
2645 {
2646 return error(err);
2647 }
2648
daniel@transgaming.com83921382011-01-08 05:46:00 +00002649 GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
2650 err = applyVertexBuffer(indexInfo.minIndex, vertexCount);
daniel@transgaming.com838bcea2010-05-20 19:17:42 +00002651 if (err != GL_NO_ERROR)
2652 {
2653 return error(err);
2654 }
2655
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002656 applyShaders();
2657 applyTextures();
2658
daniel@transgaming.comc3a0e942010-04-29 03:35:45 +00002659 if (!getCurrentProgram()->validateSamplers())
2660 {
2661 return error(GL_INVALID_OPERATION);
2662 }
2663
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002664 if (!cullSkipsDraw(mode))
2665 {
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002666 display->startScene();
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002667
daniel@transgaming.com83921382011-01-08 05:46:00 +00002668 device->DrawIndexedPrimitive(primitiveType, -(INT)indexInfo.minIndex, indexInfo.minIndex, vertexCount, indexInfo.startIndex, primitiveCount);
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002669
2670 if (mode == GL_LINE_LOOP) // Draw the last segment separately
2671 {
2672 drawClosingLine(count, type, indices);
2673 }
daniel@transgaming.comace5e662010-03-21 04:31:20 +00002674 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002675}
2676
2677void Context::finish()
2678{
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002679 egl::Display *display = getDisplay();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002680 IDirect3DDevice9 *device = getDevice();
2681 IDirect3DQuery9 *occlusionQuery = NULL;
2682
2683 HRESULT result = device->CreateQuery(D3DQUERYTYPE_OCCLUSION, &occlusionQuery);
2684
2685 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2686 {
2687 return error(GL_OUT_OF_MEMORY);
2688 }
2689
2690 ASSERT(SUCCEEDED(result));
2691
2692 if (occlusionQuery)
2693 {
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002694 IDirect3DStateBlock9 *savedState = NULL;
2695 device->CreateStateBlock(D3DSBT_ALL, &savedState);
2696
apatrick@chromium.org575e7912010-08-25 18:07:12 +00002697 HRESULT result = occlusionQuery->Issue(D3DISSUE_BEGIN);
2698 ASSERT(SUCCEEDED(result));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002699
2700 // Render something outside the render target
2701 device->SetPixelShader(NULL);
2702 device->SetVertexShader(NULL);
2703 device->SetFVF(D3DFVF_XYZRHW);
2704 float data[4] = {-1.0f, -1.0f, -1.0f, 1.0f};
daniel@transgaming.comae072af2010-05-05 18:47:28 +00002705 display->startScene();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002706 device->DrawPrimitiveUP(D3DPT_POINTLIST, 1, data, sizeof(data));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002707
apatrick@chromium.org575e7912010-08-25 18:07:12 +00002708 result = occlusionQuery->Issue(D3DISSUE_END);
2709 ASSERT(SUCCEEDED(result));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002710
2711 while (occlusionQuery->GetData(NULL, 0, D3DGETDATA_FLUSH) == S_FALSE)
2712 {
2713 // Keep polling, but allow other threads to do something useful first
2714 Sleep(0);
2715 }
2716
2717 occlusionQuery->Release();
daniel@transgaming.coma71cdd72010-05-12 16:51:14 +00002718
2719 if (savedState)
2720 {
2721 savedState->Apply();
2722 savedState->Release();
2723 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002724 }
2725}
2726
2727void Context::flush()
2728{
2729 IDirect3DDevice9 *device = getDevice();
2730 IDirect3DQuery9 *eventQuery = NULL;
2731
2732 HRESULT result = device->CreateQuery(D3DQUERYTYPE_EVENT, &eventQuery);
2733
2734 if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY)
2735 {
2736 return error(GL_OUT_OF_MEMORY);
2737 }
2738
2739 ASSERT(SUCCEEDED(result));
2740
2741 if (eventQuery)
2742 {
apatrick@chromium.org575e7912010-08-25 18:07:12 +00002743 HRESULT result = eventQuery->Issue(D3DISSUE_END);
2744 ASSERT(SUCCEEDED(result));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002745
apatrick@chromium.org575e7912010-08-25 18:07:12 +00002746 result = eventQuery->GetData(NULL, 0, D3DGETDATA_FLUSH);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002747 eventQuery->Release();
apatrick@chromium.org575e7912010-08-25 18:07:12 +00002748
2749 if (result == D3DERR_DEVICELOST)
2750 {
2751 error(GL_OUT_OF_MEMORY);
2752 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002753 }
2754}
2755
daniel@transgaming.comddcd7372011-01-08 05:46:33 +00002756void Context::drawClosingLine(unsigned int first, unsigned int last)
2757{
2758 IDirect3DDevice9 *device = getDevice();
2759 IDirect3DIndexBuffer9 *indexBuffer = NULL;
2760 HRESULT result = D3DERR_INVALIDCALL;
2761
2762 if (supports32bitIndices())
2763 {
2764 result = device->CreateIndexBuffer(8, D3DUSAGE_WRITEONLY, D3DFMT_INDEX32, D3DPOOL_DEFAULT, &indexBuffer, 0);
2765
2766 if (SUCCEEDED(result))
2767 {
2768 unsigned int *data;
2769 result = indexBuffer->Lock(0, 0, (void**)&data, 0);
2770
2771 if (SUCCEEDED(result))
2772 {
2773 data[0] = last;
2774 data[1] = first;
2775 }
2776 }
2777 }
2778 else
2779 {
2780 result = device->CreateIndexBuffer(4, D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &indexBuffer, 0);
2781
2782 if (SUCCEEDED(result))
2783 {
2784 unsigned short *data;
2785 result = indexBuffer->Lock(0, 0, (void**)&data, 0);
2786
2787 if (SUCCEEDED(result))
2788 {
2789 data[0] = last;
2790 data[1] = first;
2791 }
2792 }
2793 }
2794
2795 if (SUCCEEDED(result))
2796 {
2797 indexBuffer->Unlock();
2798 device->SetIndices(indexBuffer);
2799
2800 device->DrawIndexedPrimitive(D3DPT_LINELIST, 0, 0, 2, 0, 1);
2801
2802 indexBuffer->Release();
2803 }
2804 else
2805 {
2806 ERR("Could not create an index buffer for closing a line loop.");
2807 error(GL_OUT_OF_MEMORY);
2808 }
2809}
2810
2811void Context::drawClosingLine(GLsizei count, GLenum type, const void *indices)
2812{
2813 unsigned int first = 0;
2814 unsigned int last = 0;
2815
2816 if (mState.elementArrayBuffer.get())
2817 {
2818 Buffer *indexBuffer = mState.elementArrayBuffer.get();
2819 intptr_t offset = reinterpret_cast<intptr_t>(indices);
2820 indices = static_cast<const GLubyte*>(indexBuffer->data()) + offset;
2821 }
2822
2823 switch (type)
2824 {
2825 case GL_UNSIGNED_BYTE:
2826 first = static_cast<const GLubyte*>(indices)[0];
2827 last = static_cast<const GLubyte*>(indices)[count - 1];
2828 break;
2829 case GL_UNSIGNED_SHORT:
2830 first = static_cast<const GLushort*>(indices)[0];
2831 last = static_cast<const GLushort*>(indices)[count - 1];
2832 break;
2833 case GL_UNSIGNED_INT:
2834 first = static_cast<const GLuint*>(indices)[0];
2835 last = static_cast<const GLuint*>(indices)[count - 1];
2836 break;
2837 default: UNREACHABLE();
2838 }
2839
2840 drawClosingLine(first, last);
2841}
2842
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00002843void Context::recordInvalidEnum()
2844{
2845 mInvalidEnum = true;
2846}
2847
2848void Context::recordInvalidValue()
2849{
2850 mInvalidValue = true;
2851}
2852
2853void Context::recordInvalidOperation()
2854{
2855 mInvalidOperation = true;
2856}
2857
2858void Context::recordOutOfMemory()
2859{
2860 mOutOfMemory = true;
2861}
2862
2863void Context::recordInvalidFramebufferOperation()
2864{
2865 mInvalidFramebufferOperation = true;
2866}
2867
2868// Get one of the recorded errors and clear its flag, if any.
2869// [OpenGL ES 2.0.24] section 2.5 page 13.
2870GLenum Context::getError()
2871{
2872 if (mInvalidEnum)
2873 {
2874 mInvalidEnum = false;
2875
2876 return GL_INVALID_ENUM;
2877 }
2878
2879 if (mInvalidValue)
2880 {
2881 mInvalidValue = false;
2882
2883 return GL_INVALID_VALUE;
2884 }
2885
2886 if (mInvalidOperation)
2887 {
2888 mInvalidOperation = false;
2889
2890 return GL_INVALID_OPERATION;
2891 }
2892
2893 if (mOutOfMemory)
2894 {
2895 mOutOfMemory = false;
2896
2897 return GL_OUT_OF_MEMORY;
2898 }
2899
2900 if (mInvalidFramebufferOperation)
2901 {
2902 mInvalidFramebufferOperation = false;
2903
2904 return GL_INVALID_FRAMEBUFFER_OPERATION;
2905 }
2906
2907 return GL_NO_ERROR;
2908}
2909
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002910bool Context::supportsShaderModel3() const
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002911{
daniel@transgaming.combe5a0862010-07-28 19:20:37 +00002912 return mSupportsShaderModel3;
daniel@transgaming.com296ca9c2010-04-03 20:56:07 +00002913}
2914
daniel@transgaming.com396c6432010-11-26 16:26:12 +00002915int Context::getMaximumVaryingVectors() const
2916{
2917 return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
2918}
2919
daniel@transgaming.com458da142010-11-28 02:03:02 +00002920int Context::getMaximumFragmentUniformVectors() const
2921{
2922 return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2;
2923}
2924
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00002925int Context::getMaxSupportedSamples() const
2926{
2927 return mMaxSupportedSamples;
2928}
2929
2930int Context::getNearestSupportedSamples(D3DFORMAT format, int requested) const
2931{
2932 if (requested == 0)
2933 {
2934 return requested;
2935 }
2936
2937 std::map<D3DFORMAT, bool *>::const_iterator itr = mMultiSampleSupport.find(format);
2938 if (itr == mMultiSampleSupport.end())
2939 {
2940 return -1;
2941 }
2942
2943 for (int i = requested; i <= D3DMULTISAMPLE_16_SAMPLES; ++i)
2944 {
2945 if (itr->second[i] && i != D3DMULTISAMPLE_NONMASKABLE)
2946 {
2947 return i;
2948 }
2949 }
2950
2951 return -1;
2952}
2953
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +00002954bool Context::supportsEventQueries() const
2955{
2956 return mSupportsEventQueries;
2957}
2958
daniel@transgaming.com01868132010-08-24 19:21:17 +00002959bool Context::supportsCompressedTextures() const
2960{
2961 return mSupportsCompressedTextures;
2962}
2963
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00002964bool Context::supportsFloatTextures() const
2965{
2966 return mSupportsFloatTextures;
2967}
2968
2969bool Context::supportsFloatLinearFilter() const
2970{
2971 return mSupportsFloatLinearFilter;
2972}
2973
daniel@transgaming.com1297d922010-09-01 15:47:47 +00002974bool Context::supportsFloatRenderableTextures() const
2975{
2976 return mSupportsFloatRenderableTextures;
2977}
2978
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00002979bool Context::supportsHalfFloatTextures() const
2980{
2981 return mSupportsHalfFloatTextures;
2982}
2983
2984bool Context::supportsHalfFloatLinearFilter() const
2985{
2986 return mSupportsHalfFloatLinearFilter;
2987}
2988
daniel@transgaming.com1297d922010-09-01 15:47:47 +00002989bool Context::supportsHalfFloatRenderableTextures() const
2990{
2991 return mSupportsHalfFloatRenderableTextures;
2992}
2993
daniel@transgaming.com5d752f22010-10-07 13:37:20 +00002994int Context::getMaximumRenderbufferDimension() const
2995{
2996 return mMaxRenderbufferDimension;
2997}
2998
2999int Context::getMaximumTextureDimension() const
3000{
3001 return mMaxTextureDimension;
3002}
3003
3004int Context::getMaximumCubeTextureDimension() const
3005{
3006 return mMaxCubeTextureDimension;
3007}
3008
3009int Context::getMaximumTextureLevel() const
3010{
3011 return mMaxTextureLevel;
3012}
3013
daniel@transgaming.comed828e52010-10-15 17:57:30 +00003014bool Context::supportsLuminanceTextures() const
3015{
3016 return mSupportsLuminanceTextures;
3017}
3018
3019bool Context::supportsLuminanceAlphaTextures() const
3020{
3021 return mSupportsLuminanceAlphaTextures;
3022}
3023
daniel@transgaming.com83921382011-01-08 05:46:00 +00003024bool Context::supports32bitIndices() const
3025{
3026 return mSupports32bitIndices;
3027}
3028
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003029void Context::detachBuffer(GLuint buffer)
3030{
3031 // [OpenGL ES 2.0.24] section 2.9 page 22:
3032 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
3033 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
3034
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003035 if (mState.arrayBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003036 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003037 mState.arrayBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003038 }
3039
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003040 if (mState.elementArrayBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003041 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003042 mState.elementArrayBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003043 }
3044
3045 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
3046 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003047 if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003048 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003049 mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003050 }
3051 }
3052}
3053
3054void Context::detachTexture(GLuint texture)
3055{
3056 // [OpenGL ES 2.0.24] section 3.8 page 84:
3057 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
3058 // rebound to texture object zero
3059
daniel@transgaming.com416485f2010-03-16 06:23:23 +00003060 for (int type = 0; type < SAMPLER_TYPE_COUNT; type++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003061 {
daniel@transgaming.com416485f2010-03-16 06:23:23 +00003062 for (int sampler = 0; sampler < MAX_TEXTURE_IMAGE_UNITS; sampler++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003063 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003064 if (mState.samplerTexture[type][sampler].id() == texture)
daniel@transgaming.com416485f2010-03-16 06:23:23 +00003065 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003066 mState.samplerTexture[type][sampler].set(NULL);
daniel@transgaming.com416485f2010-03-16 06:23:23 +00003067 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003068 }
3069 }
3070
3071 // [OpenGL ES 2.0.24] section 4.4 page 112:
3072 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
3073 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
3074 // image was attached in the currently bound framebuffer.
3075
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003076 Framebuffer *readFramebuffer = getReadFramebuffer();
3077 Framebuffer *drawFramebuffer = getDrawFramebuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003078
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003079 if (readFramebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003080 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003081 readFramebuffer->detachTexture(texture);
3082 }
3083
3084 if (drawFramebuffer && drawFramebuffer != readFramebuffer)
3085 {
3086 drawFramebuffer->detachTexture(texture);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003087 }
3088}
3089
3090void Context::detachFramebuffer(GLuint framebuffer)
3091{
3092 // [OpenGL ES 2.0.24] section 4.4 page 107:
3093 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
3094 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
3095
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +00003096 if (mState.readFramebuffer == framebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003097 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003098 bindReadFramebuffer(0);
3099 }
3100
apatrick@chromium.orgff8bdfb2010-09-15 17:27:49 +00003101 if (mState.drawFramebuffer == framebuffer)
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003102 {
3103 bindDrawFramebuffer(0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003104 }
3105}
3106
3107void Context::detachRenderbuffer(GLuint renderbuffer)
3108{
3109 // [OpenGL ES 2.0.24] section 4.4 page 109:
3110 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
3111 // had been executed with the target RENDERBUFFER and name of zero.
3112
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003113 if (mState.renderbuffer.id() == renderbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003114 {
3115 bindRenderbuffer(0);
3116 }
3117
3118 // [OpenGL ES 2.0.24] section 4.4 page 111:
3119 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
3120 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
3121 // point to which this image was attached in the currently bound framebuffer.
3122
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003123 Framebuffer *readFramebuffer = getReadFramebuffer();
3124 Framebuffer *drawFramebuffer = getDrawFramebuffer();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003125
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003126 if (readFramebuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003127 {
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00003128 readFramebuffer->detachRenderbuffer(renderbuffer);
3129 }
3130
3131 if (drawFramebuffer && drawFramebuffer != readFramebuffer)
3132 {
3133 drawFramebuffer->detachRenderbuffer(renderbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003134 }
3135}
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003136
3137Texture *Context::getIncompleteTexture(SamplerType type)
3138{
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00003139 Texture *t = mIncompleteTextures[type].get();
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003140
3141 if (t == NULL)
3142 {
3143 static const GLubyte color[] = { 0, 0, 0, 255 };
3144
3145 switch (type)
3146 {
3147 default:
3148 UNREACHABLE();
3149 // default falls through to SAMPLER_2D
3150
3151 case SAMPLER_2D:
3152 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003153 Texture2D *incomplete2d = new Texture2D(Texture::INCOMPLETE_TEXTURE_ID);
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00003154 incomplete2d->setImage(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003155 t = incomplete2d;
3156 }
3157 break;
3158
3159 case SAMPLER_CUBE:
3160 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00003161 TextureCubeMap *incompleteCube = new TextureCubeMap(Texture::INCOMPLETE_TEXTURE_ID);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003162
daniel@transgaming.com3489e3a2010-03-21 04:31:11 +00003163 incompleteCube->setImagePosX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
3164 incompleteCube->setImageNegX(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
3165 incompleteCube->setImagePosY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
3166 incompleteCube->setImageNegY(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
3167 incompleteCube->setImagePosZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
3168 incompleteCube->setImageNegZ(0, GL_RGBA, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003169
3170 t = incompleteCube;
3171 }
3172 break;
3173 }
3174
apatrick@chromium.org4e3bad42010-09-15 17:31:48 +00003175 mIncompleteTextures[type].set(t);
daniel@transgaming.com12d54072010-03-16 06:23:26 +00003176 }
3177
3178 return t;
3179}
daniel@transgaming.comace5e662010-03-21 04:31:20 +00003180
daniel@transgaming.com5af64272010-04-15 20:45:12 +00003181bool Context::cullSkipsDraw(GLenum drawMode)
daniel@transgaming.comace5e662010-03-21 04:31:20 +00003182{
daniel@transgaming.com428d1582010-05-04 03:35:25 +00003183 return mState.cullFace && mState.cullMode == GL_FRONT_AND_BACK && isTriangleMode(drawMode);
daniel@transgaming.comace5e662010-03-21 04:31:20 +00003184}
3185
daniel@transgaming.com5af64272010-04-15 20:45:12 +00003186bool Context::isTriangleMode(GLenum drawMode)
3187{
3188 switch (drawMode)
3189 {
3190 case GL_TRIANGLES:
3191 case GL_TRIANGLE_FAN:
3192 case GL_TRIANGLE_STRIP:
3193 return true;
3194 case GL_POINTS:
3195 case GL_LINES:
3196 case GL_LINE_LOOP:
3197 case GL_LINE_STRIP:
3198 return false;
3199 default: UNREACHABLE();
3200 }
3201
3202 return false;
3203}
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00003204
3205void Context::setVertexAttrib(GLuint index, const GLfloat *values)
3206{
3207 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
3208
daniel@transgaming.com428d1582010-05-04 03:35:25 +00003209 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
3210 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
3211 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
3212 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00003213
daniel@transgaming.com83921382011-01-08 05:46:00 +00003214 mVertexDataManager->dirtyCurrentValue(index);
daniel@transgaming.come4b08c82010-04-20 18:53:06 +00003215}
3216
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00003217void Context::initExtensionString()
3218{
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00003219 mExtensionString += "GL_OES_packed_depth_stencil ";
daniel@transgaming.coma9198d92010-08-08 04:49:56 +00003220 mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
3221 mExtensionString += "GL_EXT_read_format_bgra ";
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003222 mExtensionString += "GL_ANGLE_framebuffer_blit ";
daniel@transgaming.comd36c2972010-08-24 19:21:07 +00003223 mExtensionString += "GL_OES_rgb8_rgba8 ";
alokp@chromium.orgd303ef92010-09-09 17:30:15 +00003224 mExtensionString += "GL_OES_standard_derivatives ";
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00003225
apatrick@chromium.orgd3bd0ad2010-08-30 18:55:36 +00003226 if (supportsEventQueries())
3227 {
3228 mExtensionString += "GL_NV_fence ";
3229 }
3230
daniel@transgaming.com01868132010-08-24 19:21:17 +00003231 if (supportsCompressedTextures())
3232 {
3233 mExtensionString += "GL_EXT_texture_compression_dxt1 ";
3234 }
daniel@transgaming.comd470a1b2010-08-24 19:20:48 +00003235
daniel@transgaming.com0a337e92010-08-28 17:38:27 +00003236 if (supportsFloatTextures())
3237 {
3238 mExtensionString += "GL_OES_texture_float ";
3239 }
3240
3241 if (supportsHalfFloatTextures())
3242 {
3243 mExtensionString += "GL_OES_texture_half_float ";
3244 }
3245
3246 if (supportsFloatLinearFilter())
3247 {
3248 mExtensionString += "GL_OES_texture_float_linear ";
3249 }
3250
3251 if (supportsHalfFloatLinearFilter())
3252 {
3253 mExtensionString += "GL_OES_texture_half_float_linear ";
3254 }
3255
daniel@transgaming.com3ea20e72010-08-24 19:20:58 +00003256 if (getMaxSupportedSamples() != 0)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003257 {
3258 mExtensionString += "GL_ANGLE_framebuffer_multisample ";
3259 }
3260
daniel@transgaming.com83921382011-01-08 05:46:00 +00003261 if (supports32bitIndices())
daniel@transgaming.com3e4c6002010-05-05 18:50:13 +00003262 {
3263 mExtensionString += "GL_OES_element_index_uint ";
3264 }
3265
3266 std::string::size_type end = mExtensionString.find_last_not_of(' ');
3267 if (end != std::string::npos)
3268 {
3269 mExtensionString.resize(end+1);
3270 }
3271}
3272
3273const char *Context::getExtensionString() const
3274{
3275 return mExtensionString.c_str();
3276}
3277
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003278void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
3279 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
3280 GLbitfield mask)
3281{
3282 IDirect3DDevice9 *device = getDevice();
3283
3284 Framebuffer *readFramebuffer = getReadFramebuffer();
3285 Framebuffer *drawFramebuffer = getDrawFramebuffer();
3286
3287 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
3288 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
3289 {
3290 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
3291 }
3292
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003293 if (drawFramebuffer->getSamples() != 0)
3294 {
3295 return error(GL_INVALID_OPERATION);
3296 }
3297
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003298 RECT sourceRect;
3299 RECT destRect;
3300
3301 if (srcX0 < srcX1)
3302 {
3303 sourceRect.left = srcX0;
3304 sourceRect.right = srcX1;
3305 destRect.left = dstX0;
3306 destRect.right = dstX1;
3307 }
3308 else
3309 {
3310 sourceRect.left = srcX1;
3311 destRect.left = dstX1;
3312 sourceRect.right = srcX0;
3313 destRect.right = dstX0;
3314 }
3315
3316 // Arguments to StretchRect must be in D3D-style (0-top) coordinates, so we must
3317 // flip our Y-values here
3318 if (srcY0 < srcY1)
3319 {
3320 sourceRect.bottom = srcY1;
3321 destRect.bottom = dstY1;
3322 sourceRect.top = srcY0;
3323 destRect.top = dstY0;
3324 }
3325 else
3326 {
3327 sourceRect.bottom = srcY0;
3328 destRect.bottom = dstY0;
3329 sourceRect.top = srcY1;
3330 destRect.top = dstY1;
3331 }
3332
3333 RECT sourceScissoredRect = sourceRect;
3334 RECT destScissoredRect = destRect;
3335
3336 if (mState.scissorTest)
3337 {
3338 // Only write to parts of the destination framebuffer which pass the scissor test
3339 // Please note: the destRect is now in D3D-style coordinates, so the *top* of the
3340 // rect will be checked against scissorY, rather than the bottom.
3341 if (destRect.left < mState.scissorX)
3342 {
3343 int xDiff = mState.scissorX - destRect.left;
3344 destScissoredRect.left = mState.scissorX;
3345 sourceScissoredRect.left += xDiff;
3346 }
3347
3348 if (destRect.right > mState.scissorX + mState.scissorWidth)
3349 {
3350 int xDiff = destRect.right - (mState.scissorX + mState.scissorWidth);
3351 destScissoredRect.right = mState.scissorX + mState.scissorWidth;
3352 sourceScissoredRect.right -= xDiff;
3353 }
3354
3355 if (destRect.top < mState.scissorY)
3356 {
3357 int yDiff = mState.scissorY - destRect.top;
3358 destScissoredRect.top = mState.scissorY;
3359 sourceScissoredRect.top += yDiff;
3360 }
3361
3362 if (destRect.bottom > mState.scissorY + mState.scissorHeight)
3363 {
3364 int yDiff = destRect.bottom - (mState.scissorY + mState.scissorHeight);
3365 destScissoredRect.bottom = mState.scissorY + mState.scissorHeight;
3366 sourceScissoredRect.bottom -= yDiff;
3367 }
3368 }
3369
3370 bool blitRenderTarget = false;
3371 bool blitDepthStencil = false;
3372
3373 RECT sourceTrimmedRect = sourceScissoredRect;
3374 RECT destTrimmedRect = destScissoredRect;
3375
3376 // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of
3377 // the actual draw and read surfaces.
3378 if (sourceTrimmedRect.left < 0)
3379 {
3380 int xDiff = 0 - sourceTrimmedRect.left;
3381 sourceTrimmedRect.left = 0;
3382 destTrimmedRect.left += xDiff;
3383 }
3384
3385 int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth();
3386 int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight();
3387 int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth();
3388 int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight();
3389
3390 if (sourceTrimmedRect.right > readBufferWidth)
3391 {
3392 int xDiff = sourceTrimmedRect.right - readBufferWidth;
3393 sourceTrimmedRect.right = readBufferWidth;
3394 destTrimmedRect.right -= xDiff;
3395 }
3396
3397 if (sourceTrimmedRect.top < 0)
3398 {
3399 int yDiff = 0 - sourceTrimmedRect.top;
3400 sourceTrimmedRect.top = 0;
3401 destTrimmedRect.top += yDiff;
3402 }
3403
3404 if (sourceTrimmedRect.bottom > readBufferHeight)
3405 {
3406 int yDiff = sourceTrimmedRect.bottom - readBufferHeight;
3407 sourceTrimmedRect.bottom = readBufferHeight;
3408 destTrimmedRect.bottom -= yDiff;
3409 }
3410
3411 if (destTrimmedRect.left < 0)
3412 {
3413 int xDiff = 0 - destTrimmedRect.left;
3414 destTrimmedRect.left = 0;
3415 sourceTrimmedRect.left += xDiff;
3416 }
3417
3418 if (destTrimmedRect.right > drawBufferWidth)
3419 {
3420 int xDiff = destTrimmedRect.right - drawBufferWidth;
3421 destTrimmedRect.right = drawBufferWidth;
3422 sourceTrimmedRect.right -= xDiff;
3423 }
3424
3425 if (destTrimmedRect.top < 0)
3426 {
3427 int yDiff = 0 - destTrimmedRect.top;
3428 destTrimmedRect.top = 0;
3429 sourceTrimmedRect.top += yDiff;
3430 }
3431
3432 if (destTrimmedRect.bottom > drawBufferHeight)
3433 {
3434 int yDiff = destTrimmedRect.bottom - drawBufferHeight;
3435 destTrimmedRect.bottom = drawBufferHeight;
3436 sourceTrimmedRect.bottom -= yDiff;
3437 }
3438
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003439 bool partialBufferCopy = false;
daniel@transgaming.com3aba7332011-01-14 15:08:35 +00003440 if (sourceTrimmedRect.bottom - sourceTrimmedRect.top < readBufferHeight ||
3441 sourceTrimmedRect.right - sourceTrimmedRect.left < readBufferWidth ||
3442 destTrimmedRect.bottom - destTrimmedRect.top < drawBufferHeight ||
3443 destTrimmedRect.right - destTrimmedRect.left < drawBufferWidth ||
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003444 sourceTrimmedRect.top != 0 || destTrimmedRect.top != 0 || sourceTrimmedRect.left != 0 || destTrimmedRect.left != 0)
3445 {
3446 partialBufferCopy = true;
3447 }
3448
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003449 if (mask & GL_COLOR_BUFFER_BIT)
3450 {
enne@chromium.org0fa74632010-09-21 16:18:52 +00003451 const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
3452 readFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
3453 const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
3454 drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
3455 if (!validReadType || !validDrawType ||
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003456 readFramebuffer->getColorbuffer()->getD3DFormat() != drawFramebuffer->getColorbuffer()->getD3DFormat())
3457 {
3458 ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
3459 return error(GL_INVALID_OPERATION);
3460 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003461
3462 if (partialBufferCopy && readFramebuffer->getSamples() != 0)
3463 {
3464 return error(GL_INVALID_OPERATION);
3465 }
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003466
3467 blitRenderTarget = true;
3468
3469 }
3470
3471 if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
3472 {
3473 DepthStencilbuffer *readDSBuffer = NULL;
3474 DepthStencilbuffer *drawDSBuffer = NULL;
3475
3476 // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
3477 // both a depth and stencil buffer, it will be the same buffer.
3478
3479 if (mask & GL_DEPTH_BUFFER_BIT)
3480 {
3481 if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
3482 {
3483 if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
3484 readFramebuffer->getDepthbuffer()->getD3DFormat() != drawFramebuffer->getDepthbuffer()->getD3DFormat())
3485 {
3486 return error(GL_INVALID_OPERATION);
3487 }
3488
3489 blitDepthStencil = true;
3490 readDSBuffer = readFramebuffer->getDepthbuffer();
3491 drawDSBuffer = drawFramebuffer->getDepthbuffer();
3492 }
3493 }
3494
3495 if (mask & GL_STENCIL_BUFFER_BIT)
3496 {
3497 if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
3498 {
3499 if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
3500 readFramebuffer->getStencilbuffer()->getD3DFormat() != drawFramebuffer->getStencilbuffer()->getD3DFormat())
3501 {
3502 return error(GL_INVALID_OPERATION);
3503 }
3504
3505 blitDepthStencil = true;
3506 readDSBuffer = readFramebuffer->getStencilbuffer();
3507 drawDSBuffer = drawFramebuffer->getStencilbuffer();
3508 }
3509 }
3510
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003511 if (partialBufferCopy)
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003512 {
3513 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
3514 return error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted
3515 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003516
daniel@transgaming.com97446d22010-08-24 19:20:54 +00003517 if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) ||
3518 (readDSBuffer && readDSBuffer->getSamples() != 0))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00003519 {
3520 return error(GL_INVALID_OPERATION);
3521 }
daniel@transgaming.com4cbc5902010-08-24 19:20:26 +00003522 }
3523
3524 if (blitRenderTarget || blitDepthStencil)
3525 {
3526 egl::Display *display = getDisplay();
3527 display->endScene();
3528
3529 if (blitRenderTarget)
3530 {
3531 HRESULT result = device->StretchRect(readFramebuffer->getRenderTarget(), &sourceTrimmedRect,
3532 drawFramebuffer->getRenderTarget(), &destTrimmedRect, D3DTEXF_NONE);
3533
3534 if (FAILED(result))
3535 {
3536 ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
3537 return;
3538 }
3539 }
3540
3541 if (blitDepthStencil)
3542 {
3543 HRESULT result = device->StretchRect(readFramebuffer->getDepthStencil(), NULL, drawFramebuffer->getDepthStencil(), NULL, D3DTEXF_NONE);
3544
3545 if (FAILED(result))
3546 {
3547 ERR("BlitFramebufferANGLE failed: StretchRect returned %x.", result);
3548 return;
3549 }
3550 }
3551 }
3552}
3553
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003554}
3555
3556extern "C"
3557{
daniel@transgaming.com0d25b002010-07-28 19:21:07 +00003558gl::Context *glCreateContext(const egl::Config *config, const gl::Context *shareContext)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003559{
daniel@transgaming.com0d25b002010-07-28 19:21:07 +00003560 return new gl::Context(config, shareContext);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003561}
3562
3563void glDestroyContext(gl::Context *context)
3564{
3565 delete context;
3566
3567 if (context == gl::getContext())
3568 {
3569 gl::makeCurrent(NULL, NULL, NULL);
3570 }
3571}
3572
3573void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
3574{
3575 gl::makeCurrent(context, display, surface);
3576}
3577
3578gl::Context *glGetCurrentContext()
3579{
3580 return gl::getContext();
3581}
3582}