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

#ifdef UNSAFE_BUFFERS_BUILD
#    pragma allow_unsafe_libc_calls
#endif

#include <mutex>
#include <set>
#include <string>

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

    // 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.
    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(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
    FramebufferID createFramebuffer();
    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;
    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; }

    angle::SimpleMutex &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);
    }

    bool isShared() const { return mShared; }
    bool isSharedContext() const { return mSharedContext; }
    // 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 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; }

    // 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 (strncmp(name, "gl_", 3) == 0) ||
               (isWebGL() && (strncmp(name, "webgl_", 6) == 0 || 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(); }
    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::PerfMonitorCounterGroups &getPerfMonitorCounterGroups() const;

    // Ends the currently active pixel local storage session with GL_STORE_OP_STORE on all planes.
    void endPixelLocalStorageImplicit();

    bool areBlobCacheFuncsSet() const;

    size_t getMemoryUsage() const;

    // Only used by vulkan backend.
    void onSwapChainImageChanged() const { mDefaultFramebuffer->onSwapChainImageChanged(); }
    void onBufferChanged(const Buffer *buffer,
                         const angle::SubjectMessage message,
                         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);
        }
    }

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

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

    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;

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

    State mState;
    bool mShared;
    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;

    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;

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

    OverlayType mOverlay;

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