X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=src%2Fthird_party%2Fangle%2Fsrc%2FlibGLESv2%2FContext.cpp;h=a16a13f365bcad2453ccc6d05e0bb5bb547ac5e8;hb=4a1a0bdd01eef90b0826a0e761d3379d3715c10f;hp=879a560045c70205901973bf9848795a91f707de;hpb=b1be5ca53587d23e7aeb77b26861fdc0a181ffd8;p=platform%2Fframework%2Fweb%2Fcrosswalk.git diff --git a/src/third_party/angle/src/libGLESv2/Context.cpp b/src/third_party/angle/src/libGLESv2/Context.cpp index 879a560..a16a13f 100644 --- a/src/third_party/angle/src/libGLESv2/Context.cpp +++ b/src/third_party/angle/src/libGLESv2/Context.cpp @@ -16,13 +16,14 @@ #include "libGLESv2/Buffer.h" #include "libGLESv2/Fence.h" #include "libGLESv2/Framebuffer.h" +#include "libGLESv2/FramebufferAttachment.h" #include "libGLESv2/Renderbuffer.h" #include "libGLESv2/Program.h" #include "libGLESv2/ProgramBinary.h" #include "libGLESv2/Query.h" #include "libGLESv2/Texture.h" #include "libGLESv2/ResourceManager.h" -#include "libGLESv2/renderer/IndexDataManager.h" +#include "libGLESv2/renderer/d3d/IndexDataManager.h" #include "libGLESv2/renderer/RenderTarget.h" #include "libGLESv2/renderer/Renderer.h" #include "libGLESv2/VertexArray.h" @@ -37,104 +38,17 @@ namespace gl { -static const char* makeStaticString(const std::string& str) -{ - static std::set strings; - std::set::iterator it = strings.find(str); - if (it != strings.end()) - return it->c_str(); - - return strings.insert(str).first->c_str(); -} -Context::Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) : mRenderer(renderer) +Context::Context(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess) + : mRenderer(renderer) { ASSERT(robustAccess == false); // Unimplemented - mFenceNVHandleAllocator.setBaseHandle(0); - - setClearColor(0.0f, 0.0f, 0.0f, 0.0f); + initCaps(clientVersion); mClientVersion = clientVersion; - mState.depthClearValue = 1.0f; - mState.stencilClearValue = 0; - - mState.rasterizer.rasterizerDiscard = false; - mState.rasterizer.cullFace = false; - mState.rasterizer.cullMode = GL_BACK; - mState.rasterizer.frontFace = GL_CCW; - mState.rasterizer.polygonOffsetFill = false; - mState.rasterizer.polygonOffsetFactor = 0.0f; - mState.rasterizer.polygonOffsetUnits = 0.0f; - mState.rasterizer.pointDrawMode = false; - mState.rasterizer.multiSample = false; - mState.scissorTest = false; - mState.scissor.x = 0; - mState.scissor.y = 0; - mState.scissor.width = 0; - mState.scissor.height = 0; - - mState.blend.blend = false; - mState.blend.sourceBlendRGB = GL_ONE; - mState.blend.sourceBlendAlpha = GL_ONE; - mState.blend.destBlendRGB = GL_ZERO; - mState.blend.destBlendAlpha = GL_ZERO; - mState.blend.blendEquationRGB = GL_FUNC_ADD; - mState.blend.blendEquationAlpha = GL_FUNC_ADD; - mState.blend.sampleAlphaToCoverage = false; - mState.blend.dither = true; - - mState.blendColor.red = 0; - mState.blendColor.green = 0; - mState.blendColor.blue = 0; - mState.blendColor.alpha = 0; - - mState.depthStencil.depthTest = false; - mState.depthStencil.depthFunc = GL_LESS; - mState.depthStencil.depthMask = true; - mState.depthStencil.stencilTest = false; - mState.depthStencil.stencilFunc = GL_ALWAYS; - mState.depthStencil.stencilMask = -1; - mState.depthStencil.stencilWritemask = -1; - mState.depthStencil.stencilBackFunc = GL_ALWAYS; - mState.depthStencil.stencilBackMask = - 1; - mState.depthStencil.stencilBackWritemask = -1; - mState.depthStencil.stencilFail = GL_KEEP; - mState.depthStencil.stencilPassDepthFail = GL_KEEP; - mState.depthStencil.stencilPassDepthPass = GL_KEEP; - mState.depthStencil.stencilBackFail = GL_KEEP; - mState.depthStencil.stencilBackPassDepthFail = GL_KEEP; - mState.depthStencil.stencilBackPassDepthPass = GL_KEEP; - - mState.stencilRef = 0; - mState.stencilBackRef = 0; - - mState.sampleCoverage = false; - mState.sampleCoverageValue = 1.0f; - mState.sampleCoverageInvert = false; - mState.generateMipmapHint = GL_DONT_CARE; - mState.fragmentShaderDerivativeHint = GL_DONT_CARE; - - mState.lineWidth = 1.0f; - - mState.viewport.x = 0; - mState.viewport.y = 0; - mState.viewport.width = 0; - mState.viewport.height = 0; - mState.zNear = 0.0f; - mState.zFar = 1.0f; - - mState.blend.colorMaskRed = true; - mState.blend.colorMaskGreen = true; - mState.blend.colorMaskBlue = true; - mState.blend.colorMaskAlpha = true; - - const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) - { - mState.vertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); - } + mFenceNVHandleAllocator.setBaseHandle(0); if (shareContext != NULL) { @@ -152,17 +66,11 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere // In order that access to these initial textures not be lost, they are treated as texture // objects all of whose names are 0. - mTexture2DZero.set(new Texture2D(mRenderer, 0)); - mTextureCubeMapZero.set(new TextureCubeMap(mRenderer, 0)); - mTexture3DZero.set(new Texture3D(mRenderer, 0)); - mTexture2DArrayZero.set(new Texture2DArray(mRenderer, 0)); - - for (unsigned int textureUnit = 0; textureUnit < ArraySize(mState.samplers); textureUnit++) - { - mState.samplers[textureUnit] = 0; - } + mTexture2DZero.set(new Texture2D(mRenderer->createTexture2D(), 0)); + mTextureCubeMapZero.set(new TextureCubeMap(mRenderer->createTextureCube(), 0)); + mTexture3DZero.set(new Texture3D(mRenderer->createTexture3D(), 0)); + mTexture2DArrayZero.set(new Texture2DArray(mRenderer->createTexture2DArray(), 0)); - mState.activeSampler = 0; bindVertexArray(0); bindArrayBuffer(0); bindElementArrayBuffer(0); @@ -172,10 +80,6 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere bindDrawFramebuffer(0); bindRenderbuffer(0); - mState.activeQueries[GL_ANY_SAMPLES_PASSED].set(NULL); - mState.activeQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL); - mState.activeQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL); - bindGenericUniformBuffer(0); for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++) { @@ -200,12 +104,6 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere mTransformFeedbackZero.set(new TransformFeedback(0)); bindTransformFeedback(0); - mState.currentProgram = 0; - mCurrentProgramBinary.set(NULL); - - mCombinedExtensionsString = NULL; - mRendererString = NULL; - mInvalidEnum = false; mInvalidValue = false; mInvalidOperation = false; @@ -218,27 +116,24 @@ Context::Context(int clientVersion, const gl::Context *shareContext, rx::Rendere mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT); mRobustAccess = robustAccess; - mSupportsBGRATextures = false; - mSupportsDXT1Textures = false; - mSupportsDXT3Textures = false; - mSupportsDXT5Textures = false; - mSupportsEventQueries = false; - mSupportsOcclusionQueries = false; mNumCompressedTextureFormats = 0; + + mState.setContext(this); } Context::~Context() { - if (mState.currentProgram != 0) + GLuint currentProgram = mState.getCurrentProgramId(); + if (currentProgram != 0) { - Program *programObject = mResourceManager->getProgram(mState.currentProgram); + Program *programObject = mResourceManager->getProgram(currentProgram); if (programObject) { programObject->release(); } - mState.currentProgram = 0; + currentProgram = 0; } - mCurrentProgramBinary.set(NULL); + mState.setCurrentProgram(0, NULL); while (!mFramebufferMap.empty()) { @@ -268,56 +163,14 @@ Context::~Context() for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) { - for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) - { - mState.samplerTexture[type][sampler].set(NULL); - } - } - - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) - { mIncompleteTextures[type].set(NULL); } - const GLfloat defaultFloatValues[] = { 0.0f, 0.0f, 0.0f, 1.0f }; - for (int attribIndex = 0; attribIndex < MAX_VERTEX_ATTRIBS; attribIndex++) - { - mState.vertexAttribCurrentValues[attribIndex].setFloatValues(defaultFloatValues); - } - - mState.arrayBuffer.set(NULL); - mState.renderbuffer.set(NULL); - - mState.transformFeedback.set(NULL); - mTexture2DZero.set(NULL); mTextureCubeMapZero.set(NULL); mTexture3DZero.set(NULL); mTexture2DArrayZero.set(NULL); - for (State::ActiveQueryMap::iterator i = mState.activeQueries.begin(); i != mState.activeQueries.end(); i++) - { - i->second.set(NULL); - } - - mState.genericUniformBuffer.set(NULL); - for (int i = 0; i < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; i++) - { - mState.uniformBuffers[i].set(NULL); - } - - mState.genericTransformFeedbackBuffer.set(NULL); - for (int i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) - { - mState.transformFeedbackBuffers[i].set(NULL); - } - - mState.copyReadBuffer.set(NULL); - mState.copyWriteBuffer.set(NULL); - - mState.pack.pixelBuffer.set(NULL); - mState.unpack.pixelBuffer.set(NULL); - mResourceManager->release(); } @@ -325,78 +178,27 @@ void Context::makeCurrent(egl::Surface *surface) { if (!mHasBeenCurrent) { - mMajorShaderModel = mRenderer->getMajorShaderModel(); - mMaximumPointSize = mRenderer->getMaxPointSize(); mSupportsVertexTexture = mRenderer->getVertexTextureSupport(); - mSupportsNonPower2Texture = mRenderer->getNonPower2TextureSupport(); - mSupportsInstancing = mRenderer->getInstancingSupport(); - - mMaxViewportDimension = mRenderer->getMaxViewportDimension(); - mMax2DTextureDimension = std::min(std::min(mRenderer->getMaxTextureWidth(), mRenderer->getMaxTextureHeight()), - (int)gl::IMPLEMENTATION_MAX_2D_TEXTURE_SIZE); - mMaxCubeTextureDimension = std::min(mMax2DTextureDimension, (int)gl::IMPLEMENTATION_MAX_CUBE_MAP_TEXTURE_SIZE); - mMax3DTextureDimension = std::min(std::min(mMax2DTextureDimension, mRenderer->getMaxTextureDepth()), - (int)gl::IMPLEMENTATION_MAX_3D_TEXTURE_SIZE); - mMax2DArrayTextureLayers = mRenderer->getMaxTextureArrayLayers(); - mMaxRenderbufferDimension = mMax2DTextureDimension; - mMax2DTextureLevel = log2(mMax2DTextureDimension) + 1; - mMaxCubeTextureLevel = log2(mMaxCubeTextureDimension) + 1; - mMax3DTextureLevel = log2(mMax3DTextureDimension) + 1; - mMax2DArrayTextureLevel = log2(mMax2DTextureDimension) + 1; - mMaxTextureAnisotropy = mRenderer->getTextureMaxAnisotropy(); - TRACE("Max2DTextureDimension=%d, MaxCubeTextureDimension=%d, Max3DTextureDimension=%d, Max2DArrayTextureLayers = %d, " - "Max2DTextureLevel=%d, MaxCubeTextureLevel=%d, Max3DTextureLevel=%d, Max2DArrayTextureLevel=%d, " - "MaxRenderbufferDimension=%d, MaxTextureAnisotropy=%f", - mMax2DTextureDimension, mMaxCubeTextureDimension, mMax3DTextureDimension, mMax2DArrayTextureLayers, - mMax2DTextureLevel, mMaxCubeTextureLevel, mMax3DTextureLevel, mMax2DArrayTextureLevel, - mMaxRenderbufferDimension, mMaxTextureAnisotropy); - - mSupportsEventQueries = mRenderer->getEventQuerySupport(); - mSupportsOcclusionQueries = mRenderer->getOcclusionQuerySupport(); - mSupportsBGRATextures = mRenderer->getBGRATextureSupport(); - mSupportsDXT1Textures = mRenderer->getDXT1TextureSupport(); - mSupportsDXT3Textures = mRenderer->getDXT3TextureSupport(); - mSupportsDXT5Textures = mRenderer->getDXT5TextureSupport(); - mSupportsFloat32Textures = mRenderer->getFloat32TextureSupport(); - mSupportsFloat32LinearFilter = mRenderer->getFloat32TextureFilteringSupport(); - mSupportsFloat32RenderableTextures = mRenderer->getFloat32TextureRenderingSupport(); - mSupportsFloat16Textures = mRenderer->getFloat16TextureSupport(); - mSupportsFloat16LinearFilter = mRenderer->getFloat16TextureFilteringSupport(); - mSupportsFloat16RenderableTextures = mRenderer->getFloat16TextureRenderingSupport(); - mSupportsLuminanceTextures = mRenderer->getLuminanceTextureSupport(); - mSupportsLuminanceAlphaTextures = mRenderer->getLuminanceAlphaTextureSupport(); - mSupportsRGTextures = mRenderer->getRGTextureSupport(); - mSupportsDepthTextures = mRenderer->getDepthTextureSupport(); - mSupportsTextureFilterAnisotropy = mRenderer->getTextureFilterAnisotropySupport(); - mSupports32bitIndices = mRenderer->get32BitIndexSupport(); - mSupportsPBOs = mRenderer->getPBOSupport(); mNumCompressedTextureFormats = 0; - if (supportsDXT1Textures()) + if (mExtensions.textureCompressionDXT1) { mNumCompressedTextureFormats += 2; } - if (supportsDXT3Textures()) + if (mExtensions.textureCompressionDXT3) { mNumCompressedTextureFormats += 1; } - if (supportsDXT5Textures()) + if (mExtensions.textureCompressionDXT5) { mNumCompressedTextureFormats += 1; } - initExtensionString(); initRendererString(); + initExtensionStrings(); - mState.viewport.x = 0; - mState.viewport.y = 0; - mState.viewport.width = surface->getWidth(); - mState.viewport.height = surface->getHeight(); - - mState.scissor.x = 0; - mState.scissor.y = 0; - mState.scissor.width = surface->getWidth(); - mState.scissor.height = surface->getHeight(); + mState.setViewportParams(0, 0, surface->getWidth(), surface->getHeight()); + mState.setScissorParams(0, 0, surface->getWidth(), surface->getHeight()); mHasBeenCurrent = true; } @@ -427,447 +229,6 @@ bool Context::isContextLost() return mContextLost; } -void Context::setCap(GLenum cap, bool enabled) -{ - switch (cap) - { - case GL_CULL_FACE: setCullFace(enabled); break; - case GL_POLYGON_OFFSET_FILL: setPolygonOffsetFill(enabled); break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(enabled); break; - case GL_SAMPLE_COVERAGE: setSampleCoverage(enabled); break; - case GL_SCISSOR_TEST: setScissorTest(enabled); break; - case GL_STENCIL_TEST: setStencilTest(enabled); break; - case GL_DEPTH_TEST: setDepthTest(enabled); break; - case GL_BLEND: setBlend(enabled); break; - case GL_DITHER: setDither(enabled); break; - case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); break; - case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break; - default: UNREACHABLE(); - } -} - -bool Context::getCap(GLenum cap) -{ - switch (cap) - { - case GL_CULL_FACE: return isCullFaceEnabled(); - case GL_POLYGON_OFFSET_FILL: return isPolygonOffsetFillEnabled(); - case GL_SAMPLE_ALPHA_TO_COVERAGE: return isSampleAlphaToCoverageEnabled(); - case GL_SAMPLE_COVERAGE: return isSampleCoverageEnabled(); - case GL_SCISSOR_TEST: return isScissorTestEnabled(); - case GL_STENCIL_TEST: return isStencilTestEnabled(); - case GL_DEPTH_TEST: return isDepthTestEnabled(); - case GL_BLEND: return isBlendEnabled(); - case GL_DITHER: return isDitherEnabled(); - case GL_PRIMITIVE_RESTART_FIXED_INDEX: UNIMPLEMENTED(); return false; - case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled(); - default: UNREACHABLE(); return false; - } -} - -void Context::setClearColor(float red, float green, float blue, float alpha) -{ - mState.colorClearValue.red = red; - mState.colorClearValue.green = green; - mState.colorClearValue.blue = blue; - mState.colorClearValue.alpha = alpha; -} - -void Context::setClearDepth(float depth) -{ - mState.depthClearValue = depth; -} - -void Context::setClearStencil(int stencil) -{ - mState.stencilClearValue = stencil; -} - -void Context::setRasterizerDiscard(bool enabled) -{ - mState.rasterizer.rasterizerDiscard = enabled; -} - -bool Context::isRasterizerDiscardEnabled() const -{ - return mState.rasterizer.rasterizerDiscard; -} - -void Context::setCullFace(bool enabled) -{ - mState.rasterizer.cullFace = enabled; -} - -bool Context::isCullFaceEnabled() const -{ - return mState.rasterizer.cullFace; -} - -void Context::setCullMode(GLenum mode) -{ - mState.rasterizer.cullMode = mode; -} - -void Context::setFrontFace(GLenum front) -{ - mState.rasterizer.frontFace = front; -} - -void Context::setDepthTest(bool enabled) -{ - mState.depthStencil.depthTest = enabled; -} - -bool Context::isDepthTestEnabled() const -{ - return mState.depthStencil.depthTest; -} - -void Context::setDepthFunc(GLenum depthFunc) -{ - mState.depthStencil.depthFunc = depthFunc; -} - -void Context::setDepthRange(float zNear, float zFar) -{ - mState.zNear = zNear; - mState.zFar = zFar; -} - -void Context::setBlend(bool enabled) -{ - mState.blend.blend = enabled; -} - -bool Context::isBlendEnabled() const -{ - return mState.blend.blend; -} - -void Context::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha) -{ - mState.blend.sourceBlendRGB = sourceRGB; - mState.blend.destBlendRGB = destRGB; - mState.blend.sourceBlendAlpha = sourceAlpha; - mState.blend.destBlendAlpha = destAlpha; -} - -void Context::setBlendColor(float red, float green, float blue, float alpha) -{ - mState.blendColor.red = red; - mState.blendColor.green = green; - mState.blendColor.blue = blue; - mState.blendColor.alpha = alpha; -} - -void Context::setBlendEquation(GLenum rgbEquation, GLenum alphaEquation) -{ - mState.blend.blendEquationRGB = rgbEquation; - mState.blend.blendEquationAlpha = alphaEquation; -} - -void Context::setStencilTest(bool enabled) -{ - mState.depthStencil.stencilTest = enabled; -} - -bool Context::isStencilTestEnabled() const -{ - return mState.depthStencil.stencilTest; -} - -void Context::setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask) -{ - mState.depthStencil.stencilFunc = stencilFunc; - mState.stencilRef = (stencilRef > 0) ? stencilRef : 0; - mState.depthStencil.stencilMask = stencilMask; -} - -void Context::setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask) -{ - mState.depthStencil.stencilBackFunc = stencilBackFunc; - mState.stencilBackRef = (stencilBackRef > 0) ? stencilBackRef : 0; - mState.depthStencil.stencilBackMask = stencilBackMask; -} - -void Context::setStencilWritemask(GLuint stencilWritemask) -{ - mState.depthStencil.stencilWritemask = stencilWritemask; -} - -void Context::setStencilBackWritemask(GLuint stencilBackWritemask) -{ - mState.depthStencil.stencilBackWritemask = stencilBackWritemask; -} - -void Context::setStencilOperations(GLenum stencilFail, GLenum stencilPassDepthFail, GLenum stencilPassDepthPass) -{ - mState.depthStencil.stencilFail = stencilFail; - mState.depthStencil.stencilPassDepthFail = stencilPassDepthFail; - mState.depthStencil.stencilPassDepthPass = stencilPassDepthPass; -} - -void Context::setStencilBackOperations(GLenum stencilBackFail, GLenum stencilBackPassDepthFail, GLenum stencilBackPassDepthPass) -{ - mState.depthStencil.stencilBackFail = stencilBackFail; - mState.depthStencil.stencilBackPassDepthFail = stencilBackPassDepthFail; - mState.depthStencil.stencilBackPassDepthPass = stencilBackPassDepthPass; -} - -void Context::setPolygonOffsetFill(bool enabled) -{ - mState.rasterizer.polygonOffsetFill = enabled; -} - -bool Context::isPolygonOffsetFillEnabled() const -{ - return mState.rasterizer.polygonOffsetFill; -} - -void Context::setPolygonOffsetParams(GLfloat factor, GLfloat units) -{ - // An application can pass NaN values here, so handle this gracefully - mState.rasterizer.polygonOffsetFactor = factor != factor ? 0.0f : factor; - mState.rasterizer.polygonOffsetUnits = units != units ? 0.0f : units; -} - -void Context::setSampleAlphaToCoverage(bool enabled) -{ - mState.blend.sampleAlphaToCoverage = enabled; -} - -bool Context::isSampleAlphaToCoverageEnabled() const -{ - return mState.blend.sampleAlphaToCoverage; -} - -void Context::setSampleCoverage(bool enabled) -{ - mState.sampleCoverage = enabled; -} - -bool Context::isSampleCoverageEnabled() const -{ - return mState.sampleCoverage; -} - -void Context::setSampleCoverageParams(GLclampf value, bool invert) -{ - mState.sampleCoverageValue = value; - mState.sampleCoverageInvert = invert; -} - -void Context::setScissorTest(bool enabled) -{ - mState.scissorTest = enabled; -} - -bool Context::isScissorTestEnabled() const -{ - return mState.scissorTest; -} - -void Context::setDither(bool enabled) -{ - mState.blend.dither = enabled; -} - -bool Context::isDitherEnabled() const -{ - return mState.blend.dither; -} - -void Context::setLineWidth(GLfloat width) -{ - mState.lineWidth = width; -} - -void Context::setGenerateMipmapHint(GLenum hint) -{ - mState.generateMipmapHint = hint; -} - -void Context::setFragmentShaderDerivativeHint(GLenum hint) -{ - mState.fragmentShaderDerivativeHint = hint; - // TODO: Propagate the hint to shader translator so we can write - // ddx, ddx_coarse, or ddx_fine depending on the hint. - // Ignore for now. It is valid for implementations to ignore hint. -} - -void Context::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) -{ - mState.viewport.x = x; - mState.viewport.y = y; - mState.viewport.width = width; - mState.viewport.height = height; -} - -void Context::setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height) -{ - mState.scissor.x = x; - mState.scissor.y = y; - mState.scissor.width = width; - mState.scissor.height = height; -} - -void Context::getScissorParams(GLint *x, GLint *y, GLsizei *width, GLsizei *height) -{ - *x = mState.scissor.x; - *y = mState.scissor.y; - *width = mState.scissor.width; - *height = mState.scissor.height; -} - -void Context::setColorMask(bool red, bool green, bool blue, bool alpha) -{ - mState.blend.colorMaskRed = red; - mState.blend.colorMaskGreen = green; - mState.blend.colorMaskBlue = blue; - mState.blend.colorMaskAlpha = alpha; -} - -void Context::setDepthMask(bool mask) -{ - mState.depthStencil.depthMask = mask; -} - -void Context::setActiveSampler(unsigned int active) -{ - mState.activeSampler = active; -} - -GLuint Context::getReadFramebufferHandle() const -{ - return mState.readFramebuffer; -} - -GLuint Context::getDrawFramebufferHandle() const -{ - return mState.drawFramebuffer; -} - -GLuint Context::getRenderbufferHandle() const -{ - return mState.renderbuffer.id(); -} - -GLuint Context::getVertexArrayHandle() const -{ - return mState.vertexArray; -} - -GLuint Context::getSamplerHandle(GLuint textureUnit) const -{ - ASSERT(textureUnit < ArraySize(mState.samplers)); - return mState.samplers[textureUnit]; -} - -unsigned int Context::getActiveSampler() const -{ - return mState.activeSampler; -} - -GLuint Context::getArrayBufferHandle() const -{ - return mState.arrayBuffer.id(); -} - -bool Context::isQueryActive() const -{ - for (State::ActiveQueryMap::const_iterator i = mState.activeQueries.begin(); - i != mState.activeQueries.end(); i++) - { - if (i->second.get() != NULL) - { - return true; - } - } - - return false; -} - -const Query *Context::getActiveQuery(GLenum target) const -{ - // All query types should already exist in the activeQueries map - ASSERT(mState.activeQueries.find(target) != mState.activeQueries.end()); - - return mState.activeQueries.at(target).get(); -} - -GLuint Context::getActiveQueryId(GLenum target) const -{ - const Query *query = getActiveQuery(target); - return (query ? query->id() : 0u); -} - -void Context::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) -{ - getCurrentVertexArray()->enableAttribute(attribNum, enabled); -} - -const VertexAttribute &Context::getVertexAttribState(unsigned int attribNum) const -{ - return getCurrentVertexArray()->getVertexAttribute(attribNum); -} - -const VertexAttribCurrentValueData &Context::getVertexAttribCurrentValue(unsigned int attribNum) const -{ - ASSERT(attribNum < MAX_VERTEX_ATTRIBS); - return mState.vertexAttribCurrentValues[attribNum]; -} - -void Context::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type, bool normalized, - bool pureInteger, GLsizei stride, const void *pointer) -{ - getCurrentVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); -} - -const void *Context::getVertexAttribPointer(unsigned int attribNum) const -{ - return getCurrentVertexArray()->getVertexAttribute(attribNum).mPointer; -} - -void Context::setPackAlignment(GLint alignment) -{ - mState.pack.alignment = alignment; -} - -GLint Context::getPackAlignment() const -{ - return mState.pack.alignment; -} - -void Context::setUnpackAlignment(GLint alignment) -{ - mState.unpack.alignment = alignment; -} - -GLint Context::getUnpackAlignment() const -{ - return mState.unpack.alignment; -} - -void Context::setPackReverseRowOrder(bool reverseRowOrder) -{ - mState.pack.reverseRowOrder = reverseRowOrder; -} - -bool Context::getPackReverseRowOrder() const -{ - return mState.pack.reverseRowOrder; -} - -const PixelUnpackState &Context::getUnpackState() const -{ - return mState.unpack; -} - -const PixelPackState &Context::getPackState() const -{ - return mState.pack; -} - GLuint Context::createBuffer() { return mResourceManager->createBuffer(); @@ -912,8 +273,8 @@ GLuint Context::createVertexArray() // Although the spec states VAO state is not initialized until the object is bound, // we create it immediately. The resulting behaviour is transparent to the application, // since it's not currently possible to access the state until the object is bound. - mVertexArrayMap[handle] = new VertexArray(mRenderer, handle); - + VertexArray *vertexArray = new VertexArray(mRenderer->createVertexArray(), handle, MAX_VERTEX_ATTRIBS); + mVertexArrayMap[handle] = vertexArray; return handle; } @@ -1100,12 +461,12 @@ Program *Context::getProgram(GLuint handle) const return mResourceManager->getProgram(handle); } -Texture *Context::getTexture(GLuint handle) +Texture *Context::getTexture(GLuint handle) const { return mResourceManager->getTexture(handle); } -FramebufferAttachment *Context::getRenderbuffer(GLuint handle) +Renderbuffer *Context::getRenderbuffer(GLuint handle) { return mResourceManager->getRenderbuffer(handle); } @@ -1147,28 +508,6 @@ TransformFeedback *Context::getTransformFeedback(GLuint handle) const } } -Framebuffer *Context::getReadFramebuffer() -{ - return getFramebuffer(mState.readFramebuffer); -} - -Framebuffer *Context::getDrawFramebuffer() -{ - return mBoundDrawFramebuffer; -} - -VertexArray *Context::getCurrentVertexArray() const -{ - VertexArray *vao = getVertexArray(mState.vertexArray); - ASSERT(vao != NULL); - return vao; -} - -TransformFeedback *Context::getCurrentTransformFeedback() const -{ - return mState.transformFeedback.get(); -} - bool Context::isSampler(GLuint samplerName) const { return mResourceManager->isSampler(samplerName); @@ -1178,167 +517,158 @@ void Context::bindArrayBuffer(unsigned int buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.arrayBuffer.set(getBuffer(buffer)); + mState.setArrayBufferBinding(getBuffer(buffer)); } void Context::bindElementArrayBuffer(unsigned int buffer) { mResourceManager->checkBufferAllocation(buffer); - getCurrentVertexArray()->setElementArrayBuffer(getBuffer(buffer)); + mState.getVertexArray()->setElementArrayBuffer(getBuffer(buffer)); } void Context::bindTexture2D(GLuint texture) { mResourceManager->checkTextureAllocation(texture, TEXTURE_2D); - mState.samplerTexture[TEXTURE_2D][mState.activeSampler].set(getTexture(texture)); + mState.setSamplerTexture(TEXTURE_2D, getTexture(texture)); } void Context::bindTextureCubeMap(GLuint texture) { mResourceManager->checkTextureAllocation(texture, TEXTURE_CUBE); - mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].set(getTexture(texture)); + mState.setSamplerTexture(TEXTURE_CUBE, getTexture(texture)); } void Context::bindTexture3D(GLuint texture) { mResourceManager->checkTextureAllocation(texture, TEXTURE_3D); - mState.samplerTexture[TEXTURE_3D][mState.activeSampler].set(getTexture(texture)); + mState.setSamplerTexture(TEXTURE_3D, getTexture(texture)); } void Context::bindTexture2DArray(GLuint texture) { mResourceManager->checkTextureAllocation(texture, TEXTURE_2D_ARRAY); - mState.samplerTexture[TEXTURE_2D_ARRAY][mState.activeSampler].set(getTexture(texture)); + mState.setSamplerTexture(TEXTURE_2D_ARRAY, getTexture(texture)); } void Context::bindReadFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(mRenderer); + mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer); } - mState.readFramebuffer = framebuffer; + mState.setReadFramebufferBinding(getFramebuffer(framebuffer)); } void Context::bindDrawFramebuffer(GLuint framebuffer) { if (!getFramebuffer(framebuffer)) { - mFramebufferMap[framebuffer] = new Framebuffer(mRenderer); + mFramebufferMap[framebuffer] = new Framebuffer(mRenderer, framebuffer); } - mState.drawFramebuffer = framebuffer; - - mBoundDrawFramebuffer = getFramebuffer(framebuffer); + mState.setDrawFramebufferBinding(getFramebuffer(framebuffer)); } void Context::bindRenderbuffer(GLuint renderbuffer) { mResourceManager->checkRenderbufferAllocation(renderbuffer); - mState.renderbuffer.set(getRenderbuffer(renderbuffer)); + mState.setRenderbufferBinding(getRenderbuffer(renderbuffer)); } void Context::bindVertexArray(GLuint vertexArray) { if (!getVertexArray(vertexArray)) { - mVertexArrayMap[vertexArray] = new VertexArray(mRenderer, vertexArray); + VertexArray *vertexArrayObject = new VertexArray(mRenderer->createVertexArray(), vertexArray, MAX_VERTEX_ATTRIBS); + mVertexArrayMap[vertexArray] = vertexArrayObject; } - mState.vertexArray = vertexArray; + mState.setVertexArrayBinding(getVertexArray(vertexArray)); } void Context::bindSampler(GLuint textureUnit, GLuint sampler) { - ASSERT(textureUnit < ArraySize(mState.samplers)); + ASSERT(textureUnit < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS); // TODO: Update for backend-determined array size mResourceManager->checkSamplerAllocation(sampler); - mState.samplers[textureUnit] = sampler; + mState.setSamplerBinding(textureUnit, getSampler(sampler)); } void Context::bindGenericUniformBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.genericUniformBuffer.set(getBuffer(buffer)); + mState.setGenericUniformBufferBinding(getBuffer(buffer)); } void Context::bindIndexedUniformBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) { mResourceManager->checkBufferAllocation(buffer); - mState.uniformBuffers[index].set(getBuffer(buffer), offset, size); + mState.setIndexedUniformBufferBinding(index, getBuffer(buffer), offset, size); } void Context::bindGenericTransformFeedbackBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.genericTransformFeedbackBuffer.set(getBuffer(buffer)); + mState.setGenericTransformFeedbackBufferBinding(getBuffer(buffer)); } void Context::bindIndexedTransformFeedbackBuffer(GLuint buffer, GLuint index, GLintptr offset, GLsizeiptr size) { mResourceManager->checkBufferAllocation(buffer); - mState.transformFeedbackBuffers[index].set(getBuffer(buffer), offset, size); + mState.setIndexedTransformFeedbackBufferBinding(index, getBuffer(buffer), offset, size); } void Context::bindCopyReadBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.copyReadBuffer.set(getBuffer(buffer)); + mState.setCopyReadBufferBinding(getBuffer(buffer)); } void Context::bindCopyWriteBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.copyWriteBuffer.set(getBuffer(buffer)); + mState.setCopyWriteBufferBinding(getBuffer(buffer)); } void Context::bindPixelPackBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.pack.pixelBuffer.set(getBuffer(buffer)); + mState.setPixelPackBufferBinding(getBuffer(buffer)); } void Context::bindPixelUnpackBuffer(GLuint buffer) { mResourceManager->checkBufferAllocation(buffer); - mState.unpack.pixelBuffer.set(getBuffer(buffer)); + mState.setPixelUnpackBufferBinding(getBuffer(buffer)); } void Context::useProgram(GLuint program) { - GLuint priorProgram = mState.currentProgram; - mState.currentProgram = program; // Must switch before trying to delete, otherwise it only gets flagged. + GLuint priorProgramId = mState.getCurrentProgramId(); + Program *priorProgram = mResourceManager->getProgram(priorProgramId); - if (priorProgram != program) + if (priorProgramId != program) { - Program *newProgram = mResourceManager->getProgram(program); - Program *oldProgram = mResourceManager->getProgram(priorProgram); - mCurrentProgramBinary.set(NULL); + mState.setCurrentProgram(program, mResourceManager->getProgram(program)); - if (newProgram) + if (priorProgram) { - newProgram->addRef(); - mCurrentProgramBinary.set(newProgram->getProgramBinary()); - } - - if (oldProgram) - { - oldProgram->release(); + priorProgram->release(); } } } @@ -1351,9 +681,9 @@ void Context::linkProgram(GLuint program) // if the current program was relinked successfully we // need to install the new executables - if (linked && program == mState.currentProgram) + if (linked && program == mState.getCurrentProgramId()) { - mCurrentProgramBinary.set(programObject->getProgramBinary()); + mState.setCurrentProgramBinary(programObject->getProgramBinary()); } } @@ -1365,17 +695,16 @@ void Context::setProgramBinary(GLuint program, const void *binary, GLint length) // if the current program was reloaded successfully we // need to install the new executables - if (loaded && program == mState.currentProgram) + if (loaded && program == mState.getCurrentProgramId()) { - mCurrentProgramBinary.set(programObject->getProgramBinary()); + mState.setCurrentProgramBinary(programObject->getProgramBinary()); } } void Context::bindTransformFeedback(GLuint transformFeedback) { - TransformFeedback *transformFeedbackObject = getTransformFeedback(transformFeedback); - mState.transformFeedback.set(transformFeedbackObject); + mState.setTransformFeedbackBinding(getTransformFeedback(transformFeedback)); } void Context::beginQuery(GLenum target, GLuint query) @@ -1384,7 +713,7 @@ void Context::beginQuery(GLenum target, GLuint query) ASSERT(queryObject); // set query as active for specified target - mState.activeQueries[target].set(queryObject); + mState.setActiveQuery(target, queryObject); // begin query queryObject->begin(); @@ -1392,56 +721,58 @@ void Context::beginQuery(GLenum target, GLuint query) void Context::endQuery(GLenum target) { - Query *queryObject = mState.activeQueries[target].get(); + Query *queryObject = mState.getActiveQuery(target); ASSERT(queryObject); queryObject->end(); - mState.activeQueries[target].set(NULL); + mState.setActiveQuery(target, NULL); } void Context::setFramebufferZero(Framebuffer *buffer) { - delete mFramebufferMap[0]; - mFramebufferMap[0] = buffer; - if (mState.drawFramebuffer == 0) + // First, check to see if the old default framebuffer + // was set for draw or read framebuffer, and change + // the bindings to point to the new one before deleting it. + if (mState.getDrawFramebuffer()->id() == 0) + { + mState.setDrawFramebufferBinding(buffer); + } + + if (mState.getReadFramebuffer()->id() == 0) { - mBoundDrawFramebuffer = buffer; + mState.setReadFramebufferBinding(buffer); } + + delete mFramebufferMap[0]; + mFramebufferMap[0] = buffer; } void Context::setRenderbufferStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) { - const bool color = gl::IsColorRenderingSupported(internalformat, this); - const bool depth = gl::IsDepthRenderingSupported(internalformat, this); - const bool stencil = gl::IsStencilRenderingSupported(internalformat, this); + ASSERT(getTextureCaps().get(internalformat).renderable); RenderbufferStorage *renderbuffer = NULL; - if (color) - { - renderbuffer = new gl::Colorbuffer(mRenderer,width, height, internalformat, samples); - } - else if (depth && stencil) + const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat); + if (formatInfo.depthBits > 0 && formatInfo.stencilBits > 0) { renderbuffer = new gl::DepthStencilbuffer(mRenderer, width, height, samples); } - else if (depth) + else if (formatInfo.depthBits > 0) { renderbuffer = new gl::Depthbuffer(mRenderer, width, height, samples); } - else if (stencil) + else if (formatInfo.stencilBits > 0) { renderbuffer = new gl::Stencilbuffer(mRenderer, width, height, samples); } else { - UNREACHABLE(); - return; + renderbuffer = new gl::Colorbuffer(mRenderer, width, height, internalformat, samples); } - FramebufferAttachment *renderbufferObject = mState.renderbuffer.get(); - renderbufferObject->setStorage(renderbuffer); + mState.getCurrentRenderbuffer()->setStorage(renderbuffer); } Framebuffer *Context::getFramebuffer(unsigned int handle) const @@ -1491,37 +822,6 @@ Query *Context::getQuery(unsigned int handle, bool create, GLenum type) } } -Buffer *Context::getTargetBuffer(GLenum target) const -{ - switch (target) - { - case GL_ARRAY_BUFFER: return mState.arrayBuffer.get(); - case GL_COPY_READ_BUFFER: return mState.copyReadBuffer.get(); - case GL_COPY_WRITE_BUFFER: return mState.copyWriteBuffer.get(); - case GL_ELEMENT_ARRAY_BUFFER: return getCurrentVertexArray()->getElementArrayBuffer(); - case GL_PIXEL_PACK_BUFFER: return mState.pack.pixelBuffer.get(); - case GL_PIXEL_UNPACK_BUFFER: return mState.unpack.pixelBuffer.get(); - case GL_TRANSFORM_FEEDBACK_BUFFER: return mState.genericTransformFeedbackBuffer.get(); - case GL_UNIFORM_BUFFER: return mState.genericUniformBuffer.get(); - default: UNREACHABLE(); return NULL; - } -} - -Buffer *Context::getArrayBuffer() -{ - return mState.arrayBuffer.get(); -} - -Buffer *Context::getElementArrayBuffer() const -{ - return getCurrentVertexArray()->getElementArrayBuffer(); -} - -ProgramBinary *Context::getCurrentProgramBinary() -{ - return mCurrentProgramBinary.get(); -} - Texture *Context::getTargetTexture(GLenum target) const { if (!ValidTextureTarget(this, target)) @@ -1539,84 +839,29 @@ Texture *Context::getTargetTexture(GLenum target) const } } -GLuint Context::getTargetFramebufferHandle(GLenum target) const -{ - if (!ValidFramebufferTarget(target)) - { - return GL_INVALID_INDEX; - } - - if (target == GL_READ_FRAMEBUFFER_ANGLE) - { - return mState.readFramebuffer; - } - else - { - return mState.drawFramebuffer; - } -} - -Framebuffer *Context::getTargetFramebuffer(GLenum target) const -{ - GLuint framebufferHandle = getTargetFramebufferHandle(target); - return (framebufferHandle == GL_INVALID_INDEX ? NULL : getFramebuffer(framebufferHandle)); -} - Texture2D *Context::getTexture2D() const { - return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_2D)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D)); } TextureCubeMap *Context::getTextureCubeMap() const { - return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_CUBE)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_CUBE)); } Texture3D *Context::getTexture3D() const { - return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_3D)); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_3D)); } Texture2DArray *Context::getTexture2DArray() const { - return static_cast(getSamplerTexture(mState.activeSampler, TEXTURE_2D_ARRAY)); -} - -Buffer *Context::getGenericUniformBuffer() -{ - return mState.genericUniformBuffer.get(); -} - -Buffer *Context::getGenericTransformFeedbackBuffer() -{ - return mState.genericTransformFeedbackBuffer.get(); -} - -Buffer *Context::getCopyReadBuffer() -{ - return mState.copyReadBuffer.get(); -} - -Buffer *Context::getCopyWriteBuffer() -{ - return mState.copyWriteBuffer.get(); -} - -Buffer *Context::getPixelPackBuffer() -{ - return mState.pack.pixelBuffer.get(); -} - -Buffer *Context::getPixelUnpackBuffer() -{ - return mState.unpack.pixelBuffer.get(); + return static_cast(getSamplerTexture(mState.getActiveSampler(), TEXTURE_2D_ARRAY)); } Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) const { - GLuint texid = mState.samplerTexture[type][sampler].id(); - - if (texid == 0) // Special case: 0 refers to different initial textures based on the target + if (mState.getSamplerTextureId(sampler, type) == 0) { switch (type) { @@ -1627,8 +872,10 @@ Texture *Context::getSamplerTexture(unsigned int sampler, TextureType type) cons case TEXTURE_2D_ARRAY: return mTexture2DArrayZero.get(); } } - - return mState.samplerTexture[type][sampler].get(); + else + { + return mState.getSamplerTexture(sampler, type); + } } void Context::getBooleanv(GLenum pname, GLboolean *params) @@ -1636,95 +883,42 @@ void Context::getBooleanv(GLenum pname, GLboolean *params) switch (pname) { case GL_SHADER_COMPILER: *params = GL_TRUE; break; - case GL_SAMPLE_COVERAGE_INVERT: *params = mState.sampleCoverageInvert; break; - case GL_DEPTH_WRITEMASK: *params = mState.depthStencil.depthMask; break; - case GL_COLOR_WRITEMASK: - params[0] = mState.blend.colorMaskRed; - params[1] = mState.blend.colorMaskGreen; - params[2] = mState.blend.colorMaskBlue; - params[3] = mState.blend.colorMaskAlpha; - break; - case GL_CULL_FACE: *params = mState.rasterizer.cullFace; break; - case GL_POLYGON_OFFSET_FILL: *params = mState.rasterizer.polygonOffsetFill; break; - case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mState.blend.sampleAlphaToCoverage; break; - case GL_SAMPLE_COVERAGE: *params = mState.sampleCoverage; break; - case GL_SCISSOR_TEST: *params = mState.scissorTest; break; - case GL_STENCIL_TEST: *params = mState.depthStencil.stencilTest; break; - case GL_DEPTH_TEST: *params = mState.depthStencil.depthTest; break; - case GL_BLEND: *params = mState.blend.blend; break; - case GL_DITHER: *params = mState.blend.dither; break; case GL_CONTEXT_ROBUST_ACCESS_EXT: *params = mRobustAccess ? GL_TRUE : GL_FALSE; break; - case GL_TRANSFORM_FEEDBACK_ACTIVE: *params = getCurrentTransformFeedback()->isStarted(); break; - case GL_TRANSFORM_FEEDBACK_PAUSED: *params = getCurrentTransformFeedback()->isPaused(); break; default: - UNREACHABLE(); + mState.getBooleanv(pname, params); break; } } void Context::getFloatv(GLenum pname, GLfloat *params) { - // Please note: DEPTH_CLEAR_VALUE is included in our internal getFloatv implementation - // because it is stored as a float, despite the fact that the GL ES 2.0 spec names - // GetIntegerv as its native query function. As it would require conversion in any - // case, this should make no difference to the calling application. + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. switch (pname) { - case GL_LINE_WIDTH: *params = mState.lineWidth; break; - case GL_SAMPLE_COVERAGE_VALUE: *params = mState.sampleCoverageValue; break; - case GL_DEPTH_CLEAR_VALUE: *params = mState.depthClearValue; break; - case GL_POLYGON_OFFSET_FACTOR: *params = mState.rasterizer.polygonOffsetFactor; break; - case GL_POLYGON_OFFSET_UNITS: *params = mState.rasterizer.polygonOffsetUnits; break; case GL_ALIASED_LINE_WIDTH_RANGE: - params[0] = gl::ALIASED_LINE_WIDTH_RANGE_MIN; - params[1] = gl::ALIASED_LINE_WIDTH_RANGE_MAX; + params[0] = mCaps.minAliasedLineWidth; + params[1] = mCaps.maxAliasedLineWidth; break; case GL_ALIASED_POINT_SIZE_RANGE: - params[0] = gl::ALIASED_POINT_SIZE_RANGE_MIN; - params[1] = getMaximumPointSize(); - break; - case GL_DEPTH_RANGE: - params[0] = mState.zNear; - params[1] = mState.zFar; - break; - case GL_COLOR_CLEAR_VALUE: - params[0] = mState.colorClearValue.red; - params[1] = mState.colorClearValue.green; - params[2] = mState.colorClearValue.blue; - params[3] = mState.colorClearValue.alpha; - break; - case GL_BLEND_COLOR: - params[0] = mState.blendColor.red; - params[1] = mState.blendColor.green; - params[2] = mState.blendColor.blue; - params[3] = mState.blendColor.alpha; + params[0] = mCaps.minAliasedPointSize; + params[1] = mCaps.maxAliasedPointSize; break; case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: - ASSERT(supportsTextureFilterAnisotropy()); - *params = mMaxTextureAnisotropy; + ASSERT(mExtensions.textureFilterAnisotropic); + *params = mExtensions.maxTextureAnisotropy; break; default: - UNREACHABLE(); + mState.getFloatv(pname, params); break; } } void Context::getIntegerv(GLenum pname, GLint *params) { - if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) - { - unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0_EXT); - ASSERT(colorAttachment < mRenderer->getMaxRenderTargets()); - Framebuffer *framebuffer = getDrawFramebuffer(); - *params = framebuffer->getDrawBufferState(colorAttachment); - return; - } + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. - // Please note: DEPTH_CLEAR_VALUE is not included in our internal getIntegerv implementation - // because it is stored as a float, despite the fact that the GL ES 2.0 spec names - // GetIntegerv as its native query function. As it would require conversion in any - // case, this should make no difference to the calling application. You may find it in - // Context::getFloatv. switch (pname) { case GL_MAX_VERTEX_ATTRIBS: *params = gl::MAX_VERTEX_ATTRIBS; break; @@ -1737,52 +931,17 @@ void Context::getIntegerv(GLenum pname, GLint *params) case GL_MAX_TEXTURE_IMAGE_UNITS: *params = gl::MAX_TEXTURE_IMAGE_UNITS; break; case GL_MAX_FRAGMENT_UNIFORM_VECTORS: *params = mRenderer->getMaxFragmentUniformVectors(); break; case GL_MAX_FRAGMENT_UNIFORM_COMPONENTS: *params = mRenderer->getMaxFragmentUniformVectors() * 4; break; - case GL_MAX_RENDERBUFFER_SIZE: *params = getMaximumRenderbufferDimension(); break; - case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mRenderer->getMaxRenderTargets(); break; - case GL_MAX_DRAW_BUFFERS_EXT: *params = mRenderer->getMaxRenderTargets(); break; + case GL_MAX_RENDERBUFFER_SIZE: *params = mCaps.maxRenderbufferSize; break; + case GL_MAX_COLOR_ATTACHMENTS_EXT: *params = mCaps.maxColorAttachments; break; + case GL_MAX_DRAW_BUFFERS_EXT: *params = mCaps.maxDrawBuffers; break; case GL_NUM_SHADER_BINARY_FORMATS: *params = 0; break; case GL_SHADER_BINARY_FORMATS: /* no shader binary formats are supported */ break; - case GL_ARRAY_BUFFER_BINDING: *params = mState.arrayBuffer.id(); break; - case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getCurrentVertexArray()->getElementArrayBufferId(); break; //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE - case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mState.drawFramebuffer; break; - case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mState.readFramebuffer; break; - case GL_RENDERBUFFER_BINDING: *params = mState.renderbuffer.id(); break; - case GL_VERTEX_ARRAY_BINDING: *params = mState.vertexArray; break; - case GL_CURRENT_PROGRAM: *params = mState.currentProgram; break; - case GL_PACK_ALIGNMENT: *params = mState.pack.alignment; break; - case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mState.pack.reverseRowOrder; break; - case GL_UNPACK_ALIGNMENT: *params = mState.unpack.alignment; break; - case GL_GENERATE_MIPMAP_HINT: *params = mState.generateMipmapHint; break; - case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mState.fragmentShaderDerivativeHint; break; - case GL_ACTIVE_TEXTURE: *params = (mState.activeSampler + GL_TEXTURE0); break; - case GL_STENCIL_FUNC: *params = mState.depthStencil.stencilFunc; break; - case GL_STENCIL_REF: *params = mState.stencilRef; break; - case GL_STENCIL_VALUE_MASK: *params = clampToInt(mState.depthStencil.stencilMask); break; - case GL_STENCIL_BACK_FUNC: *params = mState.depthStencil.stencilBackFunc; break; - case GL_STENCIL_BACK_REF: *params = mState.stencilBackRef; break; - case GL_STENCIL_BACK_VALUE_MASK: *params = clampToInt(mState.depthStencil.stencilBackMask); break; - case GL_STENCIL_FAIL: *params = mState.depthStencil.stencilFail; break; - case GL_STENCIL_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilPassDepthFail; break; - case GL_STENCIL_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilPassDepthPass; break; - case GL_STENCIL_BACK_FAIL: *params = mState.depthStencil.stencilBackFail; break; - case GL_STENCIL_BACK_PASS_DEPTH_FAIL: *params = mState.depthStencil.stencilBackPassDepthFail; break; - case GL_STENCIL_BACK_PASS_DEPTH_PASS: *params = mState.depthStencil.stencilBackPassDepthPass; break; - case GL_DEPTH_FUNC: *params = mState.depthStencil.depthFunc; break; - case GL_BLEND_SRC_RGB: *params = mState.blend.sourceBlendRGB; break; - case GL_BLEND_SRC_ALPHA: *params = mState.blend.sourceBlendAlpha; break; - case GL_BLEND_DST_RGB: *params = mState.blend.destBlendRGB; break; - case GL_BLEND_DST_ALPHA: *params = mState.blend.destBlendAlpha; break; - case GL_BLEND_EQUATION_RGB: *params = mState.blend.blendEquationRGB; break; - case GL_BLEND_EQUATION_ALPHA: *params = mState.blend.blendEquationAlpha; break; - case GL_STENCIL_WRITEMASK: *params = clampToInt(mState.depthStencil.stencilWritemask); break; - case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(mState.depthStencil.stencilBackWritemask); break; - case GL_STENCIL_CLEAR_VALUE: *params = mState.stencilClearValue; break; case GL_SUBPIXEL_BITS: *params = 4; break; - case GL_MAX_TEXTURE_SIZE: *params = getMaximum2DTextureDimension(); break; - case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = getMaximumCubeTextureDimension(); break; - case GL_MAX_3D_TEXTURE_SIZE: *params = getMaximum3DTextureDimension(); break; - case GL_MAX_ARRAY_TEXTURE_LAYERS: *params = getMaximum2DArrayTextureLayers(); break; + case GL_MAX_TEXTURE_SIZE: *params = mCaps.max2DTextureSize; break; + case GL_MAX_CUBE_MAP_TEXTURE_SIZE: *params = mCaps.maxCubeMapTextureSize; break; + case GL_MAX_3D_TEXTURE_SIZE: *params = mCaps.max3DTextureSize; break; + case GL_MAX_ARRAY_TEXTURE_LAYERS: *params = mCaps.maxArrayTextureLayers; break; case GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT: *params = getUniformBufferOffsetAlignment(); break; case GL_MAX_UNIFORM_BUFFER_BINDINGS: *params = getMaximumCombinedUniformBufferBindings(); break; case GL_MAX_VERTEX_UNIFORM_BLOCKS: *params = mRenderer->getMaxVertexShaderUniformBuffers(); break; @@ -1798,38 +957,7 @@ void Context::getIntegerv(GLenum pname, GLint *params) case GL_NUM_COMPRESSED_TEXTURE_FORMATS: params[0] = mNumCompressedTextureFormats; break; - case GL_MAX_SAMPLES_ANGLE: - *params = static_cast(getMaxSupportedSamples()); - break; - case GL_SAMPLE_BUFFERS: - case GL_SAMPLES: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - if (framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE) - { - switch (pname) - { - case GL_SAMPLE_BUFFERS: - if (framebuffer->getSamples() != 0) - { - *params = 1; - } - else - { - *params = 0; - } - break; - case GL_SAMPLES: - *params = framebuffer->getSamples(); - break; - } - } - else - { - *params = 0; - } - } - break; + case GL_MAX_SAMPLES_ANGLE: *params = mExtensions.maxSamples; break; case GL_IMPLEMENTATION_COLOR_READ_TYPE: case GL_IMPLEMENTATION_COLOR_READ_FORMAT: { @@ -1843,111 +971,27 @@ void Context::getIntegerv(GLenum pname, GLint *params) break; case GL_MAX_VIEWPORT_DIMS: { - params[0] = mMaxViewportDimension; - params[1] = mMaxViewportDimension; + params[0] = mCaps.maxViewportWidth; + params[1] = mCaps.maxViewportHeight; } break; case GL_COMPRESSED_TEXTURE_FORMATS: { - if (supportsDXT1Textures()) + if (mExtensions.textureCompressionDXT1) { *params++ = GL_COMPRESSED_RGB_S3TC_DXT1_EXT; *params++ = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT; } - if (supportsDXT3Textures()) + if (mExtensions.textureCompressionDXT3) { *params++ = GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE; } - if (supportsDXT5Textures()) + if (mExtensions.textureCompressionDXT5) { *params++ = GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE; } } break; - case GL_VIEWPORT: - params[0] = mState.viewport.x; - params[1] = mState.viewport.y; - params[2] = mState.viewport.width; - params[3] = mState.viewport.height; - break; - case GL_SCISSOR_BOX: - params[0] = mState.scissor.x; - params[1] = mState.scissor.y; - params[2] = mState.scissor.width; - params[3] = mState.scissor.height; - break; - case GL_CULL_FACE_MODE: *params = mState.rasterizer.cullMode; break; - case GL_FRONT_FACE: *params = mState.rasterizer.frontFace; break; - case GL_RED_BITS: - case GL_GREEN_BITS: - case GL_BLUE_BITS: - case GL_ALPHA_BITS: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer(); - - if (colorbuffer) - { - switch (pname) - { - case GL_RED_BITS: *params = colorbuffer->getRedSize(); break; - case GL_GREEN_BITS: *params = colorbuffer->getGreenSize(); break; - case GL_BLUE_BITS: *params = colorbuffer->getBlueSize(); break; - case GL_ALPHA_BITS: *params = colorbuffer->getAlphaSize(); break; - } - } - else - { - *params = 0; - } - } - break; - case GL_DEPTH_BITS: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer(); - - if (depthbuffer) - { - *params = depthbuffer->getDepthSize(); - } - else - { - *params = 0; - } - } - break; - case GL_STENCIL_BITS: - { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer(); - - if (stencilbuffer) - { - *params = stencilbuffer->getStencilSize(); - } - else - { - *params = 0; - } - } - break; - case GL_TEXTURE_BINDING_2D: - ASSERT(mState.activeSampler < mRenderer->getMaxCombinedTextureImageUnits()); - *params = mState.samplerTexture[TEXTURE_2D][mState.activeSampler].id(); - break; - case GL_TEXTURE_BINDING_CUBE_MAP: - ASSERT(mState.activeSampler < mRenderer->getMaxCombinedTextureImageUnits()); - *params = mState.samplerTexture[TEXTURE_CUBE][mState.activeSampler].id(); - break; - case GL_TEXTURE_BINDING_3D: - ASSERT(mState.activeSampler < mRenderer->getMaxCombinedTextureImageUnits()); - *params = mState.samplerTexture[TEXTURE_3D][mState.activeSampler].id(); - break; - case GL_TEXTURE_BINDING_2D_ARRAY: - ASSERT(mState.activeSampler < mRenderer->getMaxCombinedTextureImageUnits()); - *params = mState.samplerTexture[TEXTURE_2D_ARRAY][mState.activeSampler].id(); - break; case GL_RESET_NOTIFICATION_STRATEGY_EXT: *params = mResetStrategy; break; @@ -1957,39 +1001,23 @@ void Context::getIntegerv(GLenum pname, GLint *params) case GL_PROGRAM_BINARY_FORMATS_OES: *params = GL_PROGRAM_BINARY_ANGLE; break; - case GL_UNIFORM_BUFFER_BINDING: - *params = mState.genericUniformBuffer.id(); - break; - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - *params = mState.genericTransformFeedbackBuffer.id(); - break; - case GL_COPY_READ_BUFFER_BINDING: - *params = mState.copyReadBuffer.id(); - break; - case GL_COPY_WRITE_BUFFER_BINDING: - *params = mState.copyWriteBuffer.id(); - break; - case GL_PIXEL_PACK_BUFFER_BINDING: - *params = mState.pack.pixelBuffer.id(); - break; - case GL_PIXEL_UNPACK_BUFFER_BINDING: - *params = mState.unpack.pixelBuffer.id(); - break; case GL_NUM_EXTENSIONS: - *params = static_cast(getNumExtensions()); + *params = static_cast(mExtensionStrings.size()); break; default: - UNREACHABLE(); + mState.getIntegerv(pname, params); break; } } void Context::getInteger64v(GLenum pname, GLint64 *params) { + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. switch (pname) { case GL_MAX_ELEMENT_INDEX: - *params = static_cast(std::numeric_limits::max()); + *params = mCaps.maxElementIndex; break; case GL_MAX_UNIFORM_BLOCK_SIZE: *params = static_cast(mRenderer->getMaxUniformBufferSize()); @@ -2001,79 +1029,39 @@ void Context::getInteger64v(GLenum pname, GLint64 *params) *params = uniformBufferComponents + defaultBufferComponents; } break; - case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: - { - GLint64 uniformBufferComponents = static_cast(mRenderer->getMaxFragmentShaderUniformBuffers()) * static_cast(mRenderer->getMaxUniformBufferSize() / 4); - GLint64 defaultBufferComponents = static_cast(mRenderer->getMaxVertexUniformVectors() * 4); - *params = uniformBufferComponents + defaultBufferComponents; - } - break; - case GL_MAX_SERVER_WAIT_TIMEOUT: - // We do not wait for server fence objects internally, so report a max timeout of zero. - *params = 0; - break; - default: - UNREACHABLE(); - break; - } -} - -bool Context::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) -{ - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) - { - *data = mState.transformFeedbackBuffers[index].id(); - } - break; - case GL_UNIFORM_BUFFER_BINDING: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) - { - *data = mState.uniformBuffers[index].id(); - } - break; - default: - return false; - } - - return true; -} - -bool Context::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) -{ - switch (target) - { - case GL_TRANSFORM_FEEDBACK_BUFFER_START: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) - { - *data = mState.transformFeedbackBuffers[index].getOffset(); - } - break; - case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - if (index < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS) - { - *data = mState.transformFeedbackBuffers[index].getSize(); - } - break; - case GL_UNIFORM_BUFFER_START: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) + case GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS: { - *data = mState.uniformBuffers[index].getOffset(); + GLint64 uniformBufferComponents = static_cast(mRenderer->getMaxFragmentShaderUniformBuffers()) * static_cast(mRenderer->getMaxUniformBufferSize() / 4); + GLint64 defaultBufferComponents = static_cast(mRenderer->getMaxVertexUniformVectors() * 4); + *params = uniformBufferComponents + defaultBufferComponents; } break; - case GL_UNIFORM_BUFFER_SIZE: - if (index < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS) - { - *data = mState.uniformBuffers[index].getSize(); - } + case GL_MAX_SERVER_WAIT_TIMEOUT: + // We do not wait for server fence objects internally, so report a max timeout of zero. + *params = 0; break; default: - return false; + UNREACHABLE(); + break; } +} - return true; +bool Context::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) +{ + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + // Indexed integer queries all refer to current state, so this function is a + // mere passthrough. + return mState.getIndexedIntegerv(target, index, data); +} + +bool Context::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) +{ + // Queries about context capabilities and maximums are answered by Context. + // Queries about current GL state values are answered by State. + // Indexed integer queries all refer to current state, so this function is a + // mere passthrough. + return mState.getIndexedInteger64v(target, index, data); } bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) @@ -2180,7 +1168,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu return true; case GL_MAX_SAMPLES_ANGLE: { - if (getMaxSupportedSamples() != 0) + if (mExtensions.framebufferMultisample) { *type = GL_INT; *numParams = 1; @@ -2194,7 +1182,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu case GL_PIXEL_PACK_BUFFER_BINDING: case GL_PIXEL_UNPACK_BUFFER_BINDING: { - if (supportsPBOs()) + if (mExtensions.pixelBufferObject) { *type = GL_INT; *numParams = 1; @@ -2268,7 +1256,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu } return true; case GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT: - if (!supportsTextureFilterAnisotropy()) + if (!mExtensions.maxTextureAnisotropy) { return false; } @@ -2372,22 +1360,20 @@ bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned // scissor rectangle to the renderer bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) { - Framebuffer *framebufferObject = getDrawFramebuffer(); - - if (!framebufferObject || framebufferObject->completeness() != GL_FRAMEBUFFER_COMPLETE) - { - return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false); - } + Framebuffer *framebufferObject = mState.getDrawFramebuffer(); + ASSERT(framebufferObject && framebufferObject->completeness() == GL_FRAMEBUFFER_COMPLETE); mRenderer->applyRenderTarget(framebufferObject); - if (!mRenderer->setViewport(mState.viewport, mState.zNear, mState.zFar, drawMode, mState.rasterizer.frontFace, + float nearZ, farZ; + mState.getDepthRange(&nearZ, &farZ); + if (!mRenderer->setViewport(mState.getViewport(), nearZ, farZ, drawMode, mState.getRasterizerState().frontFace, ignoreViewport)) { return false; } - mRenderer->setScissorRectangle(mState.scissor, mState.scissorTest); + mRenderer->setScissorRectangle(mState.getScissor(), mState.isScissorTestEnabled()); return true; } @@ -2395,17 +1381,22 @@ bool Context::applyRenderTarget(GLenum drawMode, bool ignoreViewport) // Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D 9 device void Context::applyState(GLenum drawMode) { - Framebuffer *framebufferObject = getDrawFramebuffer(); + Framebuffer *framebufferObject = mState.getDrawFramebuffer(); int samples = framebufferObject->getSamples(); - mState.rasterizer.pointDrawMode = (drawMode == GL_POINTS); - mState.rasterizer.multiSample = (samples != 0); - mRenderer->setRasterizerState(mState.rasterizer); + RasterizerState rasterizer = mState.getRasterizerState(); + rasterizer.pointDrawMode = (drawMode == GL_POINTS); + rasterizer.multiSample = (samples != 0); + + mRenderer->setRasterizerState(rasterizer); unsigned int mask = 0; - if (mState.sampleCoverage) + if (mState.isSampleCoverageEnabled()) { - if (mState.sampleCoverageValue != 0) + GLclampf coverageValue; + bool coverageInvert = false; + mState.getSampleCoverageParams(&coverageValue, &coverageInvert); + if (coverageValue != 0) { float threshold = 0.5f; @@ -2414,7 +1405,7 @@ void Context::applyState(GLenum drawMode) { mask <<= 1; - if ((i + 1) * mState.sampleCoverageValue >= threshold) + if ((i + 1) * coverageValue >= threshold) { threshold += 1.0f; mask |= 1; @@ -2422,7 +1413,7 @@ void Context::applyState(GLenum drawMode) } } - if (mState.sampleCoverageInvert) + if (coverageInvert) { mask = ~mask; } @@ -2431,21 +1422,23 @@ void Context::applyState(GLenum drawMode) { mask = 0xFFFFFFFF; } - mRenderer->setBlendState(framebufferObject, mState.blend, mState.blendColor, mask); + mRenderer->setBlendState(framebufferObject, mState.getBlendState(), mState.getBlendColor(), mask); - mRenderer->setDepthStencilState(mState.depthStencil, mState.stencilRef, mState.stencilBackRef, - mState.rasterizer.frontFace == GL_CCW); + mRenderer->setDepthStencilState(mState.getDepthStencilState(), mState.getStencilRef(), mState.getStencilBackRef(), + rasterizer.frontFace == GL_CCW); } // Applies the shaders and shader constants to the Direct3D 9 device void Context::applyShaders(ProgramBinary *programBinary, bool transformFeedbackActive) { - const VertexAttribute *vertexAttributes = getCurrentVertexArray()->getVertexAttributes(); + const VertexAttribute *vertexAttributes = mState.getVertexArray()->getVertexAttributes(); VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS]; - VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.vertexAttribCurrentValues); + VertexFormat::GetInputLayout(inputLayout, programBinary, vertexAttributes, mState.getVertexAttribCurrentValues()); - mRenderer->applyShaders(programBinary, mState.rasterizer.rasterizerDiscard, transformFeedbackActive, inputLayout); + const Framebuffer *fbo = mState.getDrawFramebuffer(); + + mRenderer->applyShaders(programBinary, inputLayout, fbo, mState.getRasterizerState().rasterizerDiscard, transformFeedbackActive); programBinary->applyUniforms(); } @@ -2461,10 +1454,10 @@ size_t Context::getCurrentTexturesAndSamplerStates(ProgramBinary *programBinary, if (textureUnit != -1) { outTextures[i] = getSamplerTexture(textureUnit, outTextureTypes[i]); - outTextures[i]->getSamplerState(&outSamplers[i]); - if (mState.samplers[textureUnit] != 0) + outTextures[i]->getSamplerStateWithNativeOffset(&outSamplers[i]); + Sampler *samplerObject = mState.getSampler(textureUnit); + if (samplerObject) { - Sampler *samplerObject = getSampler(mState.samplers[textureUnit]); samplerObject->getState(&outSamplers[i]); } } @@ -2481,7 +1474,7 @@ void Context::generateSwizzles(Texture *textures[], size_t count) { for (size_t i = 0; i < count; i++) { - if (textures[i] && textures[i]->isSwizzled()) + if (textures[i] && textures[i]->getSamplerState().swizzleRequired()) { mRenderer->generateSwizzle(textures[i]); } @@ -2513,13 +1506,11 @@ void Context::applyTextures(SamplerType shaderType, Texture *textures[], Texture { mRenderer->setSamplerState(shaderType, samplerIndex, sampler); mRenderer->setTexture(shaderType, samplerIndex, texture); - texture->resetDirty(); } else { Texture *incompleteTexture = getIncompleteTexture(textureType); mRenderer->setTexture(shaderType, samplerIndex, incompleteTexture); - incompleteTexture->resetDirty(); } } else @@ -2536,7 +1527,7 @@ void Context::applyTextures(SamplerType shaderType, Texture *textures[], Texture bool Context::applyUniformBuffers() { - Program *programObject = getProgram(mState.currentProgram); + Program *programObject = getProgram(mState.getCurrentProgramId()); ProgramBinary *programBinary = programObject->getProgramBinary(); std::vector boundBuffers; @@ -2544,15 +1535,15 @@ bool Context::applyUniformBuffers() for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++) { GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex); - const OffsetBindingPointer& boundBuffer = mState.uniformBuffers[blockBinding]; - if (boundBuffer.id() == 0) + + if (mState.getIndexedUniformBuffer(blockBinding)->id() == 0) { // undefined behaviour return false; } else { - gl::Buffer *uniformBuffer = boundBuffer.get(); + Buffer *uniformBuffer = mState.getIndexedUniformBuffer(blockBinding); ASSERT(uniformBuffer); boundBuffers.push_back(uniformBuffer); } @@ -2563,15 +1554,15 @@ bool Context::applyUniformBuffers() bool Context::applyTransformFeedbackBuffers() { - TransformFeedback *curTransformFeedback = getCurrentTransformFeedback(); + TransformFeedback *curTransformFeedback = mState.getCurrentTransformFeedback(); if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused()) { Buffer *transformFeedbackBuffers[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; GLintptr transformFeedbackOffsets[IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) { - transformFeedbackBuffers[i] = mState.transformFeedbackBuffers[i].get(); - transformFeedbackOffsets[i] = mState.transformFeedbackBuffers[i].getOffset(); + transformFeedbackBuffers[i] = mState.getIndexedTransformFeedbackBuffer(i); + transformFeedbackOffsets[i] = mState.getIndexedTransformFeedbackBufferOffset(i); } mRenderer->applyTransformFeedbackBuffers(transformFeedbackBuffers, transformFeedbackOffsets); return true; @@ -2586,7 +1577,7 @@ void Context::markTransformFeedbackUsage() { for (size_t i = 0; i < IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++) { - Buffer *buffer = mState.transformFeedbackBuffers[i].get(); + Buffer *buffer = mState.getIndexedTransformFeedbackBuffer(i); if (buffer) { buffer->markTransformFeedbackUsage(); @@ -2596,86 +1587,30 @@ void Context::markTransformFeedbackUsage() void Context::clear(GLbitfield mask) { - if (isRasterizerDiscardEnabled()) + if (mState.isRasterizerDiscardEnabled()) { return; } - ClearParameters clearParams = { 0 }; - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = false; - } - clearParams.colorFClearValue = mState.colorClearValue; - clearParams.colorClearType = GL_FLOAT; - clearParams.colorMaskRed = mState.blend.colorMaskRed; - clearParams.colorMaskGreen = mState.blend.colorMaskGreen; - clearParams.colorMaskBlue = mState.blend.colorMaskBlue; - clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; - clearParams.clearDepth = false; - clearParams.depthClearValue = mState.depthClearValue; - clearParams.clearStencil = false; - clearParams.stencilClearValue = mState.stencilClearValue; - clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - clearParams.scissorEnabled = mState.scissorTest; - clearParams.scissor = mState.scissor; - - Framebuffer *framebufferObject = getDrawFramebuffer(); - if (mask & GL_COLOR_BUFFER_BIT) - { - if (framebufferObject->hasEnabledColorAttachment()) - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = true; - } - } - } - - if (mask & GL_DEPTH_BUFFER_BIT) - { - if (mState.depthStencil.depthMask && framebufferObject->getDepthbufferType() != GL_NONE) - { - clearParams.clearDepth = true; - } - } - - if (mask & GL_STENCIL_BUFFER_BIT) - { - if (framebufferObject->getStencilbufferType() != GL_NONE) - { - rx::RenderTarget *depthStencil = framebufferObject->getStencilbuffer()->getDepthStencil(); - if (!depthStencil) - { - ERR("Depth stencil pointer unexpectedly null."); - return; - } - - if (gl::GetStencilBits(depthStencil->getActualFormat(), mClientVersion) > 0) - { - clearParams.clearStencil = true; - } - } - } - + ClearParameters clearParams = mState.getClearParameters(mask); if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - mRenderer->clear(clearParams, framebufferObject); + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } void Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) { - if (isRasterizerDiscardEnabled()) + if (mState.isRasterizerDiscardEnabled()) { return; } // glClearBufferfv can be called to clear the color buffer or depth buffer - ClearParameters clearParams = { 0 }; + ClearParameters clearParams = mState.getClearParameters(0); if (buffer == GL_COLOR) { @@ -2686,90 +1621,54 @@ void Context::clearBufferfv(GLenum buffer, int drawbuffer, const float *values) clearParams.colorFClearValue = ColorF(values[0], values[1], values[2], values[3]); clearParams.colorClearType = GL_FLOAT; } - else - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = false; - } - clearParams.colorFClearValue = mState.colorClearValue; - clearParams.colorClearType = GL_FLOAT; - } - - clearParams.colorMaskRed = mState.blend.colorMaskRed; - clearParams.colorMaskGreen = mState.blend.colorMaskGreen; - clearParams.colorMaskBlue = mState.blend.colorMaskBlue; - clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; if (buffer == GL_DEPTH) { clearParams.clearDepth = true; clearParams.depthClearValue = values[0]; } - else - { - clearParams.clearDepth = false; - clearParams.depthClearValue = mState.depthClearValue; - } - - clearParams.clearStencil = false; - clearParams.stencilClearValue = mState.stencilClearValue; - clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - clearParams.scissorEnabled = mState.scissorTest; - clearParams.scissor = mState.scissor; if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - mRenderer->clear(clearParams, getDrawFramebuffer()); + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } void Context::clearBufferuiv(GLenum buffer, int drawbuffer, const unsigned int *values) { - if (isRasterizerDiscardEnabled()) + if (mState.isRasterizerDiscardEnabled()) { return; } // glClearBufferuv can only be called to clear a color buffer - ClearParameters clearParams = { 0 }; + ClearParameters clearParams = mState.getClearParameters(0); for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) { clearParams.clearColor[i] = (drawbuffer == static_cast(i)); } clearParams.colorUIClearValue = ColorUI(values[0], values[1], values[2], values[3]); clearParams.colorClearType = GL_UNSIGNED_INT; - clearParams.colorMaskRed = mState.blend.colorMaskRed; - clearParams.colorMaskGreen = mState.blend.colorMaskGreen; - clearParams.colorMaskBlue = mState.blend.colorMaskBlue; - clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; - clearParams.clearDepth = false; - clearParams.depthClearValue = mState.depthClearValue; - clearParams.clearStencil = false; - clearParams.stencilClearValue = mState.stencilClearValue; - clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - clearParams.scissorEnabled = mState.scissorTest; - clearParams.scissor = mState.scissor; if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - mRenderer->clear(clearParams, getDrawFramebuffer()); + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } void Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) { - if (isRasterizerDiscardEnabled()) + if (mState.isRasterizerDiscardEnabled()) { return; } // glClearBufferfv can be called to clear the color buffer or stencil buffer - ClearParameters clearParams = { 0 }; + ClearParameters clearParams = mState.getClearParameters(0); if (buffer == GL_COLOR) { @@ -2780,103 +1679,61 @@ void Context::clearBufferiv(GLenum buffer, int drawbuffer, const int *values) clearParams.colorIClearValue = ColorI(values[0], values[1], values[2], values[3]); clearParams.colorClearType = GL_INT; } - else - { - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = false; - } - clearParams.colorFClearValue = mState.colorClearValue; - clearParams.colorClearType = GL_FLOAT; - } - - clearParams.colorMaskRed = mState.blend.colorMaskRed; - clearParams.colorMaskGreen = mState.blend.colorMaskGreen; - clearParams.colorMaskBlue = mState.blend.colorMaskBlue; - clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; - - clearParams.clearDepth = false; - clearParams.depthClearValue = mState.depthClearValue; if (buffer == GL_STENCIL) { clearParams.clearStencil = true; clearParams.stencilClearValue = values[1]; } - else - { - clearParams.clearStencil = false; - clearParams.stencilClearValue = mState.stencilClearValue; - } - clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - - clearParams.scissorEnabled = mState.scissorTest; - clearParams.scissor = mState.scissor; if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - mRenderer->clear(clearParams, getDrawFramebuffer()); + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } void Context::clearBufferfi(GLenum buffer, int drawbuffer, float depth, int stencil) { - if (isRasterizerDiscardEnabled()) + if (mState.isRasterizerDiscardEnabled()) { return; } // glClearBufferfi can only be called to clear a depth stencil buffer - ClearParameters clearParams = { 0 }; - for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++) - { - clearParams.clearColor[i] = false; - } - clearParams.colorFClearValue = mState.colorClearValue; - clearParams.colorClearType = GL_FLOAT; - clearParams.colorMaskRed = mState.blend.colorMaskRed; - clearParams.colorMaskGreen = mState.blend.colorMaskGreen; - clearParams.colorMaskBlue = mState.blend.colorMaskBlue; - clearParams.colorMaskAlpha = mState.blend.colorMaskAlpha; + ClearParameters clearParams = mState.getClearParameters(0); clearParams.clearDepth = true; clearParams.depthClearValue = depth; clearParams.clearStencil = true; clearParams.stencilClearValue = stencil; - clearParams.stencilWriteMask = mState.depthStencil.stencilWritemask; - clearParams.scissorEnabled = mState.scissorTest; - clearParams.scissor = mState.scissor; if (!applyRenderTarget(GL_TRIANGLES, true)) // Clips the clear to the scissor rectangle but not the viewport { return; } - mRenderer->clear(clearParams, getDrawFramebuffer()); + mRenderer->clear(clearParams, mState.getDrawFramebuffer()); } void Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels) { - gl::Framebuffer *framebuffer = getReadFramebuffer(); + gl::Framebuffer *framebuffer = mState.getReadFramebuffer(); - bool isSized = IsSizedInternalFormat(format, mClientVersion); - GLenum sizedInternalFormat = (isSized ? format : GetSizedInternalFormat(format, type, mClientVersion)); - GLuint outputPitch = GetRowPitch(sizedInternalFormat, type, mClientVersion, width, mState.pack.alignment); + GLenum sizedInternalFormat = GetSizedInternalFormat(format, type); + const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat); + GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, mState.getPackAlignment()); - mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.pack, pixels); + mRenderer->readPixels(framebuffer, x, y, width, height, format, type, outputPitch, mState.getPackState(), pixels); } void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances) { - if (!mState.currentProgram) - { - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(mState.getCurrentProgramId() != 0); - ProgramBinary *programBinary = getCurrentProgramBinary(); - programBinary->applyUniforms(); + ProgramBinary *programBinary = mState.getCurrentProgramBinary(); + programBinary->updateSamplerMapping(); Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; @@ -2903,7 +1760,7 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan applyState(mode); - GLenum err = mRenderer->applyVertexBuffer(programBinary, getCurrentVertexArray()->getVertexAttributes(), mState.vertexAttribCurrentValues, first, count, instances); + GLenum err = mRenderer->applyVertexBuffer(programBinary, mState.getVertexArray()->getVertexAttributes(), mState.getVertexAttribCurrentValues(), first, count, instances); if (err != GL_NO_ERROR) { return gl::error(err); @@ -2924,11 +1781,6 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan return; } - if (!programBinary->validateSamplers(NULL)) - { - return gl::error(GL_INVALID_OPERATION); - } - if (!skipDraw(mode)) { mRenderer->drawArrays(mode, count, instances, transformFeedbackActive); @@ -2942,19 +1794,10 @@ void Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instan void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei instances) { - if (!mState.currentProgram) - { - return gl::error(GL_INVALID_OPERATION); - } - - VertexArray *vao = getCurrentVertexArray(); - if (!indices && !vao->getElementArrayBuffer()) - { - return gl::error(GL_INVALID_OPERATION); - } + ASSERT(mState.getCurrentProgramId() != 0); - ProgramBinary *programBinary = getCurrentProgramBinary(); - programBinary->applyUniforms(); + ProgramBinary *programBinary = mState.getCurrentProgramBinary(); + programBinary->updateSamplerMapping(); Texture *vsTextures[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; TextureType vsTextureTypes[IMPLEMENTATION_MAX_VERTEX_TEXTURE_IMAGE_UNITS]; @@ -2981,6 +1824,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid applyState(mode); + VertexArray *vao = mState.getVertexArray(); rx::TranslatedIndexData indexInfo; GLenum err = mRenderer->applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo); if (err != GL_NO_ERROR) @@ -2989,7 +1833,7 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid } GLsizei vertexCount = indexInfo.maxIndex - indexInfo.minIndex + 1; - err = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), mState.vertexAttribCurrentValues, indexInfo.minIndex, vertexCount, instances); + err = mRenderer->applyVertexBuffer(programBinary, vao->getVertexAttributes(), mState.getVertexAttribCurrentValues(), indexInfo.minIndex, vertexCount, instances); if (err != GL_NO_ERROR) { return gl::error(err); @@ -3013,359 +1857,191 @@ void Context::drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid return; } - if (!programBinary->validateSamplers(NULL)) - { - return gl::error(GL_INVALID_OPERATION); - } - if (!skipDraw(mode)) { mRenderer->drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances); } } -// Implements glFlush when block is false, glFinish when block is true -void Context::sync(bool block) -{ - mRenderer->sync(block); -} - -void Context::recordInvalidEnum() -{ - mInvalidEnum = true; -} - -void Context::recordInvalidValue() -{ - mInvalidValue = true; -} - -void Context::recordInvalidOperation() -{ - mInvalidOperation = true; -} - -void Context::recordOutOfMemory() -{ - mOutOfMemory = true; -} - -void Context::recordInvalidFramebufferOperation() -{ - mInvalidFramebufferOperation = true; -} - -// Get one of the recorded errors and clear its flag, if any. -// [OpenGL ES 2.0.24] section 2.5 page 13. -GLenum Context::getError() -{ - if (mInvalidEnum) - { - mInvalidEnum = false; - - return GL_INVALID_ENUM; - } - - if (mInvalidValue) - { - mInvalidValue = false; - - return GL_INVALID_VALUE; - } - - if (mInvalidOperation) - { - mInvalidOperation = false; - - return GL_INVALID_OPERATION; - } - - if (mOutOfMemory) - { - mOutOfMemory = false; - - return GL_OUT_OF_MEMORY; - } - - if (mInvalidFramebufferOperation) - { - mInvalidFramebufferOperation = false; - - return GL_INVALID_FRAMEBUFFER_OPERATION; - } - - return GL_NO_ERROR; -} - -GLenum Context::getResetStatus() -{ - if (mResetStatus == GL_NO_ERROR && !mContextLost) - { - // mResetStatus will be set by the markContextLost callback - // in the case a notification is sent - mRenderer->testDeviceLost(true); - } - - GLenum status = mResetStatus; - - if (mResetStatus != GL_NO_ERROR) - { - ASSERT(mContextLost); - - if (mRenderer->testDeviceResettable()) - { - mResetStatus = GL_NO_ERROR; - } - } - - return status; -} - -bool Context::isResetNotificationEnabled() -{ - return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT); -} - -int Context::getClientVersion() const -{ - return mClientVersion; -} - -int Context::getMajorShaderModel() const -{ - return mMajorShaderModel; -} - -float Context::getMaximumPointSize() const -{ - return mMaximumPointSize; -} - -unsigned int Context::getMaximumCombinedTextureImageUnits() const -{ - return mRenderer->getMaxCombinedTextureImageUnits(); -} - -unsigned int Context::getMaximumCombinedUniformBufferBindings() const -{ - return mRenderer->getMaxVertexShaderUniformBuffers() + - mRenderer->getMaxFragmentShaderUniformBuffers(); -} - -int Context::getMaxSupportedSamples() const -{ - return mRenderer->getMaxSupportedSamples(); -} - -GLsizei Context::getMaxSupportedFormatSamples(GLenum internalFormat) const -{ - return mRenderer->getMaxSupportedFormatSamples(internalFormat); -} - -GLsizei Context::getNumSampleCounts(GLenum internalFormat) const -{ - return mRenderer->getNumSampleCounts(internalFormat); -} - -void Context::getSampleCounts(GLenum internalFormat, GLsizei bufSize, GLint *params) const -{ - mRenderer->getSampleCounts(internalFormat, bufSize, params); -} - -unsigned int Context::getMaxTransformFeedbackBufferBindings() const -{ - return mRenderer->getMaxTransformFeedbackBuffers(); -} - -GLintptr Context::getUniformBufferOffsetAlignment() const -{ - // setting a large alignment forces uniform buffers to bind with zero offset - return static_cast(std::numeric_limits::max()); -} - -unsigned int Context::getMaximumRenderTargets() const -{ - return mRenderer->getMaxRenderTargets(); -} - -bool Context::supportsEventQueries() const -{ - return mSupportsEventQueries; -} - -bool Context::supportsOcclusionQueries() const -{ - return mSupportsOcclusionQueries; -} - -bool Context::supportsBGRATextures() const -{ - return mSupportsBGRATextures; -} - -bool Context::supportsDXT1Textures() const -{ - return mSupportsDXT1Textures; -} - -bool Context::supportsDXT3Textures() const +// Implements glFlush when block is false, glFinish when block is true +void Context::sync(bool block) { - return mSupportsDXT3Textures; + mRenderer->sync(block); } -bool Context::supportsDXT5Textures() const +void Context::recordInvalidEnum() { - return mSupportsDXT5Textures; + mInvalidEnum = true; } -bool Context::supportsFloat32Textures() const +void Context::recordInvalidValue() { - return mSupportsFloat32Textures; + mInvalidValue = true; } -bool Context::supportsFloat32LinearFilter() const +void Context::recordInvalidOperation() { - return mSupportsFloat32LinearFilter; + mInvalidOperation = true; } -bool Context::supportsFloat32RenderableTextures() const +void Context::recordOutOfMemory() { - return mSupportsFloat32RenderableTextures; + mOutOfMemory = true; } -bool Context::supportsFloat16Textures() const +void Context::recordInvalidFramebufferOperation() { - return mSupportsFloat16Textures; + mInvalidFramebufferOperation = true; } -bool Context::supportsFloat16LinearFilter() const +// Get one of the recorded errors and clear its flag, if any. +// [OpenGL ES 2.0.24] section 2.5 page 13. +GLenum Context::getError() { - return mSupportsFloat16LinearFilter; -} + if (mInvalidEnum) + { + mInvalidEnum = false; -bool Context::supportsFloat16RenderableTextures() const -{ - return mSupportsFloat16RenderableTextures; -} + return GL_INVALID_ENUM; + } -int Context::getMaximumRenderbufferDimension() const -{ - return mMaxRenderbufferDimension; -} + if (mInvalidValue) + { + mInvalidValue = false; -int Context::getMaximum2DTextureDimension() const -{ - return mMax2DTextureDimension; -} + return GL_INVALID_VALUE; + } -int Context::getMaximumCubeTextureDimension() const -{ - return mMaxCubeTextureDimension; -} + if (mInvalidOperation) + { + mInvalidOperation = false; -int Context::getMaximum3DTextureDimension() const -{ - return mMax3DTextureDimension; -} + return GL_INVALID_OPERATION; + } -int Context::getMaximum2DArrayTextureLayers() const -{ - return mMax2DArrayTextureLayers; -} + if (mOutOfMemory) + { + mOutOfMemory = false; -int Context::getMaximum2DTextureLevel() const -{ - return mMax2DTextureLevel; -} + return GL_OUT_OF_MEMORY; + } -int Context::getMaximumCubeTextureLevel() const -{ - return mMaxCubeTextureLevel; -} + if (mInvalidFramebufferOperation) + { + mInvalidFramebufferOperation = false; -int Context::getMaximum3DTextureLevel() const -{ - return mMax3DTextureLevel; -} + return GL_INVALID_FRAMEBUFFER_OPERATION; + } -int Context::getMaximum2DArrayTextureLevel() const -{ - return mMax2DArrayTextureLevel; + return GL_NO_ERROR; } -bool Context::supportsLuminanceTextures() const +GLenum Context::getResetStatus() { - return mSupportsLuminanceTextures; + if (mResetStatus == GL_NO_ERROR && !mContextLost) + { + // mResetStatus will be set by the markContextLost callback + // in the case a notification is sent + mRenderer->testDeviceLost(true); + } + + GLenum status = mResetStatus; + + if (mResetStatus != GL_NO_ERROR) + { + ASSERT(mContextLost); + + if (mRenderer->testDeviceResettable()) + { + mResetStatus = GL_NO_ERROR; + } + } + + return status; } -bool Context::supportsLuminanceAlphaTextures() const +bool Context::isResetNotificationEnabled() { - return mSupportsLuminanceAlphaTextures; + return (mResetStrategy == GL_LOSE_CONTEXT_ON_RESET_EXT); } -bool Context::supportsRGTextures() const +int Context::getClientVersion() const { - return mSupportsRGTextures; + return mClientVersion; } -bool Context::supportsDepthTextures() const +const Caps &Context::getCaps() const { - return mSupportsDepthTextures; + return mCaps; } -bool Context::supports32bitIndices() const +const TextureCapsMap &Context::getTextureCaps() const { - return mSupports32bitIndices; + return mTextureCaps; } -bool Context::supportsNonPower2Texture() const +const Extensions &Context::getExtensions() const { - return mSupportsNonPower2Texture; + return mExtensions; } -bool Context::supportsInstancing() const +unsigned int Context::getMaximumCombinedTextureImageUnits() const { - return mSupportsInstancing; + return mRenderer->getMaxCombinedTextureImageUnits(); } -bool Context::supportsTextureFilterAnisotropy() const +unsigned int Context::getMaximumCombinedUniformBufferBindings() const { - return mSupportsTextureFilterAnisotropy; + return mRenderer->getMaxVertexShaderUniformBuffers() + + mRenderer->getMaxFragmentShaderUniformBuffers(); } -bool Context::supportsPBOs() const +unsigned int Context::getMaxTransformFeedbackBufferBindings() const { - return mSupportsPBOs; + return mRenderer->getMaxTransformFeedbackBuffers(); } -float Context::getTextureMaxAnisotropy() const +GLintptr Context::getUniformBufferOffsetAlignment() const { - return mMaxTextureAnisotropy; + // setting a large alignment forces uniform buffers to bind with zero offset + return static_cast(std::numeric_limits::max()); } void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type) { - Framebuffer *framebuffer = getReadFramebuffer(); + Framebuffer *framebuffer = mState.getReadFramebuffer(); ASSERT(framebuffer && framebuffer->completeness() == GL_FRAMEBUFFER_COMPLETE); FramebufferAttachment *attachment = framebuffer->getReadColorbuffer(); ASSERT(attachment); - *internalFormat = attachment->getActualFormat(); - *format = gl::GetFormat(attachment->getActualFormat(), mClientVersion); - *type = gl::GetType(attachment->getActualFormat(), mClientVersion); + GLenum actualFormat = attachment->getActualFormat(); + const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualFormat); + + *internalFormat = actualFormat; + *format = actualFormatInfo.format; + *type = actualFormatInfo.type; +} + +void Context::detachTexture(GLuint texture) +{ + // Simple pass-through to State's detachTexture method, as textures do not require + // allocation map management either here or in the resource manager at detach time. + // Zero textures are held by the Context, and we don't attempt to request them from + // the State. + mState.detachTexture(texture); } void Context::detachBuffer(GLuint buffer) { + // Buffer detachment is handled by Context, because the buffer must also be + // attached from any VAOs in existence, and Context holds the VAO map. + // [OpenGL ES 2.0.24] section 2.9 page 22: // If a buffer object is deleted while it is bound, all bindings to that object in the current context // (i.e. in the thread that called Delete-Buffers) are reset to zero. - if (mState.arrayBuffer.id() == buffer) - { - mState.arrayBuffer.set(NULL); - } + mState.removeArrayBufferBinding(buffer); // mark as freed among the vertex array objects for (auto vaoIt = mVertexArrayMap.begin(); vaoIt != mVertexArrayMap.end(); vaoIt++) @@ -3374,54 +2050,22 @@ void Context::detachBuffer(GLuint buffer) } } -void Context::detachTexture(GLuint texture) -{ - // [OpenGL ES 2.0.24] section 3.8 page 84: - // If a texture object is deleted, it is as if all texture units which are bound to that texture object are - // rebound to texture object zero - - for (int type = 0; type < TEXTURE_TYPE_COUNT; type++) - { - for (int sampler = 0; sampler < IMPLEMENTATION_MAX_COMBINED_TEXTURE_IMAGE_UNITS; sampler++) - { - if (mState.samplerTexture[type][sampler].id() == texture) - { - mState.samplerTexture[type][sampler].set(NULL); - } - } - } - - // [OpenGL ES 2.0.24] section 4.4 page 112: - // If a texture object is deleted while its image is attached to the currently bound framebuffer, then it is - // as if Texture2DAttachment had been called, with a texture of 0, for each attachment point to which this - // image was attached in the currently bound framebuffer. - - Framebuffer *readFramebuffer = getReadFramebuffer(); - Framebuffer *drawFramebuffer = getDrawFramebuffer(); - - if (readFramebuffer) - { - readFramebuffer->detachTexture(texture); - } - - if (drawFramebuffer && drawFramebuffer != readFramebuffer) - { - drawFramebuffer->detachTexture(texture); - } -} - void Context::detachFramebuffer(GLuint framebuffer) { + // Framebuffer detachment is handled by Context, because 0 is a valid + // Framebuffer object, and a pointer to it must be passed from Context + // to State at binding time. + // [OpenGL ES 2.0.24] section 4.4 page 107: // If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though // BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero. - if (mState.readFramebuffer == framebuffer) + if (mState.removeReadFramebufferBinding(framebuffer)) { bindReadFramebuffer(0); } - if (mState.drawFramebuffer == framebuffer) + if (mState.removeDrawFramebufferBinding(framebuffer)) { bindDrawFramebuffer(0); } @@ -3429,40 +2073,19 @@ void Context::detachFramebuffer(GLuint framebuffer) void Context::detachRenderbuffer(GLuint renderbuffer) { - // [OpenGL ES 2.0.24] section 4.4 page 109: - // If a renderbuffer that is currently bound to RENDERBUFFER is deleted, it is as though BindRenderbuffer - // had been executed with the target RENDERBUFFER and name of zero. - - if (mState.renderbuffer.id() == renderbuffer) - { - bindRenderbuffer(0); - } - - // [OpenGL ES 2.0.24] section 4.4 page 111: - // If a renderbuffer object is deleted while its image is attached to the currently bound framebuffer, - // then it is as if FramebufferRenderbuffer had been called, with a renderbuffer of 0, for each attachment - // point to which this image was attached in the currently bound framebuffer. - - Framebuffer *readFramebuffer = getReadFramebuffer(); - Framebuffer *drawFramebuffer = getDrawFramebuffer(); - - if (readFramebuffer) - { - readFramebuffer->detachRenderbuffer(renderbuffer); - } - - if (drawFramebuffer && drawFramebuffer != readFramebuffer) - { - drawFramebuffer->detachRenderbuffer(renderbuffer); - } + mState.detachRenderbuffer(renderbuffer); } void Context::detachVertexArray(GLuint vertexArray) { + // Vertex array detachment is handled by Context, because 0 is a valid + // VAO, and a pointer to it must be passed from Context to State at + // binding time. + // [OpenGL ES 3.0.2] section 2.10 page 43: // If a vertex array object that is currently bound is deleted, the binding // for that object reverts to zero and the default vertex array becomes current. - if (mState.vertexArray == vertexArray) + if (mState.removeVertexArrayBinding(vertexArray)) { bindVertexArray(0); } @@ -3470,25 +2093,12 @@ void Context::detachVertexArray(GLuint vertexArray) void Context::detachTransformFeedback(GLuint transformFeedback) { - if (mState.transformFeedback.id() == transformFeedback) - { - bindTransformFeedback(0); - } + mState.detachTransformFeedback(transformFeedback); } void Context::detachSampler(GLuint sampler) { - // [OpenGL ES 3.0.2] section 3.8.2 pages 123-124: - // If a sampler object that is currently bound to one or more texture units is - // deleted, it is as though BindSampler is called once for each texture unit to - // which the sampler is bound, with unit set to the texture unit and sampler set to zero. - for (unsigned int textureUnit = 0; textureUnit < ArraySize(mState.samplers); textureUnit++) - { - if (mState.samplers[textureUnit] == sampler) - { - mState.samplers[textureUnit] = 0; - } - } + mState.detachSampler(sampler); } Texture *Context::getIncompleteTexture(TextureType type) @@ -3508,7 +2118,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_2D: { - Texture2D *incomplete2d = new Texture2D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); + Texture2D *incomplete2d = new Texture2D(mRenderer->createTexture2D(), Texture::INCOMPLETE_TEXTURE_ID); incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete2d; } @@ -3516,7 +2126,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_CUBE: { - TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); + TextureCubeMap *incompleteCube = new TextureCubeMap(mRenderer->createTextureCube(), Texture::INCOMPLETE_TEXTURE_ID); incompleteCube->setImagePosX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); incompleteCube->setImageNegX(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); @@ -3531,7 +2141,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_3D: { - Texture3D *incomplete3d = new Texture3D(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); + Texture3D *incomplete3d = new Texture3D(mRenderer->createTexture3D(), Texture::INCOMPLETE_TEXTURE_ID); incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete3d; @@ -3540,7 +2150,7 @@ Texture *Context::getIncompleteTexture(TextureType type) case TEXTURE_2D_ARRAY: { - Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer, Texture::INCOMPLETE_TEXTURE_ID); + Texture2DArray *incomplete2darray = new Texture2DArray(mRenderer->createTexture2DArray(), Texture::INCOMPLETE_TEXTURE_ID); incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color); t = incomplete2darray; @@ -3561,7 +2171,7 @@ bool Context::skipDraw(GLenum drawMode) // ProgramBinary assumes non-point rendering if gl_PointSize isn't written, // which affects varying interpolation. Since the value of gl_PointSize is // undefined when not written, just skip drawing to avoid unexpected results. - if (!getCurrentProgramBinary()->usesPointSize()) + if (!mState.getCurrentProgramBinary()->usesPointSize()) { // This is stictly speaking not an error, but developers should be // notified of risking undefined behavior. @@ -3572,7 +2182,7 @@ bool Context::skipDraw(GLenum drawMode) } else if (IsTriangleMode(drawMode)) { - if (mState.rasterizer.cullFace && mState.rasterizer.cullMode == GL_FRONT_AND_BACK) + if (mState.getRasterizerState().cullFace && mState.getRasterizerState().cullMode == GL_FRONT_AND_BACK) { return true; } @@ -3581,27 +2191,9 @@ bool Context::skipDraw(GLenum drawMode) return false; } -void Context::setVertexAttribf(GLuint index, const GLfloat values[4]) -{ - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); - mState.vertexAttribCurrentValues[index].setFloatValues(values); -} - -void Context::setVertexAttribu(GLuint index, const GLuint values[4]) -{ - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); - mState.vertexAttribCurrentValues[index].setUnsignedIntValues(values); -} - -void Context::setVertexAttribi(GLuint index, const GLint values[4]) -{ - ASSERT(index < gl::MAX_VERTEX_ATTRIBS); - mState.vertexAttribCurrentValues[index].setIntValues(values); -} - void Context::setVertexAttribDivisor(GLuint index, GLuint divisor) { - getCurrentVertexArray()->setVertexAttribDivisor(index, divisor); + mState.getVertexArray()->setVertexAttribDivisor(index, divisor); } void Context::samplerParameteri(GLuint sampler, GLenum pname, GLint param) @@ -3640,8 +2232,8 @@ void Context::samplerParameterf(GLuint sampler, GLenum pname, GLfloat param) case GL_TEXTURE_WRAP_S: samplerObject->setWrapS(uiround(param)); break; case GL_TEXTURE_WRAP_T: samplerObject->setWrapT(uiround(param)); break; case GL_TEXTURE_WRAP_R: samplerObject->setWrapR(uiround(param)); break; - case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; - case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; + case GL_TEXTURE_MIN_LOD: samplerObject->setMinLod(param); break; + case GL_TEXTURE_MAX_LOD: samplerObject->setMaxLod(param); break; case GL_TEXTURE_COMPARE_MODE: samplerObject->setComparisonMode(uiround(param)); break; case GL_TEXTURE_COMPARE_FUNC: samplerObject->setComparisonFunc(uiround(param)); break; default: UNREACHABLE(); break; @@ -3692,195 +2284,50 @@ GLfloat Context::getSamplerParameterf(GLuint sampler, GLenum pname) } } -// keep list sorted in following order -// OES extensions -// EXT extensions -// Vendor extensions -void Context::initExtensionString() +void Context::initRendererString() { - // Do not report extension in GLES 3 contexts for now - if (mClientVersion == 2) - { - // OES extensions - if (supports32bitIndices()) - { - mExtensionStringList.push_back("GL_OES_element_index_uint"); - } - - mExtensionStringList.push_back("GL_OES_packed_depth_stencil"); - mExtensionStringList.push_back("GL_OES_get_program_binary"); - mExtensionStringList.push_back("GL_OES_rgb8_rgba8"); - - if (supportsPBOs()) - { - mExtensionStringList.push_back("NV_pixel_buffer_object"); - mExtensionStringList.push_back("GL_OES_mapbuffer"); - mExtensionStringList.push_back("GL_EXT_map_buffer_range"); - } - - if (mRenderer->getDerivativeInstructionSupport()) - { - mExtensionStringList.push_back("GL_OES_standard_derivatives"); - } - - if (supportsFloat16Textures()) - { - mExtensionStringList.push_back("GL_OES_texture_half_float"); - } - if (supportsFloat16LinearFilter()) - { - mExtensionStringList.push_back("GL_OES_texture_half_float_linear"); - } - if (supportsFloat32Textures()) - { - mExtensionStringList.push_back("GL_OES_texture_float"); - } - if (supportsFloat32LinearFilter()) - { - mExtensionStringList.push_back("GL_OES_texture_float_linear"); - } - - if (supportsRGTextures()) - { - mExtensionStringList.push_back("GL_EXT_texture_rg"); - } - - if (supportsNonPower2Texture()) - { - mExtensionStringList.push_back("GL_OES_texture_npot"); - } - - // Multi-vendor (EXT) extensions - if (supportsOcclusionQueries()) - { - mExtensionStringList.push_back("GL_EXT_occlusion_query_boolean"); - } - - mExtensionStringList.push_back("GL_EXT_read_format_bgra"); - mExtensionStringList.push_back("GL_EXT_robustness"); - mExtensionStringList.push_back("GL_EXT_shader_texture_lod"); - - if (supportsDXT1Textures()) - { - mExtensionStringList.push_back("GL_EXT_texture_compression_dxt1"); - } - - if (supportsTextureFilterAnisotropy()) - { - mExtensionStringList.push_back("GL_EXT_texture_filter_anisotropic"); - } - - if (supportsBGRATextures()) - { - mExtensionStringList.push_back("GL_EXT_texture_format_BGRA8888"); - } - - if (mRenderer->getMaxRenderTargets() > 1) - { - mExtensionStringList.push_back("GL_EXT_draw_buffers"); - } - - mExtensionStringList.push_back("GL_EXT_texture_storage"); - mExtensionStringList.push_back("GL_EXT_frag_depth"); - mExtensionStringList.push_back("GL_EXT_blend_minmax"); - - // ANGLE-specific extensions - if (supportsDepthTextures()) - { - mExtensionStringList.push_back("GL_ANGLE_depth_texture"); - } - - mExtensionStringList.push_back("GL_ANGLE_framebuffer_blit"); - if (getMaxSupportedSamples() != 0) - { - mExtensionStringList.push_back("GL_ANGLE_framebuffer_multisample"); - } - - if (supportsInstancing()) - { - mExtensionStringList.push_back("GL_ANGLE_instanced_arrays"); - } - - mExtensionStringList.push_back("GL_ANGLE_pack_reverse_row_order"); - - if (supportsDXT3Textures()) - { - mExtensionStringList.push_back("GL_ANGLE_texture_compression_dxt3"); - } - if (supportsDXT5Textures()) - { - mExtensionStringList.push_back("GL_ANGLE_texture_compression_dxt5"); - } - - mExtensionStringList.push_back("GL_ANGLE_texture_usage"); - mExtensionStringList.push_back("GL_ANGLE_translated_shader_source"); - - // Other vendor-specific extensions - if (supportsEventQueries()) - { - mExtensionStringList.push_back("GL_NV_fence"); - } - } - - if (mClientVersion == 3) - { - mExtensionStringList.push_back("GL_EXT_color_buffer_float"); - - mExtensionStringList.push_back("GL_EXT_read_format_bgra"); - - if (supportsBGRATextures()) - { - mExtensionStringList.push_back("GL_EXT_texture_format_BGRA8888"); - } - } - - // Join the extension strings to one long string for use with GetString - std::stringstream strstr; - for (unsigned int extensionIndex = 0; extensionIndex < mExtensionStringList.size(); extensionIndex++) - { - strstr << mExtensionStringList[extensionIndex]; - strstr << " "; - } + std::ostringstream rendererString; + rendererString << "ANGLE ("; + rendererString << mRenderer->getRendererDescription(); + rendererString << ")"; - mCombinedExtensionsString = makeStaticString(strstr.str()); + mRendererString = MakeStaticString(rendererString.str()); } -const char *Context::getCombinedExtensionsString() const +const std::string &Context::getRendererString() const { - return mCombinedExtensionsString; + return mRendererString; } -const char *Context::getExtensionString(const GLuint index) const +void Context::initExtensionStrings() { - ASSERT(index < mExtensionStringList.size()); - return mExtensionStringList[index].c_str(); + mExtensionStrings = mExtensions.getStrings(); + + std::ostringstream combinedStringStream; + std::copy(mExtensionStrings.begin(), mExtensionStrings.end(), std::ostream_iterator(combinedStringStream, " ")); + mExtensionString = combinedStringStream.str(); } -unsigned int Context::getNumExtensions() const +const std::string &Context::getExtensionString() const { - return mExtensionStringList.size(); + return mExtensionString; } -void Context::initRendererString() +const std::string &Context::getExtensionString(size_t idx) const { - std::ostringstream rendererString; - rendererString << "ANGLE ("; - rendererString << mRenderer->getRendererDescription(); - rendererString << ")"; - - mRendererString = makeStaticString(rendererString.str()); + return mExtensionStrings[idx]; } -const char *Context::getRendererString() const +size_t Context::getExtensionStringCount() const { - return mRendererString; + return mExtensionStrings.size(); } size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray *outSerialArray) { size_t serialCount = 0; - Framebuffer *drawFramebuffer = getDrawFramebuffer(); + Framebuffer *drawFramebuffer = mState.getDrawFramebuffer(); for (unsigned int i = 0; i < IMPLEMENTATION_MAX_DRAW_BUFFERS; i++) { FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i); @@ -3904,8 +2351,8 @@ size_t Context::getBoundFramebufferTextureSerials(FramebufferTextureSerialArray void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) { - Framebuffer *readFramebuffer = getReadFramebuffer(); - Framebuffer *drawFramebuffer = getDrawFramebuffer(); + Framebuffer *readFramebuffer = mState.getReadFramebuffer(); + Framebuffer *drawFramebuffer = mState.getDrawFramebuffer(); bool blitRenderTarget = false; bool blitDepth = false; @@ -3927,7 +2374,7 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1 gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0); if (blitRenderTarget || blitDepth || blitStencil) { - const gl::Rectangle *scissor = mState.scissorTest ? &mState.scissor : NULL; + const gl::Rectangle *scissor = mState.isScissorTestEnabled() ? &mState.getScissor() : NULL; mRenderer->blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor, blitRenderTarget, blitDepth, blitStencil, filter); } @@ -3941,10 +2388,10 @@ void Context::invalidateFrameBuffer(GLenum target, GLsizei numAttachments, const { case GL_FRAMEBUFFER: case GL_DRAW_FRAMEBUFFER: - frameBuffer = getDrawFramebuffer(); + frameBuffer = mState.getDrawFramebuffer(); break; case GL_READ_FRAMEBUFFER: - frameBuffer = getReadFramebuffer(); + frameBuffer = mState.getReadFramebuffer(); break; default: UNREACHABLE(); @@ -4006,31 +2453,50 @@ void Context::invalidateFrameBuffer(GLenum target, GLsizei numAttachments, const } } -bool Context::hasMappedBuffer(GLenum target) const +void Context::initCaps(GLuint clientVersion) { - if (target == GL_ARRAY_BUFFER) + mCaps = mRenderer->getRendererCaps(); + + mExtensions = mRenderer->getRendererExtensions(); + + if (clientVersion < 3) { - for (unsigned int attribIndex = 0; attribIndex < gl::MAX_VERTEX_ATTRIBS; attribIndex++) - { - const gl::VertexAttribute &vertexAttrib = getVertexAttribState(attribIndex); - gl::Buffer *boundBuffer = vertexAttrib.mBoundBuffer.get(); - if (vertexAttrib.mArrayEnabled && boundBuffer && boundBuffer->mapped()) - { - return true; - } - } + // Disable ES3+ extensions + mExtensions.colorBufferFloat = false; } - else if (target == GL_ELEMENT_ARRAY_BUFFER) + + if (clientVersion > 2) { - Buffer *elementBuffer = getElementArrayBuffer(); - return (elementBuffer && elementBuffer->mapped()); + // FIXME(geofflang): Don't support EXT_sRGB in non-ES2 contexts + //mExtensions.sRGB = false; } - else if (target == GL_TRANSFORM_FEEDBACK_BUFFER) + + GLuint maxSamples = 0; + const TextureCapsMap &rendererFormats = mRenderer->getRendererTextureCaps(); + for (TextureCapsMap::const_iterator i = rendererFormats.begin(); i != rendererFormats.end(); i++) { - UNIMPLEMENTED(); + GLenum format = i->first; + TextureCaps formatCaps = i->second; + + const InternalFormat &formatInfo = GetInternalFormatInfo(format); + if (formatCaps.texturable && formatInfo.textureSupport(clientVersion, mExtensions)) + { + // Update the format caps based on the client version and extensions + formatCaps.renderable = formatInfo.renderSupport(clientVersion, mExtensions); + formatCaps.filterable = formatInfo.filterSupport(clientVersion, mExtensions); + + // OpenGL ES does not support multisampling with integer formats + if (formatInfo.componentType == GL_INT || formatInfo.componentType == GL_UNSIGNED_INT) + { + formatCaps.sampleCounts.clear(); + } + maxSamples = std::max(maxSamples, formatCaps.getMaxSamples()); + + mTextureCaps.insert(format, formatCaps); + } } - else UNREACHABLE(); - return false; + + mExtensions.maxSamples = maxSamples; } }