| // |
| // Copyright 2015 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. |
| // |
| |
| // StateManagerGL.h: Defines a class for caching applied OpenGL state |
| |
| #ifndef LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_ |
| #define LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_ |
| |
| #include "common/debug.h" |
| #include "libANGLE/Error.h" |
| #include "libANGLE/State.h" |
| #include "libANGLE/angletypes.h" |
| #include "libANGLE/renderer/gl/functionsgl_typedefs.h" |
| #include "platform/FeaturesGL.h" |
| |
| #include <array> |
| #include <map> |
| |
| namespace gl |
| { |
| struct Caps; |
| class FramebufferState; |
| class State; |
| } // namespace gl |
| |
| namespace rx |
| { |
| |
| class FramebufferGL; |
| class FunctionsGL; |
| class TransformFeedbackGL; |
| class VertexArrayGL; |
| class QueryGL; |
| |
| // TODO(penghuang): use gl::State? |
| struct ExternalContextState |
| { |
| GLint packAlignment; |
| GLint unpackAlignment; |
| |
| GLenum vertexArrayBufferBinding; |
| GLenum elementArrayBufferBinding; |
| |
| bool depthTest; |
| bool cullFace; |
| GLenum cullFaceMode; |
| std::array<bool, 4> colorMask; |
| gl::ColorF colorClear; |
| gl::ColorF blendColor; |
| GLfloat depthClear; |
| GLenum currentProgram; |
| GLenum depthFunc; |
| bool depthMask; |
| GLfloat depthRage[2]; |
| GLenum frontFace; |
| GLfloat lineWidth; |
| GLfloat polygonOffsetFactor; |
| GLfloat polygonOffsetUnits; |
| GLfloat sampleCoverageValue; |
| bool sampleCoverageInvert; |
| GLenum blendEquationRgb; |
| GLenum blendEquationAlpha; |
| |
| bool enableDither; |
| bool enablePolygonOffsetFill; |
| bool enableSampleAlphaToCoverage; |
| bool enableSampleCoverage; |
| bool multisampleEnabled; |
| |
| bool blendEnabled; |
| GLenum blendSrcRgb; |
| GLenum blendSrcAlpha; |
| GLenum blendDestRgb; |
| GLenum blendDestAlpha; |
| GLenum activeTexture; |
| gl::Rectangle viewport; |
| bool scissorTest; |
| gl::Rectangle scissorBox; |
| |
| struct StencilState |
| { |
| bool stencilTestEnabled; |
| GLenum stencilFrontFunc; |
| GLint stencilFrontRef; |
| GLenum stencilFrontMask; |
| GLenum stencilBackFunc; |
| GLint stencilBackRef; |
| GLenum stencilBackMask; |
| GLint stencilClear; |
| GLenum stencilFrontWritemask; |
| GLenum stencilBackWritemask; |
| GLenum stencilFrontFailOp; |
| GLenum stencilFrontZFailOp; |
| GLenum stencilFrontZPassOp; |
| GLenum stencilBackFailOp; |
| GLenum stencilBackZFailOp; |
| GLenum stencilBackZPassOp; |
| }; |
| StencilState stencilState; |
| |
| GLenum framebufferBinding; |
| |
| struct TextureBindings |
| { |
| GLenum texture2d; |
| GLenum textureCubeMap; |
| GLenum textureExternalOES; |
| // TODO(boliu): TEXTURE_RECTANGLE_ARB |
| }; |
| std::vector<TextureBindings> textureBindings; |
| |
| GLenum vertexArrayBinding; |
| }; |
| |
| struct VertexAttributeGL |
| { |
| bool enabled = false; |
| const angle::Format *format = &angle::Format::Get(angle::FormatID::R32G32B32A32_FLOAT); |
| |
| const void *pointer = nullptr; |
| GLuint relativeOffset = 0; |
| |
| GLuint bindingIndex = 0; |
| }; |
| |
| struct VertexBindingGL |
| { |
| GLuint stride = 16; |
| GLuint divisor = 0; |
| GLintptr offset = 0; |
| |
| GLuint buffer = 0; |
| }; |
| |
| struct VertexArrayStateGL |
| { |
| VertexArrayStateGL(size_t maxAttribs, size_t maxBindings); |
| |
| GLuint elementArrayBuffer = 0; |
| |
| angle::FixedVector<VertexAttributeGL, gl::MAX_VERTEX_ATTRIBS> attributes; |
| angle::FixedVector<VertexBindingGL, gl::MAX_VERTEX_ATTRIBS> bindings; |
| }; |
| |
| class StateManagerGL final : angle::NonCopyable |
| { |
| public: |
| StateManagerGL(const FunctionsGL *functions, |
| const gl::Caps &rendererCaps, |
| const gl::Extensions &extensions, |
| const angle::FeaturesGL &features); |
| ~StateManagerGL(); |
| |
| void deleteProgram(GLuint program); |
| void deleteVertexArray(GLuint vao); |
| void deleteTexture(GLuint texture); |
| void deleteSampler(GLuint sampler); |
| void deleteBuffer(GLuint buffer); |
| void deleteFramebuffer(GLuint fbo); |
| void deleteRenderbuffer(GLuint rbo); |
| void deleteTransformFeedback(GLuint transformFeedback); |
| |
| void useProgram(GLuint program); |
| void forceUseProgram(GLuint program); |
| void bindVertexArray(GLuint vao, VertexArrayStateGL *vaoState); |
| void bindBuffer(gl::BufferBinding target, GLuint buffer); |
| void bindBufferBase(gl::BufferBinding target, size_t index, GLuint buffer); |
| void bindBufferRange(gl::BufferBinding target, |
| size_t index, |
| GLuint buffer, |
| size_t offset, |
| size_t size); |
| void activeTexture(size_t unit); |
| void bindTexture(gl::TextureType type, GLuint texture); |
| void invalidateTexture(gl::TextureType type); |
| void bindSampler(size_t unit, GLuint sampler); |
| void bindImageTexture(size_t unit, |
| GLuint texture, |
| GLint level, |
| GLboolean layered, |
| GLint layer, |
| GLenum access, |
| GLenum format); |
| void bindFramebuffer(GLenum type, GLuint framebuffer); |
| void bindRenderbuffer(GLenum type, GLuint renderbuffer); |
| void bindTransformFeedback(GLenum type, GLuint transformFeedback); |
| void onTransformFeedbackStateChange(); |
| void beginQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId); |
| void endQuery(gl::QueryType type, QueryGL *queryObject, GLuint queryId); |
| |
| void setAttributeCurrentData(size_t index, const gl::VertexAttribCurrentValueData &data); |
| |
| void setScissorTestEnabled(bool enabled); |
| void setScissor(const gl::Rectangle &scissor); |
| |
| void setViewport(const gl::Rectangle &viewport); |
| void setDepthRange(float near, float far); |
| |
| void setBlendEnabled(bool enabled); |
| void setBlendEnabledIndexed(const gl::DrawBufferMask blendEnabledMask); |
| void setBlendColor(const gl::ColorF &blendColor); |
| void setBlendFuncs(const gl::BlendStateExt &blendStateExt); |
| void setBlendEquations(const gl::BlendStateExt &blendStateExt); |
| void setColorMask(bool red, bool green, bool blue, bool alpha); |
| void setSampleAlphaToCoverageEnabled(bool enabled); |
| void setSampleCoverageEnabled(bool enabled); |
| void setSampleCoverage(float value, bool invert); |
| void setSampleMaskEnabled(bool enabled); |
| void setSampleMaski(GLuint maskNumber, GLbitfield mask); |
| |
| void setDepthTestEnabled(bool enabled); |
| void setDepthFunc(GLenum depthFunc); |
| void setDepthMask(bool mask); |
| void setStencilTestEnabled(bool enabled); |
| void setStencilFrontWritemask(GLuint mask); |
| void setStencilBackWritemask(GLuint mask); |
| void setStencilFrontFuncs(GLenum func, GLint ref, GLuint mask); |
| void setStencilBackFuncs(GLenum func, GLint ref, GLuint mask); |
| void setStencilFrontOps(GLenum sfail, GLenum dpfail, GLenum dppass); |
| void setStencilBackOps(GLenum sfail, GLenum dpfail, GLenum dppass); |
| |
| void setCullFaceEnabled(bool enabled); |
| void setCullFace(gl::CullFaceMode cullFace); |
| void setFrontFace(GLenum frontFace); |
| void setPolygonOffsetFillEnabled(bool enabled); |
| void setPolygonOffset(float factor, float units); |
| void setRasterizerDiscardEnabled(bool enabled); |
| void setLineWidth(float width); |
| |
| angle::Result setPrimitiveRestartEnabled(const gl::Context *context, bool enabled); |
| angle::Result setPrimitiveRestartIndex(const gl::Context *context, GLuint index); |
| |
| void setClearColor(const gl::ColorF &clearColor); |
| void setClearDepth(float clearDepth); |
| void setClearStencil(GLint clearStencil); |
| |
| angle::Result setPixelUnpackState(const gl::Context *context, |
| const gl::PixelUnpackState &unpack); |
| angle::Result setPixelUnpackBuffer(const gl::Context *context, const gl::Buffer *pixelBuffer); |
| angle::Result setPixelPackState(const gl::Context *context, const gl::PixelPackState &pack); |
| angle::Result setPixelPackBuffer(const gl::Context *context, const gl::Buffer *pixelBuffer); |
| |
| void setFramebufferSRGBEnabled(const gl::Context *context, bool enabled); |
| void setFramebufferSRGBEnabledForFramebuffer(const gl::Context *context, |
| bool enabled, |
| const FramebufferGL *framebuffer); |
| void setColorMaskForFramebuffer(const gl::BlendStateExt &blendStateExt, |
| const bool disableAlpha); |
| |
| void setDitherEnabled(bool enabled); |
| |
| void setMultisamplingStateEnabled(bool enabled); |
| void setSampleAlphaToOneStateEnabled(bool enabled); |
| |
| void setCoverageModulation(GLenum components); |
| |
| void setProvokingVertex(GLenum mode); |
| |
| void setClipDistancesEnable(const gl::State::ClipDistanceEnableBits &enables); |
| |
| void pauseTransformFeedback(); |
| angle::Result pauseAllQueries(const gl::Context *context); |
| angle::Result pauseQuery(const gl::Context *context, gl::QueryType type); |
| angle::Result resumeAllQueries(const gl::Context *context); |
| angle::Result resumeQuery(const gl::Context *context, gl::QueryType type); |
| angle::Result onMakeCurrent(const gl::Context *context); |
| |
| angle::Result syncState(const gl::Context *context, |
| const gl::State::DirtyBits &glDirtyBits, |
| const gl::State::DirtyBits &bitMask); |
| |
| ANGLE_INLINE void updateMultiviewBaseViewLayerIndexUniform( |
| const gl::Program *program, |
| const gl::FramebufferState &drawFramebufferState) const |
| { |
| if (mIsMultiviewEnabled && program && program->usesMultiview()) |
| { |
| updateMultiviewBaseViewLayerIndexUniformImpl(program, drawFramebufferState); |
| } |
| } |
| |
| GLuint getProgramID() const { return mProgram; } |
| GLuint getVertexArrayID() const { return mVAO; } |
| GLuint getFramebufferID(angle::FramebufferBinding binding) const |
| { |
| return mFramebuffers[binding]; |
| } |
| GLuint getBufferID(gl::BufferBinding binding) const { return mBuffers[binding]; } |
| |
| bool getHasSeparateFramebufferBindings() const { return mHasSeparateFramebufferBindings; } |
| |
| GLuint getDefaultVAO() const; |
| VertexArrayStateGL *getDefaultVAOState(); |
| void setDefaultVAOStateDirty(); |
| |
| void validateState() const; |
| |
| void syncFromNativeContext(const gl::Extensions &extensions, ExternalContextState *state); |
| void restoreNativeContext(const gl::Extensions &extensions, const ExternalContextState *state); |
| |
| private: |
| void setTextureCubemapSeamlessEnabled(bool enabled); |
| |
| angle::Result propagateProgramToVAO(const gl::Context *context, |
| const gl::Program *program, |
| VertexArrayGL *vao); |
| |
| void updateProgramTextureBindings(const gl::Context *context); |
| void updateProgramStorageBufferBindings(const gl::Context *context); |
| void updateProgramUniformBufferBindings(const gl::Context *context); |
| void updateProgramAtomicCounterBufferBindings(const gl::Context *context); |
| void updateProgramImageBindings(const gl::Context *context); |
| |
| void updateDispatchIndirectBufferBinding(const gl::Context *context); |
| void updateDrawIndirectBufferBinding(const gl::Context *context); |
| |
| template <typename T> |
| void get(GLenum name, T *value); |
| |
| template <size_t n, typename T> |
| void get(GLenum name, std::array<T, n> *values); |
| |
| void syncSamplersState(const gl::Context *context); |
| void syncTransformFeedbackState(const gl::Context *context); |
| |
| void updateMultiviewBaseViewLayerIndexUniformImpl( |
| const gl::Program *program, |
| const gl::FramebufferState &drawFramebufferState) const; |
| |
| void syncBlendFromNativeContext(const gl::Extensions &extensions, ExternalContextState *state); |
| void restoreBlendNativeContext(const gl::Extensions &extensions, |
| const ExternalContextState *state); |
| |
| void syncFramebufferFromNativeContext(const gl::Extensions &extensions, |
| ExternalContextState *state); |
| void restoreFramebufferNativeContext(const gl::Extensions &extensions, |
| const ExternalContextState *state); |
| |
| void syncPixelPackUnpackFromNativeContext(const gl::Extensions &extensions, |
| ExternalContextState *state); |
| void restorePixelPackUnpackNativeContext(const gl::Extensions &extensions, |
| const ExternalContextState *state); |
| |
| void syncStencilFromNativeContext(const gl::Extensions &extensions, |
| ExternalContextState *state); |
| void restoreStencilNativeContext(const gl::Extensions &extensions, |
| const ExternalContextState *state); |
| |
| void syncBufferBindingsFromNativeContext(const gl::Extensions &extensions, |
| ExternalContextState *state); |
| void restoreBufferBindingsNativeContext(const gl::Extensions &extensions, |
| const ExternalContextState *state); |
| |
| void syncTextureUnitsFromNativeContext(const gl::Extensions &extensions, |
| ExternalContextState *state); |
| void restoreTextureUnitsNativeContext(const gl::Extensions &extensions, |
| const ExternalContextState *state); |
| |
| void syncVertexArraysFromNativeContext(const gl::Extensions &extensions, |
| ExternalContextState *state); |
| void restoreVertexArraysNativeContext(const gl::Extensions &extensions, |
| const ExternalContextState *state); |
| |
| const FunctionsGL *mFunctions; |
| const angle::FeaturesGL &mFeatures; |
| |
| GLuint mProgram; |
| |
| GLuint mVAO; |
| std::vector<gl::VertexAttribCurrentValueData> mVertexAttribCurrentValues; |
| |
| GLuint mDefaultVAO = 0; |
| // The current state of the default VAO is owned by StateManagerGL. It may be shared between |
| // multiple VertexArrayGL objects if the native driver does not support vertex array objects. |
| // When this object is shared, StateManagerGL forces VertexArrayGL to resynchronize itself every |
| // time a new vertex array is bound. |
| VertexArrayStateGL mDefaultVAOState; |
| |
| // The state of the currently bound vertex array object so StateManagerGL can know about the |
| // current element array buffer. |
| VertexArrayStateGL *mVAOState = nullptr; |
| |
| angle::PackedEnumMap<gl::BufferBinding, GLuint> mBuffers; |
| |
| struct IndexedBufferBinding |
| { |
| IndexedBufferBinding(); |
| |
| size_t offset; |
| size_t size; |
| GLuint buffer; |
| }; |
| angle::PackedEnumMap<gl::BufferBinding, std::vector<IndexedBufferBinding>> mIndexedBuffers; |
| |
| size_t mTextureUnitIndex; |
| angle::PackedEnumMap<gl::TextureType, gl::ActiveTextureArray<GLuint>> mTextures; |
| gl::ActiveTextureArray<GLuint> mSamplers; |
| |
| struct ImageUnitBinding |
| { |
| ImageUnitBinding() |
| : texture(0), level(0), layered(false), layer(0), access(GL_READ_ONLY), format(GL_R32UI) |
| {} |
| |
| GLuint texture; |
| GLint level; |
| GLboolean layered; |
| GLint layer; |
| GLenum access; |
| GLenum format; |
| }; |
| std::vector<ImageUnitBinding> mImages; |
| |
| GLuint mTransformFeedback; |
| TransformFeedbackGL *mCurrentTransformFeedback; |
| |
| // Queries that are currently running on the driver |
| angle::PackedEnumMap<gl::QueryType, QueryGL *> mQueries; |
| |
| // Queries that are temporarily in the paused state so that their results will not be affected |
| // by other operations |
| angle::PackedEnumMap<gl::QueryType, QueryGL *> mTemporaryPausedQueries; |
| |
| gl::ContextID mPrevDrawContext; |
| |
| GLint mUnpackAlignment; |
| GLint mUnpackRowLength; |
| GLint mUnpackSkipRows; |
| GLint mUnpackSkipPixels; |
| GLint mUnpackImageHeight; |
| GLint mUnpackSkipImages; |
| |
| GLint mPackAlignment; |
| GLint mPackRowLength; |
| GLint mPackSkipRows; |
| GLint mPackSkipPixels; |
| |
| // TODO(jmadill): Convert to std::array when available |
| std::vector<GLenum> mFramebuffers; |
| GLuint mRenderbuffer; |
| |
| bool mScissorTestEnabled; |
| gl::Rectangle mScissor; |
| gl::Rectangle mViewport; |
| float mNear; |
| float mFar; |
| |
| gl::ColorF mBlendColor; |
| gl::BlendStateExt mBlendStateExt; |
| const bool mIndependentBlendStates; |
| |
| bool mSampleAlphaToCoverageEnabled; |
| bool mSampleCoverageEnabled; |
| float mSampleCoverageValue; |
| bool mSampleCoverageInvert; |
| bool mSampleMaskEnabled; |
| std::array<GLbitfield, gl::MAX_SAMPLE_MASK_WORDS> mSampleMaskValues; |
| |
| bool mDepthTestEnabled; |
| GLenum mDepthFunc; |
| bool mDepthMask; |
| bool mStencilTestEnabled; |
| GLenum mStencilFrontFunc; |
| GLint mStencilFrontRef; |
| GLuint mStencilFrontValueMask; |
| GLenum mStencilFrontStencilFailOp; |
| GLenum mStencilFrontStencilPassDepthFailOp; |
| GLenum mStencilFrontStencilPassDepthPassOp; |
| GLuint mStencilFrontWritemask; |
| GLenum mStencilBackFunc; |
| GLint mStencilBackRef; |
| GLuint mStencilBackValueMask; |
| GLenum mStencilBackStencilFailOp; |
| GLenum mStencilBackStencilPassDepthFailOp; |
| GLenum mStencilBackStencilPassDepthPassOp; |
| GLuint mStencilBackWritemask; |
| |
| bool mCullFaceEnabled; |
| gl::CullFaceMode mCullFace; |
| GLenum mFrontFace; |
| bool mPolygonOffsetFillEnabled; |
| GLfloat mPolygonOffsetFactor; |
| GLfloat mPolygonOffsetUnits; |
| bool mRasterizerDiscardEnabled; |
| float mLineWidth; |
| |
| bool mPrimitiveRestartEnabled; |
| GLuint mPrimitiveRestartIndex; |
| |
| gl::ColorF mClearColor; |
| float mClearDepth; |
| GLint mClearStencil; |
| |
| bool mFramebufferSRGBAvailable; |
| bool mFramebufferSRGBEnabled; |
| const bool mHasSeparateFramebufferBindings; |
| |
| bool mDitherEnabled; |
| bool mTextureCubemapSeamlessEnabled; |
| |
| bool mMultisamplingEnabled; |
| bool mSampleAlphaToOneEnabled; |
| |
| GLenum mCoverageModulation; |
| |
| const bool mIsMultiviewEnabled; |
| |
| GLenum mProvokingVertex; |
| |
| gl::State::ClipDistanceEnableBits mEnabledClipDistances; |
| const size_t mMaxClipDistances; |
| |
| gl::State::DirtyBits mLocalDirtyBits; |
| gl::AttributesMask mLocalDirtyCurrentValues; |
| }; |
| |
| } // namespace rx |
| |
| #endif // LIBANGLE_RENDERER_GL_STATEMANAGERGL_H_ |