diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/State.h')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/State.h | 1258 |
1 files changed, 1258 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/State.h b/gfx/angle/checkout/src/libANGLE/State.h new file mode 100644 index 0000000000..08098599e1 --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/State.h @@ -0,0 +1,1258 @@ +// +// Copyright 2014 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +// State.h: Defines the State class, encapsulating raw GL state + +#ifndef LIBANGLE_STATE_H_ +#define LIBANGLE_STATE_H_ + +#include <bitset> +#include <memory> + +#include "common/Color.h" +#include "common/angleutils.h" +#include "common/bitset_utils.h" +#include "libANGLE/Debug.h" +#include "libANGLE/GLES1State.h" +#include "libANGLE/Overlay.h" +#include "libANGLE/Program.h" +#include "libANGLE/ProgramExecutable.h" +#include "libANGLE/ProgramPipeline.h" +#include "libANGLE/RefCountObject.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Sampler.h" +#include "libANGLE/Texture.h" +#include "libANGLE/TransformFeedback.h" +#include "libANGLE/Version.h" +#include "libANGLE/VertexArray.h" +#include "libANGLE/angletypes.h" + +namespace egl +{ +class ShareGroup; +} // namespace egl + +namespace gl +{ +class BufferManager; +struct Caps; +class Context; +class FramebufferManager; +class MemoryObjectManager; +class ProgramPipelineManager; +class Query; +class RenderbufferManager; +class SamplerManager; +class SemaphoreManager; +class ShaderProgramManager; +class SyncManager; +class TextureManager; +class VertexArray; + +static constexpr Version ES_1_0 = Version(1, 0); +static constexpr Version ES_1_1 = Version(1, 1); +static constexpr Version ES_2_0 = Version(2, 0); +static constexpr Version ES_3_0 = Version(3, 0); +static constexpr Version ES_3_1 = Version(3, 1); +static constexpr Version ES_3_2 = Version(3, 2); + +template <typename T> +using BufferBindingMap = angle::PackedEnumMap<BufferBinding, T>; +using BoundBufferMap = BufferBindingMap<BindingPointer<Buffer>>; +using TextureBindingVector = std::vector<BindingPointer<Texture>>; +using TextureBindingMap = angle::PackedEnumMap<TextureType, TextureBindingVector>; +using ActiveQueryMap = angle::PackedEnumMap<QueryType, BindingPointer<Query>>; + +class ActiveTexturesCache final : angle::NonCopyable +{ + public: + ActiveTexturesCache(); + ~ActiveTexturesCache(); + + Texture *operator[](size_t textureIndex) const { return mTextures[textureIndex]; } + + void clear(); + void set(size_t textureIndex, Texture *texture); + void reset(size_t textureIndex); + bool empty() const; + size_t size() const { return mTextures.size(); } + + private: + ActiveTextureArray<Texture *> mTextures; +}; + +class State : angle::NonCopyable +{ + public: + State(const State *shareContextState, + egl::ShareGroup *shareGroup, + TextureManager *shareTextures, + SemaphoreManager *shareSemaphores, + const OverlayType *overlay, + const EGLenum clientType, + const Version &clientVersion, + EGLint profileMask, + bool debug, + bool bindGeneratesResourceCHROMIUM, + bool clientArraysEnabled, + bool robustResourceInit, + bool programBinaryCacheEnabled, + EGLenum contextPriority, + bool hasRobustAccess, + bool hasProtectedContent); + ~State(); + + void initialize(Context *context); + void reset(const Context *context); + + // Getters + ContextID getContextID() const { return mID; } + EGLenum getClientType() const { return mClientType; } + EGLint getProfileMask() const { return mProfileMask; } + EGLenum getContextPriority() const { return mContextPriority; } + bool hasRobustAccess() const { return mHasRobustAccess; } + bool hasProtectedContent() const { return mHasProtectedContent; } + bool isDebugContext() const { return mIsDebugContext; } + GLint getClientMajorVersion() const { return mClientVersion.major; } + GLint getClientMinorVersion() const { return mClientVersion.minor; } + const Version &getClientVersion() const { return mClientVersion; } + const Caps &getCaps() const { return mCaps; } + const TextureCapsMap &getTextureCaps() const { return mTextureCaps; } + const Extensions &getExtensions() const { return mExtensions; } + const Limitations &getLimitations() const { return mLimitations; } + egl::ShareGroup *getShareGroup() const { return mShareGroup; } + + bool isWebGL() const { return mExtensions.webglCompatibilityANGLE; } + + bool isWebGL1() const { return (isWebGL() && mClientVersion.major == 2); } + + bool isGLES1() const { return mClientVersion < ES_2_0; } + + const TextureCaps &getTextureCap(GLenum internalFormat) const + { + return mTextureCaps.get(internalFormat); + } + + // State chunk getters + bool allActiveDrawBufferChannelsMasked() const; + bool anyActiveDrawBufferChannelMasked() const; + const RasterizerState &getRasterizerState() const; + const BlendState &getBlendState() const { return mBlendState; } + const BlendStateExt &getBlendStateExt() const { return mBlendStateExt; } + const DepthStencilState &getDepthStencilState() const; + + // Clear behavior setters & state parameter block generation function + void setColorClearValue(float red, float green, float blue, float alpha); + void setDepthClearValue(float depth); + void setStencilClearValue(int stencil); + + const ColorF &getColorClearValue() const { return mColorClearValue; } + float getDepthClearValue() const { return mDepthClearValue; } + int getStencilClearValue() const { return mStencilClearValue; } + + // Write mask manipulation + void setColorMask(bool red, bool green, bool blue, bool alpha); + void setColorMaskIndexed(bool red, bool green, bool blue, bool alpha, GLuint index); + void setDepthMask(bool mask); + + // Discard toggle & query + bool isRasterizerDiscardEnabled() const { return mRasterizer.rasterizerDiscard; } + void setRasterizerDiscard(bool enabled); + + // Primitive restart + bool isPrimitiveRestartEnabled() const { return mPrimitiveRestart; } + void setPrimitiveRestart(bool enabled); + + // Face culling state manipulation + bool isCullFaceEnabled() const { return mRasterizer.cullFace; } + void setCullFace(bool enabled); + void setCullMode(CullFaceMode mode); + void setFrontFace(GLenum front); + + // Depth test state manipulation + bool isDepthTestEnabled() const { return mDepthStencil.depthTest; } + bool isDepthWriteEnabled() const { return mDepthStencil.depthTest && mDepthStencil.depthMask; } + void setDepthTest(bool enabled); + void setDepthFunc(GLenum depthFunc); + void setDepthRange(float zNear, float zFar); + float getNearPlane() const { return mNearZ; } + float getFarPlane() const { return mFarZ; } + + // Clip control extension + void setClipControl(GLenum origin, GLenum depth); + bool isClipControlDepthZeroToOne() const { return mClipControlDepth == GL_ZERO_TO_ONE_EXT; } + gl::ClipSpaceOrigin getClipSpaceOrigin() const + { + return mClipControlOrigin == GL_UPPER_LEFT_EXT ? ClipSpaceOrigin::UpperLeft + : ClipSpaceOrigin::LowerLeft; + } + + // Blend state manipulation + bool isBlendEnabled() const { return mBlendStateExt.getEnabledMask().test(0); } + bool isBlendEnabledIndexed(GLuint index) const + { + ASSERT(static_cast<size_t>(index) < mBlendStateExt.getDrawBufferCount()); + return mBlendStateExt.getEnabledMask().test(index); + } + DrawBufferMask getBlendEnabledDrawBufferMask() const { return mBlendStateExt.getEnabledMask(); } + void setBlend(bool enabled); + void setBlendIndexed(bool enabled, GLuint index); + void setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha, GLenum destAlpha); + void setBlendFactorsIndexed(GLenum sourceRGB, + GLenum destRGB, + GLenum sourceAlpha, + GLenum destAlpha, + GLuint index); + void setBlendColor(float red, float green, float blue, float alpha); + void setBlendEquation(GLenum rgbEquation, GLenum alphaEquation); + void setBlendEquationIndexed(GLenum rgbEquation, GLenum alphaEquation, GLuint index); + const ColorF &getBlendColor() const { return mBlendColor; } + + // Stencil state maniupulation + bool isStencilTestEnabled() const { return mDepthStencil.stencilTest; } + void setStencilTest(bool enabled); + void setStencilParams(GLenum stencilFunc, GLint stencilRef, GLuint stencilMask); + void setStencilBackParams(GLenum stencilBackFunc, GLint stencilBackRef, GLuint stencilBackMask); + void setStencilWritemask(GLuint stencilWritemask); + void setStencilBackWritemask(GLuint stencilBackWritemask); + void setStencilOperations(GLenum stencilFail, + GLenum stencilPassDepthFail, + GLenum stencilPassDepthPass); + void setStencilBackOperations(GLenum stencilBackFail, + GLenum stencilBackPassDepthFail, + GLenum stencilBackPassDepthPass); + GLint getStencilRef() const { return mStencilRef; } + GLint getStencilBackRef() const { return mStencilBackRef; } + + // Depth bias/polygon offset state manipulation + bool isPolygonOffsetFillEnabled() const { return mRasterizer.polygonOffsetFill; } + void setPolygonOffsetFill(bool enabled); + void setPolygonOffsetParams(GLfloat factor, GLfloat units); + + // Multisample coverage state manipulation + bool isSampleAlphaToCoverageEnabled() const { return mSampleAlphaToCoverage; } + void setSampleAlphaToCoverage(bool enabled); + bool isSampleCoverageEnabled() const { return mSampleCoverage; } + void setSampleCoverage(bool enabled); + void setSampleCoverageParams(GLclampf value, bool invert); + GLclampf getSampleCoverageValue() const { return mSampleCoverageValue; } + bool getSampleCoverageInvert() const { return mSampleCoverageInvert; } + + // Multisample mask state manipulation. + bool isSampleMaskEnabled() const { return mSampleMask; } + void setSampleMaskEnabled(bool enabled); + void setSampleMaskParams(GLuint maskNumber, GLbitfield mask); + GLbitfield getSampleMaskWord(GLuint maskNumber) const + { + ASSERT(maskNumber < mMaxSampleMaskWords); + return mSampleMaskValues[maskNumber]; + } + SampleMaskArray<GLbitfield> getSampleMaskValues() const { return mSampleMaskValues; } + GLuint getMaxSampleMaskWords() const { return mMaxSampleMaskWords; } + + // Multisampling/alpha to one manipulation. + void setSampleAlphaToOne(bool enabled); + bool isSampleAlphaToOneEnabled() const { return mSampleAlphaToOne; } + void setMultisampling(bool enabled); + bool isMultisamplingEnabled() const { return mMultiSampling; } + + void setSampleShading(bool enabled); + bool isSampleShadingEnabled() const { return mIsSampleShadingEnabled; } + void setMinSampleShading(float value); + float getMinSampleShading() const { return mMinSampleShading; } + + // Scissor test state toggle & query + bool isScissorTestEnabled() const { return mScissorTest; } + void setScissorTest(bool enabled); + void setScissorParams(GLint x, GLint y, GLsizei width, GLsizei height); + const Rectangle &getScissor() const { return mScissor; } + + // Dither state toggle & query + bool isDitherEnabled() const { return mRasterizer.dither; } + void setDither(bool enabled); + + // Generic state toggle & query + void setEnableFeature(GLenum feature, bool enabled); + void setEnableFeatureIndexed(GLenum feature, bool enabled, GLuint index); + bool getEnableFeature(GLenum feature) const; + bool getEnableFeatureIndexed(GLenum feature, GLuint index) const; + + // Line width state setter + void setLineWidth(GLfloat width); + float getLineWidth() const { return mLineWidth; } + + // Hint setters + void setGenerateMipmapHint(GLenum hint); + GLenum getGenerateMipmapHint() const; + void setTextureFilteringHint(GLenum hint); + GLenum getTextureFilteringHint() const; + GLenum getFragmentShaderDerivativeHint() const { return mFragmentShaderDerivativeHint; } + void setFragmentShaderDerivativeHint(GLenum hint); + + // GL_CHROMIUM_bind_generates_resource + bool isBindGeneratesResourceEnabled() const { return mBindGeneratesResource; } + + // GL_ANGLE_client_arrays + bool areClientArraysEnabled() const { return mClientArraysEnabled; } + + // Viewport state setter/getter + void setViewportParams(GLint x, GLint y, GLsizei width, GLsizei height); + const Rectangle &getViewport() const { return mViewport; } + + // Texture binding & active texture unit manipulation + void setActiveSampler(unsigned int active); + unsigned int getActiveSampler() const { return static_cast<unsigned int>(mActiveSampler); } + + void setSamplerTexture(const Context *context, TextureType type, Texture *texture); + Texture *getTargetTexture(TextureType type) const; + + Texture *getSamplerTexture(unsigned int sampler, TextureType type) const + { + ASSERT(sampler < mSamplerTextures[type].size()); + return mSamplerTextures[type][sampler].get(); + } + + TextureID getSamplerTextureId(unsigned int sampler, TextureType type) const; + void detachTexture(const Context *context, const TextureMap &zeroTextures, TextureID texture); + void initializeZeroTextures(const Context *context, const TextureMap &zeroTextures); + + void invalidateTextureBindings(TextureType type); + + // Sampler object binding manipulation + void setSamplerBinding(const Context *context, GLuint textureUnit, Sampler *sampler); + SamplerID getSamplerId(GLuint textureUnit) const + { + ASSERT(textureUnit < mSamplers.size()); + return mSamplers[textureUnit].id(); + } + + Sampler *getSampler(GLuint textureUnit) const { return mSamplers[textureUnit].get(); } + + const SamplerBindingVector &getSamplers() const { return mSamplers; } + + void detachSampler(const Context *context, SamplerID sampler); + + // Renderbuffer binding manipulation + void setRenderbufferBinding(const Context *context, Renderbuffer *renderbuffer); + RenderbufferID getRenderbufferId() const { return mRenderbuffer.id(); } + Renderbuffer *getCurrentRenderbuffer() const { return mRenderbuffer.get(); } + void detachRenderbuffer(const Context *context, RenderbufferID renderbuffer); + + // Framebuffer binding manipulation + void setReadFramebufferBinding(Framebuffer *framebuffer); + void setDrawFramebufferBinding(Framebuffer *framebuffer); + Framebuffer *getTargetFramebuffer(GLenum target) const; + Framebuffer *getReadFramebuffer() const { return mReadFramebuffer; } + Framebuffer *getDrawFramebuffer() const { return mDrawFramebuffer; } + Framebuffer *getDefaultFramebuffer() const; + + bool removeReadFramebufferBinding(FramebufferID framebuffer); + bool removeDrawFramebufferBinding(FramebufferID framebuffer); + + // Vertex array object binding manipulation + void setVertexArrayBinding(const Context *context, VertexArray *vertexArray); + bool removeVertexArrayBinding(const Context *context, VertexArrayID vertexArray); + VertexArrayID getVertexArrayId() const; + + VertexArray *getVertexArray() const + { + ASSERT(mVertexArray != nullptr); + return mVertexArray; + } + + // QCOM_shading_rate helpers + void setShadingRate(GLenum rate); + ShadingRate getShadingRate() const { return mShadingRate; } + + // If both a Program and a ProgramPipeline are bound, the Program will + // always override the ProgramPipeline. + ProgramExecutable *getProgramExecutable() const { return mExecutable; } + ProgramExecutable *getLinkedProgramExecutable(const Context *context) const + { + if (mProgram) + { + mProgram->resolveLink(context); + } + else if (mProgramPipeline.get()) + { + mProgramPipeline->resolveLink(context); + } + return mExecutable; + } + + // Program binding manipulation + angle::Result setProgram(const Context *context, Program *newProgram); + + Program *getProgram() const + { + ASSERT(!mProgram || !mProgram->isLinking()); + return mProgram; + } + + Program *getLinkedProgram(const Context *context) const + { + if (mProgram) + { + mProgram->resolveLink(context); + } + return mProgram; + } + + ProgramPipeline *getProgramPipeline() const { return mProgramPipeline.get(); } + + ProgramPipeline *getLinkedProgramPipeline(const Context *context) const + { + if (mProgramPipeline.get()) + { + mProgramPipeline->resolveLink(context); + } + return mProgramPipeline.get(); + } + + // Transform feedback object (not buffer) binding manipulation + void setTransformFeedbackBinding(const Context *context, TransformFeedback *transformFeedback); + TransformFeedback *getCurrentTransformFeedback() const { return mTransformFeedback.get(); } + + ANGLE_INLINE bool isTransformFeedbackActive() const + { + TransformFeedback *curTransformFeedback = mTransformFeedback.get(); + return curTransformFeedback && curTransformFeedback->isActive(); + } + ANGLE_INLINE bool isTransformFeedbackActiveUnpaused() const + { + TransformFeedback *curTransformFeedback = mTransformFeedback.get(); + return curTransformFeedback && curTransformFeedback->isActive() && + !curTransformFeedback->isPaused(); + } + + bool removeTransformFeedbackBinding(const Context *context, + TransformFeedbackID transformFeedback); + + // Query binding manipulation + bool isQueryActive(QueryType type) const; + bool isQueryActive(Query *query) const; + void setActiveQuery(const Context *context, QueryType type, Query *query); + QueryID getActiveQueryId(QueryType type) const; + Query *getActiveQuery(QueryType type) const; + + // Program Pipeline binding manipulation + angle::Result setProgramPipelineBinding(const Context *context, ProgramPipeline *pipeline); + void detachProgramPipeline(const Context *context, ProgramPipelineID pipeline); + + //// Typed buffer binding point manipulation //// + ANGLE_INLINE void setBufferBinding(const Context *context, BufferBinding target, Buffer *buffer) + { + (this->*(kBufferSetters[target]))(context, buffer); + } + + ANGLE_INLINE Buffer *getTargetBuffer(BufferBinding target) const + { + switch (target) + { + case BufferBinding::ElementArray: + return getVertexArray()->getElementArrayBuffer(); + default: + return mBoundBuffers[target].get(); + } + } + + ANGLE_INLINE Buffer *getArrayBuffer() const { return getTargetBuffer(BufferBinding::Array); } + + angle::Result setIndexedBufferBinding(const Context *context, + BufferBinding target, + GLuint index, + Buffer *buffer, + GLintptr offset, + GLsizeiptr size); + + size_t getAtomicCounterBufferCount() const { return mAtomicCounterBuffers.size(); } + + ANGLE_INLINE bool hasValidAtomicCounterBuffer() const + { + return mBoundAtomicCounterBuffersMask.any(); + } + + const OffsetBindingPointer<Buffer> &getIndexedUniformBuffer(size_t index) const; + const OffsetBindingPointer<Buffer> &getIndexedAtomicCounterBuffer(size_t index) const; + const OffsetBindingPointer<Buffer> &getIndexedShaderStorageBuffer(size_t index) const; + + const angle::BitSet<gl::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS> &getUniformBuffersMask() + const + { + return mBoundUniformBuffersMask; + } + const angle::BitSet<gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS> + &getAtomicCounterBuffersMask() const + { + return mBoundAtomicCounterBuffersMask; + } + const angle::BitSet<gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS> + &getShaderStorageBuffersMask() const + { + return mBoundShaderStorageBuffersMask; + } + + // Detach a buffer from all bindings + angle::Result detachBuffer(Context *context, const Buffer *buffer); + + // Vertex attrib manipulation + void setEnableVertexAttribArray(unsigned int attribNum, bool enabled); + void setVertexAttribf(GLuint index, const GLfloat values[4]); + void setVertexAttribu(GLuint index, const GLuint values[4]); + void setVertexAttribi(GLuint index, const GLint values[4]); + + ANGLE_INLINE void setVertexAttribPointer(const Context *context, + unsigned int attribNum, + Buffer *boundBuffer, + GLint size, + VertexAttribType type, + bool normalized, + GLsizei stride, + const void *pointer) + { + mVertexArray->setVertexAttribPointer(context, attribNum, boundBuffer, size, type, + normalized, stride, pointer); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); + } + + ANGLE_INLINE void setVertexAttribIPointer(const Context *context, + unsigned int attribNum, + Buffer *boundBuffer, + GLint size, + VertexAttribType type, + GLsizei stride, + const void *pointer) + { + mVertexArray->setVertexAttribIPointer(context, attribNum, boundBuffer, size, type, stride, + pointer); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); + } + + void setVertexAttribDivisor(const Context *context, GLuint index, GLuint divisor); + const VertexAttribCurrentValueData &getVertexAttribCurrentValue(size_t attribNum) const + { + ASSERT(attribNum < mVertexAttribCurrentValues.size()); + return mVertexAttribCurrentValues[attribNum]; + } + + const std::vector<VertexAttribCurrentValueData> &getVertexAttribCurrentValues() const + { + return mVertexAttribCurrentValues; + } + + const void *getVertexAttribPointer(unsigned int attribNum) const; + + void bindVertexBuffer(const Context *context, + GLuint bindingIndex, + Buffer *boundBuffer, + GLintptr offset, + GLsizei stride); + void setVertexAttribFormat(GLuint attribIndex, + GLint size, + VertexAttribType type, + bool normalized, + bool pureInteger, + GLuint relativeOffset); + + void setVertexAttribBinding(const Context *context, GLuint attribIndex, GLuint bindingIndex) + { + mVertexArray->setVertexAttribBinding(context, attribIndex, bindingIndex); + mDirtyObjects.set(DIRTY_OBJECT_VERTEX_ARRAY); + } + + void setVertexBindingDivisor(const Context *context, GLuint bindingIndex, GLuint divisor); + + // Pixel pack state manipulation + void setPackAlignment(GLint alignment); + GLint getPackAlignment() const { return mPack.alignment; } + void setPackReverseRowOrder(bool reverseRowOrder); + bool getPackReverseRowOrder() const { return mPack.reverseRowOrder; } + void setPackRowLength(GLint rowLength); + GLint getPackRowLength() const { return mPack.rowLength; } + void setPackSkipRows(GLint skipRows); + GLint getPackSkipRows() const { return mPack.skipRows; } + void setPackSkipPixels(GLint skipPixels); + GLint getPackSkipPixels() const { return mPack.skipPixels; } + const PixelPackState &getPackState() const { return mPack; } + PixelPackState &getPackState() { return mPack; } + + // Pixel unpack state manipulation + void setUnpackAlignment(GLint alignment); + GLint getUnpackAlignment() const { return mUnpack.alignment; } + void setUnpackRowLength(GLint rowLength); + GLint getUnpackRowLength() const { return mUnpack.rowLength; } + void setUnpackImageHeight(GLint imageHeight); + GLint getUnpackImageHeight() const { return mUnpack.imageHeight; } + void setUnpackSkipImages(GLint skipImages); + GLint getUnpackSkipImages() const { return mUnpack.skipImages; } + void setUnpackSkipRows(GLint skipRows); + GLint getUnpackSkipRows() const { return mUnpack.skipRows; } + void setUnpackSkipPixels(GLint skipPixels); + GLint getUnpackSkipPixels() const { return mUnpack.skipPixels; } + const PixelUnpackState &getUnpackState() const { return mUnpack; } + PixelUnpackState &getUnpackState() { return mUnpack; } + + // Debug state + const Debug &getDebug() const { return mDebug; } + Debug &getDebug() { return mDebug; } + + // CHROMIUM_framebuffer_mixed_samples coverage modulation + void setCoverageModulation(GLenum components); + GLenum getCoverageModulation() const { return mCoverageModulation; } + + // GL_EXT_sRGB_write_control + void setFramebufferSRGB(bool sRGB); + bool getFramebufferSRGB() const { return mFramebufferSRGB; } + + // GL_KHR_parallel_shader_compile + void setMaxShaderCompilerThreads(GLuint count); + GLuint getMaxShaderCompilerThreads() const { return mMaxShaderCompilerThreads; } + + // GL_EXT_tessellation_shader + void setPatchVertices(GLuint value); + GLuint getPatchVertices() const { return mPatchVertices; } + + // GL_ANGLE_shader_pixel_local_storage + void setPixelLocalStorageActive(bool active); + bool getPixelLocalStorageActive() const { return mPixelLocalStorageActive; } + + // State query functions + void getBooleanv(GLenum pname, GLboolean *params) const; + void getFloatv(GLenum pname, GLfloat *params) const; + angle::Result getIntegerv(const Context *context, GLenum pname, GLint *params) const; + void getPointerv(const Context *context, GLenum pname, void **params) const; + void getIntegeri_v(const Context *context, GLenum target, GLuint index, GLint *data) const; + void getInteger64i_v(GLenum target, GLuint index, GLint64 *data) const; + void getBooleani_v(GLenum target, GLuint index, GLboolean *data) const; + + bool isRobustResourceInitEnabled() const { return mRobustResourceInit; } + + bool isDrawFramebufferBindingDirty() const + { + return mDirtyBits.test(DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING); + } + + // Sets the dirty bit for the program executable. + angle::Result onProgramExecutableChange(const Context *context, Program *program); + // Sets the dirty bit for the program pipeline executable. + angle::Result onProgramPipelineExecutableChange(const Context *context); + + enum DirtyBitType + { + // Note: process draw framebuffer binding first, so that other dirty bits whose effect + // depend on the current draw framebuffer are not processed while the old framebuffer is + // still bound. + DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING, + DIRTY_BIT_READ_FRAMEBUFFER_BINDING, + DIRTY_BIT_SCISSOR_TEST_ENABLED, + DIRTY_BIT_SCISSOR, + DIRTY_BIT_VIEWPORT, + DIRTY_BIT_DEPTH_RANGE, + DIRTY_BIT_BLEND_ENABLED, + DIRTY_BIT_BLEND_COLOR, + DIRTY_BIT_BLEND_FUNCS, + DIRTY_BIT_BLEND_EQUATIONS, + DIRTY_BIT_COLOR_MASK, + DIRTY_BIT_SAMPLE_ALPHA_TO_COVERAGE_ENABLED, + DIRTY_BIT_SAMPLE_COVERAGE_ENABLED, + DIRTY_BIT_SAMPLE_COVERAGE, + DIRTY_BIT_SAMPLE_MASK_ENABLED, + DIRTY_BIT_SAMPLE_MASK, + DIRTY_BIT_DEPTH_TEST_ENABLED, + DIRTY_BIT_DEPTH_FUNC, + DIRTY_BIT_DEPTH_MASK, + DIRTY_BIT_STENCIL_TEST_ENABLED, + DIRTY_BIT_STENCIL_FUNCS_FRONT, + DIRTY_BIT_STENCIL_FUNCS_BACK, + DIRTY_BIT_STENCIL_OPS_FRONT, + DIRTY_BIT_STENCIL_OPS_BACK, + DIRTY_BIT_STENCIL_WRITEMASK_FRONT, + DIRTY_BIT_STENCIL_WRITEMASK_BACK, + DIRTY_BIT_CULL_FACE_ENABLED, + DIRTY_BIT_CULL_FACE, + DIRTY_BIT_FRONT_FACE, + DIRTY_BIT_POLYGON_OFFSET_FILL_ENABLED, + DIRTY_BIT_POLYGON_OFFSET, + DIRTY_BIT_RASTERIZER_DISCARD_ENABLED, + DIRTY_BIT_LINE_WIDTH, + DIRTY_BIT_PRIMITIVE_RESTART_ENABLED, + DIRTY_BIT_CLEAR_COLOR, + DIRTY_BIT_CLEAR_DEPTH, + DIRTY_BIT_CLEAR_STENCIL, + DIRTY_BIT_UNPACK_STATE, + DIRTY_BIT_UNPACK_BUFFER_BINDING, + DIRTY_BIT_PACK_STATE, + DIRTY_BIT_PACK_BUFFER_BINDING, + DIRTY_BIT_DITHER_ENABLED, + DIRTY_BIT_RENDERBUFFER_BINDING, + DIRTY_BIT_VERTEX_ARRAY_BINDING, + DIRTY_BIT_DRAW_INDIRECT_BUFFER_BINDING, + DIRTY_BIT_DISPATCH_INDIRECT_BUFFER_BINDING, + // TODO(jmadill): Fine-grained dirty bits for each index. + DIRTY_BIT_PROGRAM_BINDING, // Must be before DIRTY_BIT_PROGRAM_EXECUTABLE + DIRTY_BIT_PROGRAM_EXECUTABLE, + // TODO(jmadill): Fine-grained dirty bits for each texture/sampler. + DIRTY_BIT_SAMPLER_BINDINGS, + DIRTY_BIT_TEXTURE_BINDINGS, + DIRTY_BIT_IMAGE_BINDINGS, + DIRTY_BIT_TRANSFORM_FEEDBACK_BINDING, + DIRTY_BIT_UNIFORM_BUFFER_BINDINGS, + DIRTY_BIT_SHADER_STORAGE_BUFFER_BINDING, + DIRTY_BIT_ATOMIC_COUNTER_BUFFER_BINDING, + DIRTY_BIT_MULTISAMPLING, + DIRTY_BIT_SAMPLE_ALPHA_TO_ONE, + DIRTY_BIT_COVERAGE_MODULATION, // CHROMIUM_framebuffer_mixed_samples + DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE, // GL_EXT_sRGB_write_control + DIRTY_BIT_CURRENT_VALUES, + DIRTY_BIT_PROVOKING_VERTEX, + DIRTY_BIT_SAMPLE_SHADING, + DIRTY_BIT_PATCH_VERTICES, + DIRTY_BIT_EXTENDED, // clip distances, mipmap generation hint, derivative hint, + // EXT_clip_control + DIRTY_BIT_INVALID, + DIRTY_BIT_MAX = DIRTY_BIT_INVALID, + }; + + static_assert(DIRTY_BIT_MAX <= 64, "State dirty bits must be capped at 64"); + + enum ExtendedDirtyBitType + { + EXTENDED_DIRTY_BIT_CLIP_CONTROL, // EXT_clip_control + EXTENDED_DIRTY_BIT_CLIP_DISTANCES, // clip distances + EXTENDED_DIRTY_BIT_MIPMAP_GENERATION_HINT, // mipmap generation hint + EXTENDED_DIRTY_BIT_SHADER_DERIVATIVE_HINT, // shader derivative hint + EXTENDED_DIRTY_BIT_SHADING_RATE, // QCOM_shading_rate + EXTENDED_DIRTY_BIT_LOGIC_OP_ENABLED, // ANGLE_logic_op + EXTENDED_DIRTY_BIT_LOGIC_OP, // ANGLE_logic_op + EXTENDED_DIRTY_BIT_INVALID, + EXTENDED_DIRTY_BIT_MAX = EXTENDED_DIRTY_BIT_INVALID, + }; + + static_assert(EXTENDED_DIRTY_BIT_MAX <= 32, "State extended dirty bits must be capped at 32"); + + // TODO(jmadill): Consider storing dirty objects in a list instead of by binding. + enum DirtyObjectType + { + DIRTY_OBJECT_ACTIVE_TEXTURES, // Top-level dirty bit. Also see mDirtyActiveTextures. + DIRTY_OBJECT_TEXTURES_INIT, + DIRTY_OBJECT_IMAGES_INIT, + DIRTY_OBJECT_READ_ATTACHMENTS, + DIRTY_OBJECT_DRAW_ATTACHMENTS, + DIRTY_OBJECT_READ_FRAMEBUFFER, + DIRTY_OBJECT_DRAW_FRAMEBUFFER, + DIRTY_OBJECT_VERTEX_ARRAY, + DIRTY_OBJECT_TEXTURES, // Top-level dirty bit. Also see mDirtyTextures. + DIRTY_OBJECT_IMAGES, // Top-level dirty bit. Also see mDirtyImages. + DIRTY_OBJECT_SAMPLERS, // Top-level dirty bit. Also see mDirtySamplers. + DIRTY_OBJECT_PROGRAM, + DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT, + DIRTY_OBJECT_UNKNOWN, + DIRTY_OBJECT_MAX = DIRTY_OBJECT_UNKNOWN, + }; + + using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; + const DirtyBits &getDirtyBits() const { return mDirtyBits; } + void clearDirtyBits() { mDirtyBits.reset(); } + void clearDirtyBits(const DirtyBits &bitset) { mDirtyBits &= ~bitset; } + void setAllDirtyBits() + { + mDirtyBits.set(); + mExtendedDirtyBits.set(); + mDirtyCurrentValues.set(); + } + + using ExtendedDirtyBits = angle::BitSet32<EXTENDED_DIRTY_BIT_MAX>; + const ExtendedDirtyBits &getExtendedDirtyBits() const { return mExtendedDirtyBits; } + // TODO(https://anglebug.com/5631): Handle extended dirty bits on non-vulkan backends + ExtendedDirtyBits getAndResetExtendedDirtyBits() const; + void clearExtendedDirtyBits() { mExtendedDirtyBits.reset(); } + + using DirtyObjects = angle::BitSet<DIRTY_OBJECT_MAX>; + void clearDirtyObjects() { mDirtyObjects.reset(); } + void setAllDirtyObjects() { mDirtyObjects.set(); } + angle::Result syncDirtyObjects(const Context *context, + const DirtyObjects &bitset, + Command command); + angle::Result syncDirtyObject(const Context *context, GLenum target); + void setObjectDirty(GLenum target); + void setTextureDirty(size_t textureUnitIndex); + void setSamplerDirty(size_t samplerIndex); + + ANGLE_INLINE void setReadFramebufferDirty() + { + mDirtyObjects.set(DIRTY_OBJECT_READ_FRAMEBUFFER); + mDirtyObjects.set(DIRTY_OBJECT_READ_ATTACHMENTS); + } + + ANGLE_INLINE void setDrawFramebufferDirty() + { + mDirtyObjects.set(DIRTY_OBJECT_DRAW_FRAMEBUFFER); + mDirtyObjects.set(DIRTY_OBJECT_DRAW_ATTACHMENTS); + } + + // This actually clears the current value dirty bits. + // TODO(jmadill): Pass mutable dirty bits into Impl. + AttributesMask getAndResetDirtyCurrentValues() const; + + void setImageUnit(const Context *context, + size_t unit, + Texture *texture, + GLint level, + GLboolean layered, + GLint layer, + GLenum access, + GLenum format); + + const ImageUnit &getImageUnit(size_t unit) const { return mImageUnits[unit]; } + const ActiveTexturesCache &getActiveTexturesCache() const { return mActiveTexturesCache; } + ComponentTypeMask getCurrentValuesTypeMask() const { return mCurrentValuesTypeMask; } + + // "onActiveTextureChange" is called when a texture binding changes. + void onActiveTextureChange(const Context *context, size_t textureUnit); + + // "onActiveTextureStateChange" is called when the Texture changed but the binding did not. + void onActiveTextureStateChange(const Context *context, size_t textureUnit); + + void onImageStateChange(const Context *context, size_t unit); + + void onUniformBufferStateChange(size_t uniformBufferIndex); + void onAtomicCounterBufferStateChange(size_t atomicCounterBufferIndex); + void onShaderStorageBufferStateChange(size_t shaderStorageBufferIndex); + + bool isCurrentTransformFeedback(const TransformFeedback *tf) const + { + return tf == mTransformFeedback.get(); + } + bool isCurrentVertexArray(const VertexArray *va) const { return va == mVertexArray; } + + GLES1State &gles1() { return mGLES1State; } + const GLES1State &gles1() const { return mGLES1State; } + + // Helpers for setting bound buffers. They should all have the same signature. + // Not meant to be called externally. Used for local helpers in State.cpp. + template <BufferBinding Target> + void setGenericBufferBindingWithBit(const Context *context, Buffer *buffer); + + template <BufferBinding Target> + void setGenericBufferBinding(const Context *context, Buffer *buffer); + + using BufferBindingSetter = void (State::*)(const Context *, Buffer *); + + ANGLE_INLINE bool validateSamplerFormats() const + { + return (!mExecutable || !(mTexturesIncompatibleWithSamplers.intersects( + mExecutable->getActiveSamplersMask()))); + } + + ProvokingVertexConvention getProvokingVertex() const { return mProvokingVertex; } + void setProvokingVertex(ProvokingVertexConvention val) + { + mDirtyBits.set(State::DIRTY_BIT_PROVOKING_VERTEX); + mProvokingVertex = val; + } + + ANGLE_INLINE void setReadFramebufferBindingDirty() + { + mDirtyBits.set(State::DIRTY_BIT_READ_FRAMEBUFFER_BINDING); + } + + ANGLE_INLINE void setDrawFramebufferBindingDirty() + { + mDirtyBits.set(State::DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING); + } + + using ClipDistanceEnableBits = angle::BitSet32<IMPLEMENTATION_MAX_CLIP_DISTANCES>; + const ClipDistanceEnableBits &getEnabledClipDistances() const { return mClipDistancesEnabled; } + void setClipDistanceEnable(int idx, bool enable); + + const OverlayType *getOverlay() const { return mOverlay; } + + // Not for general use. + const BufferManager &getBufferManagerForCapture() const { return *mBufferManager; } + const BoundBufferMap &getBoundBuffersForCapture() const { return mBoundBuffers; } + const TextureManager &getTextureManagerForCapture() const { return *mTextureManager; } + const TextureBindingMap &getBoundTexturesForCapture() const { return mSamplerTextures; } + const RenderbufferManager &getRenderbufferManagerForCapture() const + { + return *mRenderbufferManager; + } + const FramebufferManager &getFramebufferManagerForCapture() const + { + return *mFramebufferManager; + } + const ShaderProgramManager &getShaderProgramManagerForCapture() const + { + return *mShaderProgramManager; + } + const SyncManager &getSyncManagerForCapture() const { return *mSyncManager; } + const SamplerManager &getSamplerManagerForCapture() const { return *mSamplerManager; } + const ProgramPipelineManager *getProgramPipelineManagerForCapture() const + { + return mProgramPipelineManager; + } + const SamplerBindingVector &getSamplerBindingsForCapture() const { return mSamplers; } + const ActiveQueryMap &getActiveQueriesForCapture() const { return mActiveQueries; } + void initializeForCapture(const Context *context); + + bool hasConstantAlphaBlendFunc() const + { + return (mBlendFuncConstantAlphaDrawBuffers & mBlendStateExt.getEnabledMask()).any(); + } + + bool hasSimultaneousConstantColorAndAlphaBlendFunc() const + { + return (mBlendFuncConstantColorDrawBuffers & mBlendStateExt.getEnabledMask()).any() && + hasConstantAlphaBlendFunc(); + } + + bool noSimultaneousConstantColorAndAlphaBlendFunc() const + { + return mNoSimultaneousConstantColorAndAlphaBlendFunc; + } + + const BufferVector &getOffsetBindingPointerUniformBuffers() const { return mUniformBuffers; } + + const BufferVector &getOffsetBindingPointerAtomicCounterBuffers() const + { + return mAtomicCounterBuffers; + } + + const BufferVector &getOffsetBindingPointerShaderStorageBuffers() const + { + return mShaderStorageBuffers; + } + + ActiveTextureMask getTexturesIncompatibleWithSamplers() const + { + return mTexturesIncompatibleWithSamplers; + } + + bool isProgramBinaryCacheEnabled() const { return mProgramBinaryCacheEnabled; } + + bool isTextureRectangleEnabled() const { return mTextureRectangleEnabled; } + + DrawBufferMask getBlendFuncConstantAlphaDrawBuffers() const + { + return mBlendFuncConstantAlphaDrawBuffers; + } + + DrawBufferMask getBlendFuncConstantColorDrawBuffers() const + { + return mBlendFuncConstantColorDrawBuffers; + } + + const std::vector<ImageUnit> &getImageUnits() const { return mImageUnits; } + + bool hasDisplayTextureShareGroup() const { return mDisplayTextureShareGroup; } + + void setLogicOpEnabled(bool enabled); + bool isLogicOpEnabled() const { return mLogicOpEnabled; } + + void setLogicOp(LogicalOperation opcode); + LogicalOperation getLogicOp() const { return mLogicOp; } + + private: + friend class Context; + + void unsetActiveTextures(const ActiveTextureMask &textureMask); + void setActiveTextureDirty(size_t textureIndex, Texture *texture); + void updateTextureBinding(const Context *context, size_t textureIndex, Texture *texture); + void updateActiveTextureStateOnSync(const Context *context, + size_t textureIndex, + const Sampler *sampler, + Texture *texture); + Texture *getTextureForActiveSampler(TextureType type, size_t index); + + bool hasConstantColor(GLenum sourceRGB, GLenum destRGB) const; + bool hasConstantAlpha(GLenum sourceRGB, GLenum destRGB) const; + + // Functions to synchronize dirty states + angle::Result syncActiveTextures(const Context *context, Command command); + angle::Result syncTexturesInit(const Context *context, Command command); + angle::Result syncImagesInit(const Context *context, Command command); + angle::Result syncReadAttachments(const Context *context, Command command); + angle::Result syncDrawAttachments(const Context *context, Command command); + angle::Result syncReadFramebuffer(const Context *context, Command command); + angle::Result syncDrawFramebuffer(const Context *context, Command command); + angle::Result syncVertexArray(const Context *context, Command command); + angle::Result syncTextures(const Context *context, Command command); + angle::Result syncImages(const Context *context, Command command); + angle::Result syncSamplers(const Context *context, Command command); + angle::Result syncProgram(const Context *context, Command command); + angle::Result syncProgramPipelineObject(const Context *context, Command command); + + using DirtyObjectHandler = angle::Result (State::*)(const Context *context, Command command); + + static constexpr DirtyObjectHandler kDirtyObjectHandlers[DIRTY_OBJECT_MAX] = { + &State::syncActiveTextures, + &State::syncTexturesInit, + &State::syncImagesInit, + &State::syncReadAttachments, + &State::syncDrawAttachments, + &State::syncReadFramebuffer, + &State::syncDrawFramebuffer, + &State::syncVertexArray, + &State::syncTextures, + &State::syncImages, + &State::syncSamplers, + &State::syncProgram, + &State::syncProgramPipelineObject}; + + // Robust init must happen before Framebuffer init for the Vulkan back-end. + static_assert(DIRTY_OBJECT_ACTIVE_TEXTURES < DIRTY_OBJECT_TEXTURES_INIT, "init order"); + static_assert(DIRTY_OBJECT_TEXTURES_INIT < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order"); + static_assert(DIRTY_OBJECT_IMAGES_INIT < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order"); + static_assert(DIRTY_OBJECT_DRAW_ATTACHMENTS < DIRTY_OBJECT_DRAW_FRAMEBUFFER, "init order"); + static_assert(DIRTY_OBJECT_READ_ATTACHMENTS < DIRTY_OBJECT_READ_FRAMEBUFFER, "init order"); + + static_assert(DIRTY_OBJECT_ACTIVE_TEXTURES == 0, "check DIRTY_OBJECT_ACTIVE_TEXTURES index"); + static_assert(DIRTY_OBJECT_TEXTURES_INIT == 1, "check DIRTY_OBJECT_TEXTURES_INIT index"); + static_assert(DIRTY_OBJECT_IMAGES_INIT == 2, "check DIRTY_OBJECT_IMAGES_INIT index"); + static_assert(DIRTY_OBJECT_READ_ATTACHMENTS == 3, "check DIRTY_OBJECT_READ_ATTACHMENTS index"); + static_assert(DIRTY_OBJECT_DRAW_ATTACHMENTS == 4, "check DIRTY_OBJECT_DRAW_ATTACHMENTS index"); + static_assert(DIRTY_OBJECT_READ_FRAMEBUFFER == 5, "check DIRTY_OBJECT_READ_FRAMEBUFFER index"); + static_assert(DIRTY_OBJECT_DRAW_FRAMEBUFFER == 6, "check DIRTY_OBJECT_DRAW_FRAMEBUFFER index"); + static_assert(DIRTY_OBJECT_VERTEX_ARRAY == 7, "check DIRTY_OBJECT_VERTEX_ARRAY index"); + static_assert(DIRTY_OBJECT_TEXTURES == 8, "check DIRTY_OBJECT_TEXTURES index"); + static_assert(DIRTY_OBJECT_IMAGES == 9, "check DIRTY_OBJECT_IMAGES index"); + static_assert(DIRTY_OBJECT_SAMPLERS == 10, "check DIRTY_OBJECT_SAMPLERS index"); + static_assert(DIRTY_OBJECT_PROGRAM == 11, "check DIRTY_OBJECT_PROGRAM index"); + static_assert(DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT == 12, + "check DIRTY_OBJECT_PROGRAM_PIPELINE_OBJECT index"); + + // Dispatch table for buffer update functions. + static const angle::PackedEnumMap<BufferBinding, BufferBindingSetter> kBufferSetters; + + ContextID mID; + + EGLenum mClientType; + EGLint mProfileMask; + EGLenum mContextPriority; + bool mHasRobustAccess; + bool mHasProtectedContent; + bool mIsDebugContext; + Version mClientVersion; + + // Caps to use for validation + Caps mCaps; + TextureCapsMap mTextureCaps; + Extensions mExtensions; + Limitations mLimitations; + + egl::ShareGroup *mShareGroup; + + // Resource managers. + BufferManager *mBufferManager; + ShaderProgramManager *mShaderProgramManager; + TextureManager *mTextureManager; + RenderbufferManager *mRenderbufferManager; + SamplerManager *mSamplerManager; + SyncManager *mSyncManager; + FramebufferManager *mFramebufferManager; + ProgramPipelineManager *mProgramPipelineManager; + MemoryObjectManager *mMemoryObjectManager; + SemaphoreManager *mSemaphoreManager; + + ColorF mColorClearValue; + GLfloat mDepthClearValue; + int mStencilClearValue; + + RasterizerState mRasterizer; + bool mScissorTest; + Rectangle mScissor; + + bool mNoUnclampedBlendColor; + + BlendState mBlendState; // Buffer zero blend state legacy struct + BlendStateExt mBlendStateExt; + ColorF mBlendColor; + bool mSampleAlphaToCoverage; + bool mSampleCoverage; + GLfloat mSampleCoverageValue; + bool mSampleCoverageInvert; + bool mSampleMask; + GLuint mMaxSampleMaskWords; + SampleMaskArray<GLbitfield> mSampleMaskValues; + bool mIsSampleShadingEnabled; + float mMinSampleShading; + + DepthStencilState mDepthStencil; + GLint mStencilRef; + GLint mStencilBackRef; + + GLfloat mLineWidth; + + GLenum mGenerateMipmapHint; + GLenum mTextureFilteringHint; + GLenum mFragmentShaderDerivativeHint; + + const bool mBindGeneratesResource; + const bool mClientArraysEnabled; + + Rectangle mViewport; + float mNearZ; + float mFarZ; + + GLenum mClipControlOrigin; + GLenum mClipControlDepth; + + Framebuffer *mReadFramebuffer; + Framebuffer *mDrawFramebuffer; + BindingPointer<Renderbuffer> mRenderbuffer; + Program *mProgram; + BindingPointer<ProgramPipeline> mProgramPipeline; + ProgramExecutable *mExecutable; + + // GL_ANGLE_provoking_vertex + ProvokingVertexConvention mProvokingVertex; + + using VertexAttribVector = std::vector<VertexAttribCurrentValueData>; + VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib + VertexArray *mVertexArray; + ComponentTypeMask mCurrentValuesTypeMask; + + // Texture and sampler bindings + GLint mActiveSampler; // Active texture unit selector - GL_TEXTURE0 + + TextureBindingMap mSamplerTextures; + + // Active Textures Cache + // --------------------- + // The active textures cache gives ANGLE components access to a complete array of textures + // on a draw call. gl::State implements angle::Observer and watches gl::Texture for state + // changes via the onSubjectStateChange method above. We update the cache before draws. + // See Observer.h and the design doc linked there for more info on Subject/Observer events. + // + // On state change events (re-binding textures, samplers, programs etc) we clear the cache + // and flag dirty bits. nullptr indicates unbound or incomplete. + ActiveTexturesCache mActiveTexturesCache; + std::vector<angle::ObserverBinding> mCompleteTextureBindings; + + ActiveTextureMask mTexturesIncompatibleWithSamplers; + + SamplerBindingVector mSamplers; + + // It would be nice to merge the image and observer binding. Same for textures. + std::vector<ImageUnit> mImageUnits; + + ActiveQueryMap mActiveQueries; + + // Stores the currently bound buffer for each binding point. It has an entry for the element + // array buffer but it should not be used. Instead this bind point is owned by the current + // vertex array object. + BoundBufferMap mBoundBuffers; + + BufferVector mUniformBuffers; + BufferVector mAtomicCounterBuffers; + BufferVector mShaderStorageBuffers; + + angle::BitSet<gl::IMPLEMENTATION_MAX_UNIFORM_BUFFER_BINDINGS> mBoundUniformBuffersMask; + angle::BitSet<gl::IMPLEMENTATION_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS> + mBoundAtomicCounterBuffersMask; + angle::BitSet<gl::IMPLEMENTATION_MAX_SHADER_STORAGE_BUFFER_BINDINGS> + mBoundShaderStorageBuffersMask; + + BindingPointer<TransformFeedback> mTransformFeedback; + + PixelUnpackState mUnpack; + PixelPackState mPack; + + bool mPrimitiveRestart; + + Debug mDebug; + + bool mMultiSampling; + bool mSampleAlphaToOne; + + GLenum mCoverageModulation; + + // GL_EXT_sRGB_write_control + bool mFramebufferSRGB; + + // GL_ANGLE_robust_resource_initialization + const bool mRobustResourceInit; + + // GL_ANGLE_program_cache_control + const bool mProgramBinaryCacheEnabled; + + // GL_ANGLE_webgl_compatibility + bool mTextureRectangleEnabled; + + // GL_ANGLE_logic_op + bool mLogicOpEnabled; + LogicalOperation mLogicOp; + + // GL_KHR_parallel_shader_compile + GLuint mMaxShaderCompilerThreads; + + // GL_APPLE_clip_distance/GL_EXT_clip_cull_distance + ClipDistanceEnableBits mClipDistancesEnabled; + + // GL_EXT_tessellation_shader + GLuint mPatchVertices; + + // GL_ANGLE_shader_pixel_local_storage + bool mPixelLocalStorageActive; + + // GLES1 emulation: state specific to GLES1 + GLES1State mGLES1State; + + DirtyBits mDirtyBits; + mutable ExtendedDirtyBits mExtendedDirtyBits; + DirtyObjects mDirtyObjects; + mutable AttributesMask mDirtyCurrentValues; + ActiveTextureMask mDirtyActiveTextures; + ActiveTextureMask mDirtyTextures; + ActiveTextureMask mDirtySamplers; + ImageUnitMask mDirtyImages; + + // The Overlay object, used by the backend to render the overlay. + const OverlayType *mOverlay; + + // OES_draw_buffers_indexed + DrawBufferMask mBlendFuncConstantAlphaDrawBuffers; + DrawBufferMask mBlendFuncConstantColorDrawBuffers; + bool mNoSimultaneousConstantColorAndAlphaBlendFunc; + // Whether the indexed variants of setBlend* have been called. If so, the call to the + // non-indexed variants are not no-oped. + bool mSetBlendIndexedInvoked; + bool mSetBlendFactorsIndexedInvoked; + bool mSetBlendEquationsIndexedInvoked; + bool mDisplayTextureShareGroup; + + // GL_EXT_primitive_bounding_box + GLfloat mBoundingBoxMinX; + GLfloat mBoundingBoxMinY; + GLfloat mBoundingBoxMinZ; + GLfloat mBoundingBoxMinW; + GLfloat mBoundingBoxMaxX; + GLfloat mBoundingBoxMaxY; + GLfloat mBoundingBoxMaxZ; + GLfloat mBoundingBoxMaxW; + + // QCOM_shading_rate + bool mShadingRatePreserveAspectRatio; + ShadingRate mShadingRate; +}; + +ANGLE_INLINE angle::Result State::syncDirtyObjects(const Context *context, + const DirtyObjects &bitset, + Command command) +{ + const DirtyObjects &dirtyObjects = mDirtyObjects & bitset; + + for (size_t dirtyObject : dirtyObjects) + { + ANGLE_TRY((this->*kDirtyObjectHandlers[dirtyObject])(context, command)); + } + + mDirtyObjects &= ~dirtyObjects; + return angle::Result::Continue; +} + +} // namespace gl + +#endif // LIBANGLE_STATE_H_ |