//
//
// 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 "common/unsafe_buffers.h"

#include "angle_gl.h"
#include "common/MemoryBuffer.h"
#include "common/PackedEnums.h"
#include "common/SimpleMutex.h"
#include "common/angleutils.h"
#include "libANGLE/Caps.h"
#include "libANGLE/Constants.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/angletypes.h"

namespace angle
{
class Closure;
class FrameCapture;
class FrameCaptureShared;
struct FrontendFeatures;
class WaitableEvent;
}  // 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 PixelLocalStoragePlane;
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(Debug *debug,
                      const angle::FrontendFeatures &frontendFeatures,
                      const egl::AttributeMap &attribs);
    ~ErrorSet();

    bool empty() const { return mHasAnyErrors.load(std::memory_order_relaxed) == 0; }
    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);
    ANGLE_FORMAT_PRINTF(4, 5)
    void validationErrorF(angle::EntryPoint entryPoint, GLenum errorCode, const char *format, ...);

    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.load(std::memory_order_relaxed) != 0;
    }
    void forceValidation() { mSkipValidation = 0; }

    void markContextLost(GraphicsResetStatus status);
    bool isContextLost() const { return mContextLost.load(std::memory_order_relaxed) != 0; }
    GLenum getGraphicsResetStatus(rx::ContextImpl *contextImpl);
    GLenum getResetStrategy() const { return mResetStrategy; }
    GLenum getErrorForCapture() const;
#if defined(ANGLE_ENABLE_ASSERTS)
    uint32_t getPushedErrorCount() const { return mPushedErrors; }
#endif

  private:
    void setContextLost();
    void pushError(GLenum errorCode);
    std::unique_lock<std::mutex> getLockIfNotAlready();

    // Non-atomic members of this class are protected by a mutex.  This is to allow errors to be
    // safely set by entry points that don't hold a lock.  Note that other contexts may end up
    // triggering an error on this context (through making failable calls on other contexts in the
    // share group).
    //
    // Note also that the functionality used through the Debug class is thread-safe.
    std::mutex mMutex;

    // Error handling and reporting
    Debug *mDebug;
    std::set<GLenum> mErrors;

    const GLenum mResetStrategy;
    const bool mLoseContextOnOutOfMemory;
    const bool mLoseContextOnInternalError;

    // Context-loss handling
    bool mContextLostForced;
    GraphicsResetStatus mResetStatus;

    std::atomic<uint32_t> mErrorMessageCount;
    uint32_t mMaxErrorMessages;

    // The following are atomic and lockless as they are very frequently accessed.
    std::atomic_int mSkipValidation;
    std::atomic_int mContextLost;
#if defined(ANGLE_ENABLE_ASSERTS)
    std::atomic_uint32_t mPushedErrors;  // must be unsigned to handle overflows
#endif
    std::atomic_int mHasAnyErrors;
};

enum class VertexAttribTypeCase
{
    Invalid        = 0,
    Valid          = 1,
    ValidSize4Only = 2,
    ValidSize3or4  = 3,
};

// Part of StateCache (see below) that is private to the context and is inaccessible to other
// contexts.
class PrivateStateCache final : angle::NonCopyable
{
  public:
    PrivateStateCache();
    ~PrivateStateCache();

    void initialize(const Context *context);

    void onCapChange() { mIsCachedBasicDrawStatesErrorValid = false; }
    void onColorMaskChange() { mIsCachedBasicDrawStatesErrorValid = false; }
    void onDefaultVertexAttributeChange() { mIsCachedBasicDrawStatesErrorValid = false; }

    // Blending updates invalidate draw
    // state in the following cases:
    //
    // * Blend equations have been changed and the context
    //   supports KHR_blend_equation_advanced. The number
    //   of enabled draw buffers may need to be checked
    //   to not be greater than 1.
    //
    // * Blend funcs have been changed with indexed
    //   commands. The D3D11 backend cannot support
    //   constant color and alpha blend funcs together
    //   so a check is needed across all draw buffers.
    //
    // * Blend funcs have been changed and the context
    //   supports EXT_blend_func_extended. The number
    //   of enabled draw buffers may need to be checked
    //   against MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT limit.
    void onBlendEquationOrFuncChange() { mIsCachedBasicDrawStatesErrorValid = false; }

