#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 rx
{
class ContextImpl;
class EGLImplFactory;
}
namespace egl
{
class AttributeMap;
class Surface;
struct Config;
class Thread;
}
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
{
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();
std::mutex mMutex;
Debug *mDebug;
std::set<GLenum> mErrors;
const GLenum mResetStrategy;
const bool mLoseContextOnOutOfMemory;
bool mContextLostForced;
GraphicsResetStatus mResetStatus;
std::atomic<uint32_t> mErrorMessageCount;
uint32_t mMaxErrorMessages;
std::atomic_int mSkipValidation;
std::atomic_int mContextLost;
#if defined(ANGLE_ENABLE_ASSERTS)
std::atomic_uint32_t mPushedErrors;
#endif
std::atomic_int mHasAnyErrors;
};
enum class VertexAttribTypeCase
{
Invalid = 0,
Valid = 1,
ValidSize4Only = 2,
ValidSize3or4 = 3,
};
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; }
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;
}
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;
mutable bool mIsCachedBasicDrawStatesErrorValid;
mutable bool mIsCachedActiveAttribMasksValid;
mutable bool mIsCachedVertexElementLimitValid;
mutable intptr_t mCachedBasicDrawElementsError;
using VertexAttribTypesValidation =
angle::PackedEnumMap<VertexAttribType,
VertexAttribTypeCase,
angle::EnumSize<VertexAttribType>() + 1>;
VertexAttribTypesValidation mCachedVertexAttribTypesValidation;
VertexAttribTypesValidation mCachedIntegerVertexAttribTypesValidation;
};
class StateCache final : angle::NonCopyable
{
public:
StateCache();
~StateCache();
void initialize(Context *context);
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();
}
GLint64 getNonInstancedVertexElementLimit(const PrivateStateCache &privateStateCache) const
{
ASSERT(privateStateCache.isCachedVertexElementLimitValid());
return mCachedNonInstancedVertexElementLimit;
}
GLint64 getInstancedVertexElementLimit(const PrivateStateCache &privateStateCache) const
{
ASSERT(privateStateCache.isCachedVertexElementLimitValid());
return mCachedInstancedVertexElementLimit;
}
intptr_t getBasicDrawStatesErrorString(const Context *context,
const PrivateStateCache *privateStateCache) const
{
ASSERT(isCurrentContext(context, privateStateCache));
if (privateStateCache->isCachedBasicDrawStatesErrorValid() &&
mCachedBasicDrawStatesErrorString != kInvalidPointer)
{
return mCachedBasicDrawStatesErrorString;
}
return getBasicDrawStatesErrorImpl(context, privateStateCache);
}
GLenum getBasicDrawElementsErrorCode() const
{
ASSERT(mCachedBasicDrawStatesErrorString != kInvalidPointer);
ASSERT(mCachedBasicDrawStatesErrorCode != GL_NO_ERROR);
return mCachedBasicDrawStatesErrorCode;
}
intptr_t getProgramPipelineError(const Context *context) const
{
if (mCachedProgramPipelineError != kInvalidPointer)
{
return mCachedProgramPipelineError;
}
return getProgramPipelineErrorImpl(context);
}
bool isValidDrawMode(PrimitiveMode primitiveMode) const
{
return mCachedValidDrawModes[primitiveMode];
}
bool isValidBindTextureType(TextureType type) const
{
return mCachedValidBindTextureTypes[type];
}
bool isValidDrawElementsType(DrawElementsType type) const
{
return mCachedValidDrawElementsTypes[type];
}
bool isTransformFeedbackActiveUnpaused() const
{
return mCachedTransformFeedbackActiveUnpaused;
}
StorageBuffersMask getActiveShaderStorageBufferIndices() const
{
return mCachedActiveShaderStorageBufferIndices;
}
const ImageUnitMask &getActiveImageUnitIndices() const { return mCachedActiveImageUnitIndices; }
bool getCanDraw() const { return mCachedCanDraw; }
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);
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;
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;
GLint64 mCachedNonInstancedVertexElementLimit;
GLint64 mCachedInstancedVertexElementLimit;
mutable intptr_t mCachedBasicDrawStatesErrorString;
mutable GLenum mCachedBasicDrawStatesErrorCode;
mutable intptr_t mCachedProgramPipelineError;
bool mCachedHasAnyEnabledClientAttrib;
bool mCachedTransformFeedbackActiveUnpaused;
StorageBuffersMask mCachedActiveShaderStorageBufferIndices;
ImageUnitMask mCachedActiveImageUnitIndices;
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);
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);
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);
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;
bool createFramebuffer(FramebufferID *outFramebuffer);
void deleteFramebuffer(FramebufferID framebuffer);
bool hasActiveTransformFeedback(ShaderProgramID program) const;
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();
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; }
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;
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(); }
void contextLostErrorOnBlockingCall(angle::EntryPoint entryPoint) const;
ErrorSet *getMutableErrorSetForValidation() const { return &mErrors; }
void handleExhaustionError(angle::EntryPoint entryPoint);
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;
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]; }
int vertexArrayIndex(ClientVertexArrayType type) const;
static int TexCoordArrayIndex(unsigned int unit);
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;
std::shared_ptr<angle::WorkerThreadPool> getSingleThreadPool() const;
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::Error releaseHighPowerGPU();
egl::Error reacquireHighPowerGPU();
void onGPUSwitch();
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(); }
egl::ContextMutex &getContextMutex() const { return mState.mContextMutex; }
bool supportsGeometryOrTesselation() const;
void dirtyAllState();
bool isDestroyed() const { return mIsDestroyed; }
void setIsDestroyed() { mIsDestroyed = true; }
void setLogicOpEnabledForGLES1(bool enabled);
void finishImmutable() const;
const angle::PerfMonitorCounterGroupsInfo &getPerfMonitorCounterGroups() const;
void endPixelLocalStorageImplicit();
bool areBlobCacheFuncsSet() const;
size_t getMemoryUsage() const;
void onSwapChainImageChanged() const { mDefaultFramebuffer->onSwapChainImageChanged(); }
void onBufferChanged(const Buffer *buffer,
const angle::SubjectMessage message,
VertexArrayBufferBindingMask vertexArrayBufferBindingMask) const
{
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;
mutable ErrorSet mErrors;
angle::PackedEnumBitSet<BufferBinding> mValidBufferBindings;
std::unique_ptr<rx::ContextImpl> mImplementation;
EGLLabelKHR mLabel;
Extensions mSupportedExtensions;
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;
std::unique_ptr<GLES1Renderer> mGLES1Renderer;
bool mHasBeenCurrent;
const bool mSurfacelessSupported;
egl::Surface *mCurrentDrawSurface;
egl::Surface *mCurrentReadSurface;
egl::Display *mDisplay;
const bool mWebGLContext;
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;
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;
mutable Optional<angle::ScratchBuffer> mScratchBuffer;
mutable Optional<angle::ScratchBuffer> mZeroFilledBuffer;
std::unique_ptr<angle::FrameCapture> mFrameCapture;
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;
};
#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);
}
#endif