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.cpp579
1 files changed, 579 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..133cfba483
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/ResourceManager.cpp
@@ -0,0 +1,579 @@
+//
+// Copyright (c) 2002-2016 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/Path.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/ProgramPipeline.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>
+GLuint AllocateEmptyObject(HandleAllocator *handleAllocator, ResourceMap<ResourceType> *objectMap)
+{
+ GLuint handle = handleAllocator->allocate();
+ objectMap->assign(handle, nullptr);
+ return handle;
+}
+
+} // anonymous namespace
+
+template <typename HandleAllocatorType>
+ResourceManagerBase<HandleAllocatorType>::ResourceManagerBase() : mRefCount(1)
+{}
+
+template <typename HandleAllocatorType>
+void ResourceManagerBase<HandleAllocatorType>::addRef()
+{
+ mRefCount++;
+}
+
+template <typename HandleAllocatorType>
+void ResourceManagerBase<HandleAllocatorType>::release(const Context *context)
+{
+ if (--mRefCount == 0)
+ {
+ reset(context);
+ delete this;
+ }
+}
+
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::~TypedResourceManager()
+{
+ ASSERT(mObjectMap.empty());
+}
+
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::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 HandleAllocatorType, typename ImplT>
+void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::deleteObject(
+ const Context *context,
+ GLuint handle)
+{
+ ResourceType *resource = nullptr;
+ if (!mObjectMap.erase(handle, &resource))
+ {
+ return;
+ }
+
+ // Requires an explicit this-> because of C++ template rules.
+ this->mHandleAllocator.release(handle);
+
+ if (resource)
+ {
+ ImplT::DeleteObject(context, resource);
+ }
+}
+
+template class ResourceManagerBase<HandleAllocator>;
+template class ResourceManagerBase<HandleRangeAllocator>;
+template class TypedResourceManager<Buffer, HandleAllocator, BufferManager>;
+template class TypedResourceManager<Texture, HandleAllocator, TextureManager>;
+template class TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>;
+template class TypedResourceManager<Sampler, HandleAllocator, SamplerManager>;
+template class TypedResourceManager<Sync, HandleAllocator, SyncManager>;
+template class TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>;
+template class TypedResourceManager<ProgramPipeline, HandleAllocator, ProgramPipelineManager>;
+
+// BufferManager Implementation.
+
+// static
+Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
+{
+ Buffer *buffer = new Buffer(factory, handle);
+ buffer->addRef();
+ return buffer;
+}
+
+// static
+void BufferManager::DeleteObject(const Context *context, Buffer *buffer)
+{
+ buffer->release(context);
+}
+
+GLuint BufferManager::createBuffer()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Buffer *BufferManager::getBuffer(GLuint 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();
+}
+
+GLuint ShaderProgramManager::createShader(rx::GLImplFactory *factory,
+ const gl::Limitations &rendererLimitations,
+ ShaderType type)
+{
+ ASSERT(type != ShaderType::InvalidEnum);
+ GLuint handle = mHandleAllocator.allocate();
+ mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
+ return handle;
+}
+
+void ShaderProgramManager::deleteShader(const Context *context, GLuint shader)
+{
+ deleteObject(context, &mShaders, shader);
+}
+
+Shader *ShaderProgramManager::getShader(GLuint handle) const
+{
+ return mShaders.query(handle);
+}
+
+GLuint ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
+{
+ GLuint handle = mHandleAllocator.allocate();
+ mPrograms.assign(handle, new Program(factory, this, handle));
+ return handle;
+}
+
+void ShaderProgramManager::deleteProgram(const gl::Context *context, GLuint program)
+{
+ deleteObject(context, &mPrograms, program);
+}
+
+template <typename ObjectType>
+void ShaderProgramManager::deleteObject(const Context *context,
+ ResourceMap<ObjectType> *objectMap,
+ GLuint id)
+{
+ ObjectType *object = objectMap->query(id);
+ if (!object)
+ {
+ return;
+ }
+
+ if (object->getRefCount() == 0)
+ {
+ mHandleAllocator.release(id);
+ object->onDestroy(context);
+ objectMap->erase(id, &object);
+ }
+ else
+ {
+ object->flagForDeletion();
+ }
+}
+
+// TextureManager Implementation.
+
+// static
+Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory,
+ GLuint 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);
+}
+
+GLuint 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.
+
+// static
+Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
+{
+ Renderbuffer *renderbuffer = new Renderbuffer(factory, handle);
+ renderbuffer->addRef();
+ return renderbuffer;
+}
+
+// static
+void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
+{
+ renderbuffer->release(context);
+}
+
+GLuint RenderbufferManager::createRenderbuffer()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Renderbuffer *RenderbufferManager::getRenderbuffer(GLuint handle) const
+{
+ return mObjectMap.query(handle);
+}
+
+// SamplerManager Implementation.
+
+// static
+Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
+{
+ Sampler *sampler = new Sampler(factory, handle);
+ sampler->addRef();
+ return sampler;
+}
+
+// static
+void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
+{
+ sampler->release(context);
+}
+
+GLuint SamplerManager::createSampler()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Sampler *SamplerManager::getSampler(GLuint handle) const
+{
+ return mObjectMap.query(handle);
+}
+
+bool SamplerManager::isSampler(GLuint sampler) const
+{
+ return mObjectMap.contains(sampler);
+}
+
+// SyncManager Implementation.
+
+// 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->createSync(), handle);
+ sync->addRef();
+ mObjectMap.assign(handle, sync);
+ return handle;
+}
+
+Sync *SyncManager::getSync(GLuint handle) const
+{
+ return mObjectMap.query(handle);
+}
+
+// PathManager Implementation.
+
+PathManager::PathManager() = default;
+
+angle::Result PathManager::createPaths(Context *context, GLsizei range, GLuint *createdOut)
+{
+ *createdOut = 0;
+
+ // Allocate client side handles.
+ const GLuint client = mHandleAllocator.allocateRange(static_cast<GLuint>(range));
+ if (client == HandleRangeAllocator::kInvalidHandle)
+ {
+ context->handleError(GL_OUT_OF_MEMORY, "Failed to allocate path handle range.", __FILE__,
+ ANGLE_FUNCTION, __LINE__);
+ return angle::Result::Stop;
+ }
+
+ const auto &paths = context->getImplementation()->createPaths(range);
+ if (paths.empty())
+ {
+ mHandleAllocator.releaseRange(client, range);
+ context->handleError(GL_OUT_OF_MEMORY, "Failed to allocate path objects.", __FILE__,
+ ANGLE_FUNCTION, __LINE__);
+ return angle::Result::Stop;
+ }
+
+ for (GLsizei i = 0; i < range; ++i)
+ {
+ rx::PathImpl *impl = paths[static_cast<unsigned>(i)];
+ const auto id = client + i;
+ mPaths.assign(id, new Path(impl));
+ }
+ *createdOut = client;
+ return angle::Result::Continue;
+}
+
+void PathManager::deletePaths(GLuint first, GLsizei range)
+{
+ for (GLsizei i = 0; i < range; ++i)
+ {
+ const auto id = first + i;
+ Path *p = nullptr;
+ if (!mPaths.erase(id, &p))
+ continue;
+ delete p;
+ }
+ mHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
+}
+
+Path *PathManager::getPath(GLuint handle) const
+{
+ return mPaths.query(handle);
+}
+
+bool PathManager::hasPath(GLuint handle) const
+{
+ return mHandleAllocator.isUsed(handle);
+}
+
+PathManager::~PathManager()
+{
+ ASSERT(mPaths.empty());
+}
+
+void PathManager::reset(const Context *context)
+{
+ for (auto path : mPaths)
+ {
+ SafeDelete(path.second);
+ }
+ mPaths.clear();
+}
+
+// FramebufferManager Implementation.
+
+// static
+Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
+ GLuint handle,
+ const Caps &caps)
+{
+ return new Framebuffer(caps, factory, handle);
+}
+
+// static
+void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
+{
+ framebuffer->onDestroy(context);
+ delete framebuffer;
+}
+
+GLuint FramebufferManager::createFramebuffer()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+Framebuffer *FramebufferManager::getFramebuffer(GLuint handle) const
+{
+ return mObjectMap.query(handle);
+}
+
+void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
+{
+ ASSERT(framebuffer == nullptr || framebuffer->id() == 0);
+ mObjectMap.assign(0, framebuffer);
+}
+
+void FramebufferManager::invalidateFramebufferComplenessCache() const
+{
+ for (const auto &framebuffer : mObjectMap)
+ {
+ if (framebuffer.second)
+ {
+ framebuffer.second->invalidateCompletenessCache();
+ }
+ }
+}
+
+// ProgramPipelineManager Implementation.
+
+// static
+ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
+ GLuint handle)
+{
+ ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
+ pipeline->addRef();
+ return pipeline;
+}
+
+// static
+void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
+{
+ pipeline->release(context);
+}
+
+GLuint ProgramPipelineManager::createProgramPipeline()
+{
+ return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
+}
+
+ProgramPipeline *ProgramPipelineManager::getProgramPipeline(GLuint 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();
+}
+
+GLuint MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory)
+{
+ GLuint handle = mHandleAllocator.allocate();
+ MemoryObject *memoryObject = new MemoryObject(factory, handle);
+ memoryObject->addRef();
+ mMemoryObjects.assign(handle, memoryObject);
+ return handle;
+}
+
+void MemoryObjectManager::deleteMemoryObject(const Context *context, GLuint handle)
+{
+ MemoryObject *memoryObject = nullptr;
+ if (!mMemoryObjects.erase(handle, &memoryObject))
+ {
+ return;
+ }
+
+ // Requires an explicit this-> because of C++ template rules.
+ this->mHandleAllocator.release(handle);
+
+ if (memoryObject)
+ {
+ memoryObject->release(context);
+ }
+}
+
+MemoryObject *MemoryObjectManager::getMemoryObject(GLuint 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();
+}
+
+GLuint SemaphoreManager::createSemaphore(rx::GLImplFactory *factory)
+{
+ GLuint handle = mHandleAllocator.allocate();
+ Semaphore *semaphore = new Semaphore(factory, handle);
+ semaphore->addRef();
+ mSemaphores.assign(handle, semaphore);
+ return handle;
+}
+
+void SemaphoreManager::deleteSemaphore(const Context *context, GLuint handle)
+{
+ Semaphore *semaphore = nullptr;
+ if (!mSemaphores.erase(handle, &semaphore))
+ {
+ return;
+ }
+
+ // Requires an explicit this-> because of C++ template rules.
+ this->mHandleAllocator.release(handle);
+
+ if (semaphore)
+ {
+ semaphore->release(context);
+ }
+}
+
+Semaphore *SemaphoreManager::getSemaphore(GLuint handle) const
+{
+ return mSemaphores.query(handle);
+}
+
+} // namespace gl