    void onStencilStateChange() { mIsCachedBasicDrawStatesErrorValid = false; }

    void onBufferBindingChange()
    {
        mIsCachedBasicDrawStatesErrorValid = false;
        mCachedBasicDrawElementsError      = kInvalidPointer;
    }

    void onVertexArrayBindingChange()
    {
        mIsCachedActiveAttribMasksValid    = false;
        mIsCachedVertexElementLimitValid   = false;
        mIsCachedBasicDrawStatesErrorValid = false;
        mCachedBasicDrawElementsError      = kInvalidPointer;
    }
    void onVertexArrayStateChange()
    {
        mIsCachedActiveAttribMasksValid    = false;
        mIsCachedVertexElementLimitValid   = false;
        mIsCachedBasicDrawStatesErrorValid = false;
        mCachedBasicDrawElementsError      = kInvalidPointer;
    }
    void onVertexArrayFormatChange() { mIsCachedVertexElementLimitValid = false; }
    void onVertexArrayBufferContentsChange()
    {
        mIsCachedVertexElementLimitValid   = false;
        mIsCachedBasicDrawStatesErrorValid = false;
    }
    void onVertexArrayBufferStateChange()
    {
        mIsCachedBasicDrawStatesErrorValid = false;
        mCachedBasicDrawElementsError      = kInvalidPointer;
    }

    bool isCachedBasicDrawStatesErrorValid() const { return mIsCachedBasicDrawStatesErrorValid; }
    void setCachedBasicDrawStatesErrorValid() const { mIsCachedBasicDrawStatesErrorValid = true; }

    bool isCachedActiveAttribMasksValid() const { return mIsCachedActiveAttribMasksValid; }
    void setCachedActiveAttribMasksValid() const { mIsCachedActiveAttribMasksValid = true; }

    bool isCachedVertexElementLimitValid() const { return mIsCachedVertexElementLimitValid; }
    void setCachedVertexElementLimitValid() const { mIsCachedVertexElementLimitValid = true; }

    bool isCachedBasicDrawElementsErrorValid() const
    {
        return mCachedBasicDrawElementsError != kInvalidPointer;
    }
    intptr_t getBasicDrawElementsError() const
    {
        ASSERT(isCachedBasicDrawElementsErrorValid());
        return mCachedBasicDrawElementsError;
    }
    void invalidateCachedBasicDrawElementsError()
    {
        mCachedBasicDrawElementsError = kInvalidPointer;
    }
    void updateBasicDrawElementsError(intptr_t drawElementsError) const
    {
        ASSERT(drawElementsError != kInvalidPointer);
        mCachedBasicDrawElementsError = drawElementsError;
    }

    // Cannot change except on Context/Extension init.
    VertexAttribTypeCase getVertexAttribTypeValidation(VertexAttribType type) const
    {
        return mCachedVertexAttribTypesValidation[type];
    }
    VertexAttribTypeCase getIntegerVertexAttribTypeValidation(VertexAttribType type) const
    {
        return mCachedIntegerVertexAttribTypesValidation[type];
    }

  private:
    void updateVertexAttribTypesValidation(const Context *context);

    static constexpr intptr_t kInvalidPointer = 1;

    // StateCache::mCachedBasicDrawStatesError* may be invalidated through numerous calls (see the
    // comment on getBasicDrawStatesErrorString), some of which may originate from other contexts
    // (through the observer interface).  However, ContextPrivate* helpers may also need to
    // invalidate the draw states, but they are called without holding the share group lock.  The
    // following tracks whether StateCache::mCachedBasicDrawStatesError* values are valid and is
    // accessed only by the context itself.
    mutable bool mIsCachedBasicDrawStatesErrorValid;

