blob: 7ba10360f79e24690574dcd7aa81595d5cab907f [file] [log] [blame]
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001//
2// Copyright (c) 2002-2012 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
10#include "libGLESv2/Context.h"
11
12#include <algorithm>
13
14#include "libEGL/Display.h"
15
16#include "libGLESv2/main.h"
17#include "libGLESv2/mathutil.h"
18#include "libGLESv2/utilities.h"
daniel@transgaming.comd8e36562012-10-31 19:52:19 +000019#include "libGLESv2/renderer/renderer9_utils.h" // D3D9_REPLACE
apatrick@chromium.org144f2802012-07-12 01:42:34 +000020#include "libGLESv2/ResourceManager.h"
21#include "libGLESv2/Buffer.h"
22#include "libGLESv2/Fence.h"
daniel@transgaming.com29ab9522012-08-27 16:25:37 +000023#include "libGLESv2/Framebuffer.h"
apatrick@chromium.org144f2802012-07-12 01:42:34 +000024#include "libGLESv2/Program.h"
25#include "libGLESv2/ProgramBinary.h"
26#include "libGLESv2/Query.h"
daniel@transgaming.com29ab9522012-08-27 16:25:37 +000027#include "libGLESv2/Renderbuffer.h"
apatrick@chromium.org144f2802012-07-12 01:42:34 +000028#include "libGLESv2/Shader.h"
29#include "libGLESv2/Texture.h"
apatrick@chromium.org144f2802012-07-12 01:42:34 +000030
31#undef near
32#undef far
33
34namespace gl
35{
daniel@transgaming.com03d39092012-11-28 19:31:59 +000036Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
apatrick@chromium.org144f2802012-07-12 01:42:34 +000037{
38 ASSERT(robustAccess == false); // Unimplemented
39
daniel@transgaming.com03d39092012-11-28 19:31:59 +000040 ASSERT(dynamic_cast<rx::Renderer9*>(renderer) != NULL); // D3D9_REPLACE
41 mRenderer = static_cast<rx::Renderer9*>(renderer);
42
apatrick@chromium.org144f2802012-07-12 01:42:34 +000043 mDevice = NULL;
44
45 mFenceHandleAllocator.setBaseHandle(0);
46
47 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
48
49 mState.depthClearValue = 1.0f;
50 mState.stencilClearValue = 0;
51
daniel@transgaming.comf39967e2012-11-28 19:35:56 +000052 mState.rasterizer.cullFace = false;
53 mState.rasterizer.cullMode = GL_BACK;
54 mState.rasterizer.frontFace = GL_CCW;
55 mState.rasterizer.polygonOffsetFill = false;
56 mState.rasterizer.polygonOffsetFactor = 0.0f;
57 mState.rasterizer.polygonOffsetUnits = 0.0f;
58 mState.rasterizer.scissorTest = false;
59 mState.scissor.x = 0;
60 mState.scissor.y = 0;
61 mState.scissor.width = 0;
62 mState.scissor.height = 0;
63
64 mState.blend.blend = false;
65 mState.blend.sourceBlendRGB = GL_ONE;
66 mState.blend.sourceBlendAlpha = GL_ONE;
67 mState.blend.destBlendRGB = GL_ZERO;
68 mState.blend.destBlendAlpha = GL_ZERO;
69 mState.blend.blendEquationRGB = GL_FUNC_ADD;
70 mState.blend.blendEquationAlpha = GL_FUNC_ADD;
71 mState.blend.sampleAlphaToCoverage = false;
72 mState.blend.dither = true;
73
apatrick@chromium.org144f2802012-07-12 01:42:34 +000074 mState.blendColor.red = 0;
75 mState.blendColor.green = 0;
76 mState.blendColor.blue = 0;
77 mState.blendColor.alpha = 0;
daniel@transgaming.comf39967e2012-11-28 19:35:56 +000078
79 mState.depthStencil.depthTest = false;
80 mState.depthStencil.depthFunc = GL_LESS;
81 mState.depthStencil.depthMask = true;
82 mState.depthStencil.stencilTest = false;
83 mState.depthStencil.stencilFunc = GL_ALWAYS;
daniel@transgaming.comf39967e2012-11-28 19:35:56 +000084 mState.depthStencil.stencilMask = -1;
85 mState.depthStencil.stencilWritemask = -1;
86 mState.depthStencil.stencilBackFunc = GL_ALWAYS;
daniel@transgaming.comf39967e2012-11-28 19:35:56 +000087 mState.depthStencil.stencilBackMask = - 1;
88 mState.depthStencil.stencilBackWritemask = -1;
89 mState.depthStencil.stencilFail = GL_KEEP;
90 mState.depthStencil.stencilPassDepthFail = GL_KEEP;
91 mState.depthStencil.stencilPassDepthPass = GL_KEEP;
92 mState.depthStencil.stencilBackFail = GL_KEEP;
93 mState.depthStencil.stencilBackPassDepthFail = GL_KEEP;
94 mState.depthStencil.stencilBackPassDepthPass = GL_KEEP;
95
daniel@transgaming.com08c331d2012-11-28 19:38:39 +000096 mState.stencilRef = 0;
97 mState.stencilBackRef = 0;
98
apatrick@chromium.org144f2802012-07-12 01:42:34 +000099 mState.sampleCoverage = false;
100 mState.sampleCoverageValue = 1.0f;
101 mState.sampleCoverageInvert = false;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000102 mState.generateMipmapHint = GL_DONT_CARE;
103 mState.fragmentShaderDerivativeHint = GL_DONT_CARE;
104
105 mState.lineWidth = 1.0f;
106
daniel@transgaming.com3884e2c2012-11-28 19:41:00 +0000107 mState.viewport.x = 0;
108 mState.viewport.y = 0;
109 mState.viewport.width = 0;
110 mState.viewport.height = 0;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000111 mState.zNear = 0.0f;
112 mState.zFar = 1.0f;
113
daniel@transgaming.comf39967e2012-11-28 19:35:56 +0000114 mState.blend.colorMaskRed = true;
115 mState.blend.colorMaskGreen = true;
116 mState.blend.colorMaskBlue = true;
117 mState.blend.colorMaskAlpha = true;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000118
119 if (shareContext != NULL)
120 {
121 mResourceManager = shareContext->mResourceManager;
122 mResourceManager->addRef();
123 }
124 else
125 {
daniel@transgaming.com370482e2012-11-28 19:32:13 +0000126 mResourceManager = new ResourceManager(mRenderer);
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000127 }
128
129 // [OpenGL ES 2.0.24] section 3.7 page 83:
130 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
131 // and cube map texture state vectors respectively associated with them.
132 // In order that access to these initial textures not be lost, they are treated as texture
133 // objects all of whose names are 0.
134
daniel@transgaming.com370482e2012-11-28 19:32:13 +0000135 mTexture2DZero.set(new Texture2D(mRenderer, 0));
136 mTextureCubeMapZero.set(new TextureCubeMap(mRenderer, 0));
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000137
138 mState.activeSampler = 0;
139 bindArrayBuffer(0);
140 bindElementArrayBuffer(0);
141 bindTextureCubeMap(0);
142 bindTexture2D(0);
143 bindReadFramebuffer(0);
144 bindDrawFramebuffer(0);
145 bindRenderbuffer(0);
146
147 mState.currentProgram = 0;
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000148 mCurrentProgramBinary.set(NULL);
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000149
150 mState.packAlignment = 4;
151 mState.unpackAlignment = 4;
152 mState.packReverseRowOrder = false;
153
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000154 mInvalidEnum = false;
155 mInvalidValue = false;
156 mInvalidOperation = false;
157 mOutOfMemory = false;
158 mInvalidFramebufferOperation = false;
159
160 mHasBeenCurrent = false;
161 mContextLost = false;
162 mResetStatus = GL_NO_ERROR;
163 mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
164 mRobustAccess = robustAccess;
165
166 mSupportsDXT1Textures = false;
167 mSupportsDXT3Textures = false;
168 mSupportsDXT5Textures = false;
169 mSupportsEventQueries = false;
170 mSupportsOcclusionQueries = false;
171 mNumCompressedTextureFormats = 0;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000172 mMaskedClearSavedState = NULL;
173 markAllStateDirty();
174}
175
176Context::~Context()
177{
178 if (mState.currentProgram != 0)
179 {
180 Program *programObject = mResourceManager->getProgram(mState.currentProgram);
181 if (programObject)
182 {
183 programObject->release();
184 }
185 mState.currentProgram = 0;
186 }
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000187 mCurrentProgramBinary.set(NULL);
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000188
189 while (!mFramebufferMap.empty())
190 {
191 deleteFramebuffer(mFramebufferMap.begin()->first);
192 }
193
194 while (!mFenceMap.empty())
195 {
196 deleteFence(mFenceMap.begin()->first);
197 }
198
199 while (!mQueryMap.empty())
200 {
201 deleteQuery(mQueryMap.begin()->first);
202 }
203
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000204 for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
205 {
206 for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++)
207 {
208 mState.samplerTexture[type][sampler].set(NULL);
209 }
210 }
211
212 for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
213 {
214 mIncompleteTextures[type].set(NULL);
215 }
216
217 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
218 {
219 mState.vertexAttribute[i].mBoundBuffer.set(NULL);
220 }
221
222 for (int i = 0; i < QUERY_TYPE_COUNT; i++)
223 {
224 mState.activeQuery[i].set(NULL);
225 }
226
227 mState.arrayBuffer.set(NULL);
228 mState.elementArrayBuffer.set(NULL);
229 mState.renderbuffer.set(NULL);
230
231 mTexture2DZero.set(NULL);
232 mTextureCubeMapZero.set(NULL);
233
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000234 if (mMaskedClearSavedState)
235 {
236 mMaskedClearSavedState->Release();
237 }
238
239 mResourceManager->release();
240}
241
daniel@transgaming.comad629872012-11-28 19:32:06 +0000242void Context::makeCurrent(egl::Surface *surface)
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000243{
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000244 mDevice = mRenderer->getDevice(); // D3D9_REMOVE
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000245
246 if (!mHasBeenCurrent)
247 {
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000248 mSupportsShaderModel3 = mRenderer->getShaderModel3Support();
249 mMaximumPointSize = mRenderer->getMaxPointSize();
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000250 mSupportsVertexTexture = mRenderer->getVertexTextureSupport();
251 mSupportsNonPower2Texture = mRenderer->getNonPower2TextureSupport();
252 mSupportsInstancing = mRenderer->getInstancingSupport();
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000253
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000254 mMaxTextureDimension = std::min(std::min(mRenderer->getMaxTextureWidth(), mRenderer->getMaxTextureHeight()),
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000255 (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
256 mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
257 mMaxRenderbufferDimension = mMaxTextureDimension;
258 mMaxTextureLevel = log2(mMaxTextureDimension) + 1;
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000259 mMaxTextureAnisotropy = mRenderer->getTextureMaxAnisotropy();
daniel@transgaming.com07ab8412012-07-12 15:17:09 +0000260 TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d, MaxTextureAnisotropy=%f",
261 mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel, mMaxTextureAnisotropy);
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000262
daniel@transgaming.com621ce052012-10-31 17:52:29 +0000263 mSupportsEventQueries = mRenderer->getEventQuerySupport();
264 mSupportsOcclusionQueries = mRenderer->getOcclusionQuerySupport();
265 mSupportsDXT1Textures = mRenderer->getDXT1TextureSupport();
266 mSupportsDXT3Textures = mRenderer->getDXT3TextureSupport();
267 mSupportsDXT5Textures = mRenderer->getDXT5TextureSupport();
268 mSupportsFloat32Textures = mRenderer->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures);
269 mSupportsFloat16Textures = mRenderer->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures);
270 mSupportsLuminanceTextures = mRenderer->getLuminanceTextureSupport();
271 mSupportsLuminanceAlphaTextures = mRenderer->getLuminanceAlphaTextureSupport();
272 mSupportsDepthTextures = mRenderer->getDepthTextureSupport();
daniel@transgaming.comba0570e2012-10-31 18:07:39 +0000273 mSupportsTextureFilterAnisotropy = mRenderer->getTextureFilterAnisotropySupport();
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000274
daniel@transgaming.com5f4c1362012-10-31 18:29:00 +0000275 mSupports32bitIndices = mRenderer->get32BitIndexSupport();
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000276
277 mNumCompressedTextureFormats = 0;
278 if (supportsDXT1Textures())
279 {
280 mNumCompressedTextureFormats += 2;
281 }
282 if (supportsDXT3Textures())
283 {
284 mNumCompressedTextureFormats += 1;
285 }
286 if (supportsDXT5Textures())
287 {
288 mNumCompressedTextureFormats += 1;
289 }
290
291 initExtensionString();
292 initRendererString();
293
daniel@transgaming.com3884e2c2012-11-28 19:41:00 +0000294 mState.viewport.x = 0;
295 mState.viewport.y = 0;
296 mState.viewport.width = surface->getWidth();
297 mState.viewport.height = surface->getHeight();
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000298
daniel@transgaming.comf39967e2012-11-28 19:35:56 +0000299 mState.scissor.x = 0;
300 mState.scissor.y = 0;
301 mState.scissor.width = surface->getWidth();
302 mState.scissor.height = surface->getHeight();
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000303
304 mHasBeenCurrent = true;
305 }
306
daniel@transgaming.com024786d2012-10-31 18:42:55 +0000307 // Wrap the existing swapchain resources into GL objects and assign them to the '0' names
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000308 rx::SwapChain *swapchain = surface->getSwapChain();
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000309
daniel@transgaming.com70062c92012-11-28 19:32:30 +0000310 Colorbuffer *colorbufferZero = new Colorbuffer(mRenderer, swapchain);
311 DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(mRenderer, swapchain);
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000312 Framebuffer *framebufferZero = new DefaultFramebuffer(mRenderer, colorbufferZero, depthStencilbufferZero);
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000313
314 setFramebufferZero(framebufferZero);
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000315
316 markAllStateDirty();
317}
318
319// This function will set all of the state-related dirty flags, so that all state is set during next pre-draw.
320void Context::markAllStateDirty()
321{
322 for (int t = 0; t < MAX_TEXTURE_IMAGE_UNITS; t++)
323 {
324 mAppliedTextureSerialPS[t] = 0;
325 }
326
327 for (int t = 0; t < MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; t++)
328 {
329 mAppliedTextureSerialVS[t] = 0;
330 }
331
daniel@transgaming.come6af4f92012-07-24 18:31:31 +0000332 mAppliedProgramBinarySerial = 0;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000333
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000334 mDxUniformsDirty = true;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000335}
336
337void Context::markDxUniformsDirty()
338{
339 mDxUniformsDirty = true;
340}
341
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +0000342// NOTE: this function should not assume that this context is current!
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000343void Context::markContextLost()
344{
345 if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
346 mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
347 mContextLost = true;
348}
349
350bool Context::isContextLost()
351{
352 return mContextLost;
353}
354
355void Context::setClearColor(float red, float green, float blue, float alpha)
356{
357 mState.colorClearValue.red = red;
358 mState.colorClearValue.green = green;
359 mState.colorClearValue.blue = blue;
360 mState.colorClearValue.alpha = alpha;
361}
362
363void Context::setClearDepth(float depth)
364{
365 mState.depthClearValue = depth;
366}
367
368void Context::setClearStencil(int stencil)
369{
370 mState.stencilClearValue = stencil;
371}
372
373void Context::setCullFace(bool enabled)
374{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000375 mState.rasterizer.cullFace = enabled;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000376}
377
378bool Context::isCullFaceEnabled() const
379{
daniel@transgaming.comf39967e2012-11-28 19:35:56 +0000380 return mState.rasterizer.cullFace;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000381}
382
383void Context::setCullMode(GLenum mode)
384{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000385 mState.rasterizer.cullMode = mode;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000386}
387
388void Context::setFrontFace(GLenum front)
389{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000390 mState.rasterizer.frontFace = front;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000391}
392
393void Context::setDepthTest(bool enabled)
394{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000395 mState.depthStencil.depthTest = enabled;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000396}
397
398bool Context::isDepthTestEnabled() const
399{
daniel@transgaming.comf39967e2012-11-28 19:35:56 +0000400 return mState.depthStencil.depthTest;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000401}
402
403void Context::setDepthFunc(GLenum depthFunc)
404{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000405 mState.depthStencil.depthFunc = depthFunc;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000406}
407
408void Context::setDepthRange(float zNear, float zFar)
409{
410 mState.zNear = zNear;
411 mState.zFar = zFar;
412}
413
414void Context::setBlend(bool enabled)
415{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000416 mState.blend.blend = enabled;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000417}
418
419bool Context::isBlendEnabled() const
420{
daniel@transgaming.comf39967e2012-11-28 19:35:56 +0000421 return mState.blend.blend;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000422}
423
424void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
425{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000426 mState.blend.sourceBlendRGB = sourceRGB;
427 mState.blend.destBlendRGB = destRGB;
428 mState.blend.sourceBlendAlpha = sourceAlpha;
429 mState.blend.destBlendAlpha = destAlpha;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000430}
431
432void Context::setBlendColor(float red, float green, float blue, float alpha)
433{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000434 mState.blendColor.red = red;
435 mState.blendColor.green = green;
436 mState.blendColor.blue = blue;
437 mState.blendColor.alpha = alpha;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000438}
439
440void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
441{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000442 mState.blend.blendEquationRGB = rgbEquation;
443 mState.blend.blendEquationAlpha = alphaEquation;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000444}
445
446void Context::setStencilTest(bool enabled)
447{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000448 mState.depthStencil.stencilTest = enabled;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000449}
450
451bool Context::isStencilTestEnabled() const
452{
daniel@transgaming.comf39967e2012-11-28 19:35:56 +0000453 return mState.depthStencil.stencilTest;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000454}
455
456void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
457{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000458 mState.depthStencil.stencilFunc = stencilFunc;
daniel@transgaming.com08c331d2012-11-28 19:38:39 +0000459 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000460 mState.depthStencil.stencilMask = stencilMask;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000461}
462
463void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
464{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000465 mState.depthStencil.stencilBackFunc = stencilBackFunc;
daniel@transgaming.com08c331d2012-11-28 19:38:39 +0000466 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000467 mState.depthStencil.stencilBackMask = stencilBackMask;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000468}
469
470void Context::setStencilWritemask(GLuint stencilWritemask)
471{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000472 mState.depthStencil.stencilWritemask = stencilWritemask;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000473}
474
475void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
476{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000477 mState.depthStencil.stencilBackWritemask = stencilBackWritemask;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000478}
479
480void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
481{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000482 mState.depthStencil.stencilFail = stencilFail;
483 mState.depthStencil.stencilPassDepthFail = stencilPassDepthFail;
484 mState.depthStencil.stencilPassDepthPass = stencilPassDepthPass;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000485}
486
487void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
488{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000489 mState.depthStencil.stencilBackFail = stencilBackFail;
490 mState.depthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail;
491 mState.depthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000492}
493
494void Context::setPolygonOffsetFill(bool enabled)
495{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000496 mState.rasterizer.polygonOffsetFill = enabled;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000497}
498
499bool Context::isPolygonOffsetFillEnabled() const
500{
daniel@transgaming.comf39967e2012-11-28 19:35:56 +0000501 return mState.rasterizer.polygonOffsetFill;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000502}
503
504void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
505{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000506 mState.rasterizer.polygonOffsetFactor = factor;
507 mState.rasterizer.polygonOffsetUnits = units;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000508}
509
510void Context::setSampleAlphaToCoverage(bool enabled)
511{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000512 mState.blend.sampleAlphaToCoverage = enabled;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000513}
514
515bool Context::isSampleAlphaToCoverageEnabled() const
516{
daniel@transgaming.comf39967e2012-11-28 19:35:56 +0000517 return mState.blend.sampleAlphaToCoverage;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000518}
519
520void Context::setSampleCoverage(bool enabled)
521{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000522 mState.sampleCoverage = enabled;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000523}
524
525bool Context::isSampleCoverageEnabled() const
526{
527 return mState.sampleCoverage;
528}
529
530void Context::setSampleCoverageParams(GLclampf value, bool invert)
531{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000532 mState.sampleCoverageValue = value;
533 mState.sampleCoverageInvert = invert;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000534}
535
536void Context::setScissorTest(bool enabled)
537{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000538 mState.rasterizer.scissorTest = enabled;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000539}
540
541bool Context::isScissorTestEnabled() const
542{
daniel@transgaming.comf39967e2012-11-28 19:35:56 +0000543 return mState.rasterizer.scissorTest;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000544}
545
546void Context::setDither(bool enabled)
547{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000548 mState.blend.dither = enabled;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000549}
550
551bool Context::isDitherEnabled() const
552{
daniel@transgaming.comf39967e2012-11-28 19:35:56 +0000553 return mState.blend.dither;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000554}
555
556void Context::setLineWidth(GLfloat width)
557{
558 mState.lineWidth = width;
559}
560
561void Context::setGenerateMipmapHint(GLenum hint)
562{
563 mState.generateMipmapHint = hint;
564}
565
566void Context::setFragmentShaderDerivativeHint(GLenum hint)
567{
568 mState.fragmentShaderDerivativeHint = hint;
569 // TODO: Propagate the hint to shader translator so we can write
570 // ddx, ddx_coarse, or ddx_fine depending on the hint.
571 // Ignore for now. It is valid for implementations to ignore hint.
572}
573
574void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
575{
daniel@transgaming.com3884e2c2012-11-28 19:41:00 +0000576 mState.viewport.x = x;
577 mState.viewport.y = y;
578 mState.viewport.width = width;
579 mState.viewport.height = height;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000580}
581
582void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
583{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000584 mState.scissor.x = x;
585 mState.scissor.y = y;
586 mState.scissor.width = width;
587 mState.scissor.height = height;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000588}
589
590void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
591{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000592 mState.blend.colorMaskRed = red;
593 mState.blend.colorMaskGreen = green;
594 mState.blend.colorMaskBlue = blue;
595 mState.blend.colorMaskAlpha = alpha;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000596}
597
598void Context::setDepthMask(bool mask)
599{
daniel@transgaming.com2e258642012-11-28 19:36:18 +0000600 mState.depthStencil.depthMask = mask;
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000601}
602
603void Context::setActiveSampler(unsigned int active)
604{
605 mState.activeSampler = active;
606}
607
608GLuint Context::getReadFramebufferHandle() const
609{
610 return mState.readFramebuffer;
611}
612
613GLuint Context::getDrawFramebufferHandle() const
614{
615 return mState.drawFramebuffer;
616}
617
618GLuint Context::getRenderbufferHandle() const
619{
620 return mState.renderbuffer.id();
621}
622
623GLuint Context::getArrayBufferHandle() const
624{
625 return mState.arrayBuffer.id();
626}
627
628GLuint Context::getActiveQuery(GLenum target) const
629{
630 Query *queryObject = NULL;
631
632 switch (target)
633 {
634 case GL_ANY_SAMPLES_PASSED_EXT:
635 queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get();
636 break;
637 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
638 queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get();
639 break;
640 default:
641 ASSERT(false);
642 }
643
644 if (queryObject)
645 {
646 return queryObject->id();
647 }
648 else
649 {
650 return 0;
651 }
652}
653
654void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
655{
656 mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
657}
658
659const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
660{
661 return mState.vertexAttribute[attribNum];
662}
663
664void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
665 GLsizei stride, const void *pointer)
666{
667 mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
668 mState.vertexAttribute[attribNum].mSize = size;
669 mState.vertexAttribute[attribNum].mType = type;
670 mState.vertexAttribute[attribNum].mNormalized = normalized;
671 mState.vertexAttribute[attribNum].mStride = stride;
672 mState.vertexAttribute[attribNum].mPointer = pointer;
673}
674
675const void *Context::getVertexAttribPointer(unsigned int attribNum) const
676{
677 return mState.vertexAttribute[attribNum].mPointer;
678}
679
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000680void Context::setPackAlignment(GLint alignment)
681{
682 mState.packAlignment = alignment;
683}
684
685GLint Context::getPackAlignment() const
686{
687 return mState.packAlignment;
688}
689
690void Context::setUnpackAlignment(GLint alignment)
691{
692 mState.unpackAlignment = alignment;
693}
694
695GLint Context::getUnpackAlignment() const
696{
697 return mState.unpackAlignment;
698}
699
700void Context::setPackReverseRowOrder(bool reverseRowOrder)
701{
702 mState.packReverseRowOrder = reverseRowOrder;
703}
704
705bool Context::getPackReverseRowOrder() const
706{
707 return mState.packReverseRowOrder;
708}
709
710GLuint Context::createBuffer()
711{
712 return mResourceManager->createBuffer();
713}
714
715GLuint Context::createProgram()
716{
717 return mResourceManager->createProgram();
718}
719
720GLuint Context::createShader(GLenum type)
721{
722 return mResourceManager->createShader(type);
723}
724
725GLuint Context::createTexture()
726{
727 return mResourceManager->createTexture();
728}
729
730GLuint Context::createRenderbuffer()
731{
732 return mResourceManager->createRenderbuffer();
733}
734
735// Returns an unused framebuffer name
736GLuint Context::createFramebuffer()
737{
738 GLuint handle = mFramebufferHandleAllocator.allocate();
739
740 mFramebufferMap[handle] = NULL;
741
742 return handle;
743}
744
745GLuint Context::createFence()
746{
747 GLuint handle = mFenceHandleAllocator.allocate();
748
daniel@transgaming.comef21ab22012-10-31 17:52:47 +0000749 mFenceMap[handle] = new Fence(mRenderer);
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000750
751 return handle;
752}
753
754// Returns an unused query name
755GLuint Context::createQuery()
756{
757 GLuint handle = mQueryHandleAllocator.allocate();
758
759 mQueryMap[handle] = NULL;
760
761 return handle;
762}
763
764void Context::deleteBuffer(GLuint buffer)
765{
766 if (mResourceManager->getBuffer(buffer))
767 {
768 detachBuffer(buffer);
769 }
770
771 mResourceManager->deleteBuffer(buffer);
772}
773
774void Context::deleteShader(GLuint shader)
775{
776 mResourceManager->deleteShader(shader);
777}
778
779void Context::deleteProgram(GLuint program)
780{
781 mResourceManager->deleteProgram(program);
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000782}
783
784void Context::deleteTexture(GLuint texture)
785{
786 if (mResourceManager->getTexture(texture))
787 {
788 detachTexture(texture);
789 }
790
791 mResourceManager->deleteTexture(texture);
792}
793
794void Context::deleteRenderbuffer(GLuint renderbuffer)
795{
796 if (mResourceManager->getRenderbuffer(renderbuffer))
797 {
798 detachRenderbuffer(renderbuffer);
799 }
800
801 mResourceManager->deleteRenderbuffer(renderbuffer);
802}
803
804void Context::deleteFramebuffer(GLuint framebuffer)
805{
806 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
807
808 if (framebufferObject != mFramebufferMap.end())
809 {
810 detachFramebuffer(framebuffer);
811
812 mFramebufferHandleAllocator.release(framebufferObject->first);
813 delete framebufferObject->second;
814 mFramebufferMap.erase(framebufferObject);
815 }
816}
817
818void Context::deleteFence(GLuint fence)
819{
820 FenceMap::iterator fenceObject = mFenceMap.find(fence);
821
822 if (fenceObject != mFenceMap.end())
823 {
824 mFenceHandleAllocator.release(fenceObject->first);
825 delete fenceObject->second;
826 mFenceMap.erase(fenceObject);
827 }
828}
829
830void Context::deleteQuery(GLuint query)
831{
832 QueryMap::iterator queryObject = mQueryMap.find(query);
833 if (queryObject != mQueryMap.end())
834 {
835 mQueryHandleAllocator.release(queryObject->first);
836 if (queryObject->second)
837 {
838 queryObject->second->release();
839 }
840 mQueryMap.erase(queryObject);
841 }
842}
843
844Buffer *Context::getBuffer(GLuint handle)
845{
846 return mResourceManager->getBuffer(handle);
847}
848
849Shader *Context::getShader(GLuint handle)
850{
851 return mResourceManager->getShader(handle);
852}
853
854Program *Context::getProgram(GLuint handle)
855{
856 return mResourceManager->getProgram(handle);
857}
858
859Texture *Context::getTexture(GLuint handle)
860{
861 return mResourceManager->getTexture(handle);
862}
863
864Renderbuffer *Context::getRenderbuffer(GLuint handle)
865{
866 return mResourceManager->getRenderbuffer(handle);
867}
868
869Framebuffer *Context::getReadFramebuffer()
870{
871 return getFramebuffer(mState.readFramebuffer);
872}
873
874Framebuffer *Context::getDrawFramebuffer()
875{
876 return mBoundDrawFramebuffer;
877}
878
879void Context::bindArrayBuffer(unsigned int buffer)
880{
881 mResourceManager->checkBufferAllocation(buffer);
882
883 mState.arrayBuffer.set(getBuffer(buffer));
884}
885
886void Context::bindElementArrayBuffer(unsigned int buffer)
887{
888 mResourceManager->checkBufferAllocation(buffer);
889
890 mState.elementArrayBuffer.set(getBuffer(buffer));
891}
892
893void Context::bindTexture2D(GLuint texture)
894{
895 mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
896
897 mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));
898}
899
900void Context::bindTextureCubeMap(GLuint texture)
901{
902 mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
903
904 mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));
905}
906
907void Context::bindReadFramebuffer(GLuint framebuffer)
908{
909 if (!getFramebuffer(framebuffer))
910 {
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000911 mFramebufferMap[framebuffer] = new Framebuffer(mRenderer);
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000912 }
913
914 mState.readFramebuffer = framebuffer;
915}
916
917void Context::bindDrawFramebuffer(GLuint framebuffer)
918{
919 if (!getFramebuffer(framebuffer))
920 {
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000921 mFramebufferMap[framebuffer] = new Framebuffer(mRenderer);
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000922 }
923
924 mState.drawFramebuffer = framebuffer;
925
926 mBoundDrawFramebuffer = getFramebuffer(framebuffer);
927}
928
929void Context::bindRenderbuffer(GLuint renderbuffer)
930{
931 mResourceManager->checkRenderbufferAllocation(renderbuffer);
932
933 mState.renderbuffer.set(getRenderbuffer(renderbuffer));
934}
935
936void Context::useProgram(GLuint program)
937{
938 GLuint priorProgram = mState.currentProgram;
939 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
940
941 if (priorProgram != program)
942 {
943 Program *newProgram = mResourceManager->getProgram(program);
944 Program *oldProgram = mResourceManager->getProgram(priorProgram);
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000945 mCurrentProgramBinary.set(NULL);
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000946 mDxUniformsDirty = true;
947
948 if (newProgram)
949 {
950 newProgram->addRef();
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000951 mCurrentProgramBinary.set(newProgram->getProgramBinary());
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000952 }
953
954 if (oldProgram)
955 {
956 oldProgram->release();
957 }
958 }
959}
960
daniel@transgaming.com95d29422012-07-24 18:36:10 +0000961void Context::linkProgram(GLuint program)
962{
963 Program *programObject = mResourceManager->getProgram(program);
964
daniel@transgaming.com12394cf2012-07-24 18:37:59 +0000965 bool linked = programObject->link();
966
967 // if the current program was relinked successfully we
968 // need to install the new executables
969 if (linked && program == mState.currentProgram)
970 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000971 mCurrentProgramBinary.set(programObject->getProgramBinary());
daniel@transgaming.com12394cf2012-07-24 18:37:59 +0000972 mDxUniformsDirty = true;
973 }
daniel@transgaming.com95d29422012-07-24 18:36:10 +0000974}
975
976void Context::setProgramBinary(GLuint program, const void *binary, GLint length)
977{
978 Program *programObject = mResourceManager->getProgram(program);
979
daniel@transgaming.com12394cf2012-07-24 18:37:59 +0000980 bool loaded = programObject->setProgramBinary(binary, length);
981
982 // if the current program was reloaded successfully we
983 // need to install the new executables
984 if (loaded && program == mState.currentProgram)
985 {
daniel@transgaming.com989c1c82012-07-24 18:40:38 +0000986 mCurrentProgramBinary.set(programObject->getProgramBinary());
daniel@transgaming.com12394cf2012-07-24 18:37:59 +0000987 mDxUniformsDirty = true;
988 }
989
daniel@transgaming.com95d29422012-07-24 18:36:10 +0000990}
991
apatrick@chromium.org144f2802012-07-12 01:42:34 +0000992void Context::beginQuery(GLenum target, GLuint query)
993{
994 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
995 // of zero, if the active query object name for <target> is non-zero (for the
996 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
997 // the active query for either target is non-zero), if <id> is the name of an
998 // existing query object whose type does not match <target>, or if <id> is the
999 // active query object name for any query type, the error INVALID_OPERATION is
1000 // generated.
1001
1002 // Ensure no other queries are active
1003 // NOTE: If other queries than occlusion are supported, we will need to check
1004 // separately that:
1005 // a) The query ID passed is not the current active query for any target/type
1006 // b) There are no active queries for the requested target (and in the case
1007 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
1008 // no query may be active for either if glBeginQuery targets either.
1009 for (int i = 0; i < QUERY_TYPE_COUNT; i++)
1010 {
1011 if (mState.activeQuery[i].get() != NULL)
1012 {
1013 return error(GL_INVALID_OPERATION);
1014 }
1015 }
1016
1017 QueryType qType;
1018 switch (target)
1019 {
1020 case GL_ANY_SAMPLES_PASSED_EXT:
1021 qType = QUERY_ANY_SAMPLES_PASSED;
1022 break;
1023 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1024 qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
1025 break;
1026 default:
1027 ASSERT(false);
1028 return;
1029 }
1030
1031 Query *queryObject = getQuery(query, true, target);
1032
1033 // check that name was obtained with glGenQueries
1034 if (!queryObject)
1035 {
1036 return error(GL_INVALID_OPERATION);
1037 }
1038
1039 // check for type mismatch
1040 if (queryObject->getType() != target)
1041 {
1042 return error(GL_INVALID_OPERATION);
1043 }
1044
1045 // set query as active for specified target
1046 mState.activeQuery[qType].set(queryObject);
1047
1048 // begin query
1049 queryObject->begin();
1050}
1051
1052void Context::endQuery(GLenum target)
1053{
1054 QueryType qType;
1055
1056 switch (target)
1057 {
1058 case GL_ANY_SAMPLES_PASSED_EXT:
1059 qType = QUERY_ANY_SAMPLES_PASSED;
1060 break;
1061 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
1062 qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
1063 break;
1064 default:
1065 ASSERT(false);
1066 return;
1067 }
1068
1069 Query *queryObject = mState.activeQuery[qType].get();
1070
1071 if (queryObject == NULL)
1072 {
1073 return error(GL_INVALID_OPERATION);
1074 }
1075
1076 queryObject->end();
1077
1078 mState.activeQuery[qType].set(NULL);
1079}
1080
1081void Context::setFramebufferZero(Framebuffer *buffer)
1082{
1083 delete mFramebufferMap[0];
1084 mFramebufferMap[0] = buffer;
1085 if (mState.drawFramebuffer == 0)
1086 {
1087 mBoundDrawFramebuffer = buffer;
1088 }
1089}
1090
daniel@transgaming.com70062c92012-11-28 19:32:30 +00001091void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001092{
daniel@transgaming.com70062c92012-11-28 19:32:30 +00001093 RenderbufferStorage *renderbuffer = NULL;
1094 switch (internalformat)
1095 {
1096 case GL_DEPTH_COMPONENT16:
1097 renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples);
1098 break;
1099 case GL_RGBA4:
1100 case GL_RGB5_A1:
1101 case GL_RGB565:
1102 case GL_RGB8_OES:
1103 case GL_RGBA8_OES:
1104 renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples);
1105 break;
1106 case GL_STENCIL_INDEX8:
1107 renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples);
1108 break;
1109 case GL_DEPTH24_STENCIL8_OES:
1110 renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples);
1111 break;
1112 default:
1113 UNREACHABLE(); return;
1114 }
1115
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001116 Renderbuffer *renderbufferObject = mState.renderbuffer.get();
1117 renderbufferObject->setStorage(renderbuffer);
1118}
1119
1120Framebuffer *Context::getFramebuffer(unsigned int handle)
1121{
1122 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
1123
1124 if (framebuffer == mFramebufferMap.end())
1125 {
1126 return NULL;
1127 }
1128 else
1129 {
1130 return framebuffer->second;
1131 }
1132}
1133
1134Fence *Context::getFence(unsigned int handle)
1135{
1136 FenceMap::iterator fence = mFenceMap.find(handle);
1137
1138 if (fence == mFenceMap.end())
1139 {
1140 return NULL;
1141 }
1142 else
1143 {
1144 return fence->second;
1145 }
1146}
1147
1148Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
1149{
1150 QueryMap::iterator query = mQueryMap.find(handle);
1151
1152 if (query == mQueryMap.end())
1153 {
1154 return NULL;
1155 }
1156 else
1157 {
1158 if (!query->second && create)
1159 {
daniel@transgaming.comef21ab22012-10-31 17:52:47 +00001160 query->second = new Query(mRenderer, handle, type);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001161 query->second->addRef();
1162 }
1163 return query->second;
1164 }
1165}
1166
1167Buffer *Context::getArrayBuffer()
1168{
1169 return mState.arrayBuffer.get();
1170}
1171
1172Buffer *Context::getElementArrayBuffer()
1173{
1174 return mState.elementArrayBuffer.get();
1175}
1176
daniel@transgaming.com62a28462012-07-24 18:33:59 +00001177ProgramBinary *Context::getCurrentProgramBinary()
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001178{
daniel@transgaming.com989c1c82012-07-24 18:40:38 +00001179 return mCurrentProgramBinary.get();
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001180}
1181
1182Texture2D *Context::getTexture2D()
1183{
1184 return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
1185}
1186
1187TextureCubeMap *Context::getTextureCubeMap()
1188{
1189 return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
1190}
1191
1192Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)
1193{
1194 GLuint texid = mState.samplerTexture[type][sampler].id();
1195
1196 if (texid == 0) // Special case: 0 refers to different initial textures based on the target
1197 {
1198 switch (type)
1199 {
1200 default: UNREACHABLE();
1201 case TEXTURE_2D: return mTexture2DZero.get();
1202 case TEXTURE_CUBE: return mTextureCubeMapZero.get();
1203 }
1204 }
1205
1206 return mState.samplerTexture[type][sampler].get();
1207}
1208
1209bool Context::getBooleanv(GLenum pname, GLboolean *params)
1210{
1211 switch (pname)
1212 {
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001213 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
1214 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
1215 case GL_DEPTH_WRITEMASK: *params = mState.depthStencil.depthMask; break;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001216 case GL_COLOR_WRITEMASK:
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001217 params[0] = mState.blend.colorMaskRed;
1218 params[1] = mState.blend.colorMaskGreen;
1219 params[2] = mState.blend.colorMaskBlue;
1220 params[3] = mState.blend.colorMaskAlpha;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001221 break;
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001222 case GL_CULL_FACE: *params = mState.rasterizer.cullFace; break;
1223 case GL_POLYGON_OFFSET_FILL: *params = mState.rasterizer.polygonOffsetFill; break;
1224 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.blend.sampleAlphaToCoverage; break;
1225 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break;
1226 case GL_SCISSOR_TEST: *params = mState.rasterizer.scissorTest; break;
1227 case GL_STENCIL_TEST: *params = mState.depthStencil.stencilTest; break;
1228 case GL_DEPTH_TEST: *params = mState.depthStencil.depthTest; break;
1229 case GL_BLEND: *params = mState.blend.blend; break;
1230 case GL_DITHER: *params = mState.blend.dither; break;
1231 case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001232 default:
1233 return false;
1234 }
1235
1236 return true;
1237}
1238
1239bool Context::getFloatv(GLenum pname, GLfloat *params)
1240{
1241 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
1242 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1243 // GetIntegerv as its native query function. As it would require conversion in any
1244 // case, this should make no difference to the calling application.
1245 switch (pname)
1246 {
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001247 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
1248 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
1249 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
1250 case GL_POLYGON_OFFSET_FACTOR: *params = mState.rasterizer.polygonOffsetFactor; break;
1251 case GL_POLYGON_OFFSET_UNITS: *params = mState.rasterizer.polygonOffsetUnits; break;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001252 case GL_ALIASED_LINE_WIDTH_RANGE:
1253 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
1254 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
1255 break;
1256 case GL_ALIASED_POINT_SIZE_RANGE:
1257 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
1258 params[1] = getMaximumPointSize();
1259 break;
1260 case GL_DEPTH_RANGE:
1261 params[0] = mState.zNear;
1262 params[1] = mState.zFar;
1263 break;
1264 case GL_COLOR_CLEAR_VALUE:
1265 params[0] = mState.colorClearValue.red;
1266 params[1] = mState.colorClearValue.green;
1267 params[2] = mState.colorClearValue.blue;
1268 params[3] = mState.colorClearValue.alpha;
1269 break;
1270 case GL_BLEND_COLOR:
1271 params[0] = mState.blendColor.red;
1272 params[1] = mState.blendColor.green;
1273 params[2] = mState.blendColor.blue;
1274 params[3] = mState.blendColor.alpha;
1275 break;
daniel@transgaming.com07ab8412012-07-12 15:17:09 +00001276 case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
1277 if (!supportsTextureFilterAnisotropy())
1278 {
1279 return false;
1280 }
1281 *params = mMaxTextureAnisotropy;
1282 break;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001283 default:
1284 return false;
1285 }
1286
1287 return true;
1288}
1289
1290bool Context::getIntegerv(GLenum pname, GLint *params)
1291{
1292 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
1293 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
1294 // GetIntegerv as its native query function. As it would require conversion in any
1295 // case, this should make no difference to the calling application. You may find it in
1296 // Context::getFloatv.
1297 switch (pname)
1298 {
1299 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
1300 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = gl::MAX_VERTEX_UNIFORM_VECTORS; break;
1301 case GL_MAX_VARYING_VECTORS: *params = getMaximumVaryingVectors(); break;
1302 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = getMaximumCombinedTextureImageUnits(); break;
1303 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = getMaximumVertexTextureImageUnits(); break;
1304 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
1305 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = getMaximumFragmentUniformVectors(); break;
1306 case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break;
1307 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
1308 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
1309 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break;
1310 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break;
1311 //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
1312 case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break;
1313 case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break;
1314 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break;
1315 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
1316 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
1317 case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mState.packReverseRowOrder; break;
1318 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
1319 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
1320 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;
1321 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001322 case GL_STENCIL_FUNC: *params = mState.depthStencil.stencilFunc; break;
daniel@transgaming.com08c331d2012-11-28 19:38:39 +00001323 case GL_STENCIL_REF: *params = mState.stencilRef; break;
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001324 case GL_STENCIL_VALUE_MASK: *params = mState.depthStencil.stencilMask; break;
1325 case GL_STENCIL_BACK_FUNC: *params = mState.depthStencil.stencilBackFunc; break;
daniel@transgaming.com08c331d2012-11-28 19:38:39 +00001326 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001327 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.depthStencil.stencilBackMask; break;
1328 case GL_STENCIL_FAIL: *params = mState.depthStencil.stencilFail; break;
1329 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilPassDepthFail; break;
1330 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilPassDepthPass; break;
1331 case GL_STENCIL_BACK_FAIL: *params = mState.depthStencil.stencilBackFail; break;
1332 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilBackPassDepthFail; break;
1333 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilBackPassDepthPass; break;
1334 case GL_DEPTH_FUNC: *params = mState.depthStencil.depthFunc; break;
1335 case GL_BLEND_SRC_RGB: *params = mState.blend.sourceBlendRGB; break;
1336 case GL_BLEND_SRC_ALPHA: *params = mState.blend.sourceBlendAlpha; break;
1337 case GL_BLEND_DST_RGB: *params = mState.blend.destBlendRGB; break;
1338 case GL_BLEND_DST_ALPHA: *params = mState.blend.destBlendAlpha; break;
1339 case GL_BLEND_EQUATION_RGB: *params = mState.blend.blendEquationRGB; break;
1340 case GL_BLEND_EQUATION_ALPHA: *params = mState.blend.blendEquationAlpha; break;
1341 case GL_STENCIL_WRITEMASK: *params = mState.depthStencil.stencilWritemask; break;
1342 case GL_STENCIL_BACK_WRITEMASK: *params = mState.depthStencil.stencilBackWritemask; break;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001343 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
1344 case GL_SUBPIXEL_BITS: *params = 4; break;
1345 case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break;
1346 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break;
1347 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1348 params[0] = mNumCompressedTextureFormats;
1349 break;
1350 case GL_MAX_SAMPLES_ANGLE:
1351 {
1352 GLsizei maxSamples = getMaxSupportedSamples();
1353 if (maxSamples != 0)
1354 {
1355 *params = maxSamples;
1356 }
1357 else
1358 {
1359 return false;
1360 }
1361
1362 break;
1363 }
1364 case GL_SAMPLE_BUFFERS:
1365 case GL_SAMPLES:
1366 {
1367 gl::Framebuffer *framebuffer = getDrawFramebuffer();
1368 if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
1369 {
1370 switch (pname)
1371 {
1372 case GL_SAMPLE_BUFFERS:
1373 if (framebuffer->getSamples() != 0)
1374 {
1375 *params = 1;
1376 }
1377 else
1378 {
1379 *params = 0;
1380 }
1381 break;
1382 case GL_SAMPLES:
1383 *params = framebuffer->getSamples();
1384 break;
1385 }
1386 }
1387 else
1388 {
1389 *params = 0;
1390 }
1391 }
1392 break;
daniel@transgaming.com42944b02012-09-27 17:45:57 +00001393 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1394 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1395 {
1396 GLenum format, type;
1397 if (getCurrentReadFormatType(&format, &type))
1398 {
1399 if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT)
1400 *params = format;
1401 else
1402 *params = type;
1403 }
1404 }
1405 break;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001406 case GL_MAX_VIEWPORT_DIMS:
1407 {
1408 int maxDimension = std::max(getMaximumRenderbufferDimension(), getMaximumTextureDimension());
1409 params[0] = maxDimension;
1410 params[1] = maxDimension;
1411 }
1412 break;
1413 case GL_COMPRESSED_TEXTURE_FORMATS:
1414 {
1415 if (supportsDXT1Textures())
1416 {
1417 *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
1418 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
1419 }
1420 if (supportsDXT3Textures())
1421 {
1422 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
1423 }
1424 if (supportsDXT5Textures())
1425 {
1426 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
1427 }
1428 }
1429 break;
1430 case GL_VIEWPORT:
daniel@transgaming.com3884e2c2012-11-28 19:41:00 +00001431 params[0] = mState.viewport.x;
1432 params[1] = mState.viewport.y;
1433 params[2] = mState.viewport.width;
1434 params[3] = mState.viewport.height;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001435 break;
1436 case GL_SCISSOR_BOX:
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001437 params[0] = mState.scissor.x;
1438 params[1] = mState.scissor.y;
1439 params[2] = mState.scissor.width;
1440 params[3] = mState.scissor.height;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001441 break;
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001442 case GL_CULL_FACE_MODE: *params = mState.rasterizer.cullMode; break;
1443 case GL_FRONT_FACE: *params = mState.rasterizer.frontFace; break;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001444 case GL_RED_BITS:
1445 case GL_GREEN_BITS:
1446 case GL_BLUE_BITS:
1447 case GL_ALPHA_BITS:
1448 {
1449 gl::Framebuffer *framebuffer = getDrawFramebuffer();
1450 gl::Renderbuffer *colorbuffer = framebuffer->getColorbuffer();
1451
1452 if (colorbuffer)
1453 {
1454 switch (pname)
1455 {
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001456 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
1457 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
1458 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
1459 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001460 }
1461 }
1462 else
1463 {
1464 *params = 0;
1465 }
1466 }
1467 break;
1468 case GL_DEPTH_BITS:
1469 {
1470 gl::Framebuffer *framebuffer = getDrawFramebuffer();
1471 gl::Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
1472
1473 if (depthbuffer)
1474 {
1475 *params = depthbuffer->getDepthSize();
1476 }
1477 else
1478 {
1479 *params = 0;
1480 }
1481 }
1482 break;
1483 case GL_STENCIL_BITS:
1484 {
1485 gl::Framebuffer *framebuffer = getDrawFramebuffer();
1486 gl::Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
1487
1488 if (stencilbuffer)
1489 {
1490 *params = stencilbuffer->getStencilSize();
1491 }
1492 else
1493 {
1494 *params = 0;
1495 }
1496 }
1497 break;
1498 case GL_TEXTURE_BINDING_2D:
1499 {
daniel@transgaming.come3e826d2012-11-28 19:42:35 +00001500 if (mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001501 {
1502 error(GL_INVALID_OPERATION);
1503 return false;
1504 }
1505
1506 *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();
1507 }
1508 break;
1509 case GL_TEXTURE_BINDING_CUBE_MAP:
1510 {
daniel@transgaming.come3e826d2012-11-28 19:42:35 +00001511 if (mState.activeSampler > getMaximumCombinedTextureImageUnits() - 1)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001512 {
1513 error(GL_INVALID_OPERATION);
1514 return false;
1515 }
1516
1517 *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
1518 }
1519 break;
1520 case GL_RESET_NOTIFICATION_STRATEGY_EXT:
1521 *params = mResetStrategy;
1522 break;
1523 case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
1524 *params = 1;
1525 break;
1526 case GL_PROGRAM_BINARY_FORMATS_OES:
1527 *params = GL_PROGRAM_BINARY_ANGLE;
1528 break;
1529 default:
1530 return false;
1531 }
1532
1533 return true;
1534}
1535
1536bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
1537{
1538 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
1539 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
1540 // to the fact that it is stored internally as a float, and so would require conversion
1541 // if returned from Context::getIntegerv. Since this conversion is already implemented
1542 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
1543 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
1544 // application.
1545 switch (pname)
1546 {
1547 case GL_COMPRESSED_TEXTURE_FORMATS:
1548 {
1549 *type = GL_INT;
1550 *numParams = mNumCompressedTextureFormats;
1551 }
1552 break;
1553 case GL_SHADER_BINARY_FORMATS:
1554 {
1555 *type = GL_INT;
1556 *numParams = 0;
1557 }
1558 break;
1559 case GL_MAX_VERTEX_ATTRIBS:
1560 case GL_MAX_VERTEX_UNIFORM_VECTORS:
1561 case GL_MAX_VARYING_VECTORS:
1562 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
1563 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
1564 case GL_MAX_TEXTURE_IMAGE_UNITS:
1565 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
1566 case GL_MAX_RENDERBUFFER_SIZE:
1567 case GL_NUM_SHADER_BINARY_FORMATS:
1568 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
1569 case GL_ARRAY_BUFFER_BINDING:
1570 case GL_FRAMEBUFFER_BINDING:
1571 case GL_RENDERBUFFER_BINDING:
1572 case GL_CURRENT_PROGRAM:
1573 case GL_PACK_ALIGNMENT:
1574 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
1575 case GL_UNPACK_ALIGNMENT:
1576 case GL_GENERATE_MIPMAP_HINT:
1577 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
1578 case GL_RED_BITS:
1579 case GL_GREEN_BITS:
1580 case GL_BLUE_BITS:
1581 case GL_ALPHA_BITS:
1582 case GL_DEPTH_BITS:
1583 case GL_STENCIL_BITS:
1584 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
1585 case GL_CULL_FACE_MODE:
1586 case GL_FRONT_FACE:
1587 case GL_ACTIVE_TEXTURE:
1588 case GL_STENCIL_FUNC:
1589 case GL_STENCIL_VALUE_MASK:
1590 case GL_STENCIL_REF:
1591 case GL_STENCIL_FAIL:
1592 case GL_STENCIL_PASS_DEPTH_FAIL:
1593 case GL_STENCIL_PASS_DEPTH_PASS:
1594 case GL_STENCIL_BACK_FUNC:
1595 case GL_STENCIL_BACK_VALUE_MASK:
1596 case GL_STENCIL_BACK_REF:
1597 case GL_STENCIL_BACK_FAIL:
1598 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
1599 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
1600 case GL_DEPTH_FUNC:
1601 case GL_BLEND_SRC_RGB:
1602 case GL_BLEND_SRC_ALPHA:
1603 case GL_BLEND_DST_RGB:
1604 case GL_BLEND_DST_ALPHA:
1605 case GL_BLEND_EQUATION_RGB:
1606 case GL_BLEND_EQUATION_ALPHA:
1607 case GL_STENCIL_WRITEMASK:
1608 case GL_STENCIL_BACK_WRITEMASK:
1609 case GL_STENCIL_CLEAR_VALUE:
1610 case GL_SUBPIXEL_BITS:
1611 case GL_MAX_TEXTURE_SIZE:
1612 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
1613 case GL_SAMPLE_BUFFERS:
1614 case GL_SAMPLES:
1615 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
1616 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
1617 case GL_TEXTURE_BINDING_2D:
1618 case GL_TEXTURE_BINDING_CUBE_MAP:
1619 case GL_RESET_NOTIFICATION_STRATEGY_EXT:
1620 case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
1621 case GL_PROGRAM_BINARY_FORMATS_OES:
1622 {
1623 *type = GL_INT;
1624 *numParams = 1;
1625 }
1626 break;
1627 case GL_MAX_SAMPLES_ANGLE:
1628 {
1629 if (getMaxSupportedSamples() != 0)
1630 {
1631 *type = GL_INT;
1632 *numParams = 1;
1633 }
1634 else
1635 {
1636 return false;
1637 }
1638 }
1639 break;
1640 case GL_MAX_VIEWPORT_DIMS:
1641 {
1642 *type = GL_INT;
1643 *numParams = 2;
1644 }
1645 break;
1646 case GL_VIEWPORT:
1647 case GL_SCISSOR_BOX:
1648 {
1649 *type = GL_INT;
1650 *numParams = 4;
1651 }
1652 break;
1653 case GL_SHADER_COMPILER:
1654 case GL_SAMPLE_COVERAGE_INVERT:
1655 case GL_DEPTH_WRITEMASK:
1656 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
1657 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
1658 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
1659 case GL_SAMPLE_COVERAGE:
1660 case GL_SCISSOR_TEST:
1661 case GL_STENCIL_TEST:
1662 case GL_DEPTH_TEST:
1663 case GL_BLEND:
1664 case GL_DITHER:
1665 case GL_CONTEXT_ROBUST_ACCESS_EXT:
1666 {
1667 *type = GL_BOOL;
1668 *numParams = 1;
1669 }
1670 break;
1671 case GL_COLOR_WRITEMASK:
1672 {
1673 *type = GL_BOOL;
1674 *numParams = 4;
1675 }
1676 break;
1677 case GL_POLYGON_OFFSET_FACTOR:
1678 case GL_POLYGON_OFFSET_UNITS:
1679 case GL_SAMPLE_COVERAGE_VALUE:
1680 case GL_DEPTH_CLEAR_VALUE:
1681 case GL_LINE_WIDTH:
1682 {
1683 *type = GL_FLOAT;
1684 *numParams = 1;
1685 }
1686 break;
1687 case GL_ALIASED_LINE_WIDTH_RANGE:
1688 case GL_ALIASED_POINT_SIZE_RANGE:
1689 case GL_DEPTH_RANGE:
1690 {
1691 *type = GL_FLOAT;
1692 *numParams = 2;
1693 }
1694 break;
1695 case GL_COLOR_CLEAR_VALUE:
1696 case GL_BLEND_COLOR:
1697 {
1698 *type = GL_FLOAT;
1699 *numParams = 4;
1700 }
1701 break;
daniel@transgaming.com07ab8412012-07-12 15:17:09 +00001702 case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
1703 if (!supportsTextureFilterAnisotropy())
1704 {
1705 return false;
1706 }
1707 *type = GL_FLOAT;
1708 *numParams = 1;
1709 break;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001710 default:
1711 return false;
1712 }
1713
1714 return true;
1715}
1716
1717// Applies the render target surface, depth stencil surface, viewport rectangle and
1718// scissor rectangle to the Direct3D 9 device
1719bool Context::applyRenderTarget(bool ignoreViewport)
1720{
1721 Framebuffer *framebufferObject = getDrawFramebuffer();
1722
1723 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1724 {
1725 return error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
1726 }
1727
daniel@transgaming.com8a8b24c2012-11-28 19:36:26 +00001728 mRenderer->applyRenderTarget(framebufferObject);
1729
daniel@transgaming.come06bda92012-11-28 19:42:18 +00001730 // storing the mRenderTargetDesc in Context will be removed once refactoring
1731 // of clear is complete
1732 // D3D9_REPLACE start
1733 gl::Renderbuffer *renderbufferObject = NULL;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001734 if (framebufferObject->getColorbufferType() != GL_NONE)
1735 {
1736 renderbufferObject = framebufferObject->getColorbuffer();
1737 }
1738 else
1739 {
1740 renderbufferObject = framebufferObject->getNullColorbuffer();
1741 }
1742 if (!renderbufferObject)
1743 {
1744 ERR("unable to locate renderbuffer for FBO.");
1745 return false;
1746 }
1747
daniel@transgaming.come06bda92012-11-28 19:42:18 +00001748 mRenderTargetDesc.width = renderbufferObject->getWidth();
1749 mRenderTargetDesc.height = renderbufferObject->getHeight();
1750 mRenderTargetDesc.format = renderbufferObject->getActualFormat();
1751 // D3D9_REPLACE end
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001752
daniel@transgaming.com3ca082c2012-11-28 19:41:07 +00001753 Rectangle viewport = mState.viewport;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001754 float zNear = clamp01(mState.zNear);
1755 float zFar = clamp01(mState.zFar);
1756
1757 if (ignoreViewport)
1758 {
daniel@transgaming.com3ca082c2012-11-28 19:41:07 +00001759 viewport.x = 0;
1760 viewport.y = 0;
1761 viewport.width = mRenderTargetDesc.width;
1762 viewport.height = mRenderTargetDesc.height;
1763 zNear = 0.0f;
1764 zFar = 1.0f;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001765 }
1766
daniel@transgaming.com3ca082c2012-11-28 19:41:07 +00001767 ProgramBinary *programBinary = mState.currentProgram ? getCurrentProgramBinary() : NULL;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001768
daniel@transgaming.com3ca082c2012-11-28 19:41:07 +00001769 if (!mRenderer->setViewport(viewport, zNear, zFar, mRenderTargetDesc.width, mRenderTargetDesc.height,
1770 programBinary, mDxUniformsDirty))
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001771 {
daniel@transgaming.com3ca082c2012-11-28 19:41:07 +00001772 return false;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001773 }
daniel@transgaming.com3ca082c2012-11-28 19:41:07 +00001774 mDxUniformsDirty = false;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001775
daniel@transgaming.com39cee2e2012-11-28 19:39:14 +00001776 mRenderer->setScissorRectangle(mState.scissor, static_cast<int>(mRenderTargetDesc.width),
1777 static_cast<int>(mRenderTargetDesc.height));
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001778
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001779 return true;
1780}
1781
1782// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
1783void Context::applyState(GLenum drawMode)
1784{
daniel@transgaming.com62a28462012-07-24 18:33:59 +00001785 ProgramBinary *programBinary = getCurrentProgramBinary();
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001786
1787 Framebuffer *framebufferObject = getDrawFramebuffer();
1788
1789 GLint frontCCW = programBinary->getDxFrontCCWLocation();
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001790 GLint ccw = (mState.rasterizer.frontFace == GL_CCW);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001791 programBinary->setUniform1iv(frontCCW, 1, &ccw);
1792
1793 GLint pointsOrLines = programBinary->getDxPointsOrLinesLocation();
1794 GLint alwaysFront = !isTriangleMode(drawMode);
1795 programBinary->setUniform1iv(pointsOrLines, 1, &alwaysFront);
1796
daniel@transgaming.comb9bb2792012-11-28 19:36:49 +00001797 const gl::Renderbuffer *depthbuffer = framebufferObject->getDepthbuffer();
daniel@transgaming.com2e258642012-11-28 19:36:18 +00001798 unsigned int depthSize = depthbuffer ? depthbuffer->getDepthSize() : 0;
1799
1800 mRenderer->setRasterizerState(mState.rasterizer, depthSize);
1801
1802 unsigned int mask = 0;
1803 if (mState.sampleCoverage)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001804 {
daniel@transgaming.com2e258642012-11-28 19:36:18 +00001805 if (mState.sampleCoverageValue != 0)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001806 {
daniel@transgaming.com2e258642012-11-28 19:36:18 +00001807 float threshold = 0.5f;
1808
1809 for (int i = 0; i < framebufferObject->getSamples(); ++i)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001810 {
daniel@transgaming.com2e258642012-11-28 19:36:18 +00001811 mask <<= 1;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001812
daniel@transgaming.com2e258642012-11-28 19:36:18 +00001813 if ((i + 1) * mState.sampleCoverageValue >= threshold)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001814 {
daniel@transgaming.com2e258642012-11-28 19:36:18 +00001815 threshold += 1.0f;
1816 mask |= 1;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001817 }
1818 }
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001819 }
daniel@transgaming.com2e258642012-11-28 19:36:18 +00001820
1821 if (mState.sampleCoverageInvert)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001822 {
daniel@transgaming.com2e258642012-11-28 19:36:18 +00001823 mask = ~mask;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001824 }
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001825 }
daniel@transgaming.com2e258642012-11-28 19:36:18 +00001826 else
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001827 {
daniel@transgaming.com2e258642012-11-28 19:36:18 +00001828 mask = 0xFFFFFFFF;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001829 }
daniel@transgaming.com2e258642012-11-28 19:36:18 +00001830 mRenderer->setBlendState(mState.blend, mState.blendColor, mask);
1831
1832 unsigned int stencilSize = framebufferObject->hasStencil() ? framebufferObject->getStencilbuffer()->getStencilSize() : 0;
daniel@transgaming.com08c331d2012-11-28 19:38:39 +00001833 mRenderer->setDepthStencilState(mState.depthStencil, mState.stencilRef, mState.stencilBackRef,
1834 mState.rasterizer.frontFace == GL_CCW, stencilSize);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001835}
1836
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001837// Applies the shaders and shader constants to the Direct3D 9 device
1838void Context::applyShaders()
1839{
daniel@transgaming.com62a28462012-07-24 18:33:59 +00001840 ProgramBinary *programBinary = getCurrentProgramBinary();
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001841
daniel@transgaming.come6af4f92012-07-24 18:31:31 +00001842 if (programBinary->getSerial() != mAppliedProgramBinarySerial)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001843 {
daniel@transgaming.com5fbf1772012-11-28 20:54:43 +00001844 mRenderer->applyShaders(programBinary);
daniel@transgaming.come6af4f92012-07-24 18:31:31 +00001845 mAppliedProgramBinarySerial = programBinary->getSerial();
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001846 }
daniel@transgaming.com5fbf1772012-11-28 20:54:43 +00001847
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001848 programBinary->applyUniforms();
1849}
1850
1851// Applies the textures and sampler states to the Direct3D 9 device
1852void Context::applyTextures()
1853{
1854 applyTextures(SAMPLER_PIXEL);
1855
1856 if (mSupportsVertexTexture)
1857 {
1858 applyTextures(SAMPLER_VERTEX);
1859 }
1860}
1861
1862// For each Direct3D 9 sampler of either the pixel or vertex stage,
1863// looks up the corresponding OpenGL texture image unit and texture type,
1864// and sets the texture and its addressing/filtering state (or NULL when inactive).
1865void Context::applyTextures(SamplerType type)
1866{
daniel@transgaming.com62a28462012-07-24 18:33:59 +00001867 ProgramBinary *programBinary = getCurrentProgramBinary();
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001868
1869 int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF; // Range of Direct3D 9 samplers of given sampler type
1870 unsigned int *appliedTextureSerial = (type == SAMPLER_PIXEL) ? mAppliedTextureSerialPS : mAppliedTextureSerialVS;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001871 int samplerRange = programBinary->getUsedSamplerRange(type);
1872
1873 for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
1874 {
1875 int textureUnit = programBinary->getSamplerMapping(type, samplerIndex); // OpenGL texture image unit index
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001876
1877 if (textureUnit != -1)
1878 {
1879 TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex);
1880
1881 Texture *texture = getSamplerTexture(textureUnit, textureType);
1882 unsigned int texSerial = texture->getTextureSerial();
1883
1884 if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyParameters() || texture->hasDirtyImages())
1885 {
daniel@transgaming.coma734f272012-10-31 18:07:48 +00001886 if (texture->isSamplerComplete())
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001887 {
1888 if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyParameters())
1889 {
daniel@transgaming.comebf139f2012-10-31 18:07:32 +00001890 SamplerState samplerState;
1891 texture->getSamplerState(&samplerState);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001892
daniel@transgaming.comba0570e2012-10-31 18:07:39 +00001893 mRenderer->setSamplerState(type, samplerIndex, samplerState);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001894 }
1895
1896 if (appliedTextureSerial[samplerIndex] != texSerial || texture->hasDirtyImages())
1897 {
daniel@transgaming.coma734f272012-10-31 18:07:48 +00001898 mRenderer->setTexture(type, samplerIndex, texture);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001899 }
1900 }
1901 else
1902 {
daniel@transgaming.coma734f272012-10-31 18:07:48 +00001903 mRenderer->setTexture(type, samplerIndex, getIncompleteTexture(textureType));
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001904 }
1905
1906 appliedTextureSerial[samplerIndex] = texSerial;
1907 texture->resetDirty();
1908 }
1909 }
1910 else
1911 {
1912 if (appliedTextureSerial[samplerIndex] != 0)
1913 {
daniel@transgaming.coma734f272012-10-31 18:07:48 +00001914 mRenderer->setTexture(type, samplerIndex, NULL);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001915 appliedTextureSerial[samplerIndex] = 0;
1916 }
1917 }
1918 }
1919
1920 for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
1921 {
1922 if (appliedTextureSerial[samplerIndex] != 0)
1923 {
daniel@transgaming.coma734f272012-10-31 18:07:48 +00001924 mRenderer->setTexture(type, samplerIndex, NULL);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001925 appliedTextureSerial[samplerIndex] = 0;
1926 }
1927 }
1928}
1929
1930void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
1931 GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
1932{
1933 Framebuffer *framebuffer = getReadFramebuffer();
1934
1935 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
1936 {
1937 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1938 }
1939
1940 if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
1941 {
1942 return error(GL_INVALID_OPERATION);
1943 }
1944
daniel@transgaming.com6c872172012-11-28 19:39:33 +00001945 GLsizei outputPitch = ComputePitch(width, ConvertSizedInternalFormat(format, type), getPackAlignment());
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001946 // sized query sanity check
1947 if (bufSize)
1948 {
1949 int requiredSize = outputPitch * height;
1950 if (requiredSize > *bufSize)
1951 {
1952 return error(GL_INVALID_OPERATION);
1953 }
1954 }
1955
daniel@transgaming.com6c872172012-11-28 19:39:33 +00001956 mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, getPackReverseRowOrder(), getPackAlignment(), pixels);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001957}
1958
1959void Context::clear(GLbitfield mask)
1960{
1961 Framebuffer *framebufferObject = getDrawFramebuffer();
1962
1963 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
1964 {
1965 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
1966 }
1967
1968 DWORD flags = 0;
daniel@transgaming.com084a2572012-11-28 20:55:17 +00001969 GLbitfield finalMask = 0;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001970
1971 if (mask & GL_COLOR_BUFFER_BIT)
1972 {
1973 mask &= ~GL_COLOR_BUFFER_BIT;
1974
1975 if (framebufferObject->getColorbufferType() != GL_NONE)
1976 {
daniel@transgaming.com084a2572012-11-28 20:55:17 +00001977 finalMask |= GL_COLOR_BUFFER_BIT;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001978 }
1979 }
1980
1981 if (mask & GL_DEPTH_BUFFER_BIT)
1982 {
1983 mask &= ~GL_DEPTH_BUFFER_BIT;
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00001984 if (mState.depthStencil.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001985 {
daniel@transgaming.com084a2572012-11-28 20:55:17 +00001986 finalMask |= GL_DEPTH_BUFFER_BIT;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001987 }
1988 }
1989
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001990 if (mask & GL_STENCIL_BUFFER_BIT)
1991 {
1992 mask &= ~GL_STENCIL_BUFFER_BIT;
1993 if (framebufferObject->getStencilbufferType() != GL_NONE)
1994 {
daniel@transgaming.comd62d7142012-11-28 19:40:28 +00001995 rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
apatrick@chromium.org144f2802012-07-12 01:42:34 +00001996 if (!depthStencil)
1997 {
1998 ERR("Depth stencil pointer unexpectedly null.");
1999 return;
2000 }
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002001
daniel@transgaming.com2c1d0ab2012-11-28 20:55:42 +00002002 if (GetStencilSize(depthStencil->getActualFormat()) > 0)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002003 {
daniel@transgaming.com084a2572012-11-28 20:55:17 +00002004 finalMask |= GL_STENCIL_BUFFER_BIT;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002005 }
2006 }
2007 }
2008
2009 if (mask != 0)
2010 {
2011 return error(GL_INVALID_VALUE);
2012 }
2013
2014 if (!applyRenderTarget(true)) // Clips the clear to the scissor rectangle but not the viewport
2015 {
2016 return;
2017 }
2018
daniel@transgaming.com084a2572012-11-28 20:55:17 +00002019 ClearParameters clearParams;
2020 clearParams.mask = finalMask;
2021 clearParams.colorClearValue = mState.colorClearValue;
2022 clearParams.colorMaskRed = mState.blend.colorMaskRed;
2023 clearParams.colorMaskGreen = mState.blend.colorMaskGreen;
2024 clearParams.colorMaskBlue = mState.blend.colorMaskBlue;
2025 clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha;
2026 clearParams.depthClearValue = mState.depthClearValue;
2027 clearParams.stencilClearValue = mState.stencilClearValue;
2028 clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask;
daniel@transgaming.comd084c622012-11-28 19:36:05 +00002029
daniel@transgaming.com084a2572012-11-28 20:55:17 +00002030 mRenderer->clear(clearParams, framebufferObject);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002031}
2032
2033void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
2034{
2035 if (!mState.currentProgram)
2036 {
2037 return error(GL_INVALID_OPERATION);
2038 }
2039
daniel@transgaming.com91207b72012-11-28 20:56:43 +00002040 if (!mRenderer->applyPrimitiveType(mode, count))
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002041 {
2042 return;
2043 }
2044
2045 if (!applyRenderTarget(false))
2046 {
2047 return;
2048 }
2049
2050 applyState(mode);
2051
daniel@transgaming.com92025f52012-11-28 20:52:54 +00002052 ProgramBinary *programBinary = getCurrentProgramBinary();
2053
daniel@transgaming.com91207b72012-11-28 20:56:43 +00002054 GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002055 if (err != GL_NO_ERROR)
2056 {
2057 return error(err);
2058 }
2059
2060 applyShaders();
2061 applyTextures();
2062
daniel@transgaming.com92025f52012-11-28 20:52:54 +00002063 if (!programBinary->validateSamplers(NULL))
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002064 {
2065 return error(GL_INVALID_OPERATION);
2066 }
2067
daniel@transgaming.com087e5782012-09-17 21:28:47 +00002068 if (!skipDraw(mode))
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002069 {
daniel@transgaming.com91207b72012-11-28 20:56:43 +00002070 mRenderer->drawArrays(mode, count, instances);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002071 }
2072}
2073
2074void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances)
2075{
2076 if (!mState.currentProgram)
2077 {
2078 return error(GL_INVALID_OPERATION);
2079 }
2080
2081 if (!indices && !mState.elementArrayBuffer)
2082 {
2083 return error(GL_INVALID_OPERATION);
2084 }
daniel@transgaming.com91207b72012-11-28 20:56:43 +00002085
2086 if (!mRenderer->applyPrimitiveType(mode, count))
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002087 {
2088 return;
2089 }
2090
2091 if (!applyRenderTarget(false))
2092 {
2093 return;
2094 }
2095
2096 applyState(mode);
2097
2098 TranslatedIndexData indexInfo;
daniel@transgaming.com91207b72012-11-28 20:56:43 +00002099 GLenum err = mRenderer->applyIndexBuffer(indices, mState.elementArrayBuffer.get(), count, mode, type, &indexInfo);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002100 if (err != GL_NO_ERROR)
2101 {
2102 return error(err);
2103 }
2104
daniel@transgaming.com92025f52012-11-28 20:52:54 +00002105 ProgramBinary *programBinary = getCurrentProgramBinary();
2106
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002107 GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
daniel@transgaming.com91207b72012-11-28 20:56:43 +00002108 err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002109 if (err != GL_NO_ERROR)
2110 {
2111 return error(err);
2112 }
2113
2114 applyShaders();
2115 applyTextures();
2116
daniel@transgaming.com92025f52012-11-28 20:52:54 +00002117 if (!programBinary->validateSamplers(NULL))
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002118 {
2119 return error(GL_INVALID_OPERATION);
2120 }
2121
daniel@transgaming.com087e5782012-09-17 21:28:47 +00002122 if (!skipDraw(mode))
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002123 {
daniel@transgaming.com97400dd2012-11-28 20:57:00 +00002124 mRenderer->drawElements(mode, count, type, indices, mState.elementArrayBuffer.get(), indexInfo);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002125 }
2126}
2127
2128// Implements glFlush when block is false, glFinish when block is true
2129void Context::sync(bool block)
2130{
daniel@transgaming.comef21ab22012-10-31 17:52:47 +00002131 mRenderer->sync(block);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002132}
2133
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002134void Context::recordInvalidEnum()
2135{
2136 mInvalidEnum = true;
2137}
2138
2139void Context::recordInvalidValue()
2140{
2141 mInvalidValue = true;
2142}
2143
2144void Context::recordInvalidOperation()
2145{
2146 mInvalidOperation = true;
2147}
2148
2149void Context::recordOutOfMemory()
2150{
2151 mOutOfMemory = true;
2152}
2153
2154void Context::recordInvalidFramebufferOperation()
2155{
2156 mInvalidFramebufferOperation = true;
2157}
2158
2159// Get one of the recorded errors and clear its flag, if any.
2160// [OpenGL ES 2.0.24] section 2.5 page 13.
2161GLenum Context::getError()
2162{
2163 if (mInvalidEnum)
2164 {
2165 mInvalidEnum = false;
2166
2167 return GL_INVALID_ENUM;
2168 }
2169
2170 if (mInvalidValue)
2171 {
2172 mInvalidValue = false;
2173
2174 return GL_INVALID_VALUE;
2175 }
2176
2177 if (mInvalidOperation)
2178 {
2179 mInvalidOperation = false;
2180
2181 return GL_INVALID_OPERATION;
2182 }
2183
2184 if (mOutOfMemory)
2185 {
2186 mOutOfMemory = false;
2187
2188 return GL_OUT_OF_MEMORY;
2189 }
2190
2191 if (mInvalidFramebufferOperation)
2192 {
2193 mInvalidFramebufferOperation = false;
2194
2195 return GL_INVALID_FRAMEBUFFER_OPERATION;
2196 }
2197
2198 return GL_NO_ERROR;
2199}
2200
2201GLenum Context::getResetStatus()
2202{
2203 if (mResetStatus == GL_NO_ERROR)
2204 {
daniel@transgaming.comf688c0d2012-10-31 17:52:57 +00002205 // mResetStatus will be set by the markContextLost callback
2206 // in the case a notification is sent
2207 mRenderer->testDeviceLost(true);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002208 }
2209
2210 GLenum status = mResetStatus;
2211
2212 if (mResetStatus != GL_NO_ERROR)
2213 {
daniel@transgaming.com621ce052012-10-31 17:52:29 +00002214 if (mRenderer->testDeviceResettable())
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002215 {
2216 mResetStatus = GL_NO_ERROR;
2217 }
2218 }
2219
2220 return status;
2221}
2222
2223bool Context::isResetNotificationEnabled()
2224{
2225 return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
2226}
2227
2228bool Context::supportsShaderModel3() const
2229{
2230 return mSupportsShaderModel3;
2231}
2232
2233float Context::getMaximumPointSize() const
2234{
2235 return mSupportsShaderModel3 ? mMaximumPointSize : ALIASED_POINT_SIZE_RANGE_MAX_SM2;
2236}
2237
2238int Context::getMaximumVaryingVectors() const
2239{
2240 return mSupportsShaderModel3 ? MAX_VARYING_VECTORS_SM3 : MAX_VARYING_VECTORS_SM2;
2241}
2242
2243unsigned int Context::getMaximumVertexTextureImageUnits() const
2244{
2245 return mSupportsVertexTexture ? MAX_VERTEX_TEXTURE_IMAGE_UNITS_VTF : 0;
2246}
2247
2248unsigned int Context::getMaximumCombinedTextureImageUnits() const
2249{
2250 return MAX_TEXTURE_IMAGE_UNITS + getMaximumVertexTextureImageUnits();
2251}
2252
2253int Context::getMaximumFragmentUniformVectors() const
2254{
2255 return mSupportsShaderModel3 ? MAX_FRAGMENT_UNIFORM_VECTORS_SM3 : MAX_FRAGMENT_UNIFORM_VECTORS_SM2;
2256}
2257
2258int Context::getMaxSupportedSamples() const
2259{
daniel@transgaming.comb7833982012-10-31 18:31:46 +00002260 return mRenderer->getMaxSupportedSamples();
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002261}
2262
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002263bool Context::supportsEventQueries() const
2264{
2265 return mSupportsEventQueries;
2266}
2267
2268bool Context::supportsOcclusionQueries() const
2269{
2270 return mSupportsOcclusionQueries;
2271}
2272
2273bool Context::supportsDXT1Textures() const
2274{
2275 return mSupportsDXT1Textures;
2276}
2277
2278bool Context::supportsDXT3Textures() const
2279{
2280 return mSupportsDXT3Textures;
2281}
2282
2283bool Context::supportsDXT5Textures() const
2284{
2285 return mSupportsDXT5Textures;
2286}
2287
2288bool Context::supportsFloat32Textures() const
2289{
2290 return mSupportsFloat32Textures;
2291}
2292
2293bool Context::supportsFloat32LinearFilter() const
2294{
2295 return mSupportsFloat32LinearFilter;
2296}
2297
2298bool Context::supportsFloat32RenderableTextures() const
2299{
2300 return mSupportsFloat32RenderableTextures;
2301}
2302
2303bool Context::supportsFloat16Textures() const
2304{
2305 return mSupportsFloat16Textures;
2306}
2307
2308bool Context::supportsFloat16LinearFilter() const
2309{
2310 return mSupportsFloat16LinearFilter;
2311}
2312
2313bool Context::supportsFloat16RenderableTextures() const
2314{
2315 return mSupportsFloat16RenderableTextures;
2316}
2317
2318int Context::getMaximumRenderbufferDimension() const
2319{
2320 return mMaxRenderbufferDimension;
2321}
2322
2323int Context::getMaximumTextureDimension() const
2324{
2325 return mMaxTextureDimension;
2326}
2327
2328int Context::getMaximumCubeTextureDimension() const
2329{
2330 return mMaxCubeTextureDimension;
2331}
2332
2333int Context::getMaximumTextureLevel() const
2334{
2335 return mMaxTextureLevel;
2336}
2337
2338bool Context::supportsLuminanceTextures() const
2339{
2340 return mSupportsLuminanceTextures;
2341}
2342
2343bool Context::supportsLuminanceAlphaTextures() const
2344{
2345 return mSupportsLuminanceAlphaTextures;
2346}
2347
2348bool Context::supportsDepthTextures() const
2349{
2350 return mSupportsDepthTextures;
2351}
2352
2353bool Context::supports32bitIndices() const
2354{
2355 return mSupports32bitIndices;
2356}
2357
2358bool Context::supportsNonPower2Texture() const
2359{
2360 return mSupportsNonPower2Texture;
2361}
2362
2363bool Context::supportsInstancing() const
2364{
2365 return mSupportsInstancing;
2366}
2367
daniel@transgaming.com07ab8412012-07-12 15:17:09 +00002368bool Context::supportsTextureFilterAnisotropy() const
2369{
2370 return mSupportsTextureFilterAnisotropy;
2371}
2372
2373float Context::getTextureMaxAnisotropy() const
2374{
2375 return mMaxTextureAnisotropy;
2376}
2377
daniel@transgaming.com42944b02012-09-27 17:45:57 +00002378bool Context::getCurrentReadFormatType(GLenum *format, GLenum *type)
2379{
2380 Framebuffer *framebuffer = getReadFramebuffer();
2381 if (!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
2382 {
2383 return error(GL_INVALID_OPERATION, false);
2384 }
2385
2386 Renderbuffer *renderbuffer = framebuffer->getColorbuffer();
2387 if (!renderbuffer)
2388 {
2389 return error(GL_INVALID_OPERATION, false);
2390 }
2391
daniel@transgaming.com20d36662012-10-31 19:51:43 +00002392 *format = gl::ExtractFormat(renderbuffer->getActualFormat());
2393 *type = gl::ExtractType(renderbuffer->getActualFormat());
daniel@transgaming.com42944b02012-09-27 17:45:57 +00002394
2395 return true;
2396}
2397
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002398void Context::detachBuffer(GLuint buffer)
2399{
2400 // [OpenGL ES 2.0.24] section 2.9 page 22:
2401 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
2402 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
2403
2404 if (mState.arrayBuffer.id() == buffer)
2405 {
2406 mState.arrayBuffer.set(NULL);
2407 }
2408
2409 if (mState.elementArrayBuffer.id() == buffer)
2410 {
2411 mState.elementArrayBuffer.set(NULL);
2412 }
2413
2414 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
2415 {
2416 if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
2417 {
2418 mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
2419 }
2420 }
2421}
2422
2423void Context::detachTexture(GLuint texture)
2424{
2425 // [OpenGL ES 2.0.24] section 3.8 page 84:
2426 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
2427 // rebound to texture object zero
2428
2429 for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
2430 {
2431 for (int sampler = 0; sampler < MAX_COMBINED_TEXTURE_IMAGE_UNITS_VTF; sampler++)
2432 {
2433 if (mState.samplerTexture[type][sampler].id() == texture)
2434 {
2435 mState.samplerTexture[type][sampler].set(NULL);
2436 }
2437 }
2438 }
2439
2440 // [OpenGL ES 2.0.24] section 4.4 page 112:
2441 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
2442 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
2443 // image was attached in the currently bound framebuffer.
2444
2445 Framebuffer *readFramebuffer = getReadFramebuffer();
2446 Framebuffer *drawFramebuffer = getDrawFramebuffer();
2447
2448 if (readFramebuffer)
2449 {
2450 readFramebuffer->detachTexture(texture);
2451 }
2452
2453 if (drawFramebuffer && drawFramebuffer != readFramebuffer)
2454 {
2455 drawFramebuffer->detachTexture(texture);
2456 }
2457}
2458
2459void Context::detachFramebuffer(GLuint framebuffer)
2460{
2461 // [OpenGL ES 2.0.24] section 4.4 page 107:
2462 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
2463 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
2464
2465 if (mState.readFramebuffer == framebuffer)
2466 {
2467 bindReadFramebuffer(0);
2468 }
2469
2470 if (mState.drawFramebuffer == framebuffer)
2471 {
2472 bindDrawFramebuffer(0);
2473 }
2474}
2475
2476void Context::detachRenderbuffer(GLuint renderbuffer)
2477{
2478 // [OpenGL ES 2.0.24] section 4.4 page 109:
2479 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
2480 // had been executed with the target RENDERBUFFER and name of zero.
2481
2482 if (mState.renderbuffer.id() == renderbuffer)
2483 {
2484 bindRenderbuffer(0);
2485 }
2486
2487 // [OpenGL ES 2.0.24] section 4.4 page 111:
2488 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
2489 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
2490 // point to which this image was attached in the currently bound framebuffer.
2491
2492 Framebuffer *readFramebuffer = getReadFramebuffer();
2493 Framebuffer *drawFramebuffer = getDrawFramebuffer();
2494
2495 if (readFramebuffer)
2496 {
2497 readFramebuffer->detachRenderbuffer(renderbuffer);
2498 }
2499
2500 if (drawFramebuffer && drawFramebuffer != readFramebuffer)
2501 {
2502 drawFramebuffer->detachRenderbuffer(renderbuffer);
2503 }
2504}
2505
2506Texture *Context::getIncompleteTexture(TextureType type)
2507{
2508 Texture *t = mIncompleteTextures[type].get();
2509
2510 if (t == NULL)
2511 {
2512 static const GLubyte color[] = { 0, 0, 0, 255 };
2513
2514 switch (type)
2515 {
2516 default:
2517 UNREACHABLE();
2518 // default falls through to TEXTURE_2D
2519
2520 case TEXTURE_2D:
2521 {
daniel@transgaming.com370482e2012-11-28 19:32:13 +00002522 Texture2D *incomplete2d = new Texture2D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002523 incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2524 t = incomplete2d;
2525 }
2526 break;
2527
2528 case TEXTURE_CUBE:
2529 {
daniel@transgaming.com370482e2012-11-28 19:32:13 +00002530 TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer, Texture::INCOMPLETE_TEXTURE_ID);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002531
2532 incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2533 incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2534 incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2535 incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2536 incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2537 incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
2538
2539 t = incompleteCube;
2540 }
2541 break;
2542 }
2543
2544 mIncompleteTextures[type].set(t);
2545 }
2546
2547 return t;
2548}
2549
daniel@transgaming.com087e5782012-09-17 21:28:47 +00002550bool Context::skipDraw(GLenum drawMode)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002551{
daniel@transgaming.com087e5782012-09-17 21:28:47 +00002552 if (drawMode == GL_POINTS)
2553 {
2554 // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
2555 // which affects varying interpolation. Since the value of gl_PointSize is
2556 // undefined when not written, just skip drawing to avoid unexpected results.
2557 if (!getCurrentProgramBinary()->usesPointSize())
2558 {
2559 // This is stictly speaking not an error, but developers should be
2560 // notified of risking undefined behavior.
2561 ERR("Point rendering without writing to gl_PointSize.");
2562
2563 return true;
2564 }
2565 }
2566 else if (isTriangleMode(drawMode))
2567 {
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00002568 if (mState.rasterizer.cullFace && mState.rasterizer.cullMode == GL_FRONT_AND_BACK)
daniel@transgaming.com087e5782012-09-17 21:28:47 +00002569 {
2570 return true;
2571 }
2572 }
2573
2574 return false;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002575}
2576
2577bool Context::isTriangleMode(GLenum drawMode)
2578{
2579 switch (drawMode)
2580 {
2581 case GL_TRIANGLES:
2582 case GL_TRIANGLE_FAN:
2583 case GL_TRIANGLE_STRIP:
2584 return true;
2585 case GL_POINTS:
2586 case GL_LINES:
2587 case GL_LINE_LOOP:
2588 case GL_LINE_STRIP:
2589 return false;
2590 default: UNREACHABLE();
2591 }
2592
2593 return false;
2594}
2595
2596void Context::setVertexAttrib(GLuint index, const GLfloat *values)
2597{
2598 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2599
2600 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
2601 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
2602 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
2603 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002604}
2605
2606void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
2607{
2608 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
2609
2610 mState.vertexAttribute[index].mDivisor = divisor;
2611}
2612
2613// keep list sorted in following order
2614// OES extensions
2615// EXT extensions
2616// Vendor extensions
2617void Context::initExtensionString()
2618{
2619 mExtensionString = "";
2620
2621 // OES extensions
2622 if (supports32bitIndices())
2623 {
2624 mExtensionString += "GL_OES_element_index_uint ";
2625 }
2626
2627 mExtensionString += "GL_OES_packed_depth_stencil ";
2628 mExtensionString += "GL_OES_get_program_binary ";
2629 mExtensionString += "GL_OES_rgb8_rgba8 ";
2630 mExtensionString += "GL_OES_standard_derivatives ";
2631
2632 if (supportsFloat16Textures())
2633 {
2634 mExtensionString += "GL_OES_texture_half_float ";
2635 }
2636 if (supportsFloat16LinearFilter())
2637 {
2638 mExtensionString += "GL_OES_texture_half_float_linear ";
2639 }
2640 if (supportsFloat32Textures())
2641 {
2642 mExtensionString += "GL_OES_texture_float ";
2643 }
2644 if (supportsFloat32LinearFilter())
2645 {
2646 mExtensionString += "GL_OES_texture_float_linear ";
2647 }
2648
2649 if (supportsNonPower2Texture())
2650 {
2651 mExtensionString += "GL_OES_texture_npot ";
2652 }
2653
2654 // Multi-vendor (EXT) extensions
2655 if (supportsOcclusionQueries())
2656 {
2657 mExtensionString += "GL_EXT_occlusion_query_boolean ";
2658 }
2659
2660 mExtensionString += "GL_EXT_read_format_bgra ";
2661 mExtensionString += "GL_EXT_robustness ";
2662
2663 if (supportsDXT1Textures())
2664 {
2665 mExtensionString += "GL_EXT_texture_compression_dxt1 ";
2666 }
2667
daniel@transgaming.com07ab8412012-07-12 15:17:09 +00002668 if (supportsTextureFilterAnisotropy())
2669 {
2670 mExtensionString += "GL_EXT_texture_filter_anisotropic ";
2671 }
2672
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002673 mExtensionString += "GL_EXT_texture_format_BGRA8888 ";
2674 mExtensionString += "GL_EXT_texture_storage ";
2675
2676 // ANGLE-specific extensions
2677 if (supportsDepthTextures())
2678 {
2679 mExtensionString += "GL_ANGLE_depth_texture ";
2680 }
2681
2682 mExtensionString += "GL_ANGLE_framebuffer_blit ";
2683 if (getMaxSupportedSamples() != 0)
2684 {
2685 mExtensionString += "GL_ANGLE_framebuffer_multisample ";
2686 }
2687
2688 if (supportsInstancing())
2689 {
2690 mExtensionString += "GL_ANGLE_instanced_arrays ";
2691 }
2692
2693 mExtensionString += "GL_ANGLE_pack_reverse_row_order ";
2694
2695 if (supportsDXT3Textures())
2696 {
2697 mExtensionString += "GL_ANGLE_texture_compression_dxt3 ";
2698 }
2699 if (supportsDXT5Textures())
2700 {
2701 mExtensionString += "GL_ANGLE_texture_compression_dxt5 ";
2702 }
2703
2704 mExtensionString += "GL_ANGLE_texture_usage ";
2705 mExtensionString += "GL_ANGLE_translated_shader_source ";
2706
2707 // Other vendor-specific extensions
2708 if (supportsEventQueries())
2709 {
2710 mExtensionString += "GL_NV_fence ";
2711 }
2712
2713 std::string::size_type end = mExtensionString.find_last_not_of(' ');
2714 if (end != std::string::npos)
2715 {
2716 mExtensionString.resize(end+1);
2717 }
2718}
2719
2720const char *Context::getExtensionString() const
2721{
2722 return mExtensionString.c_str();
2723}
2724
2725void Context::initRendererString()
2726{
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002727 mRendererString = "ANGLE (";
daniel@transgaming.com4ca789e2012-10-31 18:46:40 +00002728 mRendererString += mRenderer->getAdapterDescription();
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002729 mRendererString += ")";
2730}
2731
2732const char *Context::getRendererString() const
2733{
2734 return mRendererString.c_str();
2735}
2736
2737void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
2738 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
2739 GLbitfield mask)
2740{
2741 Framebuffer *readFramebuffer = getReadFramebuffer();
2742 Framebuffer *drawFramebuffer = getDrawFramebuffer();
2743
2744 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
2745 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
2746 {
2747 return error(GL_INVALID_FRAMEBUFFER_OPERATION);
2748 }
2749
2750 if (drawFramebuffer->getSamples() != 0)
2751 {
2752 return error(GL_INVALID_OPERATION);
2753 }
2754
2755 int readBufferWidth = readFramebuffer->getColorbuffer()->getWidth();
2756 int readBufferHeight = readFramebuffer->getColorbuffer()->getHeight();
2757 int drawBufferWidth = drawFramebuffer->getColorbuffer()->getWidth();
2758 int drawBufferHeight = drawFramebuffer->getColorbuffer()->getHeight();
2759
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002760 Rectangle sourceRect;
2761 Rectangle destRect;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002762
2763 if (srcX0 < srcX1)
2764 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002765 sourceRect.x = srcX0;
2766 destRect.x = dstX0;
2767 sourceRect.width = srcX1 - srcX0;
2768 destRect.width = dstX1 - dstX0;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002769 }
2770 else
2771 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002772 sourceRect.x = srcX1;
2773 destRect.x = dstX1;
2774 sourceRect.width = srcX0 - srcX1;
2775 destRect.width = dstX0 - dstX1;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002776 }
2777
2778 if (srcY0 < srcY1)
2779 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002780 sourceRect.height = srcY1 - srcY0;
2781 destRect.height = dstY1 - dstY0;
2782 sourceRect.y = srcY0;
2783 destRect.y = dstY0;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002784 }
2785 else
2786 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002787 sourceRect.height = srcY0 - srcY1;
2788 destRect.height = dstY0 - srcY1;
2789 sourceRect.y = srcY1;
2790 destRect.y = dstY1;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002791 }
2792
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002793 Rectangle sourceScissoredRect = sourceRect;
2794 Rectangle destScissoredRect = destRect;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002795
daniel@transgaming.comf39967e2012-11-28 19:35:56 +00002796 if (mState.rasterizer.scissorTest)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002797 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002798 // Only write to parts of the destination framebuffer which pass the scissor test.
2799 if (destRect.x < mState.scissor.x)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002800 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002801 int xDiff = mState.scissor.x - destRect.x;
2802 destScissoredRect.x = mState.scissor.x;
2803 destScissoredRect.width -= xDiff;
2804 sourceScissoredRect.x += xDiff;
2805 sourceScissoredRect.width -= xDiff;
2806
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002807 }
2808
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002809 if (destRect.x + destRect.width > mState.scissor.x + mState.scissor.width)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002810 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002811 int xDiff = (destRect.x + destRect.width) - (mState.scissor.x + mState.scissor.width);
2812 destScissoredRect.width -= xDiff;
2813 sourceScissoredRect.width -= xDiff;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002814 }
2815
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002816 if (destRect.y < mState.scissor.y)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002817 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002818 int yDiff = mState.scissor.y - destRect.y;
2819 destScissoredRect.y = mState.scissor.y;
2820 destScissoredRect.height -= yDiff;
2821 sourceScissoredRect.y += yDiff;
2822 sourceScissoredRect.height -= yDiff;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002823 }
2824
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002825 if (destRect.y + destRect.height > mState.scissor.y + mState.scissor.height)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002826 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002827 int yDiff = (destRect.y + destRect.height) - (mState.scissor.y + mState.scissor.height);
2828 destScissoredRect.height -= yDiff;
2829 sourceScissoredRect.height -= yDiff;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002830 }
2831 }
2832
2833 bool blitRenderTarget = false;
2834 bool blitDepthStencil = false;
2835
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002836 Rectangle sourceTrimmedRect = sourceScissoredRect;
2837 Rectangle destTrimmedRect = destScissoredRect;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002838
2839 // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of
2840 // the actual draw and read surfaces.
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002841 if (sourceTrimmedRect.x < 0)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002842 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002843 int xDiff = 0 - sourceTrimmedRect.x;
2844 sourceTrimmedRect.x = 0;
2845 sourceTrimmedRect.width -= xDiff;
2846 destTrimmedRect.x += xDiff;
2847 destTrimmedRect.width -= xDiff;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002848 }
2849
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002850 if (sourceTrimmedRect.x + sourceTrimmedRect.width > readBufferWidth)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002851 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002852 int xDiff = (sourceTrimmedRect.x + sourceTrimmedRect.width) - readBufferWidth;
2853 sourceTrimmedRect.width -= xDiff;
2854 destTrimmedRect.width -= xDiff;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002855 }
2856
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002857 if (sourceTrimmedRect.y < 0)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002858 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002859 int yDiff = 0 - sourceTrimmedRect.y;
2860 sourceTrimmedRect.y = 0;
2861 sourceTrimmedRect.height -= yDiff;
2862 destTrimmedRect.y += yDiff;
2863 destTrimmedRect.height -= yDiff;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002864 }
2865
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002866 if (sourceTrimmedRect.y + sourceTrimmedRect.height > readBufferHeight)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002867 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002868 int yDiff = (sourceTrimmedRect.y + sourceTrimmedRect.height) - readBufferHeight;
2869 sourceTrimmedRect.height -= yDiff;
2870 destTrimmedRect.height -= yDiff;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002871 }
2872
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002873 if (destTrimmedRect.x < 0)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002874 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002875 int xDiff = 0 - destTrimmedRect.x;
2876 destTrimmedRect.x = 0;
2877 destTrimmedRect.width -= xDiff;
2878 sourceTrimmedRect.x += xDiff;
2879 sourceTrimmedRect.width -= xDiff;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002880 }
2881
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002882 if (destTrimmedRect.x + destTrimmedRect.width > drawBufferWidth)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002883 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002884 int xDiff = (destTrimmedRect.x + destTrimmedRect.width) - drawBufferWidth;
2885 destTrimmedRect.width -= xDiff;
2886 sourceTrimmedRect.width -= xDiff;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002887 }
2888
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002889 if (destTrimmedRect.y < 0)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002890 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002891 int yDiff = 0 - destTrimmedRect.y;
2892 destTrimmedRect.y = 0;
2893 destTrimmedRect.height -= yDiff;
2894 sourceTrimmedRect.y += yDiff;
2895 sourceTrimmedRect.height -= yDiff;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002896 }
2897
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002898 if (destTrimmedRect.y + destTrimmedRect.height > drawBufferHeight)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002899 {
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002900 int yDiff = (destTrimmedRect.y + destTrimmedRect.height) - drawBufferHeight;
2901 destTrimmedRect.height -= yDiff;
2902 sourceTrimmedRect.height -= yDiff;
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002903 }
2904
2905 bool partialBufferCopy = false;
daniel@transgaming.com48ab81c2012-11-28 19:39:21 +00002906 if (sourceTrimmedRect.height < readBufferHeight ||
2907 sourceTrimmedRect.width < readBufferWidth ||
2908 destTrimmedRect.height < drawBufferHeight ||
2909 destTrimmedRect.width < drawBufferWidth ||
2910 sourceTrimmedRect.y != 0 || destTrimmedRect.y != 0 || sourceTrimmedRect.x != 0 || destTrimmedRect.x != 0)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002911 {
2912 partialBufferCopy = true;
2913 }
2914
2915 if (mask & GL_COLOR_BUFFER_BIT)
2916 {
2917 const bool validReadType = readFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
2918 readFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
2919 const bool validDrawType = drawFramebuffer->getColorbufferType() == GL_TEXTURE_2D ||
2920 drawFramebuffer->getColorbufferType() == GL_RENDERBUFFER;
2921 if (!validReadType || !validDrawType ||
daniel@transgaming.com20d36662012-10-31 19:51:43 +00002922 readFramebuffer->getColorbuffer()->getActualFormat() != drawFramebuffer->getColorbuffer()->getActualFormat())
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002923 {
2924 ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
2925 return error(GL_INVALID_OPERATION);
2926 }
2927
2928 if (partialBufferCopy && readFramebuffer->getSamples() != 0)
2929 {
2930 return error(GL_INVALID_OPERATION);
2931 }
2932
2933 blitRenderTarget = true;
2934
2935 }
2936
2937 if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
2938 {
2939 Renderbuffer *readDSBuffer = NULL;
2940 Renderbuffer *drawDSBuffer = NULL;
2941
2942 // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
2943 // both a depth and stencil buffer, it will be the same buffer.
2944
2945 if (mask & GL_DEPTH_BUFFER_BIT)
2946 {
2947 if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
2948 {
2949 if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
daniel@transgaming.com20d36662012-10-31 19:51:43 +00002950 readFramebuffer->getDepthbuffer()->getActualFormat() != drawFramebuffer->getDepthbuffer()->getActualFormat())
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002951 {
2952 return error(GL_INVALID_OPERATION);
2953 }
2954
2955 blitDepthStencil = true;
2956 readDSBuffer = readFramebuffer->getDepthbuffer();
2957 drawDSBuffer = drawFramebuffer->getDepthbuffer();
2958 }
2959 }
2960
2961 if (mask & GL_STENCIL_BUFFER_BIT)
2962 {
2963 if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
2964 {
2965 if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
daniel@transgaming.com20d36662012-10-31 19:51:43 +00002966 readFramebuffer->getStencilbuffer()->getActualFormat() != drawFramebuffer->getStencilbuffer()->getActualFormat())
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002967 {
2968 return error(GL_INVALID_OPERATION);
2969 }
2970
2971 blitDepthStencil = true;
2972 readDSBuffer = readFramebuffer->getStencilbuffer();
2973 drawDSBuffer = drawFramebuffer->getStencilbuffer();
2974 }
2975 }
2976
2977 if (partialBufferCopy)
2978 {
2979 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
2980 return error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted
2981 }
2982
2983 if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) ||
2984 (readDSBuffer && readDSBuffer->getSamples() != 0))
2985 {
2986 return error(GL_INVALID_OPERATION);
2987 }
2988 }
2989
2990 if (blitRenderTarget || blitDepthStencil)
2991 {
daniel@transgaming.com6c872172012-11-28 19:39:33 +00002992 mRenderer->blitRect(readFramebuffer, &sourceTrimmedRect, drawFramebuffer, &destTrimmedRect, blitRenderTarget, blitDepthStencil);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002993 }
2994}
2995
apatrick@chromium.org144f2802012-07-12 01:42:34 +00002996}
2997
2998extern "C"
2999{
daniel@transgaming.com03d39092012-11-28 19:31:59 +00003000gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
apatrick@chromium.org144f2802012-07-12 01:42:34 +00003001{
daniel@transgaming.com03d39092012-11-28 19:31:59 +00003002 return new gl::Context(shareContext, renderer, notifyResets, robustAccess);
apatrick@chromium.org144f2802012-07-12 01:42:34 +00003003}
3004
3005void glDestroyContext(gl::Context *context)
3006{
3007 delete context;
3008
3009 if (context == gl::getContext())
3010 {
3011 gl::makeCurrent(NULL, NULL, NULL);
3012 }
3013}
3014
3015void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
3016{
3017 gl::makeCurrent(context, display, surface);
3018}
3019
3020gl::Context *glGetCurrentContext()
3021{
3022 return gl::getContext();
3023}
daniel@transgaming.com621ce052012-10-31 17:52:29 +00003024
apatrick@chromium.org144f2802012-07-12 01:42:34 +00003025}