diff options
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/State.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libANGLE/State.cpp | 1260 |
1 files changed, 926 insertions, 334 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/State.cpp b/src/3rdparty/angle/src/libANGLE/State.cpp index a1437b838b..f87e963710 100644 --- a/src/3rdparty/angle/src/libANGLE/State.cpp +++ b/src/3rdparty/angle/src/libANGLE/State.cpp @@ -8,15 +8,32 @@ #include "libANGLE/State.h" -#include "common/BitSetIterator.h" -#include "libANGLE/Context.h" +#include <limits> +#include <string.h> + +#include "common/bitset_utils.h" +#include "common/mathutil.h" +#include "common/matrix_utils.h" #include "libANGLE/Caps.h" +#include "libANGLE/Context.h" #include "libANGLE/Debug.h" #include "libANGLE/Framebuffer.h" #include "libANGLE/FramebufferAttachment.h" #include "libANGLE/Query.h" #include "libANGLE/VertexArray.h" #include "libANGLE/formatutils.h" +#include "libANGLE/queryconversions.h" +#include "libANGLE/renderer/ContextImpl.h" + +namespace +{ + +GLenum ActiveQueryType(const GLenum type) +{ + return (type == GL_ANY_SAMPLES_PASSED_CONSERVATIVE) ? GL_ANY_SAMPLES_PASSED : type; +} + +} // anonymous namepace namespace gl { @@ -30,11 +47,15 @@ State::State() mSampleCoverage(false), mSampleCoverageValue(0), mSampleCoverageInvert(false), + mSampleMask(false), + mMaxSampleMaskWords(0), mStencilRef(0), mStencilBackRef(0), mLineWidth(0), mGenerateMipmapHint(GL_NONE), mFragmentShaderDerivativeHint(GL_NONE), + mBindGeneratesResource(true), + mClientArraysEnabled(true), mNearZ(0), mFarZ(0), mReadFramebuffer(nullptr), @@ -42,49 +63,31 @@ State::State() mProgram(nullptr), mVertexArray(nullptr), mActiveSampler(0), - mPrimitiveRestart(false) -{ - // Initialize dirty bit masks - // TODO(jmadill): additional ES3 state - mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_ALIGNMENT); - mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_ROW_LENGTH); - mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT); - mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_IMAGES); - mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_ROWS); - mUnpackStateBitMask.set(DIRTY_BIT_UNPACK_SKIP_PIXELS); - - mPackStateBitMask.set(DIRTY_BIT_PACK_ALIGNMENT); - mPackStateBitMask.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER); - mPackStateBitMask.set(DIRTY_BIT_PACK_ROW_LENGTH); - mPackStateBitMask.set(DIRTY_BIT_PACK_SKIP_ROWS); - mPackStateBitMask.set(DIRTY_BIT_PACK_SKIP_PIXELS); - - mClearStateBitMask.set(DIRTY_BIT_RASTERIZER_DISCARD_ENABLED); - mClearStateBitMask.set(DIRTY_BIT_SCISSOR_TEST_ENABLED); - mClearStateBitMask.set(DIRTY_BIT_SCISSOR); - mClearStateBitMask.set(DIRTY_BIT_VIEWPORT); - mClearStateBitMask.set(DIRTY_BIT_CLEAR_COLOR); - mClearStateBitMask.set(DIRTY_BIT_CLEAR_DEPTH); - mClearStateBitMask.set(DIRTY_BIT_CLEAR_STENCIL); - mClearStateBitMask.set(DIRTY_BIT_COLOR_MASK); - mClearStateBitMask.set(DIRTY_BIT_DEPTH_MASK); - mClearStateBitMask.set(DIRTY_BIT_STENCIL_WRITEMASK_FRONT); - mClearStateBitMask.set(DIRTY_BIT_STENCIL_WRITEMASK_BACK); - - mBlitStateBitMask.set(DIRTY_BIT_SCISSOR_TEST_ENABLED); - mBlitStateBitMask.set(DIRTY_BIT_SCISSOR); + mPrimitiveRestart(false), + mMultiSampling(false), + mSampleAlphaToOne(false), + mFramebufferSRGB(true), + mRobustResourceInit(false), + mProgramBinaryCacheEnabled(false) +{ } State::~State() { - reset(); } -void State::initialize(const Caps &caps, - const Extensions &extensions, - GLuint clientVersion, - bool debug) +void State::initialize(const Context *context, + bool debug, + bool bindGeneratesResource, + bool clientArraysEnabled, + bool robustResourceInit, + bool programBinaryCacheEnabled) { + const Caps &caps = context->getCaps(); + const Extensions &extensions = context->getExtensions(); + const Extensions &nativeExtensions = context->getImplementation()->getNativeExtensions(); + const Version &clientVersion = context->getClientVersion(); + mMaxDrawBuffers = caps.maxDrawBuffers; mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits; @@ -93,62 +96,34 @@ void State::initialize(const Caps &caps, mDepthClearValue = 1.0f; mStencilClearValue = 0; - mRasterizer.rasterizerDiscard = false; - mRasterizer.cullFace = false; - mRasterizer.cullMode = GL_BACK; - mRasterizer.frontFace = GL_CCW; - mRasterizer.polygonOffsetFill = false; - mRasterizer.polygonOffsetFactor = 0.0f; - mRasterizer.polygonOffsetUnits = 0.0f; - mRasterizer.pointDrawMode = false; - mRasterizer.multiSample = false; mScissorTest = false; mScissor.x = 0; mScissor.y = 0; mScissor.width = 0; mScissor.height = 0; - mBlend.blend = false; - mBlend.sourceBlendRGB = GL_ONE; - mBlend.sourceBlendAlpha = GL_ONE; - mBlend.destBlendRGB = GL_ZERO; - mBlend.destBlendAlpha = GL_ZERO; - mBlend.blendEquationRGB = GL_FUNC_ADD; - mBlend.blendEquationAlpha = GL_FUNC_ADD; - mBlend.sampleAlphaToCoverage = false; - mBlend.dither = true; - mBlendColor.red = 0; mBlendColor.green = 0; mBlendColor.blue = 0; mBlendColor.alpha = 0; - mDepthStencil.depthTest = false; - mDepthStencil.depthFunc = GL_LESS; - mDepthStencil.depthMask = true; - mDepthStencil.stencilTest = false; - mDepthStencil.stencilFunc = GL_ALWAYS; - mDepthStencil.stencilMask = static_cast<GLuint>(-1); - mDepthStencil.stencilWritemask = static_cast<GLuint>(-1); - mDepthStencil.stencilBackFunc = GL_ALWAYS; - mDepthStencil.stencilBackMask = static_cast<GLuint>(-1); - mDepthStencil.stencilBackWritemask = static_cast<GLuint>(-1); - mDepthStencil.stencilFail = GL_KEEP; - mDepthStencil.stencilPassDepthFail = GL_KEEP; - mDepthStencil.stencilPassDepthPass = GL_KEEP; - mDepthStencil.stencilBackFail = GL_KEEP; - mDepthStencil.stencilBackPassDepthFail = GL_KEEP; - mDepthStencil.stencilBackPassDepthPass = GL_KEEP; - mStencilRef = 0; mStencilBackRef = 0; mSampleCoverage = false; mSampleCoverageValue = 1.0f; mSampleCoverageInvert = false; + + mMaxSampleMaskWords = caps.maxSampleMaskWords; + mSampleMask = false; + mSampleMaskValues.fill(~GLbitfield(0)); + mGenerateMipmapHint = GL_DONT_CARE; mFragmentShaderDerivativeHint = GL_DONT_CARE; + mBindGeneratesResource = bindGeneratesResource; + mClientArraysEnabled = clientArraysEnabled; + mLineWidth = 1.0f; mViewport.x = 0; @@ -167,23 +142,48 @@ void State::initialize(const Caps &caps, mVertexAttribCurrentValues.resize(caps.maxVertexAttributes); - mUniformBuffers.resize(caps.maxCombinedUniformBlocks); + mUniformBuffers.resize(caps.maxUniformBufferBindings); mSamplerTextures[GL_TEXTURE_2D].resize(caps.maxCombinedTextureImageUnits); mSamplerTextures[GL_TEXTURE_CUBE_MAP].resize(caps.maxCombinedTextureImageUnits); - if (clientVersion >= 3) + if (clientVersion >= Version(3, 0)) { // TODO: These could also be enabled via extension mSamplerTextures[GL_TEXTURE_2D_ARRAY].resize(caps.maxCombinedTextureImageUnits); mSamplerTextures[GL_TEXTURE_3D].resize(caps.maxCombinedTextureImageUnits); } + if (clientVersion >= Version(3, 1)) + { + mSamplerTextures[GL_TEXTURE_2D_MULTISAMPLE].resize(caps.maxCombinedTextureImageUnits); + + mAtomicCounterBuffers.resize(caps.maxAtomicCounterBufferBindings); + mShaderStorageBuffers.resize(caps.maxShaderStorageBufferBindings); + mImageUnits.resize(caps.maxImageUnits); + } + if (nativeExtensions.textureRectangle) + { + mSamplerTextures[GL_TEXTURE_RECTANGLE_ANGLE].resize(caps.maxCombinedTextureImageUnits); + } + if (nativeExtensions.eglImageExternal || nativeExtensions.eglStreamConsumerExternal) + { + mSamplerTextures[GL_TEXTURE_EXTERNAL_OES].resize(caps.maxCombinedTextureImageUnits); + } + mCompleteTextureCache.resize(caps.maxCombinedTextureImageUnits, nullptr); + mCompleteTextureBindings.reserve(caps.maxCombinedTextureImageUnits); + mCachedTexturesInitState = InitState::MayNeedInit; + for (uint32_t textureIndex = 0; textureIndex < caps.maxCombinedTextureImageUnits; + ++textureIndex) + { + mCompleteTextureBindings.emplace_back(OnAttachmentDirtyBinding(this, textureIndex)); + } mSamplers.resize(caps.maxCombinedTextureImageUnits); - mActiveQueries[GL_ANY_SAMPLES_PASSED].set(nullptr); - mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(nullptr); - mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(nullptr); - mActiveQueries[GL_TIME_ELAPSED_EXT].set(nullptr); + mActiveQueries[GL_ANY_SAMPLES_PASSED].set(context, nullptr); + mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(context, nullptr); + mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(context, nullptr); + mActiveQueries[GL_TIME_ELAPSED_EXT].set(context, nullptr); + mActiveQueries[GL_COMMANDS_COMPLETED_CHROMIUM].set(context, nullptr); mProgram = nullptr; @@ -194,52 +194,89 @@ void State::initialize(const Caps &caps, mDebug.setOutputEnabled(debug); mDebug.setMaxLoggedMessages(extensions.maxDebugLoggedMessages); + + mMultiSampling = true; + mSampleAlphaToOne = false; + + mCoverageModulation = GL_NONE; + + angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj); + angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV); + mPathStencilFunc = GL_ALWAYS; + mPathStencilRef = 0; + mPathStencilMask = std::numeric_limits<GLuint>::max(); + + mRobustResourceInit = robustResourceInit; + mProgramBinaryCacheEnabled = programBinaryCacheEnabled; } -void State::reset() +void State::reset(const Context *context) { - for (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++) + for (auto &bindingVec : mSamplerTextures) { - TextureBindingVector &textureVector = bindingVec->second; + TextureBindingVector &textureVector = bindingVec.second; for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++) { - textureVector[textureIdx].set(NULL); + textureVector[textureIdx].set(context, nullptr); } } for (size_t samplerIdx = 0; samplerIdx < mSamplers.size(); samplerIdx++) { - mSamplers[samplerIdx].set(NULL); + mSamplers[samplerIdx].set(context, nullptr); } - mArrayBuffer.set(NULL); - mRenderbuffer.set(NULL); + for (auto &imageUnit : mImageUnits) + { + imageUnit.texture.set(context, nullptr); + imageUnit.level = 0; + imageUnit.layered = false; + imageUnit.layer = 0; + imageUnit.access = GL_READ_ONLY; + imageUnit.format = GL_R32UI; + } + + mRenderbuffer.set(context, nullptr); + + for (auto type : angle::AllEnums<BufferBinding>()) + { + mBoundBuffers[type].set(context, nullptr); + } if (mProgram) { - mProgram->release(); + mProgram->release(context); } - mProgram = NULL; + mProgram = nullptr; + + mProgramPipeline.set(context, nullptr); - mTransformFeedback.set(NULL); + mTransformFeedback.set(context, nullptr); for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++) { - i->second.set(NULL); + i->second.set(context, nullptr); } - mGenericUniformBuffer.set(NULL); - for (BufferVector::iterator bufItr = mUniformBuffers.begin(); bufItr != mUniformBuffers.end(); ++bufItr) + for (auto &buf : mUniformBuffers) { - bufItr->set(NULL); + buf.set(context, nullptr); } - mCopyReadBuffer.set(NULL); - mCopyWriteBuffer.set(NULL); + for (auto &buf : mAtomicCounterBuffers) + { + buf.set(context, nullptr); + } - mPack.pixelBuffer.set(NULL); - mUnpack.pixelBuffer.set(NULL); + for (auto &buf : mShaderStorageBuffers) + { + buf.set(context, nullptr); + } - mProgram = NULL; + angle::Matrix<GLfloat>::setToIdentity(mPathMatrixProj); + angle::Matrix<GLfloat>::setToIdentity(mPathMatrixMV); + mPathStencilFunc = GL_ALWAYS; + mPathStencilRef = 0; + mPathStencilMask = std::numeric_limits<GLuint>::max(); // TODO(jmadill): Is this necessary? setAllDirtyBits(); @@ -318,7 +355,7 @@ void State::setCullFace(bool enabled) mDirtyBits.set(DIRTY_BIT_CULL_FACE_ENABLED); } -void State::setCullMode(GLenum mode) +void State::setCullMode(CullFaceMode mode) { mRasterizer.cullMode = mode; mDirtyBits.set(DIRTY_BIT_CULL_FACE); @@ -528,6 +565,58 @@ bool State::getSampleCoverageInvert() const return mSampleCoverageInvert; } +bool State::isSampleMaskEnabled() const +{ + return mSampleMask; +} + +void State::setSampleMaskEnabled(bool enabled) +{ + mSampleMask = enabled; + mDirtyBits.set(DIRTY_BIT_SAMPLE_MASK_ENABLED); +} + +void State::setSampleMaskParams(GLuint maskNumber, GLbitfield mask) +{ + ASSERT(maskNumber < mMaxSampleMaskWords); + mSampleMaskValues[maskNumber] = mask; + // TODO(jmadill): Use a child dirty bit if we ever use more than two words. + mDirtyBits.set(DIRTY_BIT_SAMPLE_MASK); +} + +GLbitfield State::getSampleMaskWord(GLuint maskNumber) const +{ + ASSERT(maskNumber < mMaxSampleMaskWords); + return mSampleMaskValues[maskNumber]; +} + +GLuint State::getMaxSampleMaskWords() const +{ + return mMaxSampleMaskWords; +} + +void State::setSampleAlphaToOne(bool enabled) +{ + mSampleAlphaToOne = enabled; + mDirtyBits.set(DIRTY_BIT_SAMPLE_ALPHA_TO_ONE); +} + +bool State::isSampleAlphaToOneEnabled() const +{ + return mSampleAlphaToOne; +} + +void State::setMultisampling(bool enabled) +{ + mMultiSampling = enabled; + mDirtyBits.set(DIRTY_BIT_MULTISAMPLING); +} + +bool State::isMultisamplingEnabled() const +{ + return mMultiSampling; +} + bool State::isScissorTestEnabled() const { return mScissorTest; @@ -579,6 +668,8 @@ void State::setEnableFeature(GLenum feature, bool enabled) { switch (feature) { + case GL_MULTISAMPLE_EXT: setMultisampling(enabled); break; + case GL_SAMPLE_ALPHA_TO_ONE_EXT: setSampleAlphaToOne(enabled); break; case GL_CULL_FACE: setCullFace(enabled); break; case GL_POLYGON_OFFSET_FILL: setPolygonOffsetFill(enabled); break; case GL_SAMPLE_ALPHA_TO_COVERAGE: setSampleAlphaToCoverage(enabled); break; @@ -590,20 +681,28 @@ void State::setEnableFeature(GLenum feature, bool enabled) case GL_DITHER: setDither(enabled); break; case GL_PRIMITIVE_RESTART_FIXED_INDEX: setPrimitiveRestart(enabled); break; case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break; + case GL_SAMPLE_MASK: + setSampleMaskEnabled(enabled); + break; case GL_DEBUG_OUTPUT_SYNCHRONOUS: mDebug.setOutputSynchronous(enabled); break; case GL_DEBUG_OUTPUT: mDebug.setOutputEnabled(enabled); break; + case GL_FRAMEBUFFER_SRGB_EXT: + setFramebufferSRGB(enabled); + break; default: UNREACHABLE(); } } -bool State::getEnableFeature(GLenum feature) +bool State::getEnableFeature(GLenum feature) const { switch (feature) { + case GL_MULTISAMPLE_EXT: return isMultisamplingEnabled(); + case GL_SAMPLE_ALPHA_TO_ONE_EXT: return isSampleAlphaToOneEnabled(); case GL_CULL_FACE: return isCullFaceEnabled(); case GL_POLYGON_OFFSET_FILL: return isPolygonOffsetFillEnabled(); case GL_SAMPLE_ALPHA_TO_COVERAGE: return isSampleAlphaToCoverageEnabled(); @@ -615,11 +714,26 @@ bool State::getEnableFeature(GLenum feature) case GL_DITHER: return isDitherEnabled(); case GL_PRIMITIVE_RESTART_FIXED_INDEX: return isPrimitiveRestartEnabled(); case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled(); + case GL_SAMPLE_MASK: + return isSampleMaskEnabled(); case GL_DEBUG_OUTPUT_SYNCHRONOUS: return mDebug.isOutputSynchronous(); case GL_DEBUG_OUTPUT: return mDebug.isOutputEnabled(); - default: UNREACHABLE(); return false; + case GL_BIND_GENERATES_RESOURCE_CHROMIUM: + return isBindGeneratesResourceEnabled(); + case GL_CLIENT_ARRAYS_ANGLE: + return areClientArraysEnabled(); + case GL_FRAMEBUFFER_SRGB_EXT: + return getFramebufferSRGB(); + case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE: + return mRobustResourceInit; + case GL_PROGRAM_CACHE_ENABLED_ANGLE: + return mProgramBinaryCacheEnabled; + + default: + UNREACHABLE(); + return false; } } @@ -649,6 +763,16 @@ void State::setFragmentShaderDerivativeHint(GLenum hint) // Ignore for now. It is valid for implementations to ignore hint. } +bool State::isBindGeneratesResourceEnabled() const +{ + return mBindGeneratesResource; +} + +bool State::areClientArraysEnabled() const +{ + return mClientArraysEnabled; +} + void State::setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height) { mViewport.x = x; @@ -673,9 +797,11 @@ unsigned int State::getActiveSampler() const return static_cast<unsigned int>(mActiveSampler); } -void State::setSamplerTexture(GLenum type, Texture *texture) +void State::setSamplerTexture(const Context *context, GLenum type, Texture *texture) { - mSamplerTextures[type][mActiveSampler].set(texture); + mSamplerTextures[type][mActiveSampler].set(context, texture); + mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS); + mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES); } Texture *State::getTargetTexture(GLenum target) const @@ -699,7 +825,7 @@ GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const return it->second[sampler].id(); } -void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) +void State::detachTexture(const Context *context, const TextureMap &zeroTextures, GLuint texture) { // Textures have a detach method on State rather than a simple // removeBinding, because the zero/null texture objects are managed @@ -710,40 +836,54 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture) // 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 (TextureBindingMap::iterator bindingVec = mSamplerTextures.begin(); bindingVec != mSamplerTextures.end(); bindingVec++) + for (auto &bindingVec : mSamplerTextures) { - GLenum textureType = bindingVec->first; - TextureBindingVector &textureVector = bindingVec->second; - for (size_t textureIdx = 0; textureIdx < textureVector.size(); textureIdx++) + GLenum textureType = bindingVec.first; + TextureBindingVector &textureVector = bindingVec.second; + for (BindingPointer<Texture> &binding : textureVector) { - BindingPointer<Texture> &binding = textureVector[textureIdx]; if (binding.id() == texture) { auto it = zeroTextures.find(textureType); ASSERT(it != zeroTextures.end()); // Zero textures are the "default" textures instead of NULL - binding.set(it->second.get()); + binding.set(context, it->second.get()); + mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS); } } } + for (auto &bindingImageUnit : mImageUnits) + { + if (bindingImageUnit.texture.id() == texture) + { + bindingImageUnit.texture.set(context, nullptr); + bindingImageUnit.level = 0; + bindingImageUnit.layered = false; + bindingImageUnit.layer = 0; + bindingImageUnit.access = GL_READ_ONLY; + bindingImageUnit.format = GL_R32UI; + break; + } + } + // [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. - if (mReadFramebuffer) + if (mReadFramebuffer && mReadFramebuffer->detachTexture(context, texture)) { - mReadFramebuffer->detachTexture(texture); + mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER); } - if (mDrawFramebuffer) + if (mDrawFramebuffer && mDrawFramebuffer->detachTexture(context, texture)) { - mDrawFramebuffer->detachTexture(texture); + mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER); } } -void State::initializeZeroTextures(const TextureMap &zeroTextures) +void State::initializeZeroTextures(const Context *context, const TextureMap &zeroTextures) { for (const auto &zeroTexture : zeroTextures) { @@ -751,14 +891,16 @@ void State::initializeZeroTextures(const TextureMap &zeroTextures) for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit) { - samplerTextureArray[textureUnit].set(zeroTexture.second.get()); + samplerTextureArray[textureUnit].set(context, zeroTexture.second.get()); } } } -void State::setSamplerBinding(GLuint textureUnit, Sampler *sampler) +void State::setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler) { - mSamplers[textureUnit].set(sampler); + mSamplers[textureUnit].set(context, sampler); + mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS); + mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES); } GLuint State::getSamplerId(GLuint textureUnit) const @@ -772,25 +914,26 @@ Sampler *State::getSampler(GLuint textureUnit) const return mSamplers[textureUnit].get(); } -void State::detachSampler(GLuint sampler) +void State::detachSampler(const Context *context, 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 (size_t textureUnit = 0; textureUnit < mSamplers.size(); textureUnit++) + for (BindingPointer<Sampler> &samplerBinding : mSamplers) { - BindingPointer<Sampler> &samplerBinding = mSamplers[textureUnit]; if (samplerBinding.id() == sampler) { - samplerBinding.set(NULL); + samplerBinding.set(context, nullptr); + mDirtyBits.set(DIRTY_BIT_SAMPLER_BINDINGS); } } } -void State::setRenderbufferBinding(Renderbuffer *renderbuffer) +void State::setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer) { - mRenderbuffer.set(renderbuffer); + mRenderbuffer.set(context, renderbuffer); + mDirtyBits.set(DIRTY_BIT_RENDERBUFFER_BINDING); } GLuint State::getRenderbufferId() const @@ -798,12 +941,12 @@ GLuint State::getRenderbufferId() const return mRenderbuffer.id(); } -Renderbuffer *State::getCurrentRenderbuffer() +Renderbuffer *State::getCurrentRenderbuffer() const { return mRenderbuffer.get(); } -void State::detachRenderbuffer(GLuint renderbuffer) +void State::detachRenderbuffer(const Context *context, 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 @@ -811,7 +954,7 @@ void State::detachRenderbuffer(GLuint renderbuffer) if (mRenderbuffer.id() == renderbuffer) { - mRenderbuffer.set(NULL); + setRenderbufferBinding(context, nullptr); } // [OpenGL ES 2.0.24] section 4.4 page 111: @@ -822,14 +965,17 @@ void State::detachRenderbuffer(GLuint renderbuffer) Framebuffer *readFramebuffer = mReadFramebuffer; Framebuffer *drawFramebuffer = mDrawFramebuffer; - if (readFramebuffer) + if (readFramebuffer && readFramebuffer->detachRenderbuffer(context, renderbuffer)) { - readFramebuffer->detachRenderbuffer(renderbuffer); + mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER); } if (drawFramebuffer && drawFramebuffer != readFramebuffer) { - drawFramebuffer->detachRenderbuffer(renderbuffer); + if (drawFramebuffer->detachRenderbuffer(context, renderbuffer)) + { + mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER); + } } } @@ -873,26 +1019,16 @@ Framebuffer *State::getTargetFramebuffer(GLenum target) const return mDrawFramebuffer; default: UNREACHABLE(); - return NULL; + return nullptr; } } -Framebuffer *State::getReadFramebuffer() +Framebuffer *State::getReadFramebuffer() const { return mReadFramebuffer; } -Framebuffer *State::getDrawFramebuffer() -{ - return mDrawFramebuffer; -} - -const Framebuffer *State::getReadFramebuffer() const -{ - return mReadFramebuffer; -} - -const Framebuffer *State::getDrawFramebuffer() const +Framebuffer *State::getDrawFramebuffer() const { return mDrawFramebuffer; } @@ -934,13 +1070,13 @@ void State::setVertexArrayBinding(VertexArray *vertexArray) GLuint State::getVertexArrayId() const { - ASSERT(mVertexArray != NULL); + ASSERT(mVertexArray != nullptr); return mVertexArray->id(); } VertexArray *State::getVertexArray() const { - ASSERT(mVertexArray != NULL); + ASSERT(mVertexArray != nullptr); return mVertexArray; } @@ -948,7 +1084,7 @@ bool State::removeVertexArrayBinding(GLuint vertexArray) { if (mVertexArray->id() == vertexArray) { - mVertexArray = NULL; + mVertexArray = nullptr; mDirtyBits.set(DIRTY_BIT_VERTEX_ARRAY_BINDING); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); return true; @@ -957,13 +1093,47 @@ bool State::removeVertexArrayBinding(GLuint vertexArray) return false; } -void State::setProgram(Program *newProgram) +void State::bindVertexBuffer(const Context *context, + GLuint bindingIndex, + Buffer *boundBuffer, + GLintptr offset, + GLsizei stride) +{ + getVertexArray()->bindVertexBuffer(context, bindingIndex, boundBuffer, offset, stride); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); +} + +void State::setVertexAttribBinding(const Context *context, GLuint attribIndex, GLuint bindingIndex) +{ + getVertexArray()->setVertexAttribBinding(context, attribIndex, bindingIndex); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); +} + +void State::setVertexAttribFormat(GLuint attribIndex, + GLint size, + GLenum type, + bool normalized, + bool pureInteger, + GLuint relativeOffset) +{ + getVertexArray()->setVertexAttribFormat(attribIndex, size, type, normalized, pureInteger, + relativeOffset); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); +} + +void State::setVertexBindingDivisor(GLuint bindingIndex, GLuint divisor) +{ + getVertexArray()->setVertexBindingDivisor(bindingIndex, divisor); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); +} + +void State::setProgram(const Context *context, Program *newProgram) { if (mProgram != newProgram) { if (mProgram) { - mProgram->release(); + mProgram->release(context); } mProgram = newProgram; @@ -971,7 +1141,10 @@ void State::setProgram(Program *newProgram) if (mProgram) { newProgram->addRef(); + mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES); } + mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE); + mDirtyBits.set(DIRTY_BIT_PROGRAM_BINDING); } } @@ -980,9 +1153,10 @@ Program *State::getProgram() const return mProgram; } -void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback) +void State::setTransformFeedbackBinding(const Context *context, + TransformFeedback *transformFeedback) { - mTransformFeedback.set(transformFeedback); + mTransformFeedback.set(context, transformFeedback); } TransformFeedback *State::getCurrentTransformFeedback() const @@ -992,23 +1166,37 @@ TransformFeedback *State::getCurrentTransformFeedback() const bool State::isTransformFeedbackActiveUnpaused() const { - gl::TransformFeedback *curTransformFeedback = getCurrentTransformFeedback(); + TransformFeedback *curTransformFeedback = getCurrentTransformFeedback(); return curTransformFeedback && curTransformFeedback->isActive() && !curTransformFeedback->isPaused(); } -void State::detachTransformFeedback(GLuint transformFeedback) +bool State::removeTransformFeedbackBinding(const Context *context, GLuint transformFeedback) { if (mTransformFeedback.id() == transformFeedback) { - mTransformFeedback.set(NULL); + mTransformFeedback.set(context, nullptr); + return true; } + + return false; +} + +void State::setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline) +{ + mProgramPipeline.set(context, pipeline); +} + +void State::detachProgramPipeline(const Context *context, GLuint pipeline) +{ + mProgramPipeline.set(context, nullptr); } -bool State::isQueryActive() const +bool State::isQueryActive(const GLenum type) const { for (auto &iter : mActiveQueries) { - if (iter.second.get() != NULL) + const Query *query = iter.second.get(); + if (query != nullptr && ActiveQueryType(query->getType()) == ActiveQueryType(type)) { return true; } @@ -1030,9 +1218,9 @@ bool State::isQueryActive(Query *query) const return false; } -void State::setActiveQuery(GLenum target, Query *query) +void State::setActiveQuery(const Context *context, GLenum target, Query *query) { - mActiveQueries[target].set(query); + mActiveQueries[target].set(context, query); } GLuint State::getActiveQueryId(GLenum target) const @@ -1051,24 +1239,64 @@ Query *State::getActiveQuery(GLenum target) const return it->second.get(); } -void State::setArrayBufferBinding(Buffer *buffer) +void State::setBufferBinding(const Context *context, BufferBinding target, Buffer *buffer) { - mArrayBuffer.set(buffer); -} - -GLuint State::getArrayBufferId() const -{ - return mArrayBuffer.id(); + switch (target) + { + case BufferBinding::PixelPack: + mBoundBuffers[target].set(context, buffer); + mDirtyBits.set(DIRTY_BIT_PACK_BUFFER_BINDING); + break; + case BufferBinding::PixelUnpack: + mBoundBuffers[target].set(context, buffer); + mDirtyBits.set(DIRTY_BIT_UNPACK_BUFFER_BINDING); + break; + case BufferBinding::DrawIndirect: + mBoundBuffers[target].set(context, buffer); + mDirtyBits.set(DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING); + break; + case BufferBinding::TransformFeedback: + if (mTransformFeedback.get() != nullptr) + { + mTransformFeedback->bindGenericBuffer(context, buffer); + } + break; + case BufferBinding::ElementArray: + getVertexArray()->setElementArrayBuffer(context, buffer); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); + break; + default: + mBoundBuffers[target].set(context, buffer); + break; + } } - -void State::setGenericUniformBufferBinding(Buffer *buffer) +void State::setIndexedBufferBinding(const Context *context, + BufferBinding target, + GLuint index, + Buffer *buffer, + GLintptr offset, + GLsizeiptr size) { - mGenericUniformBuffer.set(buffer); -} + setBufferBinding(context, target, buffer); -void State::setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size) -{ - mUniformBuffers[index].set(buffer, offset, size); + switch (target) + { + case BufferBinding::TransformFeedback: + mTransformFeedback->bindIndexedBuffer(context, index, buffer, offset, size); + break; + case BufferBinding::Uniform: + mUniformBuffers[index].set(context, buffer, offset, size); + break; + case BufferBinding::AtomicCounter: + mAtomicCounterBuffers[index].set(context, buffer, offset, size); + break; + case BufferBinding::ShaderStorage: + mShaderStorageBuffers[index].set(context, buffer, offset, size); + break; + default: + UNREACHABLE(); + break; + } } const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) const @@ -1077,62 +1305,48 @@ const OffsetBindingPointer<Buffer> &State::getIndexedUniformBuffer(size_t index) return mUniformBuffers[index]; } -void State::setCopyReadBufferBinding(Buffer *buffer) +const OffsetBindingPointer<Buffer> &State::getIndexedAtomicCounterBuffer(size_t index) const { - mCopyReadBuffer.set(buffer); + ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size()); + return mAtomicCounterBuffers[index]; } -void State::setCopyWriteBufferBinding(Buffer *buffer) +const OffsetBindingPointer<Buffer> &State::getIndexedShaderStorageBuffer(size_t index) const { - mCopyWriteBuffer.set(buffer); + ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size()); + return mShaderStorageBuffers[index]; } -void State::setPixelPackBufferBinding(Buffer *buffer) -{ - mPack.pixelBuffer.set(buffer); -} - -void State::setPixelUnpackBufferBinding(Buffer *buffer) -{ - mUnpack.pixelBuffer.set(buffer); -} - -Buffer *State::getTargetBuffer(GLenum target) const +Buffer *State::getTargetBuffer(BufferBinding target) const { switch (target) { - case GL_ARRAY_BUFFER: return mArrayBuffer.get(); - case GL_COPY_READ_BUFFER: return mCopyReadBuffer.get(); - case GL_COPY_WRITE_BUFFER: return mCopyWriteBuffer.get(); - case GL_ELEMENT_ARRAY_BUFFER: return getVertexArray()->getElementArrayBuffer().get(); - case GL_PIXEL_PACK_BUFFER: return mPack.pixelBuffer.get(); - case GL_PIXEL_UNPACK_BUFFER: return mUnpack.pixelBuffer.get(); - case GL_TRANSFORM_FEEDBACK_BUFFER: return mTransformFeedback->getGenericBuffer().get(); - case GL_UNIFORM_BUFFER: return mGenericUniformBuffer.get(); - default: UNREACHABLE(); return NULL; + case BufferBinding::ElementArray: + return getVertexArray()->getElementArrayBuffer().get(); + case BufferBinding::TransformFeedback: + return mTransformFeedback->getGenericBuffer().get(); + default: + return mBoundBuffers[target].get(); } } -void State::detachBuffer(GLuint bufferName) +void State::detachBuffer(const Context *context, GLuint bufferName) { - BindingPointer<Buffer> *buffers[] = {&mArrayBuffer, &mCopyReadBuffer, - &mCopyWriteBuffer, &mPack.pixelBuffer, - &mUnpack.pixelBuffer, &mGenericUniformBuffer}; - for (auto buffer : buffers) + for (auto &buffer : mBoundBuffers) { - if (buffer->id() == bufferName) + if (buffer.id() == bufferName) { - buffer->set(nullptr); + buffer.set(context, nullptr); } } TransformFeedback *curTransformFeedback = getCurrentTransformFeedback(); if (curTransformFeedback) { - curTransformFeedback->detachBuffer(bufferName); + curTransformFeedback->detachBuffer(context, bufferName); } - getVertexArray()->detachBuffer(bufferName); + getVertexArray()->detachBuffer(context, bufferName); } void State::setEnableVertexAttribArray(unsigned int attribNum, bool enabled) @@ -1145,46 +1359,56 @@ void State::setVertexAttribf(GLuint index, const GLfloat values[4]) { ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setFloatValues(values); - mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index); + mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES); + mDirtyCurrentValues.set(index); } void State::setVertexAttribu(GLuint index, const GLuint values[4]) { ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setUnsignedIntValues(values); - mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index); + mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES); + mDirtyCurrentValues.set(index); } void State::setVertexAttribi(GLuint index, const GLint values[4]) { ASSERT(static_cast<size_t>(index) < mVertexAttribCurrentValues.size()); mVertexAttribCurrentValues[index].setIntValues(values); - mDirtyBits.set(DIRTY_BIT_CURRENT_VALUE_0 + index); + mDirtyBits.set(DIRTY_BIT_CURRENT_VALUES); + mDirtyCurrentValues.set(index); +} + +void State::setVertexAttribPointer(const Context *context, + unsigned int attribNum, + Buffer *boundBuffer, + GLint size, + GLenum type, + bool normalized, + bool pureInteger, + GLsizei stride, + const void *pointer) +{ + getVertexArray()->setVertexAttribPointer(context, attribNum, boundBuffer, size, type, + normalized, pureInteger, stride, pointer); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); } -void State::setVertexAttribState(unsigned int attribNum, - Buffer *boundBuffer, - GLint size, - GLenum type, - bool normalized, - bool pureInteger, - GLsizei stride, - const void *pointer) +void State::setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor) { - getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer); + getVertexArray()->setVertexAttribDivisor(context, index, divisor); mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); } -void State::setVertexAttribDivisor(GLuint index, GLuint divisor) +const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(size_t attribNum) const { - getVertexArray()->setVertexAttribDivisor(index, divisor); - mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); + ASSERT(attribNum < mVertexAttribCurrentValues.size()); + return mVertexAttribCurrentValues[attribNum]; } -const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const +const std::vector<VertexAttribCurrentValueData> &State::getVertexAttribCurrentValues() const { - ASSERT(static_cast<size_t>(attribNum) < mVertexAttribCurrentValues.size()); - return mVertexAttribCurrentValues[attribNum]; + return mVertexAttribCurrentValues; } const void *State::getVertexAttribPointer(unsigned int attribNum) const @@ -1195,7 +1419,7 @@ const void *State::getVertexAttribPointer(unsigned int attribNum) const void State::setPackAlignment(GLint alignment) { mPack.alignment = alignment; - mDirtyBits.set(DIRTY_BIT_PACK_ALIGNMENT); + mDirtyBits.set(DIRTY_BIT_PACK_STATE); } GLint State::getPackAlignment() const @@ -1206,7 +1430,7 @@ GLint State::getPackAlignment() const void State::setPackReverseRowOrder(bool reverseRowOrder) { mPack.reverseRowOrder = reverseRowOrder; - mDirtyBits.set(DIRTY_BIT_PACK_REVERSE_ROW_ORDER); + mDirtyBits.set(DIRTY_BIT_PACK_STATE); } bool State::getPackReverseRowOrder() const @@ -1217,7 +1441,7 @@ bool State::getPackReverseRowOrder() const void State::setPackRowLength(GLint rowLength) { mPack.rowLength = rowLength; - mDirtyBits.set(DIRTY_BIT_PACK_ROW_LENGTH); + mDirtyBits.set(DIRTY_BIT_PACK_STATE); } GLint State::getPackRowLength() const @@ -1228,7 +1452,7 @@ GLint State::getPackRowLength() const void State::setPackSkipRows(GLint skipRows) { mPack.skipRows = skipRows; - mDirtyBits.set(DIRTY_BIT_PACK_SKIP_ROWS); + mDirtyBits.set(DIRTY_BIT_PACK_STATE); } GLint State::getPackSkipRows() const @@ -1239,7 +1463,7 @@ GLint State::getPackSkipRows() const void State::setPackSkipPixels(GLint skipPixels) { mPack.skipPixels = skipPixels; - mDirtyBits.set(DIRTY_BIT_PACK_SKIP_PIXELS); + mDirtyBits.set(DIRTY_BIT_PACK_STATE); } GLint State::getPackSkipPixels() const @@ -1260,7 +1484,7 @@ PixelPackState &State::getPackState() void State::setUnpackAlignment(GLint alignment) { mUnpack.alignment = alignment; - mDirtyBits.set(DIRTY_BIT_UNPACK_ALIGNMENT); + mDirtyBits.set(DIRTY_BIT_UNPACK_STATE); } GLint State::getUnpackAlignment() const @@ -1271,7 +1495,7 @@ GLint State::getUnpackAlignment() const void State::setUnpackRowLength(GLint rowLength) { mUnpack.rowLength = rowLength; - mDirtyBits.set(DIRTY_BIT_UNPACK_ROW_LENGTH); + mDirtyBits.set(DIRTY_BIT_UNPACK_STATE); } GLint State::getUnpackRowLength() const @@ -1282,7 +1506,7 @@ GLint State::getUnpackRowLength() const void State::setUnpackImageHeight(GLint imageHeight) { mUnpack.imageHeight = imageHeight; - mDirtyBits.set(DIRTY_BIT_UNPACK_IMAGE_HEIGHT); + mDirtyBits.set(DIRTY_BIT_UNPACK_STATE); } GLint State::getUnpackImageHeight() const @@ -1293,7 +1517,7 @@ GLint State::getUnpackImageHeight() const void State::setUnpackSkipImages(GLint skipImages) { mUnpack.skipImages = skipImages; - mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_IMAGES); + mDirtyBits.set(DIRTY_BIT_UNPACK_STATE); } GLint State::getUnpackSkipImages() const @@ -1304,7 +1528,7 @@ GLint State::getUnpackSkipImages() const void State::setUnpackSkipRows(GLint skipRows) { mUnpack.skipRows = skipRows; - mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_ROWS); + mDirtyBits.set(DIRTY_BIT_UNPACK_STATE); } GLint State::getUnpackSkipRows() const @@ -1315,7 +1539,7 @@ GLint State::getUnpackSkipRows() const void State::setUnpackSkipPixels(GLint skipPixels) { mUnpack.skipPixels = skipPixels; - mDirtyBits.set(DIRTY_BIT_UNPACK_SKIP_PIXELS); + mDirtyBits.set(DIRTY_BIT_UNPACK_STATE); } GLint State::getUnpackSkipPixels() const @@ -1343,6 +1567,84 @@ Debug &State::getDebug() return mDebug; } +void State::setCoverageModulation(GLenum components) +{ + mCoverageModulation = components; + mDirtyBits.set(DIRTY_BIT_COVERAGE_MODULATION); +} + +GLenum State::getCoverageModulation() const +{ + return mCoverageModulation; +} + +void State::loadPathRenderingMatrix(GLenum matrixMode, const GLfloat *matrix) +{ + if (matrixMode == GL_PATH_MODELVIEW_CHROMIUM) + { + memcpy(mPathMatrixMV, matrix, 16 * sizeof(GLfloat)); + mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_MV); + } + else if (matrixMode == GL_PATH_PROJECTION_CHROMIUM) + { + memcpy(mPathMatrixProj, matrix, 16 * sizeof(GLfloat)); + mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_MATRIX_PROJ); + } + else + { + UNREACHABLE(); + } +} + +const GLfloat *State::getPathRenderingMatrix(GLenum which) const +{ + if (which == GL_PATH_MODELVIEW_MATRIX_CHROMIUM) + { + return mPathMatrixMV; + } + else if (which == GL_PATH_PROJECTION_MATRIX_CHROMIUM) + { + return mPathMatrixProj; + } + + UNREACHABLE(); + return nullptr; +} + +void State::setPathStencilFunc(GLenum func, GLint ref, GLuint mask) +{ + mPathStencilFunc = func; + mPathStencilRef = ref; + mPathStencilMask = mask; + mDirtyBits.set(DIRTY_BIT_PATH_RENDERING_STENCIL_STATE); +} + +GLenum State::getPathStencilFunc() const +{ + return mPathStencilFunc; +} + +GLint State::getPathStencilRef() const +{ + return mPathStencilRef; +} + +GLuint State::getPathStencilMask() const +{ + return mPathStencilMask; +} + +void State::setFramebufferSRGB(bool sRGB) +{ + mFramebufferSRGB = sRGB; + mDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_SRGB); +} + +bool State::getFramebufferSRGB() const +{ + return mFramebufferSRGB; +} + void State::getBooleanv(GLenum pname, GLboolean *params) { switch (pname) @@ -1355,10 +1657,15 @@ void State::getBooleanv(GLenum pname, GLboolean *params) params[2] = mBlend.colorMaskBlue; params[3] = mBlend.colorMaskAlpha; break; - case GL_CULL_FACE: *params = mRasterizer.cullFace; break; + case GL_CULL_FACE: + *params = mRasterizer.cullFace; + break; case GL_POLYGON_OFFSET_FILL: *params = mRasterizer.polygonOffsetFill; break; case GL_SAMPLE_ALPHA_TO_COVERAGE: *params = mBlend.sampleAlphaToCoverage; break; case GL_SAMPLE_COVERAGE: *params = mSampleCoverage; break; + case GL_SAMPLE_MASK: + *params = mSampleMask; + break; case GL_SCISSOR_TEST: *params = mScissorTest; break; case GL_STENCIL_TEST: *params = mDepthStencil.stencilTest; break; case GL_DEPTH_TEST: *params = mDepthStencil.depthTest; break; @@ -1378,6 +1685,28 @@ void State::getBooleanv(GLenum pname, GLboolean *params) case GL_DEBUG_OUTPUT: *params = mDebug.isOutputEnabled() ? GL_TRUE : GL_FALSE; break; + case GL_MULTISAMPLE_EXT: + *params = mMultiSampling; + break; + case GL_SAMPLE_ALPHA_TO_ONE_EXT: + *params = mSampleAlphaToOne; + break; + case GL_BIND_GENERATES_RESOURCE_CHROMIUM: + *params = isBindGeneratesResourceEnabled() ? GL_TRUE : GL_FALSE; + break; + case GL_CLIENT_ARRAYS_ANGLE: + *params = areClientArraysEnabled() ? GL_TRUE : GL_FALSE; + break; + case GL_FRAMEBUFFER_SRGB_EXT: + *params = getFramebufferSRGB() ? GL_TRUE : GL_FALSE; + break; + case GL_ROBUST_RESOURCE_INITIALIZATION_ANGLE: + *params = mRobustResourceInit ? GL_TRUE : GL_FALSE; + break; + case GL_PROGRAM_CACHE_ENABLED_ANGLE: + *params = mProgramBinaryCacheEnabled ? GL_TRUE : GL_FALSE; + break; + default: UNREACHABLE(); break; @@ -1413,13 +1742,21 @@ void State::getFloatv(GLenum pname, GLfloat *params) params[2] = mBlendColor.blue; params[3] = mBlendColor.alpha; break; + case GL_MULTISAMPLE_EXT: + *params = static_cast<GLfloat>(mMultiSampling); + break; + case GL_SAMPLE_ALPHA_TO_ONE_EXT: + *params = static_cast<GLfloat>(mSampleAlphaToOne); + case GL_COVERAGE_MODULATION_CHROMIUM: + params[0] = static_cast<GLfloat>(mCoverageModulation); + break; default: UNREACHABLE(); break; } } -void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) +void State::getIntegerv(const Context *context, GLenum pname, GLint *params) { if (pname >= GL_DRAW_BUFFER0_EXT && pname <= GL_DRAW_BUFFER15_EXT) { @@ -1437,8 +1774,15 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) // State::getFloatv. switch (pname) { - case GL_ARRAY_BUFFER_BINDING: *params = mArrayBuffer.id(); break; - case GL_ELEMENT_ARRAY_BUFFER_BINDING: *params = getVertexArray()->getElementArrayBuffer().id(); break; + case GL_ARRAY_BUFFER_BINDING: + *params = mBoundBuffers[BufferBinding::Array].id(); + break; + case GL_DRAW_INDIRECT_BUFFER_BINDING: + *params = mBoundBuffers[BufferBinding::DrawIndirect].id(); + break; + case GL_ELEMENT_ARRAY_BUFFER_BINDING: + *params = getVertexArray()->getElementArrayBuffer().id(); + break; //case GL_FRAMEBUFFER_BINDING: // now equivalent to GL_DRAW_FRAMEBUFFER_BINDING_ANGLE case GL_DRAW_FRAMEBUFFER_BINDING_ANGLE: *params = mDrawFramebuffer->id(); break; case GL_READ_FRAMEBUFFER_BINDING_ANGLE: *params = mReadFramebuffer->id(); break; @@ -1477,10 +1821,14 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) break; case GL_STENCIL_FUNC: *params = mDepthStencil.stencilFunc; break; case GL_STENCIL_REF: *params = mStencilRef; break; - case GL_STENCIL_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilMask); break; + case GL_STENCIL_VALUE_MASK: + *params = CastMaskValue(context, mDepthStencil.stencilMask); + break; case GL_STENCIL_BACK_FUNC: *params = mDepthStencil.stencilBackFunc; break; case GL_STENCIL_BACK_REF: *params = mStencilBackRef; break; - case GL_STENCIL_BACK_VALUE_MASK: *params = clampToInt(mDepthStencil.stencilBackMask); break; + case GL_STENCIL_BACK_VALUE_MASK: + *params = CastMaskValue(context, mDepthStencil.stencilBackMask); + break; case GL_STENCIL_FAIL: *params = mDepthStencil.stencilFail; break; case GL_STENCIL_PASS_DEPTH_FAIL: *params = mDepthStencil.stencilPassDepthFail; break; case GL_STENCIL_PASS_DEPTH_PASS: *params = mDepthStencil.stencilPassDepthPass; break; @@ -1494,32 +1842,40 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) case GL_BLEND_DST_ALPHA: *params = mBlend.destBlendAlpha; break; case GL_BLEND_EQUATION_RGB: *params = mBlend.blendEquationRGB; break; case GL_BLEND_EQUATION_ALPHA: *params = mBlend.blendEquationAlpha; break; - case GL_STENCIL_WRITEMASK: *params = clampToInt(mDepthStencil.stencilWritemask); break; - case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(mDepthStencil.stencilBackWritemask); break; + case GL_STENCIL_WRITEMASK: + *params = CastMaskValue(context, mDepthStencil.stencilWritemask); + break; + case GL_STENCIL_BACK_WRITEMASK: + *params = CastMaskValue(context, mDepthStencil.stencilBackWritemask); + break; case GL_STENCIL_CLEAR_VALUE: *params = mStencilClearValue; break; - case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = mReadFramebuffer->getImplementationColorReadType(); break; - case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = mReadFramebuffer->getImplementationColorReadFormat(); break; + case GL_IMPLEMENTATION_COLOR_READ_TYPE: + *params = mReadFramebuffer->getImplementationColorReadType(context); + break; + case GL_IMPLEMENTATION_COLOR_READ_FORMAT: + *params = mReadFramebuffer->getImplementationColorReadFormat(context); + break; case GL_SAMPLE_BUFFERS: case GL_SAMPLES: { - gl::Framebuffer *framebuffer = mDrawFramebuffer; - if (framebuffer->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE) + Framebuffer *framebuffer = mDrawFramebuffer; + if (framebuffer->checkStatus(context) == GL_FRAMEBUFFER_COMPLETE) { switch (pname) { - case GL_SAMPLE_BUFFERS: - if (framebuffer->getSamples(data) != 0) - { - *params = 1; - } - else - { - *params = 0; - } - break; - case GL_SAMPLES: - *params = framebuffer->getSamples(data); - break; + case GL_SAMPLE_BUFFERS: + if (framebuffer->getSamples(context) != 0) + { + *params = 1; + } + else + { + *params = 0; + } + break; + case GL_SAMPLES: + *params = framebuffer->getSamples(context); + break; } } else @@ -1540,15 +1896,19 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) params[2] = mScissor.width; params[3] = mScissor.height; break; - case GL_CULL_FACE_MODE: *params = mRasterizer.cullMode; break; - case GL_FRONT_FACE: *params = mRasterizer.frontFace; break; + case GL_CULL_FACE_MODE: + *params = ToGLenum(mRasterizer.cullMode); + break; + case GL_FRONT_FACE: + *params = mRasterizer.frontFace; + break; case GL_RED_BITS: case GL_GREEN_BITS: case GL_BLUE_BITS: case GL_ALPHA_BITS: { - gl::Framebuffer *framebuffer = getDrawFramebuffer(); - const gl::FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer(); + Framebuffer *framebuffer = getDrawFramebuffer(); + const FramebufferAttachment *colorbuffer = framebuffer->getFirstColorbuffer(); if (colorbuffer) { @@ -1568,8 +1928,8 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) break; case GL_DEPTH_BITS: { - const gl::Framebuffer *framebuffer = getDrawFramebuffer(); - const gl::FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer(); + const Framebuffer *framebuffer = getDrawFramebuffer(); + const FramebufferAttachment *depthbuffer = framebuffer->getDepthbuffer(); if (depthbuffer) { @@ -1583,8 +1943,8 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) break; case GL_STENCIL_BITS: { - const gl::Framebuffer *framebuffer = getDrawFramebuffer(); - const gl::FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer(); + const Framebuffer *framebuffer = getDrawFramebuffer(); + const FramebufferAttachment *stencilbuffer = framebuffer->getStencilbuffer(); if (stencilbuffer) { @@ -1600,6 +1960,11 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_2D); break; + case GL_TEXTURE_BINDING_RECTANGLE_ANGLE: + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); + *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), + GL_TEXTURE_RECTANGLE_ANGLE); + break; case GL_TEXTURE_BINDING_CUBE_MAP: ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); *params = @@ -1614,27 +1979,45 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), GL_TEXTURE_2D_ARRAY); break; + case GL_TEXTURE_BINDING_2D_MULTISAMPLE: + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); + *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), + GL_TEXTURE_2D_MULTISAMPLE); + break; + case GL_TEXTURE_BINDING_EXTERNAL_OES: + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); + *params = getSamplerTextureId(static_cast<unsigned int>(mActiveSampler), + GL_TEXTURE_EXTERNAL_OES); + break; case GL_UNIFORM_BUFFER_BINDING: - *params = mGenericUniformBuffer.id(); - break; + *params = mBoundBuffers[BufferBinding::Uniform].id(); + break; case GL_TRANSFORM_FEEDBACK_BINDING: *params = mTransformFeedback.id(); break; case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - *params = mTransformFeedback->getGenericBuffer().id(); - break; + ASSERT(mTransformFeedback.get() != nullptr); + *params = mTransformFeedback->getGenericBuffer().id(); + break; case GL_COPY_READ_BUFFER_BINDING: - *params = mCopyReadBuffer.id(); - break; + *params = mBoundBuffers[BufferBinding::CopyRead].id(); + break; case GL_COPY_WRITE_BUFFER_BINDING: - *params = mCopyWriteBuffer.id(); - break; + *params = mBoundBuffers[BufferBinding::CopyWrite].id(); + break; case GL_PIXEL_PACK_BUFFER_BINDING: - *params = mPack.pixelBuffer.id(); - break; + *params = mBoundBuffers[BufferBinding::PixelPack].id(); + break; case GL_PIXEL_UNPACK_BUFFER_BINDING: - *params = mUnpack.pixelBuffer.id(); - break; + *params = mBoundBuffers[BufferBinding::PixelUnpack].id(); + break; + case GL_READ_BUFFER: + *params = mReadFramebuffer->getReadBufferState(); + break; + case GL_SAMPLER_BINDING: + ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits); + *params = getSamplerId(static_cast<GLuint>(mActiveSampler)); + break; case GL_DEBUG_LOGGED_MESSAGES: *params = static_cast<GLint>(mDebug.getMessageCount()); break; @@ -1644,6 +2027,20 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params) case GL_DEBUG_GROUP_STACK_DEPTH: *params = static_cast<GLint>(mDebug.getGroupStackDepth()); break; + case GL_MULTISAMPLE_EXT: + *params = static_cast<GLint>(mMultiSampling); + break; + case GL_SAMPLE_ALPHA_TO_ONE_EXT: + *params = static_cast<GLint>(mSampleAlphaToOne); + case GL_COVERAGE_MODULATION_CHROMIUM: + *params = static_cast<GLint>(mCoverageModulation); + break; + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + *params = mBoundBuffers[BufferBinding::AtomicCounter].id(); + break; + case GL_SHADER_STORAGE_BUFFER_BINDING: + *params = mBoundBuffers[BufferBinding::ShaderStorage].id(); + break; default: UNREACHABLE(); break; @@ -1666,75 +2063,111 @@ void State::getPointerv(GLenum pname, void **params) const } } -bool State::getIndexedIntegerv(GLenum target, GLuint index, GLint *data) +void State::getIntegeri_v(GLenum target, GLuint index, GLint *data) { switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING: - if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount()) - { - *data = mTransformFeedback->getIndexedBuffer(index).id(); - } - break; + ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount()); + *data = mTransformFeedback->getIndexedBuffer(index).id(); + break; case GL_UNIFORM_BUFFER_BINDING: - if (static_cast<size_t>(index) < mUniformBuffers.size()) - { - *data = mUniformBuffers[index].id(); - } - break; + ASSERT(static_cast<size_t>(index) < mUniformBuffers.size()); + *data = mUniformBuffers[index].id(); + break; + case GL_ATOMIC_COUNTER_BUFFER_BINDING: + ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size()); + *data = mAtomicCounterBuffers[index].id(); + break; + case GL_SHADER_STORAGE_BUFFER_BINDING: + ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size()); + *data = mShaderStorageBuffers[index].id(); + break; + case GL_VERTEX_BINDING_BUFFER: + ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings()); + *data = mVertexArray->getVertexBinding(index).getBuffer().id(); + break; + case GL_VERTEX_BINDING_DIVISOR: + ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings()); + *data = mVertexArray->getVertexBinding(index).getDivisor(); + break; + case GL_VERTEX_BINDING_OFFSET: + ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings()); + *data = static_cast<GLuint>(mVertexArray->getVertexBinding(index).getOffset()); + break; + case GL_VERTEX_BINDING_STRIDE: + ASSERT(static_cast<size_t>(index) < mVertexArray->getMaxBindings()); + *data = mVertexArray->getVertexBinding(index).getStride(); + break; + case GL_SAMPLE_MASK_VALUE: + ASSERT(static_cast<size_t>(index) < mSampleMaskValues.size()); + *data = mSampleMaskValues[index]; + break; default: - return false; + UNREACHABLE(); + break; } - - return true; } -bool State::getIndexedInteger64v(GLenum target, GLuint index, GLint64 *data) +void State::getInteger64i_v(GLenum target, GLuint index, GLint64 *data) { switch (target) { case GL_TRANSFORM_FEEDBACK_BUFFER_START: - if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount()) - { - *data = mTransformFeedback->getIndexedBuffer(index).getOffset(); - } - break; + ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount()); + *data = mTransformFeedback->getIndexedBuffer(index).getOffset(); + break; case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE: - if (static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount()) - { - *data = mTransformFeedback->getIndexedBuffer(index).getSize(); - } - break; + ASSERT(static_cast<size_t>(index) < mTransformFeedback->getIndexedBufferCount()); + *data = mTransformFeedback->getIndexedBuffer(index).getSize(); + break; case GL_UNIFORM_BUFFER_START: - if (static_cast<size_t>(index) < mUniformBuffers.size()) - { - *data = mUniformBuffers[index].getOffset(); - } - break; + ASSERT(static_cast<size_t>(index) < mUniformBuffers.size()); + *data = mUniformBuffers[index].getOffset(); + break; case GL_UNIFORM_BUFFER_SIZE: - if (static_cast<size_t>(index) < mUniformBuffers.size()) - { - *data = mUniformBuffers[index].getSize(); - } - break; + ASSERT(static_cast<size_t>(index) < mUniformBuffers.size()); + *data = mUniformBuffers[index].getSize(); + break; + case GL_ATOMIC_COUNTER_BUFFER_START: + ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size()); + *data = mAtomicCounterBuffers[index].getOffset(); + break; + case GL_ATOMIC_COUNTER_BUFFER_SIZE: + ASSERT(static_cast<size_t>(index) < mAtomicCounterBuffers.size()); + *data = mAtomicCounterBuffers[index].getSize(); + break; + case GL_SHADER_STORAGE_BUFFER_START: + ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size()); + *data = mShaderStorageBuffers[index].getOffset(); + break; + case GL_SHADER_STORAGE_BUFFER_SIZE: + ASSERT(static_cast<size_t>(index) < mShaderStorageBuffers.size()); + *data = mShaderStorageBuffers[index].getSize(); + break; default: - return false; + UNREACHABLE(); + break; } +} - return true; +void State::getBooleani_v(GLenum target, GLuint index, GLboolean *data) +{ + UNREACHABLE(); } -bool State::hasMappedBuffer(GLenum target) const +bool State::hasMappedBuffer(BufferBinding target) const { - if (target == GL_ARRAY_BUFFER) + if (target == BufferBinding::Array) { - const VertexArray *vao = getVertexArray(); + const VertexArray *vao = getVertexArray(); const auto &vertexAttribs = vao->getVertexAttributes(); + const auto &vertexBindings = vao->getVertexBindings(); size_t maxEnabledAttrib = vao->getMaxEnabledAttribute(); for (size_t attribIndex = 0; attribIndex < maxEnabledAttrib; attribIndex++) { - const gl::VertexAttribute &vertexAttrib = vertexAttribs[attribIndex]; - gl::Buffer *boundBuffer = vertexAttrib.buffer.get(); + const VertexAttribute &vertexAttrib = vertexAttribs[attribIndex]; + auto *boundBuffer = vertexBindings[vertexAttrib.bindingIndex].getBuffer().get(); if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped()) { return true; @@ -1750,35 +2183,36 @@ bool State::hasMappedBuffer(GLenum target) const } } -void State::syncDirtyObjects() +void State::syncDirtyObjects(const Context *context) { if (!mDirtyObjects.any()) return; - syncDirtyObjects(mDirtyObjects); + syncDirtyObjects(context, mDirtyObjects); } -void State::syncDirtyObjects(const DirtyObjects &bitset) +void State::syncDirtyObjects(const Context *context, const DirtyObjects &bitset) { - for (auto dirtyObject : angle::IterateBitSet(bitset)) + for (auto dirtyObject : bitset) { switch (dirtyObject) { case DIRTY_OBJECT_READ_FRAMEBUFFER: ASSERT(mReadFramebuffer); - mReadFramebuffer->syncState(); + mReadFramebuffer->syncState(context); break; case DIRTY_OBJECT_DRAW_FRAMEBUFFER: ASSERT(mDrawFramebuffer); - mDrawFramebuffer->syncState(); + mDrawFramebuffer->syncState(context); break; case DIRTY_OBJECT_VERTEX_ARRAY: ASSERT(mVertexArray); - mVertexArray->syncImplState(); + mVertexArray->syncState(context); break; - case DIRTY_OBJECT_PROGRAM: - // TODO(jmadill): implement this + case DIRTY_OBJECT_PROGRAM_TEXTURES: + syncProgramTextures(context); break; + default: UNREACHABLE(); break; @@ -1788,7 +2222,82 @@ void State::syncDirtyObjects(const DirtyObjects &bitset) mDirtyObjects &= ~bitset; } -void State::syncDirtyObject(GLenum target) +void State::syncProgramTextures(const Context *context) +{ + // TODO(jmadill): Fine-grained updates. + if (!mProgram) + { + return; + } + + ASSERT(mDirtyObjects[DIRTY_OBJECT_PROGRAM_TEXTURES]); + mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS); + + ActiveTextureMask newActiveTextures; + + // Initialize to the 'Initialized' state and set to 'MayNeedInit' if any texture is not + // initialized. + mCachedTexturesInitState = InitState::Initialized; + + for (const SamplerBinding &samplerBinding : mProgram->getSamplerBindings()) + { + if (samplerBinding.unreferenced) + continue; + + GLenum textureType = samplerBinding.textureType; + for (GLuint textureUnitIndex : samplerBinding.boundTextureUnits) + { + Texture *texture = getSamplerTexture(textureUnitIndex, textureType); + Sampler *sampler = getSampler(textureUnitIndex); + ASSERT(static_cast<size_t>(textureUnitIndex) < mCompleteTextureCache.size()); + ASSERT(static_cast<size_t>(textureUnitIndex) < newActiveTextures.size()); + + ASSERT(texture); + + // Mark the texture binding bit as dirty if the texture completeness changes. + // TODO(jmadill): Use specific dirty bit for completeness change. + if (texture->isSamplerComplete(context, sampler) && + !mDrawFramebuffer->hasTextureAttachment(texture)) + { + texture->syncState(); + mCompleteTextureCache[textureUnitIndex] = texture; + } + else + { + mCompleteTextureCache[textureUnitIndex] = nullptr; + } + + // Bind the texture unconditionally, to recieve completeness change notifications. + mCompleteTextureBindings[textureUnitIndex].bind(texture->getDirtyChannel()); + mActiveTexturesMask.set(textureUnitIndex); + newActiveTextures.set(textureUnitIndex); + + if (sampler != nullptr) + { + sampler->syncState(context); + } + + if (texture->initState() == InitState::MayNeedInit) + { + mCachedTexturesInitState = InitState::MayNeedInit; + } + } + } + + // Unset now missing textures. + ActiveTextureMask negativeMask = mActiveTexturesMask & ~newActiveTextures; + if (negativeMask.any()) + { + for (auto textureIndex : negativeMask) + { + mCompleteTextureBindings[textureIndex].reset(); + mCompleteTextureCache[textureIndex] = nullptr; + mActiveTexturesMask.reset(textureIndex); + } + } +} + +void State::syncDirtyObject(const Context *context, GLenum target) { DirtyObjects localSet; @@ -1807,12 +2316,14 @@ void State::syncDirtyObject(GLenum target) case GL_VERTEX_ARRAY: localSet.set(DIRTY_OBJECT_VERTEX_ARRAY); break; + case GL_TEXTURE: + case GL_SAMPLER: case GL_PROGRAM: - localSet.set(DIRTY_OBJECT_PROGRAM); + localSet.set(DIRTY_OBJECT_PROGRAM_TEXTURES); break; } - syncDirtyObjects(localSet); + syncDirtyObjects(context, localSet); } void State::setObjectDirty(GLenum target) @@ -1832,10 +2343,91 @@ void State::setObjectDirty(GLenum target) case GL_VERTEX_ARRAY: mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); break; + case GL_TEXTURE: + case GL_SAMPLER: case GL_PROGRAM: - mDirtyObjects.set(DIRTY_OBJECT_PROGRAM); + mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES); + mDirtyBits.set(DIRTY_BIT_TEXTURE_BINDINGS); break; } } +void State::onProgramExecutableChange(Program *program) +{ + // OpenGL Spec: + // "If LinkProgram or ProgramBinary successfully re-links a program object + // that was already in use as a result of a previous call to UseProgram, then the + // generated executable code will be installed as part of the current rendering state." + if (program->isLinked() && mProgram == program) + { + mDirtyBits.set(DIRTY_BIT_PROGRAM_EXECUTABLE); + mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES); + } +} + +void State::setImageUnit(const Context *context, + GLuint unit, + Texture *texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format) +{ + mImageUnits[unit].texture.set(context, texture); + mImageUnits[unit].level = level; + mImageUnits[unit].layered = layered; + mImageUnits[unit].layer = layer; + mImageUnits[unit].access = access; + mImageUnits[unit].format = format; +} + +const ImageUnit &State::getImageUnit(GLuint unit) const +{ + return mImageUnits[unit]; +} + +// Handle a dirty texture event. +void State::signal(size_t textureIndex, InitState initState) +{ + // Conservatively assume all textures are dirty. + // TODO(jmadill): More fine-grained update. + mDirtyObjects.set(DIRTY_OBJECT_PROGRAM_TEXTURES); + + if (initState == InitState::MayNeedInit) + { + mCachedTexturesInitState = InitState::MayNeedInit; + } +} + +Error State::clearUnclearedActiveTextures(const Context *context) +{ + ASSERT(mRobustResourceInit); + + if (mCachedTexturesInitState == InitState::Initialized) + { + return NoError(); + } + + for (auto textureIndex : mActiveTexturesMask) + { + Texture *texture = mCompleteTextureCache[textureIndex]; + if (texture) + { + ANGLE_TRY(texture->ensureInitialized(context)); + } + } + + mCachedTexturesInitState = InitState::Initialized; + + return NoError(); +} + +AttributesMask State::getAndResetDirtyCurrentValues() const +{ + AttributesMask retVal = mDirtyCurrentValues; + mDirtyCurrentValues.reset(); + return retVal; +} + } // namespace gl |