    // When any one of these cached values needs to be updated, we will set
    // mIsCachedActiveAttribMasksValid to false. Whenever these cached value are used, we check this
    // boolean and update if needed: StateCache::mCachedActiveClientAttribsMask,
    // StateCache::mCachedActiveBufferedAttribsMask, StateCache::mCachedActiveDefaultAttribsMask,
    // StateCache::mCachedHasAnyEnabledClientAttrib,
    mutable bool mIsCachedActiveAttribMasksValid;

    // When any one of these cached values needs to be updated, we will set it to false. Whenever
    // these cached value are used, we check this boolean and update if needed:
    // StateCache::mCachedNonInstancedVertexElementLimit,
    // StateCache::mCachedInstancedVertexElementLimit
    mutable bool mIsCachedVertexElementLimitValid;

    // This only gets modified by the current context, with or without shared lock. But it is always
    // thread safe since context can only be current in one thread.
    mutable intptr_t mCachedBasicDrawElementsError;

    using VertexAttribTypesValidation =
        angle::PackedEnumMap<VertexAttribType,
                             VertexAttribTypeCase,
                             angle::EnumSize<VertexAttribType>() + 1>;
    VertexAttribTypesValidation mCachedVertexAttribTypesValidation;
    VertexAttribTypesValidation mCachedIntegerVertexAttribTypesValidation;
};

