diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/ResourceManager.cpp')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/ResourceManager.cpp | 526 |
1 files changed, 526 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/ResourceManager.cpp b/gfx/angle/checkout/src/libANGLE/ResourceManager.cpp new file mode 100644 index 0000000000..c440f8d444 --- /dev/null +++ b/gfx/angle/checkout/src/libANGLE/ResourceManager.cpp @@ -0,0 +1,526 @@ +// +// 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.cpp: Implements the the ResourceManager classes, which handle allocation and +// lifetime of GL objects. + +#include "libANGLE/ResourceManager.h" + +#include "libANGLE/Buffer.h" +#include "libANGLE/Context.h" +#include "libANGLE/Fence.h" +#include "libANGLE/MemoryObject.h" +#include "libANGLE/Program.h" +#include "libANGLE/ProgramPipeline.h" +#include "libANGLE/Query.h" +#include "libANGLE/Renderbuffer.h" +#include "libANGLE/Sampler.h" +#include "libANGLE/Semaphore.h" +#include "libANGLE/Shader.h" +#include "libANGLE/Texture.h" +#include "libANGLE/renderer/ContextImpl.h" + +namespace gl +{ + +namespace +{ + +template <typename ResourceType, typename IDType> +IDType AllocateEmptyObject(HandleAllocator *handleAllocator, + ResourceMap<ResourceType, IDType> *objectMap) +{ + IDType handle = PackParam<IDType>(handleAllocator->allocate()); + objectMap->assign(handle, nullptr); + return handle; +} + +} // anonymous namespace + +ResourceManagerBase::ResourceManagerBase() : mRefCount(1) {} + +ResourceManagerBase::~ResourceManagerBase() = default; + +void ResourceManagerBase::addRef() +{ + mRefCount++; +} + +void ResourceManagerBase::release(const Context *context) +{ + if (--mRefCount == 0) + { + reset(context); + delete this; + } +} + +template <typename ResourceType, typename ImplT, typename IDType> +TypedResourceManager<ResourceType, ImplT, IDType>::~TypedResourceManager() +{ + ASSERT(mObjectMap.empty()); +} + +template <typename ResourceType, typename ImplT, typename IDType> +void TypedResourceManager<ResourceType, ImplT, IDType>::reset(const Context *context) +{ + this->mHandleAllocator.reset(); + for (const auto &resource : mObjectMap) + { + if (resource.second) + { + ImplT::DeleteObject(context, resource.second); + } + } + mObjectMap.clear(); +} + +template <typename ResourceType, typename ImplT, typename IDType> +void TypedResourceManager<ResourceType, ImplT, IDType>::deleteObject(const Context *context, + IDType handle) +{ + ResourceType *resource = nullptr; + if (!mObjectMap.erase(handle, &resource)) + { + return; + } + + // Requires an explicit this-> because of C++ template rules. + this->mHandleAllocator.release(GetIDValue(handle)); + + if (resource) + { + ImplT::DeleteObject(context, resource); + } +} + +// Unclear why Clang warns about weak vtables in this case. +ANGLE_DISABLE_WEAK_TEMPLATE_VTABLES_WARNING +template class TypedResourceManager<Buffer, BufferManager, BufferID>; +template class TypedResourceManager<Texture, TextureManager, TextureID>; +template class TypedResourceManager<Renderbuffer, RenderbufferManager, RenderbufferID>; +template class TypedResourceManager<Sampler, SamplerManager, SamplerID>; +template class TypedResourceManager<Sync, SyncManager, GLuint>; +template class TypedResourceManager<Framebuffer, FramebufferManager, FramebufferID>; +template class TypedResourceManager<ProgramPipeline, ProgramPipelineManager, ProgramPipelineID>; +ANGLE_REENABLE_WEAK_TEMPLATE_VTABLES_WARNING + +// BufferManager Implementation. +BufferManager::~BufferManager() = default; + +// static +Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, BufferID handle) +{ + Buffer *buffer = new Buffer(factory, handle); + buffer->addRef(); + return buffer; +} + +// static +void BufferManager::DeleteObject(const Context *context, Buffer *buffer) +{ + buffer->release(context); +} + +BufferID BufferManager::createBuffer() +{ + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); +} + +Buffer *BufferManager::getBuffer(BufferID handle) const +{ + return mObjectMap.query(handle); +} + +// ShaderProgramManager Implementation. + +ShaderProgramManager::ShaderProgramManager() {} + +ShaderProgramManager::~ShaderProgramManager() +{ + ASSERT(mPrograms.empty()); + ASSERT(mShaders.empty()); +} + +void ShaderProgramManager::reset(const Context *context) +{ + while (!mPrograms.empty()) + { + deleteProgram(context, {mPrograms.begin()->first}); + } + mPrograms.clear(); + while (!mShaders.empty()) + { + deleteShader(context, {mShaders.begin()->first}); + } + mShaders.clear(); +} + +ShaderProgramID ShaderProgramManager::createShader(rx::GLImplFactory *factory, + const gl::Limitations &rendererLimitations, + ShaderType type) +{ + ASSERT(type != ShaderType::InvalidEnum); + ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()}; + mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle)); + return handle; +} + +void ShaderProgramManager::deleteShader(const Context *context, ShaderProgramID shader) +{ + deleteObject(context, &mShaders, shader); +} + +Shader *ShaderProgramManager::getShader(ShaderProgramID handle) const +{ + return mShaders.query(handle); +} + +ShaderProgramID ShaderProgramManager::createProgram(rx::GLImplFactory *factory) +{ + ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()}; + mPrograms.assign(handle, new Program(factory, this, handle)); + return handle; +} + +void ShaderProgramManager::deleteProgram(const gl::Context *context, ShaderProgramID program) +{ + deleteObject(context, &mPrograms, program); +} + +template <typename ObjectType, typename IDType> +void ShaderProgramManager::deleteObject(const Context *context, + ResourceMap<ObjectType, IDType> *objectMap, + IDType id) +{ + ObjectType *object = objectMap->query(id); + if (!object) + { + return; + } + + if (object->getRefCount() == 0) + { + mHandleAllocator.release(id.value); + object->onDestroy(context); + objectMap->erase(id, &object); + } + else + { + object->flagForDeletion(); + } +} + +// TextureManager Implementation. + +TextureManager::~TextureManager() = default; + +// static +Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory, + TextureID handle, + TextureType type) +{ + Texture *texture = new Texture(factory, handle, type); + texture->addRef(); + return texture; +} + +// static +void TextureManager::DeleteObject(const Context *context, Texture *texture) +{ + texture->release(context); +} + +TextureID TextureManager::createTexture() +{ + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); +} + +void TextureManager::signalAllTexturesDirty() const +{ + for (const auto &texture : mObjectMap) + { + if (texture.second) + { + // We don't know if the Texture needs init, but that's ok, since it will only force + // a re-check, and will not initialize the pixels if it's not needed. + texture.second->signalDirtyStorage(InitState::MayNeedInit); + } + } +} + +void TextureManager::enableHandleAllocatorLogging() +{ + mHandleAllocator.enableLogging(true); +} + +// RenderbufferManager Implementation. + +RenderbufferManager::~RenderbufferManager() = default; + +// static +Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory, + RenderbufferID handle) +{ + Renderbuffer *renderbuffer = new Renderbuffer(factory, handle); + renderbuffer->addRef(); + return renderbuffer; +} + +// static +void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer) +{ + renderbuffer->release(context); +} + +RenderbufferID RenderbufferManager::createRenderbuffer() +{ + return {AllocateEmptyObject(&mHandleAllocator, &mObjectMap)}; +} + +Renderbuffer *RenderbufferManager::getRenderbuffer(RenderbufferID handle) const +{ + return mObjectMap.query(handle); +} + +// SamplerManager Implementation. + +SamplerManager::~SamplerManager() = default; + +// static +Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, SamplerID handle) +{ + Sampler *sampler = new Sampler(factory, handle); + sampler->addRef(); + return sampler; +} + +// static +void SamplerManager::DeleteObject(const Context *context, Sampler *sampler) +{ + sampler->release(context); +} + +SamplerID SamplerManager::createSampler() +{ + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); +} + +Sampler *SamplerManager::getSampler(SamplerID handle) const +{ + return mObjectMap.query(handle); +} + +bool SamplerManager::isSampler(SamplerID sampler) const +{ + return mObjectMap.contains(sampler); +} + +// SyncManager Implementation. + +SyncManager::~SyncManager() = default; + +// static +void SyncManager::DeleteObject(const Context *context, Sync *sync) +{ + sync->release(context); +} + +GLuint SyncManager::createSync(rx::GLImplFactory *factory) +{ + GLuint handle = mHandleAllocator.allocate(); + Sync *sync = new Sync(factory, handle); + sync->addRef(); + mObjectMap.assign(handle, sync); + return handle; +} + +Sync *SyncManager::getSync(GLuint handle) const +{ + return mObjectMap.query(handle); +} + +// FramebufferManager Implementation. + +FramebufferManager::~FramebufferManager() = default; + +// static +Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory, + FramebufferID handle, + const Caps &caps, + egl::ShareGroup *shareGroup) +{ + // Make sure the caller isn't using a reserved handle. + ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle); + return new Framebuffer(caps, factory, handle, shareGroup); +} + +// static +void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer) +{ + framebuffer->onDestroy(context); + delete framebuffer; +} + +FramebufferID FramebufferManager::createFramebuffer() +{ + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); +} + +Framebuffer *FramebufferManager::getFramebuffer(FramebufferID handle) const +{ + return mObjectMap.query(handle); +} + +void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer) +{ + ASSERT(framebuffer == nullptr || framebuffer->isDefault()); + mObjectMap.assign(Framebuffer::kDefaultDrawFramebufferHandle, framebuffer); +} + +Framebuffer *FramebufferManager::getDefaultFramebuffer() const +{ + return getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle); +} + +void FramebufferManager::invalidateFramebufferCompletenessCache() const +{ + for (const auto &framebuffer : mObjectMap) + { + if (framebuffer.second) + { + framebuffer.second->invalidateCompletenessCache(); + } + } +} + +// ProgramPipelineManager Implementation. + +ProgramPipelineManager::~ProgramPipelineManager() = default; + +// static +ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory, + ProgramPipelineID handle) +{ + ProgramPipeline *pipeline = new ProgramPipeline(factory, handle); + pipeline->addRef(); + return pipeline; +} + +// static +void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline) +{ + pipeline->release(context); +} + +ProgramPipelineID ProgramPipelineManager::createProgramPipeline() +{ + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); +} + +ProgramPipeline *ProgramPipelineManager::getProgramPipeline(ProgramPipelineID handle) const +{ + return mObjectMap.query(handle); +} + +// MemoryObjectManager Implementation. + +MemoryObjectManager::MemoryObjectManager() {} + +MemoryObjectManager::~MemoryObjectManager() +{ + ASSERT(mMemoryObjects.empty()); +} + +void MemoryObjectManager::reset(const Context *context) +{ + while (!mMemoryObjects.empty()) + { + deleteMemoryObject(context, {mMemoryObjects.begin()->first}); + } + mMemoryObjects.clear(); +} + +MemoryObjectID MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory) +{ + MemoryObjectID handle = MemoryObjectID{mHandleAllocator.allocate()}; + MemoryObject *memoryObject = new MemoryObject(factory, handle); + memoryObject->addRef(); + mMemoryObjects.assign(handle, memoryObject); + return handle; +} + +void MemoryObjectManager::deleteMemoryObject(const Context *context, MemoryObjectID handle) +{ + MemoryObject *memoryObject = nullptr; + if (!mMemoryObjects.erase(handle, &memoryObject)) + { + return; + } + + // Requires an explicit this-> because of C++ template rules. + this->mHandleAllocator.release(handle.value); + + if (memoryObject) + { + memoryObject->release(context); + } +} + +MemoryObject *MemoryObjectManager::getMemoryObject(MemoryObjectID handle) const +{ + return mMemoryObjects.query(handle); +} + +// SemaphoreManager Implementation. + +SemaphoreManager::SemaphoreManager() {} + +SemaphoreManager::~SemaphoreManager() +{ + ASSERT(mSemaphores.empty()); +} + +void SemaphoreManager::reset(const Context *context) +{ + while (!mSemaphores.empty()) + { + deleteSemaphore(context, {mSemaphores.begin()->first}); + } + mSemaphores.clear(); +} + +SemaphoreID SemaphoreManager::createSemaphore(rx::GLImplFactory *factory) +{ + SemaphoreID handle = SemaphoreID{mHandleAllocator.allocate()}; + Semaphore *semaphore = new Semaphore(factory, handle); + semaphore->addRef(); + mSemaphores.assign(handle, semaphore); + return handle; +} + +void SemaphoreManager::deleteSemaphore(const Context *context, SemaphoreID handle) +{ + Semaphore *semaphore = nullptr; + if (!mSemaphores.erase(handle, &semaphore)) + { + return; + } + + // Requires an explicit this-> because of C++ template rules. + this->mHandleAllocator.release(handle.value); + + if (semaphore) + { + semaphore->release(context); + } +} + +Semaphore *SemaphoreManager::getSemaphore(SemaphoreID handle) const +{ + return mSemaphores.query(handle); +} +} // namespace gl |