summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE/ResourceManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/ResourceManager.cpp')
-rw-r--r--gfx/angle/checkout/src/libANGLE/ResourceManager.cpp526
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