// 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.
    // 5. onGLES1TextureStateChange.
    AttributesMask getActiveBufferedAttribsMask(const PrivateStateCache &privateStateCache) const
    {
        ASSERT(privateStateCache.isCachedActiveAttribMasksValid());
        return mCachedActiveBufferedAttribsMask;
    }
    AttributesMask getActiveClientAttribsMask(const PrivateStateCache &privateStateCache) const
    {
        ASSERT(privateStateCache.isCachedActiveAttribMasksValid());
        return mCachedActiveClientAttribsMask;
    }
    AttributesMask getActiveDefaultAttribsMask(const PrivateStateCache &privateStateCache) const
    {
        ASSERT(privateStateCache.isCachedActiveAttribMasksValid());
        return mCachedActiveDefaultAttribsMask;
    }
    bool hasAnyEnabledClientAttrib(const PrivateStateCache &privateStateCache) const
    {
        ASSERT(privateStateCache.isCachedActiveAttribMasksValid());
        return mCachedHasAnyEnabledClientAttrib;
    }
    bool hasAnyActiveClientAttrib(const PrivateStateCache &privateStateCache) const
    {
        ASSERT(privateStateCache.isCachedActiveAttribMasksValid());
        return mCachedActiveClientAttribsMask.any();
    }

    // Places that can trigger updateVertexElementLimits:
    // 1. onVertexArrayBindingChange.
    // 2. onProgramExecutableChange.
    // 3. onVertexArrayFormatChange.
    // 4. onVertexArrayBufferChange.
    // 5. onVertexArrayStateChange.
    GLint64 getNonInstancedVertexElementLimit(const PrivateStateCache &privateStateCache) const
    {
        ASSERT(privateStateCache.isCachedVertexElementLimitValid());
        return mCachedNonInstancedVertexElementLimit;
    }
    GLint64 getInstancedVertexElementLimit(const PrivateStateCache &privateStateCache) const
    {
        ASSERT(privateStateCache.isCachedVertexElementLimitValid());
        return mCachedInstancedVertexElementLimit;
    }

    // Places that can trigger updateBasicDrawStatesError:
    // 1. onVertexArrayBindingChange.
    // 2. onProgramExecutableChange.
    // 3. onVertexArrayBufferContentsChange.
    // 4. onVertexArrayStateChange.
    // 5. onVertexArrayBufferStateChange.
    // 6. onDrawFramebufferChange.
    // 7. onActiveTextureChange.
    // 8. onQueryChange.
    // 9. onActiveTransformFeedbackChange.
    // 10. onUniformBufferStateChange.
    // 11. onBufferBindingChange.
    //
    // Additionally, the following in PrivateStateCache can lead to updateBasicDrawStatesError:
    // 1. onCapChange.
    // 2. onStencilStateChange.
    // 3. onDefaultVertexAttributeChange.
    // 4. onColorMaskChange.
    // 5. onBlendEquationOrFuncChange.
    intptr_t getBasicDrawStatesErrorString(const Context *context,
                                           const PrivateStateCache *privateStateCache) const
    {
        // This is only ever called with the context that owns this state cache
        ASSERT(isCurrentContext(context, privateStateCache));
        if (privateStateCache->isCachedBasicDrawStatesErrorValid() &&
            mCachedBasicDrawStatesErrorString != kInvalidPointer)
        {
            return mCachedBasicDrawStatesErrorString;
        }

        return getBasicDrawStatesErrorImpl(context, privateStateCache);
    }

    // The GL error enum to use when generating errors due to failed draw states. Only valid if
    // getBasicDrawStatesErrorString returns non-zero.
    GLenum getBasicDrawElementsErrorCode() const
    {
        ASSERT(mCachedBasicDrawStatesErrorString != kInvalidPointer);
        ASSERT(mCachedBasicDrawStatesErrorCode != GL_NO_ERROR);
        return mCachedBasicDrawStatesErrorCode;
    }

    // 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 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;
    }

    // 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 onProgramExecutableChange(Context *context);
    void onGLES1TextureStateChange(Context *context);
    void onGLES1ClientStateChange(Context *context);
    void onDrawFramebufferChange(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);

    // Cache update functions.
    void updateActiveAttribsMask(const Context *context);
    void updateVertexElementLimits(const Context *context);
    void updateVertexElementLimitsImpl(const Context *context);

  private:
    bool isCurrentContext(const Context *context, const PrivateStateCache *privateStateCache) const;

    // Cache update functions.
    void updateValidDrawModes(Context *context);
    void updateValidBindTextureTypes(Context *context);
    void updateValidDrawElementsTypes(Context *context);
    void updateBasicDrawStatesError()
    {
        mCachedBasicDrawStatesErrorString = kInvalidPointer;
        mCachedBasicDrawStatesErrorCode   = GL_NO_ERROR;
    }
    void updateProgramPipelineError() { mCachedProgramPipelineError = kInvalidPointer; }
    void updateTransformFeedbackActiveUnpaused(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 PrivateStateCache *privateStateCache) const;
    intptr_t getProgramPipelineErrorImpl(const Context *context) const;

    static constexpr intptr_t kInvalidPointer = 1;

    AttributesMask mCachedActiveBufferedAttribsMask;
    AttributesMask mCachedActiveClientAttribsMask;
    AttributesMask mCachedActiveDefaultAttribsMask;

    // Given a vertex attribute's stride, the corresponding vertex buffer can fit a number of such
    // attributes.  A draw call that attempts to use more vertex attributes thus needs to fail (when
    // robust access is enabled).  The following variables help implement this limit given the
    // following situations:
    //
    // Assume:
    //
    // Ni = Number of vertex attributes that can fit in buffer bound to attribute i.
    // Di = Vertex attribute divisor set for attribute i.
    // F = Draw calls "first" vertex index
    // C = Draw calls vertex "count"
    // B = Instanced draw calls "baseinstance"
    // P = Instanced draw calls "primcount"
    //
    // Then, for each attribute i:
    //
    //   If Di == 0 (i.e. non-instanced)
    //     Vertices [F, F+C) are accessed
    //     Draw call should fail if F+C > Ni
    //
    //   If Di != 0 (i.e. instanced), in a non-instanced draw call:
    //     Only vertex 0 is accessed - note that a non-zero divisor in a non-instanced draw call
    //       implies that F is ignored and the vertex index is not incremented.
    //     Draw call should fail if Ni < 1
    //
    //   If Di != 0, in an instanced draw call:
    //     Vertices [B, B+ceil(P/Di)) are accessed
    //     Draw call should fail if B+ceil(P/Di) > Ni
    //
    // To avoid needing to iterate over all attributes in the hot paths, the following is
    // calculated:
    //
    // Non-instanced limit: min(Ni) for all non-instanced attributes.  At draw time F+C <= min(Ni)
    // is validated.
    // Instanced limit: min(Ni*Di) for all instanced attributes.  At draw time, B+P <= min(Ni*Di) is
    // validated (the math works out, try with an example!)
    //
    // For instanced attributes in a non-instanced draw call, need to check that min(Ni) > 0.
    // Evaluating min(Ni*DI) > 0 produces the same result though, so the instanced limit is used
    // there too.
    //
    // If there are no instanced attributes, the non-instanced limit is set to infinity.  If there
    // are no instanced attributes, the instanced limits are set to infinity.
    GLint64 mCachedNonInstancedVertexElementLimit;
    GLint64 mCachedInstancedVertexElementLimit;

    mutable intptr_t mCachedBasicDrawStatesErrorString;
    mutable GLenum mCachedBasicDrawStatesErrorCode;
    // 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 mCachedHasAnyEnabledClientAttrib;
    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;

    bool mCachedCanDraw;
};

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,
            egl::ContextMutex *sharedContextMutex,
            MemoryProgramCache *memoryProgramCache,
            MemoryShaderCache *memoryShaderCache,
            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.
    bool createBuffer(BufferID *outBuffer);
    bool createTexture(TextureID *outTexture);
    bool createRenderbuffer(RenderbufferID *outRenderbuffer);
    bool createProgramPipeline(ProgramPipelineID *outProgramPipeline);
    bool createMemoryObject(MemoryObjectID *outMemoryObject);
    bool createSemaphore(SemaphoreID *outSemaphore);

    void deleteBuffer(BufferID buffer);
    void deleteTexture(TextureID texture);
    void deleteRenderbuffer(RenderbufferID renderbuffer);
    void deleteProgramPipeline(ProgramPipelineID pipeline);
    void deleteMemoryObject(MemoryObjectID memoryObject);
    void deleteSemaphore(SemaphoreID semaphore);

    // Only used for capturing frame data in ANGLE_capture_enabled builds.
    bool canProtectCoherentMemoryDirectly();

    void bindReadFramebuffer(FramebufferID framebufferHandle);
    void bindDrawFramebuffer(FramebufferID framebufferHandle);

    Buffer *getBuffer(BufferID handle) const;
    FenceNV *getFenceNV(FenceNVID handle) const;
    Sync *getSync(SyncID syncPacked) const;
    ANGLE_INLINE Texture *getTexture(TextureID handle) const
    {
        return mState.mTextureManager->getTexture(handle);
    }

    Framebuffer *getFramebuffer(FramebufferID handle) const;
    Renderbuffer *getRenderbuffer(RenderbufferID 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 isTransformFeedbackGenerated(TransformFeedbackID transformFeedback) const;

    bool isZeroTextureBound(TextureType textureType) const;

    bool isExternal() const { return mState.isExternal(); }

    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
    bool createFramebuffer(FramebufferID *outFramebuffer);
    void deleteFramebuffer(FramebufferID framebuffer);

    bool hasActiveTransformFeedback(ShaderProgramID program) const;

    // 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);

    bool isResetNotificationEnabled() const;

    bool isRobustnessEnabled() const { return mState.hasRobustAccess(); }

    const egl::Config *getConfig() const { return mConfig; }
    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;
    size_t getRequestableExtensionStringCount() const;
    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,
                                           const 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; }

    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);
    }

    bool isShared() const { return mShared; }
    bool isSharedContext() const { return mSharedContext.load(std::memory_order_relaxed); }
    // Once a context is setShared() it cannot be undone
    void setShared()
    {
        mShared        = true;
        mSharedContext = true;
    }

    const State &getState() const { return mState; }
    const PrivateState &getPrivateState() const { return mState.privateState(); }
    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 getExtensionsEnabled() const { return mExtensionsEnabled; }
    bool isGLES1() const;

    // To be used **only** directly by the entry points.
    PrivateState *getMutablePrivateState() { return mState.getMutablePrivateState(); }
    GLES1State *getMutableGLES1State() { return mState.getMutableGLES1State(); }

    bool skipValidation() const { return mErrors.skipValidation(); }
    void markContextLost(GraphicsResetStatus status) { mErrors.markContextLost(status); }
    bool isContextLost() const { return mErrors.isContextLost(); }

    // Some commands may need to generate a context lost error but still return a value.
    // The validation layer does not generate the context lost error in such cases.
    void contextLostErrorOnBlockingCall(angle::EntryPoint entryPoint) const;

    ErrorSet *getMutableErrorSetForValidation() const { return &mErrors; }

    void handleExhaustionError(angle::EntryPoint entryPoint);

    // 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 (ANGLE_LIKELY(program))
        {
            program->resolveLink(this);
        }
        return program;
    }

    Program *getProgramNoResolveLink(ShaderProgramID handle) const;
    Shader *getShaderResolveCompile(ShaderProgramID handle) const;
    Shader *getShaderNoResolveCompile(ShaderProgramID handle) const;

    bool nameStartsWithReservedPrefix(const GLchar *name) const
    {
        return (ANGLE_UNSAFE_TODO(strncmp(name, "gl_", 3)) == 0) ||
               (isWebGL() && (ANGLE_UNSAFE_TODO(strncmp(name, "webgl_", 6)) == 0 ||
                              ANGLE_UNSAFE_TODO(strncmp(name, "_webgl_", 7)) == 0));
    }

    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 isHardenedContext() const { return mHardenedContext; }
    const char *getRendererString() const { return mRendererString; }

    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;
    std::shared_ptr<angle::WorkerThreadPool> getLinkSubTaskThreadPool() const;
    std::shared_ptr<angle::WaitableEvent> postCompileLinkTask(
        const std::shared_ptr<angle::Closure> &task,
        angle::JobThreadSafety safety,
        angle::JobResultExpectancy resultExpectancy) const;

    // Single-threaded pool; runs everything instantly
    std::shared_ptr<angle::WorkerThreadPool> getSingleThreadPool() const;

    // Generic multithread pool.
    std::shared_ptr<angle::WorkerThreadPool> getWorkerThreadPool() const;

    const StateCache &getStateCache() const { return mStateCache; }
    StateCache &getStateCache() { return mStateCache; }

    const PrivateStateCache &getPrivateStateCache() const { return mPrivateStateCache; }
    PrivateStateCache *getMutablePrivateStateCache() { return &mPrivateStateCache; }

    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 getPrivateState().getVertexArrayMap();
    }
    const QueryMap &getQueriesForCapture() const { return mQueryMap; }
    const TransformFeedbackMap &getTransformFeedbacksForCapture() const
    {
        return mTransformFeedbackMap;
    }
    GLenum getErrorForCapture() const { return mErrors.getErrorForCapture(); }
