| // |
| // 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. |
| // |
| |
| // ResourceManager.h : Defines the ResourceManager classes, which handle allocation and lifetime of |
| // GL objects. |
| |
| #ifndef LIBANGLE_RESOURCEMANAGER_H_ |
| #define LIBANGLE_RESOURCEMANAGER_H_ |
| |
| #include "angle_gl.h" |
| #include "common/angleutils.h" |
| #include "libANGLE/Error.h" |
| #include "libANGLE/HandleAllocator.h" |
| #include "libANGLE/ResourceMap.h" |
| |
| namespace rx |
| { |
| class GLImplFactory; |
| } // namespace rx |
| |
| namespace egl |
| { |
| class ShareGroup; |
| } // namespace egl |
| |
| namespace gl |
| { |
| class Buffer; |
| struct Caps; |
| class Context; |
| class Framebuffer; |
| struct Limitations; |
| class MemoryObject; |
| class Path; |
| class Program; |
| class ProgramPipeline; |
| class Renderbuffer; |
| class Sampler; |
| class Semaphore; |
| class Shader; |
| class Sync; |
| class Texture; |
| |
| class ResourceManagerBase : angle::NonCopyable |
| { |
| public: |
| ResourceManagerBase(); |
| |
| void addRef(); |
| void release(const Context *context); |
| |
| protected: |
| virtual void reset(const Context *context) = 0; |
| virtual ~ResourceManagerBase(); |
| |
| HandleAllocator mHandleAllocator; |
| |
| private: |
| size_t mRefCount; |
| }; |
| |
| template <typename ResourceType, typename ImplT, typename IDType> |
| class TypedResourceManager : public ResourceManagerBase |
| { |
| public: |
| TypedResourceManager() {} |
| |
| void deleteObject(const Context *context, IDType handle); |
| ANGLE_INLINE bool isHandleGenerated(IDType handle) const |
| { |
| // Zero is always assumed to have been generated implicitly. |
| return GetIDValue(handle) == 0 || mObjectMap.contains(handle); |
| } |
| |
| typename ResourceMap<ResourceType, IDType>::Iterator begin() const |
| { |
| return mObjectMap.begin(); |
| } |
| typename ResourceMap<ResourceType, IDType>::Iterator end() const { return mObjectMap.end(); } |
| |
| protected: |
| ~TypedResourceManager() override; |
| |
| // Inlined in the header for performance. |
| template <typename... ArgTypes> |
| ANGLE_INLINE ResourceType *checkObjectAllocation(rx::GLImplFactory *factory, |
| IDType handle, |
| ArgTypes... args) |
| { |
| ResourceType *value = mObjectMap.query(handle); |
| if (value) |
| { |
| return value; |
| } |
| |
| if (GetIDValue(handle) == 0) |
| { |
| return nullptr; |
| } |
| |
| return checkObjectAllocationImpl(factory, handle, args...); |
| } |
| |
| void reset(const Context *context) override; |
| |
| ResourceMap<ResourceType, IDType> mObjectMap; |
| |
| private: |
| template <typename... ArgTypes> |
| ResourceType *checkObjectAllocationImpl(rx::GLImplFactory *factory, |
| IDType handle, |
| ArgTypes... args) |
| { |
| ResourceType *object = ImplT::AllocateNewObject(factory, handle, args...); |
| |
| if (!mObjectMap.contains(handle)) |
| { |
| this->mHandleAllocator.reserve(GetIDValue(handle)); |
| } |
| mObjectMap.assign(handle, object); |
| |
| return object; |
| } |
| }; |
| |
| class BufferManager : public TypedResourceManager<Buffer, BufferManager, BufferID> |
| { |
| public: |
| BufferID createBuffer(); |
| Buffer *getBuffer(BufferID handle) const; |
| |
| ANGLE_INLINE Buffer *checkBufferAllocation(rx::GLImplFactory *factory, BufferID handle) |
| { |
| return checkObjectAllocation(factory, handle); |
| } |
| |
| // TODO(jmadill): Investigate design which doesn't expose these methods publicly. |
| static Buffer *AllocateNewObject(rx::GLImplFactory *factory, BufferID handle); |
| static void DeleteObject(const Context *context, Buffer *buffer); |
| |
| protected: |
| ~BufferManager() override; |
| }; |
| |
| class ShaderProgramManager : public ResourceManagerBase |
| { |
| public: |
| ShaderProgramManager(); |
| |
| ShaderProgramID createShader(rx::GLImplFactory *factory, |
| const Limitations &rendererLimitations, |
| ShaderType type); |
| void deleteShader(const Context *context, ShaderProgramID shader); |
| Shader *getShader(ShaderProgramID handle) const; |
| |
| ShaderProgramID createProgram(rx::GLImplFactory *factory); |
| void deleteProgram(const Context *context, ShaderProgramID program); |
| |
| ANGLE_INLINE Program *getProgram(ShaderProgramID handle) const |
| { |
| return mPrograms.query(handle); |
| } |
| |
| // For capture and performance counters only. |
| const ResourceMap<Shader, ShaderProgramID> &getShadersForCapture() const { return mShaders; } |
| const ResourceMap<Program, ShaderProgramID> &getProgramsForCaptureAndPerf() const |
| { |
| return mPrograms; |
| } |
| |
| protected: |
| ~ShaderProgramManager() override; |
| |
| private: |
| template <typename ObjectType, typename IDType> |
| void deleteObject(const Context *context, |
| ResourceMap<ObjectType, IDType> *objectMap, |
| IDType id); |
| |
| void reset(const Context *context) override; |
| |
| ResourceMap<Shader, ShaderProgramID> mShaders; |
| ResourceMap<Program, ShaderProgramID> mPrograms; |
| }; |
| |
| class TextureManager : public TypedResourceManager<Texture, TextureManager, TextureID> |
| { |
| public: |
| TextureID createTexture(); |
| ANGLE_INLINE Texture *getTexture(TextureID handle) const |
| { |
| ASSERT(mObjectMap.query({0}) == nullptr); |
| return mObjectMap.query(handle); |
| } |
| |
| void signalAllTexturesDirty() const; |
| |
| ANGLE_INLINE Texture *checkTextureAllocation(rx::GLImplFactory *factory, |
| TextureID handle, |
| TextureType type) |
| { |
| return checkObjectAllocation(factory, handle, type); |
| } |
| |
| static Texture *AllocateNewObject(rx::GLImplFactory *factory, |
| TextureID handle, |
| TextureType type); |
| static void DeleteObject(const Context *context, Texture *texture); |
| |
| void enableHandleAllocatorLogging(); |
| |
| protected: |
| ~TextureManager() override; |
| }; |
| |
| class RenderbufferManager |
| : public TypedResourceManager<Renderbuffer, RenderbufferManager, RenderbufferID> |
| { |
| public: |
| RenderbufferID createRenderbuffer(); |
| Renderbuffer *getRenderbuffer(RenderbufferID handle) const; |
| |
| Renderbuffer *checkRenderbufferAllocation(rx::GLImplFactory *factory, RenderbufferID handle) |
| { |
| return checkObjectAllocation(factory, handle); |
| } |
| |
| static Renderbuffer *AllocateNewObject(rx::GLImplFactory *factory, RenderbufferID handle); |
| static void DeleteObject(const Context *context, Renderbuffer *renderbuffer); |
| |
| protected: |
| ~RenderbufferManager() override; |
| }; |
| |
| class SamplerManager : public TypedResourceManager<Sampler, SamplerManager, SamplerID> |
| { |
| public: |
| SamplerID createSampler(); |
| Sampler *getSampler(SamplerID handle) const; |
| bool isSampler(SamplerID sampler) const; |
| |
| Sampler *checkSamplerAllocation(rx::GLImplFactory *factory, SamplerID handle) |
| { |
| return checkObjectAllocation(factory, handle); |
| } |
| |
| static Sampler *AllocateNewObject(rx::GLImplFactory *factory, SamplerID handle); |
| static void DeleteObject(const Context *context, Sampler *sampler); |
| |
| protected: |
| ~SamplerManager() override; |
| }; |
| |
| class SyncManager : public TypedResourceManager<Sync, SyncManager, GLuint> |
| { |
| public: |
| GLuint createSync(rx::GLImplFactory *factory); |
| Sync *getSync(GLuint handle) const; |
| |
| static void DeleteObject(const Context *context, Sync *sync); |
| |
| protected: |
| ~SyncManager() override; |
| }; |
| |
| class FramebufferManager |
| : public TypedResourceManager<Framebuffer, FramebufferManager, FramebufferID> |
| { |
| public: |
| FramebufferID createFramebuffer(); |
| Framebuffer *getFramebuffer(FramebufferID handle) const; |
| void setDefaultFramebuffer(Framebuffer *framebuffer); |
| Framebuffer *getDefaultFramebuffer() const; |
| |
| void invalidateFramebufferCompletenessCache() const; |
| |
| Framebuffer *checkFramebufferAllocation(rx::GLImplFactory *factory, |
| const Caps &caps, |
| FramebufferID handle, |
| egl::ShareGroup *shareGroup) |
| { |
| return checkObjectAllocation<const Caps &>(factory, handle, caps, shareGroup); |
| } |
| |
| static Framebuffer *AllocateNewObject(rx::GLImplFactory *factory, |
| FramebufferID handle, |
| const Caps &caps, |
| egl::ShareGroup *shareGroup); |
| static void DeleteObject(const Context *context, Framebuffer *framebuffer); |
| |
| protected: |
| ~FramebufferManager() override; |
| }; |
| |
| class ProgramPipelineManager |
| : public TypedResourceManager<ProgramPipeline, ProgramPipelineManager, ProgramPipelineID> |
| { |
| public: |
| ProgramPipelineID createProgramPipeline(); |
| ProgramPipeline *getProgramPipeline(ProgramPipelineID handle) const; |
| |
| ProgramPipeline *checkProgramPipelineAllocation(rx::GLImplFactory *factory, |
| ProgramPipelineID handle) |
| { |
| return checkObjectAllocation(factory, handle); |
| } |
| |
| static ProgramPipeline *AllocateNewObject(rx::GLImplFactory *factory, ProgramPipelineID handle); |
| static void DeleteObject(const Context *context, ProgramPipeline *pipeline); |
| |
| protected: |
| ~ProgramPipelineManager() override; |
| }; |
| |
| class MemoryObjectManager : public ResourceManagerBase |
| { |
| public: |
| MemoryObjectManager(); |
| |
| MemoryObjectID createMemoryObject(rx::GLImplFactory *factory); |
| void deleteMemoryObject(const Context *context, MemoryObjectID handle); |
| MemoryObject *getMemoryObject(MemoryObjectID handle) const; |
| |
| protected: |
| ~MemoryObjectManager() override; |
| |
| private: |
| void reset(const Context *context) override; |
| |
| ResourceMap<MemoryObject, MemoryObjectID> mMemoryObjects; |
| }; |
| |
| class SemaphoreManager : public ResourceManagerBase |
| { |
| public: |
| SemaphoreManager(); |
| |
| SemaphoreID createSemaphore(rx::GLImplFactory *factory); |
| void deleteSemaphore(const Context *context, SemaphoreID handle); |
| Semaphore *getSemaphore(SemaphoreID handle) const; |
| |
| protected: |
| ~SemaphoreManager() override; |
| |
| private: |
| void reset(const Context *context) override; |
| |
| ResourceMap<Semaphore, SemaphoreID> mSemaphores; |
| }; |
| } // namespace gl |
| |
| #endif // LIBANGLE_RESOURCEMANAGER_H_ |