diff options
Diffstat (limited to '')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/Context.h | 901 |
1 files changed, 901 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/Context.h b/gfx/angle/checkout/src/libANGLE/Context.h new file mode 100644 index 0000000000..fec6a6653c --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/Context.h @@ -0,0 +1,901 @@ +// +// Copyright 2002 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. +// + +// Context.h: Defines the gl::Context class, managing all GL state and performing +// rendering operations. It is the GLES2 specific implementation of EGLContext. + +#ifndef LIBANGLE_CONTEXT_H_ +#define LIBANGLE_CONTEXT_H_ + +#include <mutex> +#include <set> +#include <string> + +#include "angle_gl.h" +#include "common/MemoryBuffer.h" +#include "common/PackedEnums.h" +#include "common/angleutils.h" +#include "libANGLE/Caps.h" +#include "libANGLE/Constants.h" +#include "libANGLE/Context_gl_1_autogen.h" +#include "libANGLE/Context_gl_2_autogen.h" +#include "libANGLE/Context_gl_3_autogen.h" +#include "libANGLE/Context_gl_4_autogen.h" +#include "libANGLE/Context_gles_1_0_autogen.h" +#include "libANGLE/Context_gles_2_0_autogen.h" +#include "libANGLE/Context_gles_3_0_autogen.h" +#include "libANGLE/Context_gles_3_1_autogen.h" +#include "libANGLE/Context_gles_3_2_autogen.h" +#include "libANGLE/Context_gles_ext_autogen.h" +#include "libANGLE/Error.h" +#include "libANGLE/Framebuffer.h" +#include "libANGLE/HandleAllocator.h" +#include "libANGLE/RefCountObject.h" +#include "libANGLE/ResourceManager.h" +#include "libANGLE/ResourceMap.h" +#include "libANGLE/State.h" +#include "libANGLE/VertexAttribute.h" +#include "libANGLE/WorkerThread.h" +#include "libANGLE/angletypes.h" + +namespace angle +{ +class FrameCapture; +class FrameCaptureShared; +struct FrontendFeatures; +} // namespace angle + +namespace rx +{ +class ContextImpl; +class EGLImplFactory; +} // namespace rx + +namespace egl +{ +class AttributeMap; +class Surface; +struct Config; +class Thread; +} // namespace egl + +namespace gl +{ +class Buffer; +class Compiler; +class FenceNV; +class GLES1Renderer; +class MemoryProgramCache; +class MemoryShaderCache; +class MemoryObject; +class Program; +class ProgramPipeline; +class Query; +class Renderbuffer; +class Sampler; +class Semaphore; +class Shader; +class Sync; +class Texture; +class TransformFeedback; +class VertexArray; +struct VertexAttribute; + +class ErrorSet : angle::NonCopyable +{ + public: + explicit ErrorSet(Context *context); + ~ErrorSet(); + + bool empty() const; + GLenum popError(); + + void handleError(GLenum errorCode, + const char *message, + const char *file, + const char *function, + unsigned int line); + + void validationError(angle::EntryPoint entryPoint, GLenum errorCode, const char *message); + + private: + Context *mContext; + std::set<GLenum> mErrors; +}; + +enum class VertexAttribTypeCase +{ + Invalid = 0, + Valid = 1, + ValidSize4Only = 2, + ValidSize3or4 = 3, +}; + +// Helper class for managing cache variables and state changes. +class StateCache final : angle::NonCopyable +{ + public: + StateCache(); + ~StateCache(); + + void initialize(Context *context); + + // Places that can trigger updateActiveAttribsMask: + // 1. onVertexArrayBindingChange. + // 2. onProgramExecutableChange. + // 3. onVertexArrayStateChange. + // 4. onGLES1ClientStateChange. + AttributesMask getActiveBufferedAttribsMask() const { return mCachedActiveBufferedAttribsMask; } + AttributesMask getActiveClientAttribsMask() const { return mCachedActiveClientAttribsMask; } + AttributesMask getActiveDefaultAttribsMask() const { return mCachedActiveDefaultAttribsMask; } + bool hasAnyEnabledClientAttrib() const { return mCachedHasAnyEnabledClientAttrib; } + bool hasAnyActiveClientAttrib() const { return mCachedActiveClientAttribsMask.any(); } + + // Places that can trigger updateVertexElementLimits: + // 1. onVertexArrayBindingChange. + // 2. onProgramExecutableChange. + // 3. onVertexArrayFormatChange. + // 4. onVertexArrayBufferChange. + // 5. onVertexArrayStateChange. + GLint64 getNonInstancedVertexElementLimit() const + { + return mCachedNonInstancedVertexElementLimit; + } + GLint64 getInstancedVertexElementLimit() const { return mCachedInstancedVertexElementLimit; } + + // Places that can trigger updateBasicDrawStatesError: + // 1. onVertexArrayBindingChange. + // 2. onProgramExecutableChange. + // 3. onVertexArrayBufferContentsChange. + // 4. onVertexArrayStateChange. + // 5. onVertexArrayBufferStateChange. + // 6. onDrawFramebufferChange. + // 7. onContextCapChange. + // 8. onStencilStateChange. + // 9. onDefaultVertexAttributeChange. + // 10. onActiveTextureChange. + // 11. onQueryChange. + // 12. onActiveTransformFeedbackChange. + // 13. onUniformBufferStateChange. + // 14. onColorMaskChange. + // 15. onBufferBindingChange. + // 16. onBlendFuncIndexedChange. + bool hasBasicDrawStatesError(Context *context) const + { + if (mCachedBasicDrawStatesError == 0) + { + return false; + } + if (mCachedBasicDrawStatesError != kInvalidPointer) + { + return true; + } + return getBasicDrawStatesErrorImpl(context) != 0; + } + + intptr_t getBasicDrawStatesError(const Context *context) const + { + if (mCachedBasicDrawStatesError != kInvalidPointer) + { + return mCachedBasicDrawStatesError; + } + + return getBasicDrawStatesErrorImpl(context); + } + + // Places that can trigger updateProgramPipelineError: + // 1. onProgramExecutableChange. + intptr_t getProgramPipelineError(const Context *context) const + { + if (mCachedProgramPipelineError != kInvalidPointer) + { + return mCachedProgramPipelineError; + } + + return getProgramPipelineErrorImpl(context); + } + + // Places that can trigger updateBasicDrawElementsError: + // 1. onActiveTransformFeedbackChange. + // 2. onVertexArrayBufferStateChange. + // 3. onBufferBindingChange. + // 4. onVertexArrayStateChange. + // 5. onVertexArrayBindingStateChange. + intptr_t getBasicDrawElementsError(const Context *context) const + { + if (mCachedBasicDrawElementsError != kInvalidPointer) + { + return mCachedBasicDrawElementsError; + } + + return getBasicDrawElementsErrorImpl(context); + } + + // Places that can trigger updateValidDrawModes: + // 1. onProgramExecutableChange. + // 2. onActiveTransformFeedbackChange. + bool isValidDrawMode(PrimitiveMode primitiveMode) const + { + return mCachedValidDrawModes[primitiveMode]; + } + + // Cannot change except on Context/Extension init. + bool isValidBindTextureType(TextureType type) const + { + return mCachedValidBindTextureTypes[type]; + } + + // Cannot change except on Context/Extension init. + bool isValidDrawElementsType(DrawElementsType type) const + { + return mCachedValidDrawElementsTypes[type]; + } + + // Places that can trigger updateTransformFeedbackActiveUnpaused: + // 1. onActiveTransformFeedbackChange. + bool isTransformFeedbackActiveUnpaused() const + { + return mCachedTransformFeedbackActiveUnpaused; + } + + // Cannot change except on Context/Extension init. + VertexAttribTypeCase getVertexAttribTypeValidation(VertexAttribType type) const + { + return mCachedVertexAttribTypesValidation[type]; + } + + VertexAttribTypeCase getIntegerVertexAttribTypeValidation(VertexAttribType type) const + { + return mCachedIntegerVertexAttribTypesValidation[type]; + } + + // Places that can trigger updateActiveShaderStorageBufferIndices: + // 1. onProgramExecutableChange. + StorageBuffersMask getActiveShaderStorageBufferIndices() const + { + return mCachedActiveShaderStorageBufferIndices; + } + + // Places that can trigger updateActiveImageUnitIndices: + // 1. onProgramExecutableChange. + const ImageUnitMask &getActiveImageUnitIndices() const { return mCachedActiveImageUnitIndices; } + + // Places that can trigger updateCanDraw: + // 1. onProgramExecutableChange. + bool getCanDraw() const { return mCachedCanDraw; } + + // State change notifications. + void onVertexArrayBindingChange(Context *context); + void onProgramExecutableChange(Context *context); + void onVertexArrayFormatChange(Context *context); + void onVertexArrayBufferContentsChange(Context *context); + void onVertexArrayStateChange(Context *context); + void onVertexArrayBufferStateChange(Context *context); + void onGLES1ClientStateChange(Context *context); + void onDrawFramebufferChange(Context *context); + void onContextCapChange(Context *context); + void onStencilStateChange(Context *context); + void onDefaultVertexAttributeChange(Context *context); + void onActiveTextureChange(Context *context); + void onQueryChange(Context *context); + void onActiveTransformFeedbackChange(Context *context); + void onUniformBufferStateChange(Context *context); + void onAtomicCounterBufferStateChange(Context *context); + void onShaderStorageBufferStateChange(Context *context); + void onColorMaskChange(Context *context); + void onBufferBindingChange(Context *context); + void onBlendFuncIndexedChange(Context *context); + void onBlendEquationChange(Context *context); + + private: + // Cache update functions. + void updateActiveAttribsMask(Context *context); + void updateVertexElementLimits(Context *context); + void updateVertexElementLimitsImpl(Context *context); + void updateValidDrawModes(Context *context); + void updateValidBindTextureTypes(Context *context); + void updateValidDrawElementsTypes(Context *context); + void updateBasicDrawStatesError(); + void updateProgramPipelineError(); + void updateBasicDrawElementsError(); + void updateTransformFeedbackActiveUnpaused(Context *context); + void updateVertexAttribTypesValidation(Context *context); + void updateActiveShaderStorageBufferIndices(Context *context); + void updateActiveImageUnitIndices(Context *context); + void updateCanDraw(Context *context); + + void setValidDrawModes(bool pointsOK, + bool linesOK, + bool trisOK, + bool lineAdjOK, + bool triAdjOK, + bool patchOK); + + intptr_t getBasicDrawStatesErrorImpl(const Context *context) const; + intptr_t getProgramPipelineErrorImpl(const Context *context) const; + intptr_t getBasicDrawElementsErrorImpl(const Context *context) const; + + static constexpr intptr_t kInvalidPointer = 1; + + AttributesMask mCachedActiveBufferedAttribsMask; + AttributesMask mCachedActiveClientAttribsMask; + AttributesMask mCachedActiveDefaultAttribsMask; + bool mCachedHasAnyEnabledClientAttrib; + GLint64 mCachedNonInstancedVertexElementLimit; + GLint64 mCachedInstancedVertexElementLimit; + mutable intptr_t mCachedBasicDrawStatesError; + mutable intptr_t mCachedBasicDrawElementsError; + // mCachedProgramPipelineError checks only the + // current-program-exists subset of mCachedBasicDrawStatesError. + // Therefore, mCachedProgramPipelineError follows + // mCachedBasicDrawStatesError in that if mCachedBasicDrawStatesError is + // no-error, so is mCachedProgramPipelineError. Otherwise, if + // mCachedBasicDrawStatesError is in error, the state of + // mCachedProgramPipelineError can be no-error or also in error, or + // unknown due to early exiting. + mutable intptr_t mCachedProgramPipelineError; + bool mCachedTransformFeedbackActiveUnpaused; + StorageBuffersMask mCachedActiveShaderStorageBufferIndices; + ImageUnitMask mCachedActiveImageUnitIndices; + + // Reserve an extra slot at the end of these maps for invalid enum. + angle::PackedEnumMap<PrimitiveMode, bool, angle::EnumSize<PrimitiveMode>() + 1> + mCachedValidDrawModes; + angle::PackedEnumMap<TextureType, bool, angle::EnumSize<TextureType>() + 1> + mCachedValidBindTextureTypes; + angle::PackedEnumMap<DrawElementsType, bool, angle::EnumSize<DrawElementsType>() + 1> + mCachedValidDrawElementsTypes; + angle::PackedEnumMap<VertexAttribType, + VertexAttribTypeCase, + angle::EnumSize<VertexAttribType>() + 1> + mCachedVertexAttribTypesValidation; + angle::PackedEnumMap<VertexAttribType, + VertexAttribTypeCase, + angle::EnumSize<VertexAttribType>() + 1> + mCachedIntegerVertexAttribTypesValidation; + + bool mCachedCanDraw; +}; + +using VertexArrayMap = ResourceMap<VertexArray, VertexArrayID>; +using QueryMap = ResourceMap<Query, QueryID>; +using TransformFeedbackMap = ResourceMap<TransformFeedback, TransformFeedbackID>; + +class Context final : public egl::LabeledObject, angle::NonCopyable, public angle::ObserverInterface +{ + public: + Context(egl::Display *display, + const egl::Config *config, + const Context *shareContext, + TextureManager *shareTextures, + SemaphoreManager *shareSemaphores, + MemoryProgramCache *memoryProgramCache, + MemoryShaderCache *memoryShaderCache, + const EGLenum clientType, + const egl::AttributeMap &attribs, + const egl::DisplayExtensions &displayExtensions, + const egl::ClientExtensions &clientExtensions); + + // Use for debugging. + ContextID id() const { return mState.getContextID(); } + + egl::Error initialize(); + + egl::Error onDestroy(const egl::Display *display); + ~Context() override; + + void setLabel(EGLLabelKHR label) override; + EGLLabelKHR getLabel() const override; + + egl::Error makeCurrent(egl::Display *display, + egl::Surface *drawSurface, + egl::Surface *readSurface); + egl::Error unMakeCurrent(const egl::Display *display); + + // These create and destroy methods pass through to ResourceManager, which owns these objects. + BufferID createBuffer(); + TextureID createTexture(); + RenderbufferID createRenderbuffer(); + ProgramPipelineID createProgramPipeline(); + MemoryObjectID createMemoryObject(); + SemaphoreID createSemaphore(); + + void deleteBuffer(BufferID buffer); + void deleteTexture(TextureID texture); + void deleteRenderbuffer(RenderbufferID renderbuffer); + void deleteProgramPipeline(ProgramPipelineID pipeline); + void deleteMemoryObject(MemoryObjectID memoryObject); + void deleteSemaphore(SemaphoreID semaphore); + + void bindReadFramebuffer(FramebufferID framebufferHandle); + void bindDrawFramebuffer(FramebufferID framebufferHandle); + + Buffer *getBuffer(BufferID handle) const; + FenceNV *getFenceNV(FenceNVID handle) const; + Sync *getSync(GLsync handle) const; + ANGLE_INLINE Texture *getTexture(TextureID handle) const + { + return mState.mTextureManager->getTexture(handle); + } + + Framebuffer *getFramebuffer(FramebufferID handle) const; + Renderbuffer *getRenderbuffer(RenderbufferID handle) const; + VertexArray *getVertexArray(VertexArrayID handle) const; + Sampler *getSampler(SamplerID handle) const; + Query *getOrCreateQuery(QueryID handle, QueryType type); + Query *getQuery(QueryID handle) const; + TransformFeedback *getTransformFeedback(TransformFeedbackID handle) const; + ProgramPipeline *getProgramPipeline(ProgramPipelineID handle) const; + MemoryObject *getMemoryObject(MemoryObjectID handle) const; + Semaphore *getSemaphore(SemaphoreID handle) const; + + Texture *getTextureByType(TextureType type) const; + Texture *getTextureByTarget(TextureTarget target) const; + Texture *getSamplerTexture(unsigned int sampler, TextureType type) const; + + Compiler *getCompiler() const; + + bool isVertexArrayGenerated(VertexArrayID vertexArray) const; + bool isTransformFeedbackGenerated(TransformFeedbackID transformFeedback) const; + + bool isExternal() const { return mIsExternal; } + bool saveAndRestoreState() const { return mSaveAndRestoreState; } + + void getBooleanvImpl(GLenum pname, GLboolean *params) const; + void getFloatvImpl(GLenum pname, GLfloat *params) const; + void getIntegervImpl(GLenum pname, GLint *params) const; + void getInteger64vImpl(GLenum pname, GLint64 *params) const; + void getIntegerVertexAttribImpl(GLenum pname, GLenum attribpname, GLint *params) const; + void getVertexAttribivImpl(GLuint index, GLenum pname, GLint *params) const; + + // Framebuffers are owned by the Context, so these methods do not pass through + FramebufferID createFramebuffer(); + void deleteFramebuffer(FramebufferID framebuffer); + + bool hasActiveTransformFeedback(ShaderProgramID program) const; + + // Desktop GL entry point interface + ANGLE_GL_1_CONTEXT_API + ANGLE_GL_2_CONTEXT_API + ANGLE_GL_3_CONTEXT_API + ANGLE_GL_4_CONTEXT_API + + // GLES entry point interface + ANGLE_GLES_1_0_CONTEXT_API + ANGLE_GLES_2_0_CONTEXT_API + ANGLE_GLES_3_0_CONTEXT_API + ANGLE_GLES_3_1_CONTEXT_API + ANGLE_GLES_3_2_CONTEXT_API + ANGLE_GLES_EXT_CONTEXT_API + + angle::Result handleNoopDrawEvent(); + + // Consumes an error. + void handleError(GLenum errorCode, + const char *message, + const char *file, + const char *function, + unsigned int line); + + void validationError(angle::EntryPoint entryPoint, GLenum errorCode, const char *message) const; + ANGLE_FORMAT_PRINTF(4, 5) + void validationErrorF(angle::EntryPoint entryPoint, + GLenum errorCode, + const char *format, + ...) const; + + void markContextLost(GraphicsResetStatus status); + + bool isContextLost() const { return mContextLost; } + void setContextLost(); + + GLenum getGraphicsResetStrategy() const { return mResetStrategy; } + bool isResetNotificationEnabled() const; + + bool isRobustnessEnabled() const; + + const egl::Config *getConfig() const; + EGLenum getClientType() const; + EGLenum getRenderBuffer() const; + EGLenum getContextPriority() const; + + const GLubyte *getString(GLenum name) const; + const GLubyte *getStringi(GLenum name, GLuint index) const; + + size_t getExtensionStringCount() const; + + bool isExtensionRequestable(const char *name) const; + bool isExtensionDisablable(const char *name) const; + size_t getRequestableExtensionStringCount() const; + void setExtensionEnabled(const char *name, bool enabled); + void reinitializeAfterExtensionsChanged(); + + rx::ContextImpl *getImplementation() const { return mImplementation.get(); } + + [[nodiscard]] bool getScratchBuffer(size_t requestedSizeBytes, + angle::MemoryBuffer **scratchBufferOut) const; + [[nodiscard]] bool getZeroFilledBuffer(size_t requstedSizeBytes, + angle::MemoryBuffer **zeroBufferOut) const; + angle::ScratchBuffer *getScratchBuffer() const; + + angle::Result prepareForCopyImage(); + angle::Result prepareForDispatch(); + angle::Result prepareForInvalidate(GLenum target); + + MemoryProgramCache *getMemoryProgramCache() const { return mMemoryProgramCache; } + MemoryShaderCache *getMemoryShaderCache() const { return mMemoryShaderCache; } + + std::mutex &getProgramCacheMutex() const; + + bool hasBeenCurrent() const { return mHasBeenCurrent; } + egl::Display *getDisplay() const { return mDisplay; } + egl::Surface *getCurrentDrawSurface() const { return mCurrentDrawSurface; } + egl::Surface *getCurrentReadSurface() const { return mCurrentReadSurface; } + + bool isRobustResourceInitEnabled() const { return mState.isRobustResourceInitEnabled(); } + + bool isCurrentTransformFeedback(const TransformFeedback *tf) const; + + bool isCurrentVertexArray(const VertexArray *va) const + { + return mState.isCurrentVertexArray(va); + } + + ANGLE_INLINE bool isShared() const { return mShared; } + // Once a context is setShared() it cannot be undone + void setShared() { mShared = true; } + + const State &getState() const { return mState; } + GLint getClientMajorVersion() const { return mState.getClientMajorVersion(); } + GLint getClientMinorVersion() const { return mState.getClientMinorVersion(); } + const Version &getClientVersion() const { return mState.getClientVersion(); } + const Caps &getCaps() const { return mState.getCaps(); } + const TextureCapsMap &getTextureCaps() const { return mState.getTextureCaps(); } + const Extensions &getExtensions() const { return mState.getExtensions(); } + const Limitations &getLimitations() const { return mState.getLimitations(); } + bool isGLES1() const; + + bool skipValidation() const + { + // Ensure we don't skip validation when context becomes lost, since implementations + // generally assume a non-lost context, non-null objects, etc. + ASSERT(!isContextLost() || !mSkipValidation); + return mSkipValidation; + } + + // Specific methods needed for validation. + bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams) const; + bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams) const; + + ANGLE_INLINE Program *getProgramResolveLink(ShaderProgramID handle) const + { + Program *program = mState.mShaderProgramManager->getProgram(handle); + if (program) + { + program->resolveLink(this); + } + return program; + } + + Program *getProgramNoResolveLink(ShaderProgramID handle) const; + Shader *getShader(ShaderProgramID handle) const; + + ANGLE_INLINE bool isTextureGenerated(TextureID texture) const + { + return mState.mTextureManager->isHandleGenerated(texture); + } + + ANGLE_INLINE bool isBufferGenerated(BufferID buffer) const + { + return mState.mBufferManager->isHandleGenerated(buffer); + } + + bool isRenderbufferGenerated(RenderbufferID renderbuffer) const; + bool isFramebufferGenerated(FramebufferID framebuffer) const; + bool isProgramPipelineGenerated(ProgramPipelineID pipeline) const; + bool isQueryGenerated(QueryID query) const; + + bool usingDisplayTextureShareGroup() const; + bool usingDisplaySemaphoreShareGroup() const; + + // Hack for the special WebGL 1 "DEPTH_STENCIL" internal format. + GLenum getConvertedRenderbufferFormat(GLenum internalformat) const; + + bool isWebGL() const { return mState.isWebGL(); } + bool isWebGL1() const { return mState.isWebGL1(); } + + bool isValidBufferBinding(BufferBinding binding) const { return mValidBufferBindings[binding]; } + + // GLES1 emulation: Renderer level (for validation) + int vertexArrayIndex(ClientVertexArrayType type) const; + static int TexCoordArrayIndex(unsigned int unit); + + // GL_KHR_parallel_shader_compile + std::shared_ptr<angle::WorkerThreadPool> getShaderCompileThreadPool() const + { + if (mState.mExtensions.parallelShaderCompileKHR) + { + return mMultiThreadPool; + } + return mSingleThreadPool; + } + + // Generic multithread pool. + std::shared_ptr<angle::WorkerThreadPool> getWorkerThreadPool() const + { + return mMultiThreadPool; + } + + const StateCache &getStateCache() const { return mStateCache; } + StateCache &getStateCache() { return mStateCache; } + + void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; + + void onSamplerUniformChange(size_t textureUnitIndex); + + bool isBufferAccessValidationEnabled() const { return mBufferAccessValidationEnabled; } + + const angle::FrontendFeatures &getFrontendFeatures() const; + + angle::FrameCapture *getFrameCapture() const { return mFrameCapture.get(); } + + const VertexArrayMap &getVertexArraysForCapture() const { return mVertexArrayMap; } + const QueryMap &getQueriesForCapture() const { return mQueryMap; } + const TransformFeedbackMap &getTransformFeedbacksForCapture() const + { + return mTransformFeedbackMap; + } + + void onPreSwap() const; + + Program *getActiveLinkedProgram() const; + + // EGL_ANGLE_power_preference implementation. + egl::Error releaseHighPowerGPU(); + egl::Error reacquireHighPowerGPU(); + void onGPUSwitch(); + + bool noopDraw(PrimitiveMode mode, GLsizei count) const; + bool noopDrawInstanced(PrimitiveMode mode, GLsizei count, GLsizei instanceCount) const; + + bool isClearBufferMaskedOut(GLenum buffer, GLint drawbuffer) const; + bool noopClearBuffer(GLenum buffer, GLint drawbuffer) const; + + void addRef() const { mRefCount++; } + void release() const { mRefCount--; } + size_t getRefCount() const { return mRefCount; } + + egl::ShareGroup *getShareGroup() const { return mState.getShareGroup(); } + + bool supportsGeometryOrTesselation() const; + void dirtyAllState(); + + bool isDestroyed() const { return mIsDestroyed; } + void setIsDestroyed() { mIsDestroyed = true; } + + void setLogicOpEnabled(bool enabled) { mState.setLogicOpEnabled(enabled); } + void setLogicOp(LogicalOperation opcode) { mState.setLogicOp(opcode); } + + // Needed by capture serialization logic that works with a "const" Context pointer. + void finishImmutable() const; + + const angle::PerfMonitorCounterGroups &getPerfMonitorCounterGroups() const; + + private: + void initializeDefaultResources(); + + angle::Result prepareForDraw(PrimitiveMode mode); + angle::Result prepareForClear(GLbitfield mask); + angle::Result prepareForClearBuffer(GLenum buffer, GLint drawbuffer); + angle::Result syncState(const State::DirtyBits &bitMask, + const State::DirtyObjects &objectMask, + Command command); + angle::Result syncDirtyBits(Command command); + angle::Result syncDirtyBits(const State::DirtyBits &bitMask, Command command); + angle::Result syncDirtyObjects(const State::DirtyObjects &objectMask, Command command); + angle::Result syncStateForReadPixels(); + angle::Result syncStateForTexImage(); + angle::Result syncStateForBlit(GLbitfield mask); + angle::Result syncStateForClear(); + angle::Result syncTextureForCopy(Texture *texture); + + VertexArray *checkVertexArrayAllocation(VertexArrayID vertexArrayHandle); + TransformFeedback *checkTransformFeedbackAllocation(TransformFeedbackID transformFeedback); + + angle::Result onProgramLink(Program *programObject); + + void detachBuffer(Buffer *buffer); + void detachTexture(TextureID texture); + void detachFramebuffer(FramebufferID framebuffer); + void detachRenderbuffer(RenderbufferID renderbuffer); + void detachVertexArray(VertexArrayID vertexArray); + void detachTransformFeedback(TransformFeedbackID transformFeedback); + void detachSampler(SamplerID sampler); + void detachProgramPipeline(ProgramPipelineID pipeline); + + egl::Error setDefaultFramebuffer(egl::Surface *drawSurface, egl::Surface *readSurface); + egl::Error unsetDefaultFramebuffer(); + + void initRendererString(); + void initVersionStrings(); + void initExtensionStrings(); + + Extensions generateSupportedExtensions() const; + void initCaps(); + void updateCaps(); + + gl::LabeledObject *getLabeledObject(GLenum identifier, GLuint name) const; + gl::LabeledObject *getLabeledObjectFromPtr(const void *ptr) const; + + void setUniform1iImpl(Program *program, + UniformLocation location, + GLsizei count, + const GLint *v); + void renderbufferStorageMultisampleImpl(GLenum target, + GLsizei samples, + GLenum internalformat, + GLsizei width, + GLsizei height, + MultisamplingMode mode); + + State mState; + bool mShared; + bool mSkipValidation; + bool mDisplayTextureShareGroup; + bool mDisplaySemaphoreShareGroup; + + // Recorded errors + ErrorSet mErrors; + + // Stores for each buffer binding type whether is it allowed to be used in this context. + angle::PackedEnumBitSet<BufferBinding> mValidBufferBindings; + + std::unique_ptr<rx::ContextImpl> mImplementation; + + EGLLabelKHR mLabel; + + // Extensions supported by the implementation plus extensions that are implemented entirely + // within the frontend. + Extensions mSupportedExtensions; + + // Shader compiler. Lazily initialized hence the mutable value. + mutable BindingPointer<Compiler> mCompiler; + + const egl::Config *mConfig; + + TextureMap mZeroTextures; + + ResourceMap<FenceNV, FenceNVID> mFenceNVMap; + HandleAllocator mFenceNVHandleAllocator; + + QueryMap mQueryMap; + HandleAllocator mQueryHandleAllocator; + + VertexArrayMap mVertexArrayMap; + HandleAllocator mVertexArrayHandleAllocator; + + TransformFeedbackMap mTransformFeedbackMap; + HandleAllocator mTransformFeedbackHandleAllocator; + + const char *mVersionString; + const char *mShadingLanguageString; + const char *mRendererString; + const char *mExtensionString; + std::vector<const char *> mExtensionStrings; + const char *mRequestableExtensionString; + std::vector<const char *> mRequestableExtensionStrings; + + // GLES1 renderer state + std::unique_ptr<GLES1Renderer> mGLES1Renderer; + + // Current/lost context flags + bool mHasBeenCurrent; + bool mContextLost; // Set with setContextLost so that we also set mSkipValidation=false. + GraphicsResetStatus mResetStatus; + bool mContextLostForced; + GLenum mResetStrategy; + const bool mSurfacelessSupported; + egl::Surface *mCurrentDrawSurface; + egl::Surface *mCurrentReadSurface; + egl::Display *mDisplay; + const bool mWebGLContext; + bool mBufferAccessValidationEnabled; + const bool mExtensionsEnabled; + MemoryProgramCache *mMemoryProgramCache; + MemoryShaderCache *mMemoryShaderCache; + + State::DirtyObjects mDrawDirtyObjects; + + StateCache mStateCache; + + State::DirtyBits mAllDirtyBits; + State::DirtyBits mTexImageDirtyBits; + State::DirtyObjects mTexImageDirtyObjects; + State::DirtyBits mReadPixelsDirtyBits; + State::DirtyObjects mReadPixelsDirtyObjects; + State::DirtyBits mClearDirtyBits; + State::DirtyObjects mClearDirtyObjects; + State::DirtyBits mBlitDirtyBits; + State::DirtyObjects mBlitDirtyObjects; + State::DirtyBits mComputeDirtyBits; + State::DirtyObjects mComputeDirtyObjects; + State::DirtyBits mCopyImageDirtyBits; + State::DirtyObjects mCopyImageDirtyObjects; + State::DirtyBits mReadInvalidateDirtyBits; + State::DirtyBits mDrawInvalidateDirtyBits; + + // Binding to container objects that use dependent state updates. + angle::ObserverBinding mVertexArrayObserverBinding; + angle::ObserverBinding mDrawFramebufferObserverBinding; + angle::ObserverBinding mReadFramebufferObserverBinding; + angle::ObserverBinding mProgramPipelineObserverBinding; + std::vector<angle::ObserverBinding> mUniformBufferObserverBindings; + std::vector<angle::ObserverBinding> mAtomicCounterBufferObserverBindings; + std::vector<angle::ObserverBinding> mShaderStorageBufferObserverBindings; + std::vector<angle::ObserverBinding> mSamplerObserverBindings; + std::vector<angle::ObserverBinding> mImageObserverBindings; + + // Not really a property of context state. The size and contexts change per-api-call. + mutable Optional<angle::ScratchBuffer> mScratchBuffer; + mutable Optional<angle::ScratchBuffer> mZeroFilledBuffer; + + // Single-threaded pool may not always be initialized. It currently depends on the extension + // GL_KHR_parallel_shader_compile being disabled. + std::shared_ptr<angle::WorkerThreadPool> mSingleThreadPool; + // Multithreaded pool will always be initialized so it can be used for more generic work. + std::shared_ptr<angle::WorkerThreadPool> mMultiThreadPool; + + // Note: we use a raw pointer here so we can exclude frame capture sources from the build. + std::unique_ptr<angle::FrameCapture> mFrameCapture; + + // Cache representation of the serialized context string. + mutable std::string mCachedSerializedStateString; + + mutable size_t mRefCount; + + OverlayType mOverlay; + + const bool mIsExternal; + const bool mSaveAndRestoreState; + + bool mIsDestroyed; + + std::unique_ptr<Framebuffer> mDefaultFramebuffer; +}; + +class [[nodiscard]] ScopedContextRef +{ + public: + ScopedContextRef(Context *context) : mContext(context) + { + if (mContext) + { + mContext->addRef(); + } + } + ~ScopedContextRef() + { + if (mContext) + { + mContext->release(); + } + } + + private: + Context *const mContext; +}; + +// Thread-local current valid context bound to the thread. +#if defined(ANGLE_PLATFORM_APPLE) +extern Context *GetCurrentValidContextTLS(); +extern void SetCurrentValidContextTLS(Context *context); +#else +extern thread_local Context *gCurrentValidContext; +#endif + +} // namespace gl + +#endif // LIBANGLE_CONTEXT_H_ |