gfx/angle/src/libGLESv2/Context.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

michael@0 1 #include "precompiled.h"
michael@0 2 //
michael@0 3 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
michael@0 4 // Use of this source code is governed by a BSD-style license that can be
michael@0 5 // found in the LICENSE file.
michael@0 6 //
michael@0 7
michael@0 8 // Context.cpp: Implements the gl::Context class, managing all GL state and performing
michael@0 9 // rendering operations. It is the GLES2 specific implementation of EGLContext.
michael@0 10
michael@0 11 #include "libGLESv2/Context.h"
michael@0 12
michael@0 13 #include "libGLESv2/main.h"
michael@0 14 #include "libGLESv2/utilities.h"
michael@0 15 #include "libGLESv2/Buffer.h"
michael@0 16 #include "libGLESv2/Fence.h"
michael@0 17 #include "libGLESv2/Framebuffer.h"
michael@0 18 #include "libGLESv2/Renderbuffer.h"
michael@0 19 #include "libGLESv2/Program.h"
michael@0 20 #include "libGLESv2/ProgramBinary.h"
michael@0 21 #include "libGLESv2/Query.h"
michael@0 22 #include "libGLESv2/Texture.h"
michael@0 23 #include "libGLESv2/ResourceManager.h"
michael@0 24 #include "libGLESv2/renderer/IndexDataManager.h"
michael@0 25 #include "libGLESv2/renderer/RenderTarget.h"
michael@0 26 #include "libGLESv2/renderer/Renderer.h"
michael@0 27
michael@0 28 #include "libEGL/Surface.h"
michael@0 29
michael@0 30 #undef near
michael@0 31 #undef far
michael@0 32
michael@0 33 namespace gl
michael@0 34 {
michael@0 35 static const char* makeStaticString(const std::string& str)
michael@0 36 {
michael@0 37 static std::set<std::string> strings;
michael@0 38 std::set<std::string>::iterator it = strings.find(str);
michael@0 39 if (it != strings.end())
michael@0 40 return it->c_str();
michael@0 41
michael@0 42 return strings.insert(str).first->c_str();
michael@0 43 }
michael@0 44
michael@0 45 Context::Context(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) : mRenderer(renderer)
michael@0 46 {
michael@0 47 ASSERT(robustAccess == false); // Unimplemented
michael@0 48
michael@0 49 mFenceHandleAllocator.setBaseHandle(0);
michael@0 50
michael@0 51 setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
michael@0 52
michael@0 53 mState.depthClearValue = 1.0f;
michael@0 54 mState.stencilClearValue = 0;
michael@0 55
michael@0 56 mState.rasterizer.cullFace = false;
michael@0 57 mState.rasterizer.cullMode = GL_BACK;
michael@0 58 mState.rasterizer.frontFace = GL_CCW;
michael@0 59 mState.rasterizer.polygonOffsetFill = false;
michael@0 60 mState.rasterizer.polygonOffsetFactor = 0.0f;
michael@0 61 mState.rasterizer.polygonOffsetUnits = 0.0f;
michael@0 62 mState.rasterizer.pointDrawMode = false;
michael@0 63 mState.rasterizer.multiSample = false;
michael@0 64 mState.scissorTest = false;
michael@0 65 mState.scissor.x = 0;
michael@0 66 mState.scissor.y = 0;
michael@0 67 mState.scissor.width = 0;
michael@0 68 mState.scissor.height = 0;
michael@0 69
michael@0 70 mState.blend.blend = false;
michael@0 71 mState.blend.sourceBlendRGB = GL_ONE;
michael@0 72 mState.blend.sourceBlendAlpha = GL_ONE;
michael@0 73 mState.blend.destBlendRGB = GL_ZERO;
michael@0 74 mState.blend.destBlendAlpha = GL_ZERO;
michael@0 75 mState.blend.blendEquationRGB = GL_FUNC_ADD;
michael@0 76 mState.blend.blendEquationAlpha = GL_FUNC_ADD;
michael@0 77 mState.blend.sampleAlphaToCoverage = false;
michael@0 78 mState.blend.dither = true;
michael@0 79
michael@0 80 mState.blendColor.red = 0;
michael@0 81 mState.blendColor.green = 0;
michael@0 82 mState.blendColor.blue = 0;
michael@0 83 mState.blendColor.alpha = 0;
michael@0 84
michael@0 85 mState.depthStencil.depthTest = false;
michael@0 86 mState.depthStencil.depthFunc = GL_LESS;
michael@0 87 mState.depthStencil.depthMask = true;
michael@0 88 mState.depthStencil.stencilTest = false;
michael@0 89 mState.depthStencil.stencilFunc = GL_ALWAYS;
michael@0 90 mState.depthStencil.stencilMask = -1;
michael@0 91 mState.depthStencil.stencilWritemask = -1;
michael@0 92 mState.depthStencil.stencilBackFunc = GL_ALWAYS;
michael@0 93 mState.depthStencil.stencilBackMask = - 1;
michael@0 94 mState.depthStencil.stencilBackWritemask = -1;
michael@0 95 mState.depthStencil.stencilFail = GL_KEEP;
michael@0 96 mState.depthStencil.stencilPassDepthFail = GL_KEEP;
michael@0 97 mState.depthStencil.stencilPassDepthPass = GL_KEEP;
michael@0 98 mState.depthStencil.stencilBackFail = GL_KEEP;
michael@0 99 mState.depthStencil.stencilBackPassDepthFail = GL_KEEP;
michael@0 100 mState.depthStencil.stencilBackPassDepthPass = GL_KEEP;
michael@0 101
michael@0 102 mState.stencilRef = 0;
michael@0 103 mState.stencilBackRef = 0;
michael@0 104
michael@0 105 mState.sampleCoverage = false;
michael@0 106 mState.sampleCoverageValue = 1.0f;
michael@0 107 mState.sampleCoverageInvert = false;
michael@0 108 mState.generateMipmapHint = GL_DONT_CARE;
michael@0 109 mState.fragmentShaderDerivativeHint = GL_DONT_CARE;
michael@0 110
michael@0 111 mState.lineWidth = 1.0f;
michael@0 112
michael@0 113 mState.viewport.x = 0;
michael@0 114 mState.viewport.y = 0;
michael@0 115 mState.viewport.width = 0;
michael@0 116 mState.viewport.height = 0;
michael@0 117 mState.zNear = 0.0f;
michael@0 118 mState.zFar = 1.0f;
michael@0 119
michael@0 120 mState.blend.colorMaskRed = true;
michael@0 121 mState.blend.colorMaskGreen = true;
michael@0 122 mState.blend.colorMaskBlue = true;
michael@0 123 mState.blend.colorMaskAlpha = true;
michael@0 124
michael@0 125 if (shareContext != NULL)
michael@0 126 {
michael@0 127 mResourceManager = shareContext->mResourceManager;
michael@0 128 mResourceManager->addRef();
michael@0 129 }
michael@0 130 else
michael@0 131 {
michael@0 132 mResourceManager = new ResourceManager(mRenderer);
michael@0 133 }
michael@0 134
michael@0 135 // [OpenGL ES 2.0.24] section 3.7 page 83:
michael@0 136 // In the initial state, TEXTURE_2D and TEXTURE_CUBE_MAP have twodimensional
michael@0 137 // and cube map texture state vectors respectively associated with them.
michael@0 138 // In order that access to these initial textures not be lost, they are treated as texture
michael@0 139 // objects all of whose names are 0.
michael@0 140
michael@0 141 mTexture2DZero.set(new Texture2D(mRenderer, 0));
michael@0 142 mTextureCubeMapZero.set(new TextureCubeMap(mRenderer, 0));
michael@0 143
michael@0 144 mState.activeSampler = 0;
michael@0 145 bindArrayBuffer(0);
michael@0 146 bindElementArrayBuffer(0);
michael@0 147 bindTextureCubeMap(0);
michael@0 148 bindTexture2D(0);
michael@0 149 bindReadFramebuffer(0);
michael@0 150 bindDrawFramebuffer(0);
michael@0 151 bindRenderbuffer(0);
michael@0 152
michael@0 153 mState.currentProgram = 0;
michael@0 154 mCurrentProgramBinary.set(NULL);
michael@0 155
michael@0 156 mState.packAlignment = 4;
michael@0 157 mState.unpackAlignment = 4;
michael@0 158 mState.packReverseRowOrder = false;
michael@0 159
michael@0 160 mExtensionString = NULL;
michael@0 161 mRendererString = NULL;
michael@0 162
michael@0 163 mInvalidEnum = false;
michael@0 164 mInvalidValue = false;
michael@0 165 mInvalidOperation = false;
michael@0 166 mOutOfMemory = false;
michael@0 167 mInvalidFramebufferOperation = false;
michael@0 168
michael@0 169 mHasBeenCurrent = false;
michael@0 170 mContextLost = false;
michael@0 171 mResetStatus = GL_NO_ERROR;
michael@0 172 mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
michael@0 173 mRobustAccess = robustAccess;
michael@0 174
michael@0 175 mSupportsBGRATextures = false;
michael@0 176 mSupportsDXT1Textures = false;
michael@0 177 mSupportsDXT3Textures = false;
michael@0 178 mSupportsDXT5Textures = false;
michael@0 179 mSupportsEventQueries = false;
michael@0 180 mSupportsOcclusionQueries = false;
michael@0 181 mNumCompressedTextureFormats = 0;
michael@0 182 }
michael@0 183
michael@0 184 Context::~Context()
michael@0 185 {
michael@0 186 if (mState.currentProgram != 0)
michael@0 187 {
michael@0 188 Program *programObject = mResourceManager->getProgram(mState.currentProgram);
michael@0 189 if (programObject)
michael@0 190 {
michael@0 191 programObject->release();
michael@0 192 }
michael@0 193 mState.currentProgram = 0;
michael@0 194 }
michael@0 195 mCurrentProgramBinary.set(NULL);
michael@0 196
michael@0 197 while (!mFramebufferMap.empty())
michael@0 198 {
michael@0 199 deleteFramebuffer(mFramebufferMap.begin()->first);
michael@0 200 }
michael@0 201
michael@0 202 while (!mFenceMap.empty())
michael@0 203 {
michael@0 204 deleteFence(mFenceMap.begin()->first);
michael@0 205 }
michael@0 206
michael@0 207 while (!mQueryMap.empty())
michael@0 208 {
michael@0 209 deleteQuery(mQueryMap.begin()->first);
michael@0 210 }
michael@0 211
michael@0 212 for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
michael@0 213 {
michael@0 214 for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
michael@0 215 {
michael@0 216 mState.samplerTexture[type][sampler].set(NULL);
michael@0 217 }
michael@0 218 }
michael@0 219
michael@0 220 for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
michael@0 221 {
michael@0 222 mIncompleteTextures[type].set(NULL);
michael@0 223 }
michael@0 224
michael@0 225 for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
michael@0 226 {
michael@0 227 mState.vertexAttribute[i].mBoundBuffer.set(NULL);
michael@0 228 }
michael@0 229
michael@0 230 for (int i = 0; i < QUERY_TYPE_COUNT; i++)
michael@0 231 {
michael@0 232 mState.activeQuery[i].set(NULL);
michael@0 233 }
michael@0 234
michael@0 235 mState.arrayBuffer.set(NULL);
michael@0 236 mState.elementArrayBuffer.set(NULL);
michael@0 237 mState.renderbuffer.set(NULL);
michael@0 238
michael@0 239 mTexture2DZero.set(NULL);
michael@0 240 mTextureCubeMapZero.set(NULL);
michael@0 241
michael@0 242 mResourceManager->release();
michael@0 243 }
michael@0 244
michael@0 245 void Context::makeCurrent(egl::Surface *surface)
michael@0 246 {
michael@0 247 if (!mHasBeenCurrent)
michael@0 248 {
michael@0 249 mMajorShaderModel = mRenderer->getMajorShaderModel();
michael@0 250 mMaximumPointSize = mRenderer->getMaxPointSize();
michael@0 251 mSupportsVertexTexture = mRenderer->getVertexTextureSupport();
michael@0 252 mSupportsNonPower2Texture = mRenderer->getNonPower2TextureSupport();
michael@0 253 mSupportsInstancing = mRenderer->getInstancingSupport();
michael@0 254
michael@0 255 mMaxViewportDimension = mRenderer->getMaxViewportDimension();
michael@0 256 mMaxTextureDimension = std::min(std::min(mRenderer->getMaxTextureWidth(), mRenderer->getMaxTextureHeight()),
michael@0 257 (int)gl::IMPLEMENTATION_MAX_TEXTURE_SIZE);
michael@0 258 mMaxCubeTextureDimension = std::min(mMaxTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE);
michael@0 259 mMaxRenderbufferDimension = mMaxTextureDimension;
michael@0 260 mMaxTextureLevel = log2(mMaxTextureDimension) + 1;
michael@0 261 mMaxTextureAnisotropy = mRenderer->getTextureMaxAnisotropy();
michael@0 262 TRACE("MaxTextureDimension=%d, MaxCubeTextureDimension=%d, MaxRenderbufferDimension=%d, MaxTextureLevel=%d, MaxTextureAnisotropy=%f",
michael@0 263 mMaxTextureDimension, mMaxCubeTextureDimension, mMaxRenderbufferDimension, mMaxTextureLevel, mMaxTextureAnisotropy);
michael@0 264
michael@0 265 mSupportsEventQueries = mRenderer->getEventQuerySupport();
michael@0 266 mSupportsOcclusionQueries = mRenderer->getOcclusionQuerySupport();
michael@0 267 mSupportsBGRATextures = mRenderer->getBGRATextureSupport();
michael@0 268 mSupportsDXT1Textures = mRenderer->getDXT1TextureSupport();
michael@0 269 mSupportsDXT3Textures = mRenderer->getDXT3TextureSupport();
michael@0 270 mSupportsDXT5Textures = mRenderer->getDXT5TextureSupport();
michael@0 271 mSupportsFloat32Textures = mRenderer->getFloat32TextureSupport(&mSupportsFloat32LinearFilter, &mSupportsFloat32RenderableTextures);
michael@0 272 mSupportsFloat16Textures = mRenderer->getFloat16TextureSupport(&mSupportsFloat16LinearFilter, &mSupportsFloat16RenderableTextures);
michael@0 273 mSupportsLuminanceTextures = mRenderer->getLuminanceTextureSupport();
michael@0 274 mSupportsLuminanceAlphaTextures = mRenderer->getLuminanceAlphaTextureSupport();
michael@0 275 mSupportsDepthTextures = mRenderer->getDepthTextureSupport();
michael@0 276 mSupportsTextureFilterAnisotropy = mRenderer->getTextureFilterAnisotropySupport();
michael@0 277 mSupports32bitIndices = mRenderer->get32BitIndexSupport();
michael@0 278
michael@0 279 mNumCompressedTextureFormats = 0;
michael@0 280 if (supportsDXT1Textures())
michael@0 281 {
michael@0 282 mNumCompressedTextureFormats += 2;
michael@0 283 }
michael@0 284 if (supportsDXT3Textures())
michael@0 285 {
michael@0 286 mNumCompressedTextureFormats += 1;
michael@0 287 }
michael@0 288 if (supportsDXT5Textures())
michael@0 289 {
michael@0 290 mNumCompressedTextureFormats += 1;
michael@0 291 }
michael@0 292
michael@0 293 initExtensionString();
michael@0 294 initRendererString();
michael@0 295
michael@0 296 mState.viewport.x = 0;
michael@0 297 mState.viewport.y = 0;
michael@0 298 mState.viewport.width = surface->getWidth();
michael@0 299 mState.viewport.height = surface->getHeight();
michael@0 300
michael@0 301 mState.scissor.x = 0;
michael@0 302 mState.scissor.y = 0;
michael@0 303 mState.scissor.width = surface->getWidth();
michael@0 304 mState.scissor.height = surface->getHeight();
michael@0 305
michael@0 306 mHasBeenCurrent = true;
michael@0 307 }
michael@0 308
michael@0 309 // Wrap the existing swapchain resources into GL objects and assign them to the '0' names
michael@0 310 rx::SwapChain *swapchain = surface->getSwapChain();
michael@0 311
michael@0 312 Colorbuffer *colorbufferZero = new Colorbuffer(mRenderer, swapchain);
michael@0 313 DepthStencilbuffer *depthStencilbufferZero = new DepthStencilbuffer(mRenderer, swapchain);
michael@0 314 Framebuffer *framebufferZero = new DefaultFramebuffer(mRenderer, colorbufferZero, depthStencilbufferZero);
michael@0 315
michael@0 316 setFramebufferZero(framebufferZero);
michael@0 317 }
michael@0 318
michael@0 319 // NOTE: this function should not assume that this context is current!
michael@0 320 void Context::markContextLost()
michael@0 321 {
michael@0 322 if (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT)
michael@0 323 mResetStatus = GL_UNKNOWN_CONTEXT_RESET_EXT;
michael@0 324 mContextLost = true;
michael@0 325 }
michael@0 326
michael@0 327 bool Context::isContextLost()
michael@0 328 {
michael@0 329 return mContextLost;
michael@0 330 }
michael@0 331
michael@0 332 void Context::setClearColor(float red, float green, float blue, float alpha)
michael@0 333 {
michael@0 334 mState.colorClearValue.red = red;
michael@0 335 mState.colorClearValue.green = green;
michael@0 336 mState.colorClearValue.blue = blue;
michael@0 337 mState.colorClearValue.alpha = alpha;
michael@0 338 }
michael@0 339
michael@0 340 void Context::setClearDepth(float depth)
michael@0 341 {
michael@0 342 mState.depthClearValue = depth;
michael@0 343 }
michael@0 344
michael@0 345 void Context::setClearStencil(int stencil)
michael@0 346 {
michael@0 347 mState.stencilClearValue = stencil;
michael@0 348 }
michael@0 349
michael@0 350 void Context::setCullFace(bool enabled)
michael@0 351 {
michael@0 352 mState.rasterizer.cullFace = enabled;
michael@0 353 }
michael@0 354
michael@0 355 bool Context::isCullFaceEnabled() const
michael@0 356 {
michael@0 357 return mState.rasterizer.cullFace;
michael@0 358 }
michael@0 359
michael@0 360 void Context::setCullMode(GLenum mode)
michael@0 361 {
michael@0 362 mState.rasterizer.cullMode = mode;
michael@0 363 }
michael@0 364
michael@0 365 void Context::setFrontFace(GLenum front)
michael@0 366 {
michael@0 367 mState.rasterizer.frontFace = front;
michael@0 368 }
michael@0 369
michael@0 370 void Context::setDepthTest(bool enabled)
michael@0 371 {
michael@0 372 mState.depthStencil.depthTest = enabled;
michael@0 373 }
michael@0 374
michael@0 375 bool Context::isDepthTestEnabled() const
michael@0 376 {
michael@0 377 return mState.depthStencil.depthTest;
michael@0 378 }
michael@0 379
michael@0 380 void Context::setDepthFunc(GLenum depthFunc)
michael@0 381 {
michael@0 382 mState.depthStencil.depthFunc = depthFunc;
michael@0 383 }
michael@0 384
michael@0 385 void Context::setDepthRange(float zNear, float zFar)
michael@0 386 {
michael@0 387 mState.zNear = zNear;
michael@0 388 mState.zFar = zFar;
michael@0 389 }
michael@0 390
michael@0 391 void Context::setBlend(bool enabled)
michael@0 392 {
michael@0 393 mState.blend.blend = enabled;
michael@0 394 }
michael@0 395
michael@0 396 bool Context::isBlendEnabled() const
michael@0 397 {
michael@0 398 return mState.blend.blend;
michael@0 399 }
michael@0 400
michael@0 401 void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha)
michael@0 402 {
michael@0 403 mState.blend.sourceBlendRGB = sourceRGB;
michael@0 404 mState.blend.destBlendRGB = destRGB;
michael@0 405 mState.blend.sourceBlendAlpha = sourceAlpha;
michael@0 406 mState.blend.destBlendAlpha = destAlpha;
michael@0 407 }
michael@0 408
michael@0 409 void Context::setBlendColor(float red, float green, float blue, float alpha)
michael@0 410 {
michael@0 411 mState.blendColor.red = red;
michael@0 412 mState.blendColor.green = green;
michael@0 413 mState.blendColor.blue = blue;
michael@0 414 mState.blendColor.alpha = alpha;
michael@0 415 }
michael@0 416
michael@0 417 void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation)
michael@0 418 {
michael@0 419 mState.blend.blendEquationRGB = rgbEquation;
michael@0 420 mState.blend.blendEquationAlpha = alphaEquation;
michael@0 421 }
michael@0 422
michael@0 423 void Context::setStencilTest(bool enabled)
michael@0 424 {
michael@0 425 mState.depthStencil.stencilTest = enabled;
michael@0 426 }
michael@0 427
michael@0 428 bool Context::isStencilTestEnabled() const
michael@0 429 {
michael@0 430 return mState.depthStencil.stencilTest;
michael@0 431 }
michael@0 432
michael@0 433 void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask)
michael@0 434 {
michael@0 435 mState.depthStencil.stencilFunc = stencilFunc;
michael@0 436 mState.stencilRef = (stencilRef > 0) ? stencilRef : 0;
michael@0 437 mState.depthStencil.stencilMask = stencilMask;
michael@0 438 }
michael@0 439
michael@0 440 void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask)
michael@0 441 {
michael@0 442 mState.depthStencil.stencilBackFunc = stencilBackFunc;
michael@0 443 mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0;
michael@0 444 mState.depthStencil.stencilBackMask = stencilBackMask;
michael@0 445 }
michael@0 446
michael@0 447 void Context::setStencilWritemask(GLuint stencilWritemask)
michael@0 448 {
michael@0 449 mState.depthStencil.stencilWritemask = stencilWritemask;
michael@0 450 }
michael@0 451
michael@0 452 void Context::setStencilBackWritemask(GLuint stencilBackWritemask)
michael@0 453 {
michael@0 454 mState.depthStencil.stencilBackWritemask = stencilBackWritemask;
michael@0 455 }
michael@0 456
michael@0 457 void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass)
michael@0 458 {
michael@0 459 mState.depthStencil.stencilFail = stencilFail;
michael@0 460 mState.depthStencil.stencilPassDepthFail = stencilPassDepthFail;
michael@0 461 mState.depthStencil.stencilPassDepthPass = stencilPassDepthPass;
michael@0 462 }
michael@0 463
michael@0 464 void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass)
michael@0 465 {
michael@0 466 mState.depthStencil.stencilBackFail = stencilBackFail;
michael@0 467 mState.depthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail;
michael@0 468 mState.depthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass;
michael@0 469 }
michael@0 470
michael@0 471 void Context::setPolygonOffsetFill(bool enabled)
michael@0 472 {
michael@0 473 mState.rasterizer.polygonOffsetFill = enabled;
michael@0 474 }
michael@0 475
michael@0 476 bool Context::isPolygonOffsetFillEnabled() const
michael@0 477 {
michael@0 478 return mState.rasterizer.polygonOffsetFill;
michael@0 479 }
michael@0 480
michael@0 481 void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units)
michael@0 482 {
michael@0 483 // An application can pass NaN values here, so handle this gracefully
michael@0 484 mState.rasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor;
michael@0 485 mState.rasterizer.polygonOffsetUnits = units != units ? 0.0f : units;
michael@0 486 }
michael@0 487
michael@0 488 void Context::setSampleAlphaToCoverage(bool enabled)
michael@0 489 {
michael@0 490 mState.blend.sampleAlphaToCoverage = enabled;
michael@0 491 }
michael@0 492
michael@0 493 bool Context::isSampleAlphaToCoverageEnabled() const
michael@0 494 {
michael@0 495 return mState.blend.sampleAlphaToCoverage;
michael@0 496 }
michael@0 497
michael@0 498 void Context::setSampleCoverage(bool enabled)
michael@0 499 {
michael@0 500 mState.sampleCoverage = enabled;
michael@0 501 }
michael@0 502
michael@0 503 bool Context::isSampleCoverageEnabled() const
michael@0 504 {
michael@0 505 return mState.sampleCoverage;
michael@0 506 }
michael@0 507
michael@0 508 void Context::setSampleCoverageParams(GLclampf value, bool invert)
michael@0 509 {
michael@0 510 mState.sampleCoverageValue = value;
michael@0 511 mState.sampleCoverageInvert = invert;
michael@0 512 }
michael@0 513
michael@0 514 void Context::setScissorTest(bool enabled)
michael@0 515 {
michael@0 516 mState.scissorTest = enabled;
michael@0 517 }
michael@0 518
michael@0 519 bool Context::isScissorTestEnabled() const
michael@0 520 {
michael@0 521 return mState.scissorTest;
michael@0 522 }
michael@0 523
michael@0 524 void Context::setDither(bool enabled)
michael@0 525 {
michael@0 526 mState.blend.dither = enabled;
michael@0 527 }
michael@0 528
michael@0 529 bool Context::isDitherEnabled() const
michael@0 530 {
michael@0 531 return mState.blend.dither;
michael@0 532 }
michael@0 533
michael@0 534 void Context::setLineWidth(GLfloat width)
michael@0 535 {
michael@0 536 mState.lineWidth = width;
michael@0 537 }
michael@0 538
michael@0 539 void Context::setGenerateMipmapHint(GLenum hint)
michael@0 540 {
michael@0 541 mState.generateMipmapHint = hint;
michael@0 542 }
michael@0 543
michael@0 544 void Context::setFragmentShaderDerivativeHint(GLenum hint)
michael@0 545 {
michael@0 546 mState.fragmentShaderDerivativeHint = hint;
michael@0 547 // TODO: Propagate the hint to shader translator so we can write
michael@0 548 // ddx, ddx_coarse, or ddx_fine depending on the hint.
michael@0 549 // Ignore for now. It is valid for implementations to ignore hint.
michael@0 550 }
michael@0 551
michael@0 552 void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height)
michael@0 553 {
michael@0 554 mState.viewport.x = x;
michael@0 555 mState.viewport.y = y;
michael@0 556 mState.viewport.width = width;
michael@0 557 mState.viewport.height = height;
michael@0 558 }
michael@0 559
michael@0 560 void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height)
michael@0 561 {
michael@0 562 mState.scissor.x = x;
michael@0 563 mState.scissor.y = y;
michael@0 564 mState.scissor.width = width;
michael@0 565 mState.scissor.height = height;
michael@0 566 }
michael@0 567
michael@0 568 void Context::setColorMask(bool red, bool green, bool blue, bool alpha)
michael@0 569 {
michael@0 570 mState.blend.colorMaskRed = red;
michael@0 571 mState.blend.colorMaskGreen = green;
michael@0 572 mState.blend.colorMaskBlue = blue;
michael@0 573 mState.blend.colorMaskAlpha = alpha;
michael@0 574 }
michael@0 575
michael@0 576 void Context::setDepthMask(bool mask)
michael@0 577 {
michael@0 578 mState.depthStencil.depthMask = mask;
michael@0 579 }
michael@0 580
michael@0 581 void Context::setActiveSampler(unsigned int active)
michael@0 582 {
michael@0 583 mState.activeSampler = active;
michael@0 584 }
michael@0 585
michael@0 586 GLuint Context::getReadFramebufferHandle() const
michael@0 587 {
michael@0 588 return mState.readFramebuffer;
michael@0 589 }
michael@0 590
michael@0 591 GLuint Context::getDrawFramebufferHandle() const
michael@0 592 {
michael@0 593 return mState.drawFramebuffer;
michael@0 594 }
michael@0 595
michael@0 596 GLuint Context::getRenderbufferHandle() const
michael@0 597 {
michael@0 598 return mState.renderbuffer.id();
michael@0 599 }
michael@0 600
michael@0 601 GLuint Context::getArrayBufferHandle() const
michael@0 602 {
michael@0 603 return mState.arrayBuffer.id();
michael@0 604 }
michael@0 605
michael@0 606 GLuint Context::getActiveQuery(GLenum target) const
michael@0 607 {
michael@0 608 Query *queryObject = NULL;
michael@0 609
michael@0 610 switch (target)
michael@0 611 {
michael@0 612 case GL_ANY_SAMPLES_PASSED_EXT:
michael@0 613 queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED].get();
michael@0 614 break;
michael@0 615 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
michael@0 616 queryObject = mState.activeQuery[QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE].get();
michael@0 617 break;
michael@0 618 default:
michael@0 619 ASSERT(false);
michael@0 620 }
michael@0 621
michael@0 622 if (queryObject)
michael@0 623 {
michael@0 624 return queryObject->id();
michael@0 625 }
michael@0 626 else
michael@0 627 {
michael@0 628 return 0;
michael@0 629 }
michael@0 630 }
michael@0 631
michael@0 632 void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled)
michael@0 633 {
michael@0 634 mState.vertexAttribute[attribNum].mArrayEnabled = enabled;
michael@0 635 }
michael@0 636
michael@0 637 const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum)
michael@0 638 {
michael@0 639 return mState.vertexAttribute[attribNum];
michael@0 640 }
michael@0 641
michael@0 642 void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized,
michael@0 643 GLsizei stride, const void *pointer)
michael@0 644 {
michael@0 645 mState.vertexAttribute[attribNum].mBoundBuffer.set(boundBuffer);
michael@0 646 mState.vertexAttribute[attribNum].mSize = size;
michael@0 647 mState.vertexAttribute[attribNum].mType = type;
michael@0 648 mState.vertexAttribute[attribNum].mNormalized = normalized;
michael@0 649 mState.vertexAttribute[attribNum].mStride = stride;
michael@0 650 mState.vertexAttribute[attribNum].mPointer = pointer;
michael@0 651 }
michael@0 652
michael@0 653 const void *Context::getVertexAttribPointer(unsigned int attribNum) const
michael@0 654 {
michael@0 655 return mState.vertexAttribute[attribNum].mPointer;
michael@0 656 }
michael@0 657
michael@0 658 void Context::setPackAlignment(GLint alignment)
michael@0 659 {
michael@0 660 mState.packAlignment = alignment;
michael@0 661 }
michael@0 662
michael@0 663 GLint Context::getPackAlignment() const
michael@0 664 {
michael@0 665 return mState.packAlignment;
michael@0 666 }
michael@0 667
michael@0 668 void Context::setUnpackAlignment(GLint alignment)
michael@0 669 {
michael@0 670 mState.unpackAlignment = alignment;
michael@0 671 }
michael@0 672
michael@0 673 GLint Context::getUnpackAlignment() const
michael@0 674 {
michael@0 675 return mState.unpackAlignment;
michael@0 676 }
michael@0 677
michael@0 678 void Context::setPackReverseRowOrder(bool reverseRowOrder)
michael@0 679 {
michael@0 680 mState.packReverseRowOrder = reverseRowOrder;
michael@0 681 }
michael@0 682
michael@0 683 bool Context::getPackReverseRowOrder() const
michael@0 684 {
michael@0 685 return mState.packReverseRowOrder;
michael@0 686 }
michael@0 687
michael@0 688 GLuint Context::createBuffer()
michael@0 689 {
michael@0 690 return mResourceManager->createBuffer();
michael@0 691 }
michael@0 692
michael@0 693 GLuint Context::createProgram()
michael@0 694 {
michael@0 695 return mResourceManager->createProgram();
michael@0 696 }
michael@0 697
michael@0 698 GLuint Context::createShader(GLenum type)
michael@0 699 {
michael@0 700 return mResourceManager->createShader(type);
michael@0 701 }
michael@0 702
michael@0 703 GLuint Context::createTexture()
michael@0 704 {
michael@0 705 return mResourceManager->createTexture();
michael@0 706 }
michael@0 707
michael@0 708 GLuint Context::createRenderbuffer()
michael@0 709 {
michael@0 710 return mResourceManager->createRenderbuffer();
michael@0 711 }
michael@0 712
michael@0 713 // Returns an unused framebuffer name
michael@0 714 GLuint Context::createFramebuffer()
michael@0 715 {
michael@0 716 GLuint handle = mFramebufferHandleAllocator.allocate();
michael@0 717
michael@0 718 mFramebufferMap[handle] = NULL;
michael@0 719
michael@0 720 return handle;
michael@0 721 }
michael@0 722
michael@0 723 GLuint Context::createFence()
michael@0 724 {
michael@0 725 GLuint handle = mFenceHandleAllocator.allocate();
michael@0 726
michael@0 727 mFenceMap[handle] = new Fence(mRenderer);
michael@0 728
michael@0 729 return handle;
michael@0 730 }
michael@0 731
michael@0 732 // Returns an unused query name
michael@0 733 GLuint Context::createQuery()
michael@0 734 {
michael@0 735 GLuint handle = mQueryHandleAllocator.allocate();
michael@0 736
michael@0 737 mQueryMap[handle] = NULL;
michael@0 738
michael@0 739 return handle;
michael@0 740 }
michael@0 741
michael@0 742 void Context::deleteBuffer(GLuint buffer)
michael@0 743 {
michael@0 744 if (mResourceManager->getBuffer(buffer))
michael@0 745 {
michael@0 746 detachBuffer(buffer);
michael@0 747 }
michael@0 748
michael@0 749 mResourceManager->deleteBuffer(buffer);
michael@0 750 }
michael@0 751
michael@0 752 void Context::deleteShader(GLuint shader)
michael@0 753 {
michael@0 754 mResourceManager->deleteShader(shader);
michael@0 755 }
michael@0 756
michael@0 757 void Context::deleteProgram(GLuint program)
michael@0 758 {
michael@0 759 mResourceManager->deleteProgram(program);
michael@0 760 }
michael@0 761
michael@0 762 void Context::deleteTexture(GLuint texture)
michael@0 763 {
michael@0 764 if (mResourceManager->getTexture(texture))
michael@0 765 {
michael@0 766 detachTexture(texture);
michael@0 767 }
michael@0 768
michael@0 769 mResourceManager->deleteTexture(texture);
michael@0 770 }
michael@0 771
michael@0 772 void Context::deleteRenderbuffer(GLuint renderbuffer)
michael@0 773 {
michael@0 774 if (mResourceManager->getRenderbuffer(renderbuffer))
michael@0 775 {
michael@0 776 detachRenderbuffer(renderbuffer);
michael@0 777 }
michael@0 778
michael@0 779 mResourceManager->deleteRenderbuffer(renderbuffer);
michael@0 780 }
michael@0 781
michael@0 782 void Context::deleteFramebuffer(GLuint framebuffer)
michael@0 783 {
michael@0 784 FramebufferMap::iterator framebufferObject = mFramebufferMap.find(framebuffer);
michael@0 785
michael@0 786 if (framebufferObject != mFramebufferMap.end())
michael@0 787 {
michael@0 788 detachFramebuffer(framebuffer);
michael@0 789
michael@0 790 mFramebufferHandleAllocator.release(framebufferObject->first);
michael@0 791 delete framebufferObject->second;
michael@0 792 mFramebufferMap.erase(framebufferObject);
michael@0 793 }
michael@0 794 }
michael@0 795
michael@0 796 void Context::deleteFence(GLuint fence)
michael@0 797 {
michael@0 798 FenceMap::iterator fenceObject = mFenceMap.find(fence);
michael@0 799
michael@0 800 if (fenceObject != mFenceMap.end())
michael@0 801 {
michael@0 802 mFenceHandleAllocator.release(fenceObject->first);
michael@0 803 delete fenceObject->second;
michael@0 804 mFenceMap.erase(fenceObject);
michael@0 805 }
michael@0 806 }
michael@0 807
michael@0 808 void Context::deleteQuery(GLuint query)
michael@0 809 {
michael@0 810 QueryMap::iterator queryObject = mQueryMap.find(query);
michael@0 811 if (queryObject != mQueryMap.end())
michael@0 812 {
michael@0 813 mQueryHandleAllocator.release(queryObject->first);
michael@0 814 if (queryObject->second)
michael@0 815 {
michael@0 816 queryObject->second->release();
michael@0 817 }
michael@0 818 mQueryMap.erase(queryObject);
michael@0 819 }
michael@0 820 }
michael@0 821
michael@0 822 Buffer *Context::getBuffer(GLuint handle)
michael@0 823 {
michael@0 824 return mResourceManager->getBuffer(handle);
michael@0 825 }
michael@0 826
michael@0 827 Shader *Context::getShader(GLuint handle)
michael@0 828 {
michael@0 829 return mResourceManager->getShader(handle);
michael@0 830 }
michael@0 831
michael@0 832 Program *Context::getProgram(GLuint handle)
michael@0 833 {
michael@0 834 return mResourceManager->getProgram(handle);
michael@0 835 }
michael@0 836
michael@0 837 Texture *Context::getTexture(GLuint handle)
michael@0 838 {
michael@0 839 return mResourceManager->getTexture(handle);
michael@0 840 }
michael@0 841
michael@0 842 Renderbuffer *Context::getRenderbuffer(GLuint handle)
michael@0 843 {
michael@0 844 return mResourceManager->getRenderbuffer(handle);
michael@0 845 }
michael@0 846
michael@0 847 Framebuffer *Context::getReadFramebuffer()
michael@0 848 {
michael@0 849 return getFramebuffer(mState.readFramebuffer);
michael@0 850 }
michael@0 851
michael@0 852 Framebuffer *Context::getDrawFramebuffer()
michael@0 853 {
michael@0 854 return mBoundDrawFramebuffer;
michael@0 855 }
michael@0 856
michael@0 857 void Context::bindArrayBuffer(unsigned int buffer)
michael@0 858 {
michael@0 859 mResourceManager->checkBufferAllocation(buffer);
michael@0 860
michael@0 861 mState.arrayBuffer.set(getBuffer(buffer));
michael@0 862 }
michael@0 863
michael@0 864 void Context::bindElementArrayBuffer(unsigned int buffer)
michael@0 865 {
michael@0 866 mResourceManager->checkBufferAllocation(buffer);
michael@0 867
michael@0 868 mState.elementArrayBuffer.set(getBuffer(buffer));
michael@0 869 }
michael@0 870
michael@0 871 void Context::bindTexture2D(GLuint texture)
michael@0 872 {
michael@0 873 mResourceManager->checkTextureAllocation(texture, TEXTURE_2D);
michael@0 874
michael@0 875 mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture));
michael@0 876 }
michael@0 877
michael@0 878 void Context::bindTextureCubeMap(GLuint texture)
michael@0 879 {
michael@0 880 mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE);
michael@0 881
michael@0 882 mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture));
michael@0 883 }
michael@0 884
michael@0 885 void Context::bindReadFramebuffer(GLuint framebuffer)
michael@0 886 {
michael@0 887 if (!getFramebuffer(framebuffer))
michael@0 888 {
michael@0 889 mFramebufferMap[framebuffer] = new Framebuffer(mRenderer);
michael@0 890 }
michael@0 891
michael@0 892 mState.readFramebuffer = framebuffer;
michael@0 893 }
michael@0 894
michael@0 895 void Context::bindDrawFramebuffer(GLuint framebuffer)
michael@0 896 {
michael@0 897 if (!getFramebuffer(framebuffer))
michael@0 898 {
michael@0 899 mFramebufferMap[framebuffer] = new Framebuffer(mRenderer);
michael@0 900 }
michael@0 901
michael@0 902 mState.drawFramebuffer = framebuffer;
michael@0 903
michael@0 904 mBoundDrawFramebuffer = getFramebuffer(framebuffer);
michael@0 905 }
michael@0 906
michael@0 907 void Context::bindRenderbuffer(GLuint renderbuffer)
michael@0 908 {
michael@0 909 mResourceManager->checkRenderbufferAllocation(renderbuffer);
michael@0 910
michael@0 911 mState.renderbuffer.set(getRenderbuffer(renderbuffer));
michael@0 912 }
michael@0 913
michael@0 914 void Context::useProgram(GLuint program)
michael@0 915 {
michael@0 916 GLuint priorProgram = mState.currentProgram;
michael@0 917 mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged.
michael@0 918
michael@0 919 if (priorProgram != program)
michael@0 920 {
michael@0 921 Program *newProgram = mResourceManager->getProgram(program);
michael@0 922 Program *oldProgram = mResourceManager->getProgram(priorProgram);
michael@0 923 mCurrentProgramBinary.set(NULL);
michael@0 924
michael@0 925 if (newProgram)
michael@0 926 {
michael@0 927 newProgram->addRef();
michael@0 928 mCurrentProgramBinary.set(newProgram->getProgramBinary());
michael@0 929 }
michael@0 930
michael@0 931 if (oldProgram)
michael@0 932 {
michael@0 933 oldProgram->release();
michael@0 934 }
michael@0 935 }
michael@0 936 }
michael@0 937
michael@0 938 void Context::linkProgram(GLuint program)
michael@0 939 {
michael@0 940 Program *programObject = mResourceManager->getProgram(program);
michael@0 941
michael@0 942 bool linked = programObject->link();
michael@0 943
michael@0 944 // if the current program was relinked successfully we
michael@0 945 // need to install the new executables
michael@0 946 if (linked && program == mState.currentProgram)
michael@0 947 {
michael@0 948 mCurrentProgramBinary.set(programObject->getProgramBinary());
michael@0 949 }
michael@0 950 }
michael@0 951
michael@0 952 void Context::setProgramBinary(GLuint program, const void *binary, GLint length)
michael@0 953 {
michael@0 954 Program *programObject = mResourceManager->getProgram(program);
michael@0 955
michael@0 956 bool loaded = programObject->setProgramBinary(binary, length);
michael@0 957
michael@0 958 // if the current program was reloaded successfully we
michael@0 959 // need to install the new executables
michael@0 960 if (loaded && program == mState.currentProgram)
michael@0 961 {
michael@0 962 mCurrentProgramBinary.set(programObject->getProgramBinary());
michael@0 963 }
michael@0 964
michael@0 965 }
michael@0 966
michael@0 967 void Context::beginQuery(GLenum target, GLuint query)
michael@0 968 {
michael@0 969 // From EXT_occlusion_query_boolean: If BeginQueryEXT is called with an <id>
michael@0 970 // of zero, if the active query object name for <target> is non-zero (for the
michael@0 971 // targets ANY_SAMPLES_PASSED_EXT and ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, if
michael@0 972 // the active query for either target is non-zero), if <id> is the name of an
michael@0 973 // existing query object whose type does not match <target>, or if <id> is the
michael@0 974 // active query object name for any query type, the error INVALID_OPERATION is
michael@0 975 // generated.
michael@0 976
michael@0 977 // Ensure no other queries are active
michael@0 978 // NOTE: If other queries than occlusion are supported, we will need to check
michael@0 979 // separately that:
michael@0 980 // a) The query ID passed is not the current active query for any target/type
michael@0 981 // b) There are no active queries for the requested target (and in the case
michael@0 982 // of GL_ANY_SAMPLES_PASSED_EXT and GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT,
michael@0 983 // no query may be active for either if glBeginQuery targets either.
michael@0 984 for (int i = 0; i < QUERY_TYPE_COUNT; i++)
michael@0 985 {
michael@0 986 if (mState.activeQuery[i].get() != NULL)
michael@0 987 {
michael@0 988 return gl::error(GL_INVALID_OPERATION);
michael@0 989 }
michael@0 990 }
michael@0 991
michael@0 992 QueryType qType;
michael@0 993 switch (target)
michael@0 994 {
michael@0 995 case GL_ANY_SAMPLES_PASSED_EXT:
michael@0 996 qType = QUERY_ANY_SAMPLES_PASSED;
michael@0 997 break;
michael@0 998 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
michael@0 999 qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
michael@0 1000 break;
michael@0 1001 default:
michael@0 1002 ASSERT(false);
michael@0 1003 return;
michael@0 1004 }
michael@0 1005
michael@0 1006 Query *queryObject = getQuery(query, true, target);
michael@0 1007
michael@0 1008 // check that name was obtained with glGenQueries
michael@0 1009 if (!queryObject)
michael@0 1010 {
michael@0 1011 return gl::error(GL_INVALID_OPERATION);
michael@0 1012 }
michael@0 1013
michael@0 1014 // check for type mismatch
michael@0 1015 if (queryObject->getType() != target)
michael@0 1016 {
michael@0 1017 return gl::error(GL_INVALID_OPERATION);
michael@0 1018 }
michael@0 1019
michael@0 1020 // set query as active for specified target
michael@0 1021 mState.activeQuery[qType].set(queryObject);
michael@0 1022
michael@0 1023 // begin query
michael@0 1024 queryObject->begin();
michael@0 1025 }
michael@0 1026
michael@0 1027 void Context::endQuery(GLenum target)
michael@0 1028 {
michael@0 1029 QueryType qType;
michael@0 1030
michael@0 1031 switch (target)
michael@0 1032 {
michael@0 1033 case GL_ANY_SAMPLES_PASSED_EXT:
michael@0 1034 qType = QUERY_ANY_SAMPLES_PASSED;
michael@0 1035 break;
michael@0 1036 case GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT:
michael@0 1037 qType = QUERY_ANY_SAMPLES_PASSED_CONSERVATIVE;
michael@0 1038 break;
michael@0 1039 default:
michael@0 1040 ASSERT(false);
michael@0 1041 return;
michael@0 1042 }
michael@0 1043
michael@0 1044 Query *queryObject = mState.activeQuery[qType].get();
michael@0 1045
michael@0 1046 if (queryObject == NULL)
michael@0 1047 {
michael@0 1048 return gl::error(GL_INVALID_OPERATION);
michael@0 1049 }
michael@0 1050
michael@0 1051 queryObject->end();
michael@0 1052
michael@0 1053 mState.activeQuery[qType].set(NULL);
michael@0 1054 }
michael@0 1055
michael@0 1056 void Context::setFramebufferZero(Framebuffer *buffer)
michael@0 1057 {
michael@0 1058 delete mFramebufferMap[0];
michael@0 1059 mFramebufferMap[0] = buffer;
michael@0 1060 if (mState.drawFramebuffer == 0)
michael@0 1061 {
michael@0 1062 mBoundDrawFramebuffer = buffer;
michael@0 1063 }
michael@0 1064 }
michael@0 1065
michael@0 1066 void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
michael@0 1067 {
michael@0 1068 RenderbufferStorage *renderbuffer = NULL;
michael@0 1069 switch (internalformat)
michael@0 1070 {
michael@0 1071 case GL_DEPTH_COMPONENT16:
michael@0 1072 renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples);
michael@0 1073 break;
michael@0 1074 case GL_RGBA4:
michael@0 1075 case GL_RGB5_A1:
michael@0 1076 case GL_RGB565:
michael@0 1077 case GL_RGB8_OES:
michael@0 1078 case GL_RGBA8_OES:
michael@0 1079 renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples);
michael@0 1080 break;
michael@0 1081 case GL_STENCIL_INDEX8:
michael@0 1082 renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples);
michael@0 1083 break;
michael@0 1084 case GL_DEPTH24_STENCIL8_OES:
michael@0 1085 renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples);
michael@0 1086 break;
michael@0 1087 default:
michael@0 1088 UNREACHABLE(); return;
michael@0 1089 }
michael@0 1090
michael@0 1091 Renderbuffer *renderbufferObject = mState.renderbuffer.get();
michael@0 1092 renderbufferObject->setStorage(renderbuffer);
michael@0 1093 }
michael@0 1094
michael@0 1095 Framebuffer *Context::getFramebuffer(unsigned int handle)
michael@0 1096 {
michael@0 1097 FramebufferMap::iterator framebuffer = mFramebufferMap.find(handle);
michael@0 1098
michael@0 1099 if (framebuffer == mFramebufferMap.end())
michael@0 1100 {
michael@0 1101 return NULL;
michael@0 1102 }
michael@0 1103 else
michael@0 1104 {
michael@0 1105 return framebuffer->second;
michael@0 1106 }
michael@0 1107 }
michael@0 1108
michael@0 1109 Fence *Context::getFence(unsigned int handle)
michael@0 1110 {
michael@0 1111 FenceMap::iterator fence = mFenceMap.find(handle);
michael@0 1112
michael@0 1113 if (fence == mFenceMap.end())
michael@0 1114 {
michael@0 1115 return NULL;
michael@0 1116 }
michael@0 1117 else
michael@0 1118 {
michael@0 1119 return fence->second;
michael@0 1120 }
michael@0 1121 }
michael@0 1122
michael@0 1123 Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
michael@0 1124 {
michael@0 1125 QueryMap::iterator query = mQueryMap.find(handle);
michael@0 1126
michael@0 1127 if (query == mQueryMap.end())
michael@0 1128 {
michael@0 1129 return NULL;
michael@0 1130 }
michael@0 1131 else
michael@0 1132 {
michael@0 1133 if (!query->second && create)
michael@0 1134 {
michael@0 1135 query->second = new Query(mRenderer, type, handle);
michael@0 1136 query->second->addRef();
michael@0 1137 }
michael@0 1138 return query->second;
michael@0 1139 }
michael@0 1140 }
michael@0 1141
michael@0 1142 Buffer *Context::getArrayBuffer()
michael@0 1143 {
michael@0 1144 return mState.arrayBuffer.get();
michael@0 1145 }
michael@0 1146
michael@0 1147 Buffer *Context::getElementArrayBuffer()
michael@0 1148 {
michael@0 1149 return mState.elementArrayBuffer.get();
michael@0 1150 }
michael@0 1151
michael@0 1152 ProgramBinary *Context::getCurrentProgramBinary()
michael@0 1153 {
michael@0 1154 return mCurrentProgramBinary.get();
michael@0 1155 }
michael@0 1156
michael@0 1157 Texture2D *Context::getTexture2D()
michael@0 1158 {
michael@0 1159 return static_cast<Texture2D*>(getSamplerTexture(mState.activeSampler, TEXTURE_2D));
michael@0 1160 }
michael@0 1161
michael@0 1162 TextureCubeMap *Context::getTextureCubeMap()
michael@0 1163 {
michael@0 1164 return static_cast<TextureCubeMap*>(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE));
michael@0 1165 }
michael@0 1166
michael@0 1167 Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type)
michael@0 1168 {
michael@0 1169 GLuint texid = mState.samplerTexture[type][sampler].id();
michael@0 1170
michael@0 1171 if (texid == 0) // Special case: 0 refers to different initial textures based on the target
michael@0 1172 {
michael@0 1173 switch (type)
michael@0 1174 {
michael@0 1175 default: UNREACHABLE();
michael@0 1176 case TEXTURE_2D: return mTexture2DZero.get();
michael@0 1177 case TEXTURE_CUBE: return mTextureCubeMapZero.get();
michael@0 1178 }
michael@0 1179 }
michael@0 1180
michael@0 1181 return mState.samplerTexture[type][sampler].get();
michael@0 1182 }
michael@0 1183
michael@0 1184 bool Context::getBooleanv(GLenum pname, GLboolean *params)
michael@0 1185 {
michael@0 1186 switch (pname)
michael@0 1187 {
michael@0 1188 case GL_SHADER_COMPILER: *params = GL_TRUE; break;
michael@0 1189 case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break;
michael@0 1190 case GL_DEPTH_WRITEMASK: *params = mState.depthStencil.depthMask; break;
michael@0 1191 case GL_COLOR_WRITEMASK:
michael@0 1192 params[0] = mState.blend.colorMaskRed;
michael@0 1193 params[1] = mState.blend.colorMaskGreen;
michael@0 1194 params[2] = mState.blend.colorMaskBlue;
michael@0 1195 params[3] = mState.blend.colorMaskAlpha;
michael@0 1196 break;
michael@0 1197 case GL_CULL_FACE: *params = mState.rasterizer.cullFace; break;
michael@0 1198 case GL_POLYGON_OFFSET_FILL: *params = mState.rasterizer.polygonOffsetFill; break;
michael@0 1199 case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.blend.sampleAlphaToCoverage; break;
michael@0 1200 case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break;
michael@0 1201 case GL_SCISSOR_TEST: *params = mState.scissorTest; break;
michael@0 1202 case GL_STENCIL_TEST: *params = mState.depthStencil.stencilTest; break;
michael@0 1203 case GL_DEPTH_TEST: *params = mState.depthStencil.depthTest; break;
michael@0 1204 case GL_BLEND: *params = mState.blend.blend; break;
michael@0 1205 case GL_DITHER: *params = mState.blend.dither; break;
michael@0 1206 case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break;
michael@0 1207 default:
michael@0 1208 return false;
michael@0 1209 }
michael@0 1210
michael@0 1211 return true;
michael@0 1212 }
michael@0 1213
michael@0 1214 bool Context::getFloatv(GLenum pname, GLfloat *params)
michael@0 1215 {
michael@0 1216 // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation
michael@0 1217 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
michael@0 1218 // GetIntegerv as its native query function. As it would require conversion in any
michael@0 1219 // case, this should make no difference to the calling application.
michael@0 1220 switch (pname)
michael@0 1221 {
michael@0 1222 case GL_LINE_WIDTH: *params = mState.lineWidth; break;
michael@0 1223 case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break;
michael@0 1224 case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break;
michael@0 1225 case GL_POLYGON_OFFSET_FACTOR: *params = mState.rasterizer.polygonOffsetFactor; break;
michael@0 1226 case GL_POLYGON_OFFSET_UNITS: *params = mState.rasterizer.polygonOffsetUnits; break;
michael@0 1227 case GL_ALIASED_LINE_WIDTH_RANGE:
michael@0 1228 params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN;
michael@0 1229 params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX;
michael@0 1230 break;
michael@0 1231 case GL_ALIASED_POINT_SIZE_RANGE:
michael@0 1232 params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN;
michael@0 1233 params[1] = getMaximumPointSize();
michael@0 1234 break;
michael@0 1235 case GL_DEPTH_RANGE:
michael@0 1236 params[0] = mState.zNear;
michael@0 1237 params[1] = mState.zFar;
michael@0 1238 break;
michael@0 1239 case GL_COLOR_CLEAR_VALUE:
michael@0 1240 params[0] = mState.colorClearValue.red;
michael@0 1241 params[1] = mState.colorClearValue.green;
michael@0 1242 params[2] = mState.colorClearValue.blue;
michael@0 1243 params[3] = mState.colorClearValue.alpha;
michael@0 1244 break;
michael@0 1245 case GL_BLEND_COLOR:
michael@0 1246 params[0] = mState.blendColor.red;
michael@0 1247 params[1] = mState.blendColor.green;
michael@0 1248 params[2] = mState.blendColor.blue;
michael@0 1249 params[3] = mState.blendColor.alpha;
michael@0 1250 break;
michael@0 1251 case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
michael@0 1252 if (!supportsTextureFilterAnisotropy())
michael@0 1253 {
michael@0 1254 return false;
michael@0 1255 }
michael@0 1256 *params = mMaxTextureAnisotropy;
michael@0 1257 break;
michael@0 1258 default:
michael@0 1259 return false;
michael@0 1260 }
michael@0 1261
michael@0 1262 return true;
michael@0 1263 }
michael@0 1264
michael@0 1265 bool Context::getIntegerv(GLenum pname, GLint *params)
michael@0 1266 {
michael@0 1267 if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
michael@0 1268 {
michael@0 1269 unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT);
michael@0 1270
michael@0 1271 if (colorAttachment >= mRenderer->getMaxRenderTargets())
michael@0 1272 {
michael@0 1273 // return true to stop further operation in the parent call
michael@0 1274 return gl::error(GL_INVALID_OPERATION, true);
michael@0 1275 }
michael@0 1276
michael@0 1277 Framebuffer *framebuffer = getDrawFramebuffer();
michael@0 1278
michael@0 1279 *params = framebuffer->getDrawBufferState(colorAttachment);
michael@0 1280 return true;
michael@0 1281 }
michael@0 1282
michael@0 1283 // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation
michael@0 1284 // because it is stored as a float, despite the fact that the GL ES 2.0 spec names
michael@0 1285 // GetIntegerv as its native query function. As it would require conversion in any
michael@0 1286 // case, this should make no difference to the calling application. You may find it in
michael@0 1287 // Context::getFloatv.
michael@0 1288 switch (pname)
michael@0 1289 {
michael@0 1290 case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break;
michael@0 1291 case GL_MAX_VERTEX_UNIFORM_VECTORS: *params = mRenderer->getMaxVertexUniformVectors(); break;
michael@0 1292 case GL_MAX_VARYING_VECTORS: *params = mRenderer->getMaxVaryingVectors(); break;
michael@0 1293 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxCombinedTextureImageUnits(); break;
michael@0 1294 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS: *params = mRenderer->getMaxVertexTextureImageUnits(); break;
michael@0 1295 case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break;
michael@0 1296 case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mRenderer->getMaxFragmentUniformVectors(); break;
michael@0 1297 case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break;
michael@0 1298 case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mRenderer->getMaxRenderTargets(); break;
michael@0 1299 case GL_MAX_DRAW_BUFFERS_EXT: *params = mRenderer->getMaxRenderTargets(); break;
michael@0 1300 case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break;
michael@0 1301 case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break;
michael@0 1302 case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break;
michael@0 1303 case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = mState.elementArrayBuffer.id(); break;
michael@0 1304 //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE
michael@0 1305 case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break;
michael@0 1306 case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break;
michael@0 1307 case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break;
michael@0 1308 case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break;
michael@0 1309 case GL_PACK_ALIGNMENT: *params = mState.packAlignment; break;
michael@0 1310 case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mState.packReverseRowOrder; break;
michael@0 1311 case GL_UNPACK_ALIGNMENT: *params = mState.unpackAlignment; break;
michael@0 1312 case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break;
michael@0 1313 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break;
michael@0 1314 case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break;
michael@0 1315 case GL_STENCIL_FUNC: *params = mState.depthStencil.stencilFunc; break;
michael@0 1316 case GL_STENCIL_REF: *params = mState.stencilRef; break;
michael@0 1317 case GL_STENCIL_VALUE_MASK: *params = mState.depthStencil.stencilMask; break;
michael@0 1318 case GL_STENCIL_BACK_FUNC: *params = mState.depthStencil.stencilBackFunc; break;
michael@0 1319 case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break;
michael@0 1320 case GL_STENCIL_BACK_VALUE_MASK: *params = mState.depthStencil.stencilBackMask; break;
michael@0 1321 case GL_STENCIL_FAIL: *params = mState.depthStencil.stencilFail; break;
michael@0 1322 case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilPassDepthFail; break;
michael@0 1323 case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilPassDepthPass; break;
michael@0 1324 case GL_STENCIL_BACK_FAIL: *params = mState.depthStencil.stencilBackFail; break;
michael@0 1325 case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilBackPassDepthFail; break;
michael@0 1326 case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilBackPassDepthPass; break;
michael@0 1327 case GL_DEPTH_FUNC: *params = mState.depthStencil.depthFunc; break;
michael@0 1328 case GL_BLEND_SRC_RGB: *params = mState.blend.sourceBlendRGB; break;
michael@0 1329 case GL_BLEND_SRC_ALPHA: *params = mState.blend.sourceBlendAlpha; break;
michael@0 1330 case GL_BLEND_DST_RGB: *params = mState.blend.destBlendRGB; break;
michael@0 1331 case GL_BLEND_DST_ALPHA: *params = mState.blend.destBlendAlpha; break;
michael@0 1332 case GL_BLEND_EQUATION_RGB: *params = mState.blend.blendEquationRGB; break;
michael@0 1333 case GL_BLEND_EQUATION_ALPHA: *params = mState.blend.blendEquationAlpha; break;
michael@0 1334 case GL_STENCIL_WRITEMASK: *params = mState.depthStencil.stencilWritemask; break;
michael@0 1335 case GL_STENCIL_BACK_WRITEMASK: *params = mState.depthStencil.stencilBackWritemask; break;
michael@0 1336 case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break;
michael@0 1337 case GL_SUBPIXEL_BITS: *params = 4; break;
michael@0 1338 case GL_MAX_TEXTURE_SIZE: *params = getMaximumTextureDimension(); break;
michael@0 1339 case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break;
michael@0 1340 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
michael@0 1341 params[0] = mNumCompressedTextureFormats;
michael@0 1342 break;
michael@0 1343 case GL_MAX_SAMPLES_ANGLE:
michael@0 1344 {
michael@0 1345 GLsizei maxSamples = getMaxSupportedSamples();
michael@0 1346 if (maxSamples != 0)
michael@0 1347 {
michael@0 1348 *params = maxSamples;
michael@0 1349 }
michael@0 1350 else
michael@0 1351 {
michael@0 1352 return false;
michael@0 1353 }
michael@0 1354
michael@0 1355 break;
michael@0 1356 }
michael@0 1357 case GL_SAMPLE_BUFFERS:
michael@0 1358 case GL_SAMPLES:
michael@0 1359 {
michael@0 1360 gl::Framebuffer *framebuffer = getDrawFramebuffer();
michael@0 1361 if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE)
michael@0 1362 {
michael@0 1363 switch (pname)
michael@0 1364 {
michael@0 1365 case GL_SAMPLE_BUFFERS:
michael@0 1366 if (framebuffer->getSamples() != 0)
michael@0 1367 {
michael@0 1368 *params = 1;
michael@0 1369 }
michael@0 1370 else
michael@0 1371 {
michael@0 1372 *params = 0;
michael@0 1373 }
michael@0 1374 break;
michael@0 1375 case GL_SAMPLES:
michael@0 1376 *params = framebuffer->getSamples();
michael@0 1377 break;
michael@0 1378 }
michael@0 1379 }
michael@0 1380 else
michael@0 1381 {
michael@0 1382 *params = 0;
michael@0 1383 }
michael@0 1384 }
michael@0 1385 break;
michael@0 1386 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
michael@0 1387 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
michael@0 1388 {
michael@0 1389 GLenum format, type;
michael@0 1390 if (getCurrentReadFormatType(&format, &type))
michael@0 1391 {
michael@0 1392 if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT)
michael@0 1393 *params = format;
michael@0 1394 else
michael@0 1395 *params = type;
michael@0 1396 }
michael@0 1397 }
michael@0 1398 break;
michael@0 1399 case GL_MAX_VIEWPORT_DIMS:
michael@0 1400 {
michael@0 1401 params[0] = mMaxViewportDimension;
michael@0 1402 params[1] = mMaxViewportDimension;
michael@0 1403 }
michael@0 1404 break;
michael@0 1405 case GL_COMPRESSED_TEXTURE_FORMATS:
michael@0 1406 {
michael@0 1407 if (supportsDXT1Textures())
michael@0 1408 {
michael@0 1409 *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
michael@0 1410 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
michael@0 1411 }
michael@0 1412 if (supportsDXT3Textures())
michael@0 1413 {
michael@0 1414 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE;
michael@0 1415 }
michael@0 1416 if (supportsDXT5Textures())
michael@0 1417 {
michael@0 1418 *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE;
michael@0 1419 }
michael@0 1420 }
michael@0 1421 break;
michael@0 1422 case GL_VIEWPORT:
michael@0 1423 params[0] = mState.viewport.x;
michael@0 1424 params[1] = mState.viewport.y;
michael@0 1425 params[2] = mState.viewport.width;
michael@0 1426 params[3] = mState.viewport.height;
michael@0 1427 break;
michael@0 1428 case GL_SCISSOR_BOX:
michael@0 1429 params[0] = mState.scissor.x;
michael@0 1430 params[1] = mState.scissor.y;
michael@0 1431 params[2] = mState.scissor.width;
michael@0 1432 params[3] = mState.scissor.height;
michael@0 1433 break;
michael@0 1434 case GL_CULL_FACE_MODE: *params = mState.rasterizer.cullMode; break;
michael@0 1435 case GL_FRONT_FACE: *params = mState.rasterizer.frontFace; break;
michael@0 1436 case GL_RED_BITS:
michael@0 1437 case GL_GREEN_BITS:
michael@0 1438 case GL_BLUE_BITS:
michael@0 1439 case GL_ALPHA_BITS:
michael@0 1440 {
michael@0 1441 gl::Framebuffer *framebuffer = getDrawFramebuffer();
michael@0 1442 gl::Renderbuffer *colorbuffer = framebuffer->getFirstColorbuffer();
michael@0 1443
michael@0 1444 if (colorbuffer)
michael@0 1445 {
michael@0 1446 switch (pname)
michael@0 1447 {
michael@0 1448 case GL_RED_BITS: *params = colorbuffer->getRedSize(); break;
michael@0 1449 case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break;
michael@0 1450 case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break;
michael@0 1451 case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break;
michael@0 1452 }
michael@0 1453 }
michael@0 1454 else
michael@0 1455 {
michael@0 1456 *params = 0;
michael@0 1457 }
michael@0 1458 }
michael@0 1459 break;
michael@0 1460 case GL_DEPTH_BITS:
michael@0 1461 {
michael@0 1462 gl::Framebuffer *framebuffer = getDrawFramebuffer();
michael@0 1463 gl::Renderbuffer *depthbuffer = framebuffer->getDepthbuffer();
michael@0 1464
michael@0 1465 if (depthbuffer)
michael@0 1466 {
michael@0 1467 *params = depthbuffer->getDepthSize();
michael@0 1468 }
michael@0 1469 else
michael@0 1470 {
michael@0 1471 *params = 0;
michael@0 1472 }
michael@0 1473 }
michael@0 1474 break;
michael@0 1475 case GL_STENCIL_BITS:
michael@0 1476 {
michael@0 1477 gl::Framebuffer *framebuffer = getDrawFramebuffer();
michael@0 1478 gl::Renderbuffer *stencilbuffer = framebuffer->getStencilbuffer();
michael@0 1479
michael@0 1480 if (stencilbuffer)
michael@0 1481 {
michael@0 1482 *params = stencilbuffer->getStencilSize();
michael@0 1483 }
michael@0 1484 else
michael@0 1485 {
michael@0 1486 *params = 0;
michael@0 1487 }
michael@0 1488 }
michael@0 1489 break;
michael@0 1490 case GL_TEXTURE_BINDING_2D:
michael@0 1491 {
michael@0 1492 if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1)
michael@0 1493 {
michael@0 1494 gl::error(GL_INVALID_OPERATION);
michael@0 1495 return false;
michael@0 1496 }
michael@0 1497
michael@0 1498 *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id();
michael@0 1499 }
michael@0 1500 break;
michael@0 1501 case GL_TEXTURE_BINDING_CUBE_MAP:
michael@0 1502 {
michael@0 1503 if (mState.activeSampler > mRenderer->getMaxCombinedTextureImageUnits() - 1)
michael@0 1504 {
michael@0 1505 gl::error(GL_INVALID_OPERATION);
michael@0 1506 return false;
michael@0 1507 }
michael@0 1508
michael@0 1509 *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id();
michael@0 1510 }
michael@0 1511 break;
michael@0 1512 case GL_RESET_NOTIFICATION_STRATEGY_EXT:
michael@0 1513 *params = mResetStrategy;
michael@0 1514 break;
michael@0 1515 case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
michael@0 1516 *params = 1;
michael@0 1517 break;
michael@0 1518 case GL_PROGRAM_BINARY_FORMATS_OES:
michael@0 1519 *params = GL_PROGRAM_BINARY_ANGLE;
michael@0 1520 break;
michael@0 1521 default:
michael@0 1522 return false;
michael@0 1523 }
michael@0 1524
michael@0 1525 return true;
michael@0 1526 }
michael@0 1527
michael@0 1528 bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams)
michael@0 1529 {
michael@0 1530 if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT)
michael@0 1531 {
michael@0 1532 *type = GL_INT;
michael@0 1533 *numParams = 1;
michael@0 1534 return true;
michael@0 1535 }
michael@0 1536
michael@0 1537 // Please note: the query type returned for DEPTH_CLEAR_VALUE in this implementation
michael@0 1538 // is FLOAT rather than INT, as would be suggested by the GL ES 2.0 spec. This is due
michael@0 1539 // to the fact that it is stored internally as a float, and so would require conversion
michael@0 1540 // if returned from Context::getIntegerv. Since this conversion is already implemented
michael@0 1541 // in the case that one calls glGetIntegerv to retrieve a float-typed state variable, we
michael@0 1542 // place DEPTH_CLEAR_VALUE with the floats. This should make no difference to the calling
michael@0 1543 // application.
michael@0 1544 switch (pname)
michael@0 1545 {
michael@0 1546 case GL_COMPRESSED_TEXTURE_FORMATS:
michael@0 1547 {
michael@0 1548 *type = GL_INT;
michael@0 1549 *numParams = mNumCompressedTextureFormats;
michael@0 1550 }
michael@0 1551 break;
michael@0 1552 case GL_SHADER_BINARY_FORMATS:
michael@0 1553 {
michael@0 1554 *type = GL_INT;
michael@0 1555 *numParams = 0;
michael@0 1556 }
michael@0 1557 break;
michael@0 1558 case GL_MAX_VERTEX_ATTRIBS:
michael@0 1559 case GL_MAX_VERTEX_UNIFORM_VECTORS:
michael@0 1560 case GL_MAX_VARYING_VECTORS:
michael@0 1561 case GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS:
michael@0 1562 case GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS:
michael@0 1563 case GL_MAX_TEXTURE_IMAGE_UNITS:
michael@0 1564 case GL_MAX_FRAGMENT_UNIFORM_VECTORS:
michael@0 1565 case GL_MAX_RENDERBUFFER_SIZE:
michael@0 1566 case GL_MAX_COLOR_ATTACHMENTS_EXT:
michael@0 1567 case GL_MAX_DRAW_BUFFERS_EXT:
michael@0 1568 case GL_NUM_SHADER_BINARY_FORMATS:
michael@0 1569 case GL_NUM_COMPRESSED_TEXTURE_FORMATS:
michael@0 1570 case GL_ARRAY_BUFFER_BINDING:
michael@0 1571 case GL_FRAMEBUFFER_BINDING:
michael@0 1572 case GL_RENDERBUFFER_BINDING:
michael@0 1573 case GL_CURRENT_PROGRAM:
michael@0 1574 case GL_PACK_ALIGNMENT:
michael@0 1575 case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
michael@0 1576 case GL_UNPACK_ALIGNMENT:
michael@0 1577 case GL_GENERATE_MIPMAP_HINT:
michael@0 1578 case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
michael@0 1579 case GL_RED_BITS:
michael@0 1580 case GL_GREEN_BITS:
michael@0 1581 case GL_BLUE_BITS:
michael@0 1582 case GL_ALPHA_BITS:
michael@0 1583 case GL_DEPTH_BITS:
michael@0 1584 case GL_STENCIL_BITS:
michael@0 1585 case GL_ELEMENT_ARRAY_BUFFER_BINDING:
michael@0 1586 case GL_CULL_FACE_MODE:
michael@0 1587 case GL_FRONT_FACE:
michael@0 1588 case GL_ACTIVE_TEXTURE:
michael@0 1589 case GL_STENCIL_FUNC:
michael@0 1590 case GL_STENCIL_VALUE_MASK:
michael@0 1591 case GL_STENCIL_REF:
michael@0 1592 case GL_STENCIL_FAIL:
michael@0 1593 case GL_STENCIL_PASS_DEPTH_FAIL:
michael@0 1594 case GL_STENCIL_PASS_DEPTH_PASS:
michael@0 1595 case GL_STENCIL_BACK_FUNC:
michael@0 1596 case GL_STENCIL_BACK_VALUE_MASK:
michael@0 1597 case GL_STENCIL_BACK_REF:
michael@0 1598 case GL_STENCIL_BACK_FAIL:
michael@0 1599 case GL_STENCIL_BACK_PASS_DEPTH_FAIL:
michael@0 1600 case GL_STENCIL_BACK_PASS_DEPTH_PASS:
michael@0 1601 case GL_DEPTH_FUNC:
michael@0 1602 case GL_BLEND_SRC_RGB:
michael@0 1603 case GL_BLEND_SRC_ALPHA:
michael@0 1604 case GL_BLEND_DST_RGB:
michael@0 1605 case GL_BLEND_DST_ALPHA:
michael@0 1606 case GL_BLEND_EQUATION_RGB:
michael@0 1607 case GL_BLEND_EQUATION_ALPHA:
michael@0 1608 case GL_STENCIL_WRITEMASK:
michael@0 1609 case GL_STENCIL_BACK_WRITEMASK:
michael@0 1610 case GL_STENCIL_CLEAR_VALUE:
michael@0 1611 case GL_SUBPIXEL_BITS:
michael@0 1612 case GL_MAX_TEXTURE_SIZE:
michael@0 1613 case GL_MAX_CUBE_MAP_TEXTURE_SIZE:
michael@0 1614 case GL_SAMPLE_BUFFERS:
michael@0 1615 case GL_SAMPLES:
michael@0 1616 case GL_IMPLEMENTATION_COLOR_READ_TYPE:
michael@0 1617 case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
michael@0 1618 case GL_TEXTURE_BINDING_2D:
michael@0 1619 case GL_TEXTURE_BINDING_CUBE_MAP:
michael@0 1620 case GL_RESET_NOTIFICATION_STRATEGY_EXT:
michael@0 1621 case GL_NUM_PROGRAM_BINARY_FORMATS_OES:
michael@0 1622 case GL_PROGRAM_BINARY_FORMATS_OES:
michael@0 1623 {
michael@0 1624 *type = GL_INT;
michael@0 1625 *numParams = 1;
michael@0 1626 }
michael@0 1627 break;
michael@0 1628 case GL_MAX_SAMPLES_ANGLE:
michael@0 1629 {
michael@0 1630 if (getMaxSupportedSamples() != 0)
michael@0 1631 {
michael@0 1632 *type = GL_INT;
michael@0 1633 *numParams = 1;
michael@0 1634 }
michael@0 1635 else
michael@0 1636 {
michael@0 1637 return false;
michael@0 1638 }
michael@0 1639 }
michael@0 1640 break;
michael@0 1641 case GL_MAX_VIEWPORT_DIMS:
michael@0 1642 {
michael@0 1643 *type = GL_INT;
michael@0 1644 *numParams = 2;
michael@0 1645 }
michael@0 1646 break;
michael@0 1647 case GL_VIEWPORT:
michael@0 1648 case GL_SCISSOR_BOX:
michael@0 1649 {
michael@0 1650 *type = GL_INT;
michael@0 1651 *numParams = 4;
michael@0 1652 }
michael@0 1653 break;
michael@0 1654 case GL_SHADER_COMPILER:
michael@0 1655 case GL_SAMPLE_COVERAGE_INVERT:
michael@0 1656 case GL_DEPTH_WRITEMASK:
michael@0 1657 case GL_CULL_FACE: // CULL_FACE through DITHER are natural to IsEnabled,
michael@0 1658 case GL_POLYGON_OFFSET_FILL: // but can be retrieved through the Get{Type}v queries.
michael@0 1659 case GL_SAMPLE_ALPHA_TO_COVERAGE: // For this purpose, they are treated here as bool-natural
michael@0 1660 case GL_SAMPLE_COVERAGE:
michael@0 1661 case GL_SCISSOR_TEST:
michael@0 1662 case GL_STENCIL_TEST:
michael@0 1663 case GL_DEPTH_TEST:
michael@0 1664 case GL_BLEND:
michael@0 1665 case GL_DITHER:
michael@0 1666 case GL_CONTEXT_ROBUST_ACCESS_EXT:
michael@0 1667 {
michael@0 1668 *type = GL_BOOL;
michael@0 1669 *numParams = 1;
michael@0 1670 }
michael@0 1671 break;
michael@0 1672 case GL_COLOR_WRITEMASK:
michael@0 1673 {
michael@0 1674 *type = GL_BOOL;
michael@0 1675 *numParams = 4;
michael@0 1676 }
michael@0 1677 break;
michael@0 1678 case GL_POLYGON_OFFSET_FACTOR:
michael@0 1679 case GL_POLYGON_OFFSET_UNITS:
michael@0 1680 case GL_SAMPLE_COVERAGE_VALUE:
michael@0 1681 case GL_DEPTH_CLEAR_VALUE:
michael@0 1682 case GL_LINE_WIDTH:
michael@0 1683 {
michael@0 1684 *type = GL_FLOAT;
michael@0 1685 *numParams = 1;
michael@0 1686 }
michael@0 1687 break;
michael@0 1688 case GL_ALIASED_LINE_WIDTH_RANGE:
michael@0 1689 case GL_ALIASED_POINT_SIZE_RANGE:
michael@0 1690 case GL_DEPTH_RANGE:
michael@0 1691 {
michael@0 1692 *type = GL_FLOAT;
michael@0 1693 *numParams = 2;
michael@0 1694 }
michael@0 1695 break;
michael@0 1696 case GL_COLOR_CLEAR_VALUE:
michael@0 1697 case GL_BLEND_COLOR:
michael@0 1698 {
michael@0 1699 *type = GL_FLOAT;
michael@0 1700 *numParams = 4;
michael@0 1701 }
michael@0 1702 break;
michael@0 1703 case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT:
michael@0 1704 if (!supportsTextureFilterAnisotropy())
michael@0 1705 {
michael@0 1706 return false;
michael@0 1707 }
michael@0 1708 *type = GL_FLOAT;
michael@0 1709 *numParams = 1;
michael@0 1710 break;
michael@0 1711 default:
michael@0 1712 return false;
michael@0 1713 }
michael@0 1714
michael@0 1715 return true;
michael@0 1716 }
michael@0 1717
michael@0 1718 // Applies the render target surface, depth stencil surface, viewport rectangle and
michael@0 1719 // scissor rectangle to the renderer
michael@0 1720 bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport)
michael@0 1721 {
michael@0 1722 Framebuffer *framebufferObject = getDrawFramebuffer();
michael@0 1723
michael@0 1724 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
michael@0 1725 {
michael@0 1726 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
michael@0 1727 }
michael@0 1728
michael@0 1729 mRenderer->applyRenderTarget(framebufferObject);
michael@0 1730
michael@0 1731 if (!mRenderer->setViewport(mState.viewport, mState.zNear, mState.zFar, drawMode, mState.rasterizer.frontFace,
michael@0 1732 ignoreViewport))
michael@0 1733 {
michael@0 1734 return false;
michael@0 1735 }
michael@0 1736
michael@0 1737 mRenderer->setScissorRectangle(mState.scissor, mState.scissorTest);
michael@0 1738
michael@0 1739 return true;
michael@0 1740 }
michael@0 1741
michael@0 1742 // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device
michael@0 1743 void Context::applyState(GLenum drawMode)
michael@0 1744 {
michael@0 1745 Framebuffer *framebufferObject = getDrawFramebuffer();
michael@0 1746 int samples = framebufferObject->getSamples();
michael@0 1747
michael@0 1748 mState.rasterizer.pointDrawMode = (drawMode == GL_POINTS);
michael@0 1749 mState.rasterizer.multiSample = (samples != 0);
michael@0 1750 mRenderer->setRasterizerState(mState.rasterizer);
michael@0 1751
michael@0 1752 unsigned int mask = 0;
michael@0 1753 if (mState.sampleCoverage)
michael@0 1754 {
michael@0 1755 if (mState.sampleCoverageValue != 0)
michael@0 1756 {
michael@0 1757
michael@0 1758 float threshold = 0.5f;
michael@0 1759
michael@0 1760 for (int i = 0; i < samples; ++i)
michael@0 1761 {
michael@0 1762 mask <<= 1;
michael@0 1763
michael@0 1764 if ((i + 1) * mState.sampleCoverageValue >= threshold)
michael@0 1765 {
michael@0 1766 threshold += 1.0f;
michael@0 1767 mask |= 1;
michael@0 1768 }
michael@0 1769 }
michael@0 1770 }
michael@0 1771
michael@0 1772 if (mState.sampleCoverageInvert)
michael@0 1773 {
michael@0 1774 mask = ~mask;
michael@0 1775 }
michael@0 1776 }
michael@0 1777 else
michael@0 1778 {
michael@0 1779 mask = 0xFFFFFFFF;
michael@0 1780 }
michael@0 1781 mRenderer->setBlendState(mState.blend, mState.blendColor, mask);
michael@0 1782
michael@0 1783 mRenderer->setDepthStencilState(mState.depthStencil, mState.stencilRef, mState.stencilBackRef,
michael@0 1784 mState.rasterizer.frontFace == GL_CCW);
michael@0 1785 }
michael@0 1786
michael@0 1787 // Applies the shaders and shader constants to the Direct3D 9 device
michael@0 1788 void Context::applyShaders()
michael@0 1789 {
michael@0 1790 ProgramBinary *programBinary = getCurrentProgramBinary();
michael@0 1791
michael@0 1792 mRenderer->applyShaders(programBinary);
michael@0 1793
michael@0 1794 programBinary->applyUniforms();
michael@0 1795 }
michael@0 1796
michael@0 1797 // Applies the textures and sampler states to the Direct3D 9 device
michael@0 1798 void Context::applyTextures()
michael@0 1799 {
michael@0 1800 applyTextures(SAMPLER_PIXEL);
michael@0 1801
michael@0 1802 if (mSupportsVertexTexture)
michael@0 1803 {
michael@0 1804 applyTextures(SAMPLER_VERTEX);
michael@0 1805 }
michael@0 1806 }
michael@0 1807
michael@0 1808 // For each Direct3D 9 sampler of either the pixel or vertex stage,
michael@0 1809 // looks up the corresponding OpenGL texture image unit and texture type,
michael@0 1810 // and sets the texture and its addressing/filtering state (or NULL when inactive).
michael@0 1811 void Context::applyTextures(SamplerType type)
michael@0 1812 {
michael@0 1813 ProgramBinary *programBinary = getCurrentProgramBinary();
michael@0 1814
michael@0 1815 // Range of Direct3D samplers of given sampler type
michael@0 1816 int samplerCount = (type == SAMPLER_PIXEL) ? MAX_TEXTURE_IMAGE_UNITS : mRenderer->getMaxVertexTextureImageUnits();
michael@0 1817 int samplerRange = programBinary->getUsedSamplerRange(type);
michael@0 1818
michael@0 1819 for (int samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
michael@0 1820 {
michael@0 1821 int textureUnit = programBinary->getSamplerMapping(type, samplerIndex); // OpenGL texture image unit index
michael@0 1822
michael@0 1823 if (textureUnit != -1)
michael@0 1824 {
michael@0 1825 TextureType textureType = programBinary->getSamplerTextureType(type, samplerIndex);
michael@0 1826 Texture *texture = getSamplerTexture(textureUnit, textureType);
michael@0 1827
michael@0 1828 if (texture->isSamplerComplete())
michael@0 1829 {
michael@0 1830 SamplerState samplerState;
michael@0 1831 texture->getSamplerState(&samplerState);
michael@0 1832 mRenderer->setSamplerState(type, samplerIndex, samplerState);
michael@0 1833
michael@0 1834 mRenderer->setTexture(type, samplerIndex, texture);
michael@0 1835
michael@0 1836 texture->resetDirty();
michael@0 1837 }
michael@0 1838 else
michael@0 1839 {
michael@0 1840 mRenderer->setTexture(type, samplerIndex, getIncompleteTexture(textureType));
michael@0 1841 }
michael@0 1842 }
michael@0 1843 else
michael@0 1844 {
michael@0 1845 mRenderer->setTexture(type, samplerIndex, NULL);
michael@0 1846 }
michael@0 1847 }
michael@0 1848
michael@0 1849 for (int samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
michael@0 1850 {
michael@0 1851 mRenderer->setTexture(type, samplerIndex, NULL);
michael@0 1852 }
michael@0 1853 }
michael@0 1854
michael@0 1855 void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
michael@0 1856 GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
michael@0 1857 {
michael@0 1858 Framebuffer *framebuffer = getReadFramebuffer();
michael@0 1859
michael@0 1860 if (framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
michael@0 1861 {
michael@0 1862 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
michael@0 1863 }
michael@0 1864
michael@0 1865 if (getReadFramebufferHandle() != 0 && framebuffer->getSamples() != 0)
michael@0 1866 {
michael@0 1867 return gl::error(GL_INVALID_OPERATION);
michael@0 1868 }
michael@0 1869
michael@0 1870 GLsizei outputPitch = ComputePitch(width, ConvertSizedInternalFormat(format, type), getPackAlignment());
michael@0 1871 // sized query sanity check
michael@0 1872 if (bufSize)
michael@0 1873 {
michael@0 1874 int requiredSize = outputPitch * height;
michael@0 1875 if (requiredSize > *bufSize)
michael@0 1876 {
michael@0 1877 return gl::error(GL_INVALID_OPERATION);
michael@0 1878 }
michael@0 1879 }
michael@0 1880
michael@0 1881 mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, getPackReverseRowOrder(), getPackAlignment(), pixels);
michael@0 1882 }
michael@0 1883
michael@0 1884 void Context::clear(GLbitfield mask)
michael@0 1885 {
michael@0 1886 Framebuffer *framebufferObject = getDrawFramebuffer();
michael@0 1887
michael@0 1888 if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE)
michael@0 1889 {
michael@0 1890 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
michael@0 1891 }
michael@0 1892
michael@0 1893 DWORD flags = 0;
michael@0 1894 GLbitfield finalMask = 0;
michael@0 1895
michael@0 1896 if (mask & GL_COLOR_BUFFER_BIT)
michael@0 1897 {
michael@0 1898 mask &= ~GL_COLOR_BUFFER_BIT;
michael@0 1899
michael@0 1900 if (framebufferObject->hasEnabledColorAttachment())
michael@0 1901 {
michael@0 1902 finalMask |= GL_COLOR_BUFFER_BIT;
michael@0 1903 }
michael@0 1904 }
michael@0 1905
michael@0 1906 if (mask & GL_DEPTH_BUFFER_BIT)
michael@0 1907 {
michael@0 1908 mask &= ~GL_DEPTH_BUFFER_BIT;
michael@0 1909 if (mState.depthStencil.depthMask && framebufferObject->getDepthbufferType() != GL_NONE)
michael@0 1910 {
michael@0 1911 finalMask |= GL_DEPTH_BUFFER_BIT;
michael@0 1912 }
michael@0 1913 }
michael@0 1914
michael@0 1915 if (mask & GL_STENCIL_BUFFER_BIT)
michael@0 1916 {
michael@0 1917 mask &= ~GL_STENCIL_BUFFER_BIT;
michael@0 1918 if (framebufferObject->getStencilbufferType() != GL_NONE)
michael@0 1919 {
michael@0 1920 rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil();
michael@0 1921 if (!depthStencil)
michael@0 1922 {
michael@0 1923 ERR("Depth stencil pointer unexpectedly null.");
michael@0 1924 return;
michael@0 1925 }
michael@0 1926
michael@0 1927 if (GetStencilSize(depthStencil->getActualFormat()) > 0)
michael@0 1928 {
michael@0 1929 finalMask |= GL_STENCIL_BUFFER_BIT;
michael@0 1930 }
michael@0 1931 }
michael@0 1932 }
michael@0 1933
michael@0 1934 if (mask != 0)
michael@0 1935 {
michael@0 1936 return gl::error(GL_INVALID_VALUE);
michael@0 1937 }
michael@0 1938
michael@0 1939 if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport
michael@0 1940 {
michael@0 1941 return;
michael@0 1942 }
michael@0 1943
michael@0 1944 ClearParameters clearParams;
michael@0 1945 clearParams.mask = finalMask;
michael@0 1946 clearParams.colorClearValue = mState.colorClearValue;
michael@0 1947 clearParams.colorMaskRed = mState.blend.colorMaskRed;
michael@0 1948 clearParams.colorMaskGreen = mState.blend.colorMaskGreen;
michael@0 1949 clearParams.colorMaskBlue = mState.blend.colorMaskBlue;
michael@0 1950 clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha;
michael@0 1951 clearParams.depthClearValue = mState.depthClearValue;
michael@0 1952 clearParams.stencilClearValue = mState.stencilClearValue;
michael@0 1953 clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask;
michael@0 1954
michael@0 1955 mRenderer->clear(clearParams, framebufferObject);
michael@0 1956 }
michael@0 1957
michael@0 1958 void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
michael@0 1959 {
michael@0 1960 if (!mState.currentProgram)
michael@0 1961 {
michael@0 1962 return gl::error(GL_INVALID_OPERATION);
michael@0 1963 }
michael@0 1964
michael@0 1965 if (!mRenderer->applyPrimitiveType(mode, count))
michael@0 1966 {
michael@0 1967 return;
michael@0 1968 }
michael@0 1969
michael@0 1970 if (!applyRenderTarget(mode, false))
michael@0 1971 {
michael@0 1972 return;
michael@0 1973 }
michael@0 1974
michael@0 1975 applyState(mode);
michael@0 1976
michael@0 1977 ProgramBinary *programBinary = getCurrentProgramBinary();
michael@0 1978
michael@0 1979 GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, first, count, instances);
michael@0 1980 if (err != GL_NO_ERROR)
michael@0 1981 {
michael@0 1982 return gl::error(err);
michael@0 1983 }
michael@0 1984
michael@0 1985 applyShaders();
michael@0 1986 applyTextures();
michael@0 1987
michael@0 1988 if (!programBinary->validateSamplers(NULL))
michael@0 1989 {
michael@0 1990 return gl::error(GL_INVALID_OPERATION);
michael@0 1991 }
michael@0 1992
michael@0 1993 if (!skipDraw(mode))
michael@0 1994 {
michael@0 1995 mRenderer->drawArrays(mode, count, instances);
michael@0 1996 }
michael@0 1997 }
michael@0 1998
michael@0 1999 void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances)
michael@0 2000 {
michael@0 2001 if (!mState.currentProgram)
michael@0 2002 {
michael@0 2003 return gl::error(GL_INVALID_OPERATION);
michael@0 2004 }
michael@0 2005
michael@0 2006 if (!indices && !mState.elementArrayBuffer)
michael@0 2007 {
michael@0 2008 return gl::error(GL_INVALID_OPERATION);
michael@0 2009 }
michael@0 2010
michael@0 2011 if (!mRenderer->applyPrimitiveType(mode, count))
michael@0 2012 {
michael@0 2013 return;
michael@0 2014 }
michael@0 2015
michael@0 2016 if (!applyRenderTarget(mode, false))
michael@0 2017 {
michael@0 2018 return;
michael@0 2019 }
michael@0 2020
michael@0 2021 applyState(mode);
michael@0 2022
michael@0 2023 rx::TranslatedIndexData indexInfo;
michael@0 2024 GLenum err = mRenderer->applyIndexBuffer(indices, mState.elementArrayBuffer.get(), count, mode, type, &indexInfo);
michael@0 2025 if (err != GL_NO_ERROR)
michael@0 2026 {
michael@0 2027 return gl::error(err);
michael@0 2028 }
michael@0 2029
michael@0 2030 ProgramBinary *programBinary = getCurrentProgramBinary();
michael@0 2031
michael@0 2032 GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1;
michael@0 2033 err = mRenderer->applyVertexBuffer(programBinary, mState.vertexAttribute, indexInfo.minIndex, vertexCount, instances);
michael@0 2034 if (err != GL_NO_ERROR)
michael@0 2035 {
michael@0 2036 return gl::error(err);
michael@0 2037 }
michael@0 2038
michael@0 2039 applyShaders();
michael@0 2040 applyTextures();
michael@0 2041
michael@0 2042 if (!programBinary->validateSamplers(NULL))
michael@0 2043 {
michael@0 2044 return gl::error(GL_INVALID_OPERATION);
michael@0 2045 }
michael@0 2046
michael@0 2047 if (!skipDraw(mode))
michael@0 2048 {
michael@0 2049 mRenderer->drawElements(mode, count, type, indices, mState.elementArrayBuffer.get(), indexInfo, instances);
michael@0 2050 }
michael@0 2051 }
michael@0 2052
michael@0 2053 // Implements glFlush when block is false, glFinish when block is true
michael@0 2054 void Context::sync(bool block)
michael@0 2055 {
michael@0 2056 mRenderer->sync(block);
michael@0 2057 }
michael@0 2058
michael@0 2059 void Context::recordInvalidEnum()
michael@0 2060 {
michael@0 2061 mInvalidEnum = true;
michael@0 2062 }
michael@0 2063
michael@0 2064 void Context::recordInvalidValue()
michael@0 2065 {
michael@0 2066 mInvalidValue = true;
michael@0 2067 }
michael@0 2068
michael@0 2069 void Context::recordInvalidOperation()
michael@0 2070 {
michael@0 2071 mInvalidOperation = true;
michael@0 2072 }
michael@0 2073
michael@0 2074 void Context::recordOutOfMemory()
michael@0 2075 {
michael@0 2076 mOutOfMemory = true;
michael@0 2077 }
michael@0 2078
michael@0 2079 void Context::recordInvalidFramebufferOperation()
michael@0 2080 {
michael@0 2081 mInvalidFramebufferOperation = true;
michael@0 2082 }
michael@0 2083
michael@0 2084 // Get one of the recorded errors and clear its flag, if any.
michael@0 2085 // [OpenGL ES 2.0.24] section 2.5 page 13.
michael@0 2086 GLenum Context::getError()
michael@0 2087 {
michael@0 2088 if (mInvalidEnum)
michael@0 2089 {
michael@0 2090 mInvalidEnum = false;
michael@0 2091
michael@0 2092 return GL_INVALID_ENUM;
michael@0 2093 }
michael@0 2094
michael@0 2095 if (mInvalidValue)
michael@0 2096 {
michael@0 2097 mInvalidValue = false;
michael@0 2098
michael@0 2099 return GL_INVALID_VALUE;
michael@0 2100 }
michael@0 2101
michael@0 2102 if (mInvalidOperation)
michael@0 2103 {
michael@0 2104 mInvalidOperation = false;
michael@0 2105
michael@0 2106 return GL_INVALID_OPERATION;
michael@0 2107 }
michael@0 2108
michael@0 2109 if (mOutOfMemory)
michael@0 2110 {
michael@0 2111 mOutOfMemory = false;
michael@0 2112
michael@0 2113 return GL_OUT_OF_MEMORY;
michael@0 2114 }
michael@0 2115
michael@0 2116 if (mInvalidFramebufferOperation)
michael@0 2117 {
michael@0 2118 mInvalidFramebufferOperation = false;
michael@0 2119
michael@0 2120 return GL_INVALID_FRAMEBUFFER_OPERATION;
michael@0 2121 }
michael@0 2122
michael@0 2123 return GL_NO_ERROR;
michael@0 2124 }
michael@0 2125
michael@0 2126 GLenum Context::getResetStatus()
michael@0 2127 {
michael@0 2128 if (mResetStatus == GL_NO_ERROR && !mContextLost)
michael@0 2129 {
michael@0 2130 // mResetStatus will be set by the markContextLost callback
michael@0 2131 // in the case a notification is sent
michael@0 2132 mRenderer->testDeviceLost(true);
michael@0 2133 }
michael@0 2134
michael@0 2135 GLenum status = mResetStatus;
michael@0 2136
michael@0 2137 if (mResetStatus != GL_NO_ERROR)
michael@0 2138 {
michael@0 2139 ASSERT(mContextLost);
michael@0 2140
michael@0 2141 if (mRenderer->testDeviceResettable())
michael@0 2142 {
michael@0 2143 mResetStatus = GL_NO_ERROR;
michael@0 2144 }
michael@0 2145 }
michael@0 2146
michael@0 2147 return status;
michael@0 2148 }
michael@0 2149
michael@0 2150 bool Context::isResetNotificationEnabled()
michael@0 2151 {
michael@0 2152 return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT);
michael@0 2153 }
michael@0 2154
michael@0 2155 int Context::getMajorShaderModel() const
michael@0 2156 {
michael@0 2157 return mMajorShaderModel;
michael@0 2158 }
michael@0 2159
michael@0 2160 float Context::getMaximumPointSize() const
michael@0 2161 {
michael@0 2162 return mMaximumPointSize;
michael@0 2163 }
michael@0 2164
michael@0 2165 unsigned int Context::getMaximumCombinedTextureImageUnits() const
michael@0 2166 {
michael@0 2167 return mRenderer->getMaxCombinedTextureImageUnits();
michael@0 2168 }
michael@0 2169
michael@0 2170 int Context::getMaxSupportedSamples() const
michael@0 2171 {
michael@0 2172 return mRenderer->getMaxSupportedSamples();
michael@0 2173 }
michael@0 2174
michael@0 2175 unsigned int Context::getMaximumRenderTargets() const
michael@0 2176 {
michael@0 2177 return mRenderer->getMaxRenderTargets();
michael@0 2178 }
michael@0 2179
michael@0 2180 bool Context::supportsEventQueries() const
michael@0 2181 {
michael@0 2182 return mSupportsEventQueries;
michael@0 2183 }
michael@0 2184
michael@0 2185 bool Context::supportsOcclusionQueries() const
michael@0 2186 {
michael@0 2187 return mSupportsOcclusionQueries;
michael@0 2188 }
michael@0 2189
michael@0 2190 bool Context::supportsBGRATextures() const
michael@0 2191 {
michael@0 2192 return mSupportsBGRATextures;
michael@0 2193 }
michael@0 2194
michael@0 2195 bool Context::supportsDXT1Textures() const
michael@0 2196 {
michael@0 2197 return mSupportsDXT1Textures;
michael@0 2198 }
michael@0 2199
michael@0 2200 bool Context::supportsDXT3Textures() const
michael@0 2201 {
michael@0 2202 return mSupportsDXT3Textures;
michael@0 2203 }
michael@0 2204
michael@0 2205 bool Context::supportsDXT5Textures() const
michael@0 2206 {
michael@0 2207 return mSupportsDXT5Textures;
michael@0 2208 }
michael@0 2209
michael@0 2210 bool Context::supportsFloat32Textures() const
michael@0 2211 {
michael@0 2212 return mSupportsFloat32Textures;
michael@0 2213 }
michael@0 2214
michael@0 2215 bool Context::supportsFloat32LinearFilter() const
michael@0 2216 {
michael@0 2217 return mSupportsFloat32LinearFilter;
michael@0 2218 }
michael@0 2219
michael@0 2220 bool Context::supportsFloat32RenderableTextures() const
michael@0 2221 {
michael@0 2222 return mSupportsFloat32RenderableTextures;
michael@0 2223 }
michael@0 2224
michael@0 2225 bool Context::supportsFloat16Textures() const
michael@0 2226 {
michael@0 2227 return mSupportsFloat16Textures;
michael@0 2228 }
michael@0 2229
michael@0 2230 bool Context::supportsFloat16LinearFilter() const
michael@0 2231 {
michael@0 2232 return mSupportsFloat16LinearFilter;
michael@0 2233 }
michael@0 2234
michael@0 2235 bool Context::supportsFloat16RenderableTextures() const
michael@0 2236 {
michael@0 2237 return mSupportsFloat16RenderableTextures;
michael@0 2238 }
michael@0 2239
michael@0 2240 int Context::getMaximumRenderbufferDimension() const
michael@0 2241 {
michael@0 2242 return mMaxRenderbufferDimension;
michael@0 2243 }
michael@0 2244
michael@0 2245 int Context::getMaximumTextureDimension() const
michael@0 2246 {
michael@0 2247 return mMaxTextureDimension;
michael@0 2248 }
michael@0 2249
michael@0 2250 int Context::getMaximumCubeTextureDimension() const
michael@0 2251 {
michael@0 2252 return mMaxCubeTextureDimension;
michael@0 2253 }
michael@0 2254
michael@0 2255 int Context::getMaximumTextureLevel() const
michael@0 2256 {
michael@0 2257 return mMaxTextureLevel;
michael@0 2258 }
michael@0 2259
michael@0 2260 bool Context::supportsLuminanceTextures() const
michael@0 2261 {
michael@0 2262 return mSupportsLuminanceTextures;
michael@0 2263 }
michael@0 2264
michael@0 2265 bool Context::supportsLuminanceAlphaTextures() const
michael@0 2266 {
michael@0 2267 return mSupportsLuminanceAlphaTextures;
michael@0 2268 }
michael@0 2269
michael@0 2270 bool Context::supportsDepthTextures() const
michael@0 2271 {
michael@0 2272 return mSupportsDepthTextures;
michael@0 2273 }
michael@0 2274
michael@0 2275 bool Context::supports32bitIndices() const
michael@0 2276 {
michael@0 2277 return mSupports32bitIndices;
michael@0 2278 }
michael@0 2279
michael@0 2280 bool Context::supportsNonPower2Texture() const
michael@0 2281 {
michael@0 2282 return mSupportsNonPower2Texture;
michael@0 2283 }
michael@0 2284
michael@0 2285 bool Context::supportsInstancing() const
michael@0 2286 {
michael@0 2287 return mSupportsInstancing;
michael@0 2288 }
michael@0 2289
michael@0 2290 bool Context::supportsTextureFilterAnisotropy() const
michael@0 2291 {
michael@0 2292 return mSupportsTextureFilterAnisotropy;
michael@0 2293 }
michael@0 2294
michael@0 2295 float Context::getTextureMaxAnisotropy() const
michael@0 2296 {
michael@0 2297 return mMaxTextureAnisotropy;
michael@0 2298 }
michael@0 2299
michael@0 2300 bool Context::getCurrentReadFormatType(GLenum *format, GLenum *type)
michael@0 2301 {
michael@0 2302 Framebuffer *framebuffer = getReadFramebuffer();
michael@0 2303 if (!framebuffer || framebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
michael@0 2304 {
michael@0 2305 return gl::error(GL_INVALID_OPERATION, false);
michael@0 2306 }
michael@0 2307
michael@0 2308 Renderbuffer *renderbuffer = framebuffer->getReadColorbuffer();
michael@0 2309 if (!renderbuffer)
michael@0 2310 {
michael@0 2311 return gl::error(GL_INVALID_OPERATION, false);
michael@0 2312 }
michael@0 2313
michael@0 2314 *format = gl::ExtractFormat(renderbuffer->getActualFormat());
michael@0 2315 *type = gl::ExtractType(renderbuffer->getActualFormat());
michael@0 2316
michael@0 2317 return true;
michael@0 2318 }
michael@0 2319
michael@0 2320 void Context::detachBuffer(GLuint buffer)
michael@0 2321 {
michael@0 2322 // [OpenGL ES 2.0.24] section 2.9 page 22:
michael@0 2323 // If a buffer object is deleted while it is bound, all bindings to that object in the current context
michael@0 2324 // (i.e. in the thread that called Delete-Buffers) are reset to zero.
michael@0 2325
michael@0 2326 if (mState.arrayBuffer.id() == buffer)
michael@0 2327 {
michael@0 2328 mState.arrayBuffer.set(NULL);
michael@0 2329 }
michael@0 2330
michael@0 2331 if (mState.elementArrayBuffer.id() == buffer)
michael@0 2332 {
michael@0 2333 mState.elementArrayBuffer.set(NULL);
michael@0 2334 }
michael@0 2335
michael@0 2336 for (int attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
michael@0 2337 {
michael@0 2338 if (mState.vertexAttribute[attribute].mBoundBuffer.id() == buffer)
michael@0 2339 {
michael@0 2340 mState.vertexAttribute[attribute].mBoundBuffer.set(NULL);
michael@0 2341 }
michael@0 2342 }
michael@0 2343 }
michael@0 2344
michael@0 2345 void Context::detachTexture(GLuint texture)
michael@0 2346 {
michael@0 2347 // [OpenGL ES 2.0.24] section 3.8 page 84:
michael@0 2348 // If a texture object is deleted, it is as if all texture units which are bound to that texture object are
michael@0 2349 // rebound to texture object zero
michael@0 2350
michael@0 2351 for (int type = 0; type < TEXTURE_TYPE_COUNT; type++)
michael@0 2352 {
michael@0 2353 for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++)
michael@0 2354 {
michael@0 2355 if (mState.samplerTexture[type][sampler].id() == texture)
michael@0 2356 {
michael@0 2357 mState.samplerTexture[type][sampler].set(NULL);
michael@0 2358 }
michael@0 2359 }
michael@0 2360 }
michael@0 2361
michael@0 2362 // [OpenGL ES 2.0.24] section 4.4 page 112:
michael@0 2363 // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is
michael@0 2364 // as if FramebufferTexture2D had been called, with a texture of 0, for each attachment point to which this
michael@0 2365 // image was attached in the currently bound framebuffer.
michael@0 2366
michael@0 2367 Framebuffer *readFramebuffer = getReadFramebuffer();
michael@0 2368 Framebuffer *drawFramebuffer = getDrawFramebuffer();
michael@0 2369
michael@0 2370 if (readFramebuffer)
michael@0 2371 {
michael@0 2372 readFramebuffer->detachTexture(texture);
michael@0 2373 }
michael@0 2374
michael@0 2375 if (drawFramebuffer && drawFramebuffer != readFramebuffer)
michael@0 2376 {
michael@0 2377 drawFramebuffer->detachTexture(texture);
michael@0 2378 }
michael@0 2379 }
michael@0 2380
michael@0 2381 void Context::detachFramebuffer(GLuint framebuffer)
michael@0 2382 {
michael@0 2383 // [OpenGL ES 2.0.24] section 4.4 page 107:
michael@0 2384 // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
michael@0 2385 // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
michael@0 2386
michael@0 2387 if (mState.readFramebuffer == framebuffer)
michael@0 2388 {
michael@0 2389 bindReadFramebuffer(0);
michael@0 2390 }
michael@0 2391
michael@0 2392 if (mState.drawFramebuffer == framebuffer)
michael@0 2393 {
michael@0 2394 bindDrawFramebuffer(0);
michael@0 2395 }
michael@0 2396 }
michael@0 2397
michael@0 2398 void Context::detachRenderbuffer(GLuint renderbuffer)
michael@0 2399 {
michael@0 2400 // [OpenGL ES 2.0.24] section 4.4 page 109:
michael@0 2401 // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer
michael@0 2402 // had been executed with the target RENDERBUFFER and name of zero.
michael@0 2403
michael@0 2404 if (mState.renderbuffer.id() == renderbuffer)
michael@0 2405 {
michael@0 2406 bindRenderbuffer(0);
michael@0 2407 }
michael@0 2408
michael@0 2409 // [OpenGL ES 2.0.24] section 4.4 page 111:
michael@0 2410 // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer,
michael@0 2411 // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment
michael@0 2412 // point to which this image was attached in the currently bound framebuffer.
michael@0 2413
michael@0 2414 Framebuffer *readFramebuffer = getReadFramebuffer();
michael@0 2415 Framebuffer *drawFramebuffer = getDrawFramebuffer();
michael@0 2416
michael@0 2417 if (readFramebuffer)
michael@0 2418 {
michael@0 2419 readFramebuffer->detachRenderbuffer(renderbuffer);
michael@0 2420 }
michael@0 2421
michael@0 2422 if (drawFramebuffer && drawFramebuffer != readFramebuffer)
michael@0 2423 {
michael@0 2424 drawFramebuffer->detachRenderbuffer(renderbuffer);
michael@0 2425 }
michael@0 2426 }
michael@0 2427
michael@0 2428 Texture *Context::getIncompleteTexture(TextureType type)
michael@0 2429 {
michael@0 2430 Texture *t = mIncompleteTextures[type].get();
michael@0 2431
michael@0 2432 if (t == NULL)
michael@0 2433 {
michael@0 2434 static const GLubyte color[] = { 0, 0, 0, 255 };
michael@0 2435
michael@0 2436 switch (type)
michael@0 2437 {
michael@0 2438 default:
michael@0 2439 UNREACHABLE();
michael@0 2440 // default falls through to TEXTURE_2D
michael@0 2441
michael@0 2442 case TEXTURE_2D:
michael@0 2443 {
michael@0 2444 Texture2D *incomplete2d = new Texture2D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID);
michael@0 2445 incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
michael@0 2446 t = incomplete2d;
michael@0 2447 }
michael@0 2448 break;
michael@0 2449
michael@0 2450 case TEXTURE_CUBE:
michael@0 2451 {
michael@0 2452 TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer, Texture::INCOMPLETE_TEXTURE_ID);
michael@0 2453
michael@0 2454 incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
michael@0 2455 incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
michael@0 2456 incompleteCube->setImagePosY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
michael@0 2457 incompleteCube->setImageNegY(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
michael@0 2458 incompleteCube->setImagePosZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
michael@0 2459 incompleteCube->setImageNegZ(0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, 1, color);
michael@0 2460
michael@0 2461 t = incompleteCube;
michael@0 2462 }
michael@0 2463 break;
michael@0 2464 }
michael@0 2465
michael@0 2466 mIncompleteTextures[type].set(t);
michael@0 2467 }
michael@0 2468
michael@0 2469 return t;
michael@0 2470 }
michael@0 2471
michael@0 2472 bool Context::skipDraw(GLenum drawMode)
michael@0 2473 {
michael@0 2474 if (drawMode == GL_POINTS)
michael@0 2475 {
michael@0 2476 // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
michael@0 2477 // which affects varying interpolation. Since the value of gl_PointSize is
michael@0 2478 // undefined when not written, just skip drawing to avoid unexpected results.
michael@0 2479 if (!getCurrentProgramBinary()->usesPointSize())
michael@0 2480 {
michael@0 2481 // This is stictly speaking not an error, but developers should be
michael@0 2482 // notified of risking undefined behavior.
michael@0 2483 ERR("Point rendering without writing to gl_PointSize.");
michael@0 2484
michael@0 2485 return true;
michael@0 2486 }
michael@0 2487 }
michael@0 2488 else if (IsTriangleMode(drawMode))
michael@0 2489 {
michael@0 2490 if (mState.rasterizer.cullFace && mState.rasterizer.cullMode == GL_FRONT_AND_BACK)
michael@0 2491 {
michael@0 2492 return true;
michael@0 2493 }
michael@0 2494 }
michael@0 2495
michael@0 2496 return false;
michael@0 2497 }
michael@0 2498
michael@0 2499 void Context::setVertexAttrib(GLuint index, const GLfloat *values)
michael@0 2500 {
michael@0 2501 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
michael@0 2502
michael@0 2503 mState.vertexAttribute[index].mCurrentValue[0] = values[0];
michael@0 2504 mState.vertexAttribute[index].mCurrentValue[1] = values[1];
michael@0 2505 mState.vertexAttribute[index].mCurrentValue[2] = values[2];
michael@0 2506 mState.vertexAttribute[index].mCurrentValue[3] = values[3];
michael@0 2507 }
michael@0 2508
michael@0 2509 void Context::setVertexAttribDivisor(GLuint index, GLuint divisor)
michael@0 2510 {
michael@0 2511 ASSERT(index < gl::MAX_VERTEX_ATTRIBS);
michael@0 2512
michael@0 2513 mState.vertexAttribute[index].mDivisor = divisor;
michael@0 2514 }
michael@0 2515
michael@0 2516 // keep list sorted in following order
michael@0 2517 // OES extensions
michael@0 2518 // EXT extensions
michael@0 2519 // Vendor extensions
michael@0 2520 void Context::initExtensionString()
michael@0 2521 {
michael@0 2522 std::string extensionString = "";
michael@0 2523
michael@0 2524 // OES extensions
michael@0 2525 if (supports32bitIndices())
michael@0 2526 {
michael@0 2527 extensionString += "GL_OES_element_index_uint ";
michael@0 2528 }
michael@0 2529
michael@0 2530 extensionString += "GL_OES_packed_depth_stencil ";
michael@0 2531 extensionString += "GL_OES_get_program_binary ";
michael@0 2532 extensionString += "GL_OES_rgb8_rgba8 ";
michael@0 2533 if (mRenderer->getDerivativeInstructionSupport())
michael@0 2534 {
michael@0 2535 extensionString += "GL_OES_standard_derivatives ";
michael@0 2536 }
michael@0 2537
michael@0 2538 if (supportsFloat16Textures())
michael@0 2539 {
michael@0 2540 extensionString += "GL_OES_texture_half_float ";
michael@0 2541 }
michael@0 2542 if (supportsFloat16LinearFilter())
michael@0 2543 {
michael@0 2544 extensionString += "GL_OES_texture_half_float_linear ";
michael@0 2545 }
michael@0 2546 if (supportsFloat32Textures())
michael@0 2547 {
michael@0 2548 extensionString += "GL_OES_texture_float ";
michael@0 2549 }
michael@0 2550 if (supportsFloat32LinearFilter())
michael@0 2551 {
michael@0 2552 extensionString += "GL_OES_texture_float_linear ";
michael@0 2553 }
michael@0 2554
michael@0 2555 if (supportsNonPower2Texture())
michael@0 2556 {
michael@0 2557 extensionString += "GL_OES_texture_npot ";
michael@0 2558 }
michael@0 2559
michael@0 2560 // Multi-vendor (EXT) extensions
michael@0 2561 if (supportsOcclusionQueries())
michael@0 2562 {
michael@0 2563 extensionString += "GL_EXT_occlusion_query_boolean ";
michael@0 2564 }
michael@0 2565
michael@0 2566 extensionString += "GL_EXT_read_format_bgra ";
michael@0 2567 extensionString += "GL_EXT_robustness ";
michael@0 2568
michael@0 2569 if (supportsDXT1Textures())
michael@0 2570 {
michael@0 2571 extensionString += "GL_EXT_texture_compression_dxt1 ";
michael@0 2572 }
michael@0 2573
michael@0 2574 if (supportsTextureFilterAnisotropy())
michael@0 2575 {
michael@0 2576 extensionString += "GL_EXT_texture_filter_anisotropic ";
michael@0 2577 }
michael@0 2578
michael@0 2579 if (supportsBGRATextures())
michael@0 2580 {
michael@0 2581 extensionString += "GL_EXT_texture_format_BGRA8888 ";
michael@0 2582 }
michael@0 2583
michael@0 2584 if (mRenderer->getMaxRenderTargets() > 1)
michael@0 2585 {
michael@0 2586 extensionString += "GL_EXT_draw_buffers ";
michael@0 2587 }
michael@0 2588
michael@0 2589 extensionString += "GL_EXT_texture_storage ";
michael@0 2590 extensionString += "GL_EXT_frag_depth ";
michael@0 2591
michael@0 2592 // ANGLE-specific extensions
michael@0 2593 if (supportsDepthTextures())
michael@0 2594 {
michael@0 2595 extensionString += "GL_ANGLE_depth_texture ";
michael@0 2596 }
michael@0 2597
michael@0 2598 extensionString += "GL_ANGLE_framebuffer_blit ";
michael@0 2599 if (getMaxSupportedSamples() != 0)
michael@0 2600 {
michael@0 2601 extensionString += "GL_ANGLE_framebuffer_multisample ";
michael@0 2602 }
michael@0 2603
michael@0 2604 if (supportsInstancing())
michael@0 2605 {
michael@0 2606 extensionString += "GL_ANGLE_instanced_arrays ";
michael@0 2607 }
michael@0 2608
michael@0 2609 extensionString += "GL_ANGLE_pack_reverse_row_order ";
michael@0 2610
michael@0 2611 if (supportsDXT3Textures())
michael@0 2612 {
michael@0 2613 extensionString += "GL_ANGLE_texture_compression_dxt3 ";
michael@0 2614 }
michael@0 2615 if (supportsDXT5Textures())
michael@0 2616 {
michael@0 2617 extensionString += "GL_ANGLE_texture_compression_dxt5 ";
michael@0 2618 }
michael@0 2619
michael@0 2620 extensionString += "GL_ANGLE_texture_usage ";
michael@0 2621 extensionString += "GL_ANGLE_translated_shader_source ";
michael@0 2622
michael@0 2623 // Other vendor-specific extensions
michael@0 2624 if (supportsEventQueries())
michael@0 2625 {
michael@0 2626 extensionString += "GL_NV_fence ";
michael@0 2627 }
michael@0 2628
michael@0 2629 std::string::size_type end = extensionString.find_last_not_of(' ');
michael@0 2630 if (end != std::string::npos)
michael@0 2631 {
michael@0 2632 extensionString.resize(end+1);
michael@0 2633 }
michael@0 2634
michael@0 2635 mExtensionString = makeStaticString(extensionString);
michael@0 2636 }
michael@0 2637
michael@0 2638 const char *Context::getExtensionString() const
michael@0 2639 {
michael@0 2640 return mExtensionString;
michael@0 2641 }
michael@0 2642
michael@0 2643 void Context::initRendererString()
michael@0 2644 {
michael@0 2645 std::ostringstream rendererString;
michael@0 2646 rendererString << "ANGLE (";
michael@0 2647 rendererString << mRenderer->getRendererDescription();
michael@0 2648 rendererString << ")";
michael@0 2649
michael@0 2650 mRendererString = makeStaticString(rendererString.str());
michael@0 2651 }
michael@0 2652
michael@0 2653 const char *Context::getRendererString() const
michael@0 2654 {
michael@0 2655 return mRendererString;
michael@0 2656 }
michael@0 2657
michael@0 2658 void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
michael@0 2659 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
michael@0 2660 GLbitfield mask)
michael@0 2661 {
michael@0 2662 Framebuffer *readFramebuffer = getReadFramebuffer();
michael@0 2663 Framebuffer *drawFramebuffer = getDrawFramebuffer();
michael@0 2664
michael@0 2665 if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
michael@0 2666 !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
michael@0 2667 {
michael@0 2668 return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
michael@0 2669 }
michael@0 2670
michael@0 2671 if (drawFramebuffer->getSamples() != 0)
michael@0 2672 {
michael@0 2673 return gl::error(GL_INVALID_OPERATION);
michael@0 2674 }
michael@0 2675
michael@0 2676 Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
michael@0 2677 Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
michael@0 2678
michael@0 2679 if (drawColorBuffer == NULL)
michael@0 2680 {
michael@0 2681 ERR("Draw buffers formats don't match, which is not supported in this implementation of BlitFramebufferANGLE");
michael@0 2682 return gl::error(GL_INVALID_OPERATION);
michael@0 2683 }
michael@0 2684
michael@0 2685 int readBufferWidth = readColorBuffer->getWidth();
michael@0 2686 int readBufferHeight = readColorBuffer->getHeight();
michael@0 2687 int drawBufferWidth = drawColorBuffer->getWidth();
michael@0 2688 int drawBufferHeight = drawColorBuffer->getHeight();
michael@0 2689
michael@0 2690 Rectangle sourceRect;
michael@0 2691 Rectangle destRect;
michael@0 2692
michael@0 2693 if (srcX0 < srcX1)
michael@0 2694 {
michael@0 2695 sourceRect.x = srcX0;
michael@0 2696 destRect.x = dstX0;
michael@0 2697 sourceRect.width = srcX1 - srcX0;
michael@0 2698 destRect.width = dstX1 - dstX0;
michael@0 2699 }
michael@0 2700 else
michael@0 2701 {
michael@0 2702 sourceRect.x = srcX1;
michael@0 2703 destRect.x = dstX1;
michael@0 2704 sourceRect.width = srcX0 - srcX1;
michael@0 2705 destRect.width = dstX0 - dstX1;
michael@0 2706 }
michael@0 2707
michael@0 2708 if (srcY0 < srcY1)
michael@0 2709 {
michael@0 2710 sourceRect.height = srcY1 - srcY0;
michael@0 2711 destRect.height = dstY1 - dstY0;
michael@0 2712 sourceRect.y = srcY0;
michael@0 2713 destRect.y = dstY0;
michael@0 2714 }
michael@0 2715 else
michael@0 2716 {
michael@0 2717 sourceRect.height = srcY0 - srcY1;
michael@0 2718 destRect.height = dstY0 - srcY1;
michael@0 2719 sourceRect.y = srcY1;
michael@0 2720 destRect.y = dstY1;
michael@0 2721 }
michael@0 2722
michael@0 2723 Rectangle sourceScissoredRect = sourceRect;
michael@0 2724 Rectangle destScissoredRect = destRect;
michael@0 2725
michael@0 2726 if (mState.scissorTest)
michael@0 2727 {
michael@0 2728 // Only write to parts of the destination framebuffer which pass the scissor test.
michael@0 2729 if (destRect.x < mState.scissor.x)
michael@0 2730 {
michael@0 2731 int xDiff = mState.scissor.x - destRect.x;
michael@0 2732 destScissoredRect.x = mState.scissor.x;
michael@0 2733 destScissoredRect.width -= xDiff;
michael@0 2734 sourceScissoredRect.x += xDiff;
michael@0 2735 sourceScissoredRect.width -= xDiff;
michael@0 2736
michael@0 2737 }
michael@0 2738
michael@0 2739 if (destRect.x + destRect.width > mState.scissor.x + mState.scissor.width)
michael@0 2740 {
michael@0 2741 int xDiff = (destRect.x + destRect.width) - (mState.scissor.x + mState.scissor.width);
michael@0 2742 destScissoredRect.width -= xDiff;
michael@0 2743 sourceScissoredRect.width -= xDiff;
michael@0 2744 }
michael@0 2745
michael@0 2746 if (destRect.y < mState.scissor.y)
michael@0 2747 {
michael@0 2748 int yDiff = mState.scissor.y - destRect.y;
michael@0 2749 destScissoredRect.y = mState.scissor.y;
michael@0 2750 destScissoredRect.height -= yDiff;
michael@0 2751 sourceScissoredRect.y += yDiff;
michael@0 2752 sourceScissoredRect.height -= yDiff;
michael@0 2753 }
michael@0 2754
michael@0 2755 if (destRect.y + destRect.height > mState.scissor.y + mState.scissor.height)
michael@0 2756 {
michael@0 2757 int yDiff = (destRect.y + destRect.height) - (mState.scissor.y + mState.scissor.height);
michael@0 2758 destScissoredRect.height -= yDiff;
michael@0 2759 sourceScissoredRect.height -= yDiff;
michael@0 2760 }
michael@0 2761 }
michael@0 2762
michael@0 2763 bool blitRenderTarget = false;
michael@0 2764 bool blitDepthStencil = false;
michael@0 2765
michael@0 2766 Rectangle sourceTrimmedRect = sourceScissoredRect;
michael@0 2767 Rectangle destTrimmedRect = destScissoredRect;
michael@0 2768
michael@0 2769 // The source & destination rectangles also may need to be trimmed if they fall out of the bounds of
michael@0 2770 // the actual draw and read surfaces.
michael@0 2771 if (sourceTrimmedRect.x < 0)
michael@0 2772 {
michael@0 2773 int xDiff = 0 - sourceTrimmedRect.x;
michael@0 2774 sourceTrimmedRect.x = 0;
michael@0 2775 sourceTrimmedRect.width -= xDiff;
michael@0 2776 destTrimmedRect.x += xDiff;
michael@0 2777 destTrimmedRect.width -= xDiff;
michael@0 2778 }
michael@0 2779
michael@0 2780 if (sourceTrimmedRect.x + sourceTrimmedRect.width > readBufferWidth)
michael@0 2781 {
michael@0 2782 int xDiff = (sourceTrimmedRect.x + sourceTrimmedRect.width) - readBufferWidth;
michael@0 2783 sourceTrimmedRect.width -= xDiff;
michael@0 2784 destTrimmedRect.width -= xDiff;
michael@0 2785 }
michael@0 2786
michael@0 2787 if (sourceTrimmedRect.y < 0)
michael@0 2788 {
michael@0 2789 int yDiff = 0 - sourceTrimmedRect.y;
michael@0 2790 sourceTrimmedRect.y = 0;
michael@0 2791 sourceTrimmedRect.height -= yDiff;
michael@0 2792 destTrimmedRect.y += yDiff;
michael@0 2793 destTrimmedRect.height -= yDiff;
michael@0 2794 }
michael@0 2795
michael@0 2796 if (sourceTrimmedRect.y + sourceTrimmedRect.height > readBufferHeight)
michael@0 2797 {
michael@0 2798 int yDiff = (sourceTrimmedRect.y + sourceTrimmedRect.height) - readBufferHeight;
michael@0 2799 sourceTrimmedRect.height -= yDiff;
michael@0 2800 destTrimmedRect.height -= yDiff;
michael@0 2801 }
michael@0 2802
michael@0 2803 if (destTrimmedRect.x < 0)
michael@0 2804 {
michael@0 2805 int xDiff = 0 - destTrimmedRect.x;
michael@0 2806 destTrimmedRect.x = 0;
michael@0 2807 destTrimmedRect.width -= xDiff;
michael@0 2808 sourceTrimmedRect.x += xDiff;
michael@0 2809 sourceTrimmedRect.width -= xDiff;
michael@0 2810 }
michael@0 2811
michael@0 2812 if (destTrimmedRect.x + destTrimmedRect.width > drawBufferWidth)
michael@0 2813 {
michael@0 2814 int xDiff = (destTrimmedRect.x + destTrimmedRect.width) - drawBufferWidth;
michael@0 2815 destTrimmedRect.width -= xDiff;
michael@0 2816 sourceTrimmedRect.width -= xDiff;
michael@0 2817 }
michael@0 2818
michael@0 2819 if (destTrimmedRect.y < 0)
michael@0 2820 {
michael@0 2821 int yDiff = 0 - destTrimmedRect.y;
michael@0 2822 destTrimmedRect.y = 0;
michael@0 2823 destTrimmedRect.height -= yDiff;
michael@0 2824 sourceTrimmedRect.y += yDiff;
michael@0 2825 sourceTrimmedRect.height -= yDiff;
michael@0 2826 }
michael@0 2827
michael@0 2828 if (destTrimmedRect.y + destTrimmedRect.height > drawBufferHeight)
michael@0 2829 {
michael@0 2830 int yDiff = (destTrimmedRect.y + destTrimmedRect.height) - drawBufferHeight;
michael@0 2831 destTrimmedRect.height -= yDiff;
michael@0 2832 sourceTrimmedRect.height -= yDiff;
michael@0 2833 }
michael@0 2834
michael@0 2835 bool partialBufferCopy = false;
michael@0 2836 if (sourceTrimmedRect.height < readBufferHeight ||
michael@0 2837 sourceTrimmedRect.width < readBufferWidth ||
michael@0 2838 destTrimmedRect.height < drawBufferHeight ||
michael@0 2839 destTrimmedRect.width < drawBufferWidth ||
michael@0 2840 sourceTrimmedRect.y != 0 || destTrimmedRect.y != 0 || sourceTrimmedRect.x != 0 || destTrimmedRect.x != 0)
michael@0 2841 {
michael@0 2842 partialBufferCopy = true;
michael@0 2843 }
michael@0 2844
michael@0 2845 if (mask & GL_COLOR_BUFFER_BIT)
michael@0 2846 {
michael@0 2847 const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
michael@0 2848 const bool validReadType = (readColorbufferType == GL_TEXTURE_2D) || (readColorbufferType == GL_RENDERBUFFER);
michael@0 2849 bool validDrawType = true;
michael@0 2850 bool validDrawFormat = true;
michael@0 2851
michael@0 2852 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
michael@0 2853 {
michael@0 2854 if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
michael@0 2855 {
michael@0 2856 if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
michael@0 2857 drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
michael@0 2858 {
michael@0 2859 validDrawType = false;
michael@0 2860 }
michael@0 2861
michael@0 2862 if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
michael@0 2863 {
michael@0 2864 validDrawFormat = false;
michael@0 2865 }
michael@0 2866 }
michael@0 2867 }
michael@0 2868
michael@0 2869 if (!validReadType || !validDrawType || !validDrawFormat)
michael@0 2870 {
michael@0 2871 ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
michael@0 2872 return gl::error(GL_INVALID_OPERATION);
michael@0 2873 }
michael@0 2874
michael@0 2875 if (partialBufferCopy && readFramebuffer->getSamples() != 0)
michael@0 2876 {
michael@0 2877 return gl::error(GL_INVALID_OPERATION);
michael@0 2878 }
michael@0 2879
michael@0 2880 blitRenderTarget = true;
michael@0 2881
michael@0 2882 }
michael@0 2883
michael@0 2884 if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
michael@0 2885 {
michael@0 2886 Renderbuffer *readDSBuffer = NULL;
michael@0 2887 Renderbuffer *drawDSBuffer = NULL;
michael@0 2888
michael@0 2889 // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
michael@0 2890 // both a depth and stencil buffer, it will be the same buffer.
michael@0 2891
michael@0 2892 if (mask & GL_DEPTH_BUFFER_BIT)
michael@0 2893 {
michael@0 2894 if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
michael@0 2895 {
michael@0 2896 if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
michael@0 2897 readFramebuffer->getDepthbuffer()->getActualFormat() != drawFramebuffer->getDepthbuffer()->getActualFormat())
michael@0 2898 {
michael@0 2899 return gl::error(GL_INVALID_OPERATION);
michael@0 2900 }
michael@0 2901
michael@0 2902 blitDepthStencil = true;
michael@0 2903 readDSBuffer = readFramebuffer->getDepthbuffer();
michael@0 2904 drawDSBuffer = drawFramebuffer->getDepthbuffer();
michael@0 2905 }
michael@0 2906 }
michael@0 2907
michael@0 2908 if (mask & GL_STENCIL_BUFFER_BIT)
michael@0 2909 {
michael@0 2910 if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
michael@0 2911 {
michael@0 2912 if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
michael@0 2913 readFramebuffer->getStencilbuffer()->getActualFormat() != drawFramebuffer->getStencilbuffer()->getActualFormat())
michael@0 2914 {
michael@0 2915 return gl::error(GL_INVALID_OPERATION);
michael@0 2916 }
michael@0 2917
michael@0 2918 blitDepthStencil = true;
michael@0 2919 readDSBuffer = readFramebuffer->getStencilbuffer();
michael@0 2920 drawDSBuffer = drawFramebuffer->getStencilbuffer();
michael@0 2921 }
michael@0 2922 }
michael@0 2923
michael@0 2924 if (partialBufferCopy)
michael@0 2925 {
michael@0 2926 ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
michael@0 2927 return gl::error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted
michael@0 2928 }
michael@0 2929
michael@0 2930 if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) ||
michael@0 2931 (readDSBuffer && readDSBuffer->getSamples() != 0))
michael@0 2932 {
michael@0 2933 return gl::error(GL_INVALID_OPERATION);
michael@0 2934 }
michael@0 2935 }
michael@0 2936
michael@0 2937 if (blitRenderTarget || blitDepthStencil)
michael@0 2938 {
michael@0 2939 mRenderer->blitRect(readFramebuffer, sourceTrimmedRect, drawFramebuffer, destTrimmedRect, blitRenderTarget, blitDepthStencil);
michael@0 2940 }
michael@0 2941 }
michael@0 2942
michael@0 2943 }
michael@0 2944
michael@0 2945 extern "C"
michael@0 2946 {
michael@0 2947 gl::Context *glCreateContext(const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
michael@0 2948 {
michael@0 2949 return new gl::Context(shareContext, renderer, notifyResets, robustAccess);
michael@0 2950 }
michael@0 2951
michael@0 2952 void glDestroyContext(gl::Context *context)
michael@0 2953 {
michael@0 2954 delete context;
michael@0 2955
michael@0 2956 if (context == gl::getContext())
michael@0 2957 {
michael@0 2958 gl::makeCurrent(NULL, NULL, NULL);
michael@0 2959 }
michael@0 2960 }
michael@0 2961
michael@0 2962 void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
michael@0 2963 {
michael@0 2964 gl::makeCurrent(context, display, surface);
michael@0 2965 }
michael@0 2966
michael@0 2967 gl::Context *glGetCurrentContext()
michael@0 2968 {
michael@0 2969 return gl::getContext();
michael@0 2970 }
michael@0 2971
michael@0 2972 }

mercurial