#if defined(ANGLE_ENABLE_ASSERTS)
    uint32_t getPushedErrorCount() const { return mErrors.getPushedErrorCount(); }
#endif

    void onPreSwap();

    ANGLE_INLINE Program *getActiveLinkedProgram() const
    {
        Program *program = mState.getLinkedProgram(this);
        if (ANGLE_LIKELY(program))
        {
            return program;
        }
        return getActiveLinkedProgramPPO();
    }

    ANGLE_NOINLINE Program *getActiveLinkedProgramPPO() const;

    // EGL_ANGLE_power_preference implementation.
    egl::Error releaseHighPowerGPU();
    egl::Error reacquireHighPowerGPU();
    void onGPUSwitch();

    // EGL_ANGLE_external_context_and_surface implementation.
    egl::Error acquireExternalContext(egl::Surface *drawAndReadSurface);
    egl::Error releaseExternalContext();

    bool noopDrawProgram() const;
    bool noopDraw(PrimitiveMode mode, GLsizei count) const;
    bool noopDrawInstanced(PrimitiveMode mode, GLsizei count, GLsizei instanceCount) const;
    bool noopMultiDraw(GLsizei drawcount) const;

    bool isClearBufferMaskedOut(GLenum buffer,
                                GLint drawbuffer,
                                GLuint framebufferStencilSize) const;
    bool noopClearBuffer(GLenum buffer, GLint drawbuffer) const;

    void addRef() const { mRefCount++; }
    void release() const { mRefCount--; }
    bool isReferenced() const { return mRefCount > 0; }

    egl::ShareGroup *getShareGroup() const { return mState.getShareGroup(); }

    // Warning! When need to store pointer to the mutex in other object use `getRoot()` pointer, do
    // NOT get pointer of the `getContextMutex()` reference.
    egl::ContextMutex &getContextMutex() const { return mState.mContextMutex; }

    bool supportsGeometryOrTesselation() const;
    void dirtyAllState();

    bool isDestroyed() const { return mIsDestroyed; }
    void setIsDestroyed() { mIsDestroyed = true; }

    // This function acts as glEnable(GL_COLOR_LOGIC_OP), but it's called from the GLES1 emulation
    // code to implement logicOp using the non-GLES1 functionality (i.e. GL_ANGLE_logic_op).  The
    // ContextPrivateEnable() entry point implementation cannot be used (as ContextPrivate*
    // functions are typically used by other frontend-emulated features) because it forwards this
    // back to GLES1.
    void setLogicOpEnabledForGLES1(bool enabled);

    // Needed by capture serialization logic that works with a "const" Context pointer.
    void finishImmutable() const;

    const angle::PerfMonitorCounterGroupsInfo &getPerfMonitorCounterGroups() const;

    bool areBlobCacheFuncsSet() const;

    size_t getMemoryUsage() const;

    void onSwapChainImageChanged() const { mDefaultFramebuffer->onSwapChainImageChanged(); }
    void onBufferChanged(const Buffer *buffer,
                         const angle::SubjectMessage message,
                         bool isUsedInTransformFeedback,
                         VertexArrayBufferBindingMask vertexArrayBufferBindingMask) const
    {
        // Notify current vertex array of the buffer changed. Note that other vertex arrays of this
        // context or other context requires rebind which will check buffer changes
        // at that time.
        if (vertexArrayBufferBindingMask.any())
        {
            ASSERT(mState.mVertexArray != nullptr);
            mState.mVertexArray->onBufferChanged(this, buffer, message,
                                                 vertexArrayBufferBindingMask);
        }
        if (isUsedInTransformFeedback && message == angle::SubjectMessage::SubjectChanged)
        {
            invalidateTransformFeedbackCapacities(buffer);
        }
    }

    AttributesMask getActiveBufferedAttribsMask() const;
    AttributesMask getActiveClientAttribsMask() const;
    AttributesMask getActiveDefaultAttribsMask() const;
    bool hasAnyEnabledClientAttrib() const;
    bool hasAnyActiveClientAttrib() const;
    GLint64 getNonInstancedVertexElementLimit() const;
    GLint64 getInstancedVertexElementLimit() const;
    void onActiveTransformFeedbackChange();

    bool retainIdUntilObjectDestroyed() const;

    void onBufferDestroy(const Buffer *buffer) const;
    void onTextureDestroy(const Texture *texture) const;
    void onRenderbufferDestroy(const Renderbuffer *renderBuffer) const;
    void onSamplerDestroy(const Sampler *sampler) const;
    void onSyncDestroy(const Sync *sync) const;
    void onFramebufferDestroy(const Framebuffer *framebuffer) const;
    void onProgramPipelineDestroy(const ProgramPipeline *programPipeline) const;

  private:
    void initializeDefaultResources();
    void releaseSharedObjects();

    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::ExtendedDirtyBits extendedBitMask,
                            const state::DirtyObjects &objectMask,
                            Command command);
    angle::Result syncDirtyBits(const state::DirtyBits bitMask,
                                const state::ExtendedDirtyBits extendedBitMask,
                                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);

    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();

    const char *makeStaticString(const std::string &str);
    void initRendererString();
    void initVendorString();
    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;

    angle::Result readPixelsImpl(GLint x,
                                 GLint y,
                                 GLsizei width,
                                 GLsizei height,
                                 GLenum format,
                                 GLenum type,
                                 void *pixels);

    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);

    void onUniformBlockBindingUpdated(GLuint uniformBlockIndex);
    void updateActiveAttribsMaskIfNeeded() const;

    void endTilingImplicit();
    void invalidateTransformFeedbackCapacities(const Buffer *buffer) const;

    State mState;
    bool mShared;
    std::atomic<bool> mSharedContext;
    bool mDisplayTextureShareGroup;
    bool mDisplaySemaphoreShareGroup;

    // Recorded errors
    mutable 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;

    TransformFeedbackMap mTransformFeedbackMap;
    HandleAllocator mTransformFeedbackHandleAllocator;

    // Some GL queries return a "static" string, which ANGLE interprets as a string that doesn't
    // need to be deallocated by the application but which automatically gets freed on context
    // destruction, following mesa.  In typical drivers, these strings are calculated once and never
    // change and so could have been std::string, but ANGLE_request_extension makes it such that
    // some strings do change and so the "static string cache" is used to store the backing for
    // these pointers.
    const char *mVendorString;
    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;
    std::set<std::string> mStaticStrings;

    // GLES1 renderer state
    std::unique_ptr<GLES1Renderer> mGLES1Renderer;

    // Current/lost context flags
    bool mHasBeenCurrent;
    const bool mSurfacelessSupported;
    egl::Surface *mCurrentDrawSurface;
    egl::Surface *mCurrentReadSurface;
    egl::Display *mDisplay;
    const bool mWebGLContext;
    const bool mHardenedContext;
    bool mBufferAccessValidationEnabled;
    bool mRequiresRobustBehavior;
    const bool mExtensionsEnabled;
    MemoryProgramCache *mMemoryProgramCache;
    MemoryShaderCache *mMemoryShaderCache;

    state::DirtyObjects mDrawDirtyObjects;

    mutable StateCache mStateCache;
    PrivateStateCache mPrivateStateCache;

    state::DirtyObjects mTexImageDirtyObjects;
    state::DirtyObjects mReadPixelsDirtyObjects;
    state::DirtyObjects mClearDirtyObjects;
    state::DirtyObjects mBlitDirtyObjects;
    state::DirtyObjects mComputeDirtyObjects;
    state::DirtyBits mCopyImageDirtyBits;
    state::DirtyObjects mCopyImageDirtyObjects;
    state::DirtyObjects mTilingDirtyObjects;

    // Binding to container objects that use dependent state updates.
    angle::ObserverBinding mVertexArrayObserverBinding;
    angle::ObserverBinding mDrawFramebufferObserverBinding;
    angle::ObserverBinding mReadFramebufferObserverBinding;
    angle::ObserverBinding mProgramObserverBinding;
    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;

    // 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;

    bool mIsDestroyed;
    bool mDestroyedManagers;

    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) || defined(ANGLE_USE_STATIC_THREAD_LOCAL_VARIABLES)
extern Context *GetCurrentValidContextTLS();
extern void SetCurrentValidContextTLS(Context *context);
#else
extern thread_local Context *gCurrentValidContext;
#endif

extern void SetCurrentValidContext(Context *context);

}  // namespace gl

#endif  // LIBANGLE_CONTEXT_H_
