diff options
Diffstat (limited to 'src/3rdparty/angle/src/libANGLE/ResourceManager.cpp')
-rw-r--r-- | src/3rdparty/angle/src/libANGLE/ResourceManager.cpp | 603 |
1 files changed, 315 insertions, 288 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp index dc9dad1e9f..79eb7e5f42 100644 --- a/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp +++ b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp @@ -1,456 +1,483 @@ // -// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. +// 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 gl::ResourceManager class, which tracks and -// retrieves objects which may be shared by multiple Contexts. +// 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/Fence.h" +#include "libANGLE/Path.h" #include "libANGLE/Program.h" +#include "libANGLE/ProgramPipeline.h" #include "libANGLE/Renderbuffer.h" +#include "libANGLE/Sampler.h" #include "libANGLE/Shader.h" #include "libANGLE/Texture.h" -#include "libANGLE/Sampler.h" -#include "libANGLE/Fence.h" -#include "libANGLE/renderer/Renderer.h" +#include "libANGLE/renderer/GLImplFactory.h" namespace gl { -ResourceManager::ResourceManager(rx::ImplFactory *factory) - : mFactory(factory), - mRefCount(1) + +namespace +{ + +template <typename ResourceType> +GLuint AllocateEmptyObject(HandleAllocator *handleAllocator, ResourceMap<ResourceType> *objectMap) { + GLuint handle = handleAllocator->allocate(); + objectMap->assign(handle, nullptr); + return handle; } -ResourceManager::~ResourceManager() +} // anonymous namespace + +template <typename HandleAllocatorType> +ResourceManagerBase<HandleAllocatorType>::ResourceManagerBase() : mRefCount(1) { - while (!mBufferMap.empty()) - { - deleteBuffer(mBufferMap.begin()->first); - } +} - while (!mProgramMap.empty()) - { - deleteProgram(mProgramMap.begin()->first); - } +template <typename HandleAllocatorType> +void ResourceManagerBase<HandleAllocatorType>::addRef() +{ + mRefCount++; +} - while (!mShaderMap.empty()) +template <typename HandleAllocatorType> +void ResourceManagerBase<HandleAllocatorType>::release(const Context *context) +{ + if (--mRefCount == 0) { - deleteShader(mShaderMap.begin()->first); + reset(context); + delete this; } +} - while (!mRenderbufferMap.empty()) - { - deleteRenderbuffer(mRenderbufferMap.begin()->first); - } +template <typename ResourceType, typename HandleAllocatorType, typename ImplT> +TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::~TypedResourceManager() +{ + ASSERT(mObjectMap.empty()); +} - while (!mTextureMap.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) { - deleteTexture(mTextureMap.begin()->first); + if (resource.second) + { + ImplT::DeleteObject(context, resource.second); + } } + mObjectMap.clear(); +} - while (!mSamplerMap.empty()) +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)) { - deleteSampler(mSamplerMap.begin()->first); + return; } - while (!mFenceSyncMap.empty()) + // Requires an explicit this-> because of C++ template rules. + this->mHandleAllocator.release(handle); + + if (resource) { - deleteFenceSync(mFenceSyncMap.begin()->first); + ImplT::DeleteObject(context, resource); } } -void ResourceManager::addRef() +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) { - mRefCount++; + Buffer *buffer = new Buffer(factory, handle); + buffer->addRef(); + return buffer; } -void ResourceManager::release() +// static +void BufferManager::DeleteObject(const Context *context, Buffer *buffer) { - if (--mRefCount == 0) - { - delete this; - } + buffer->release(context); } -// Returns an unused buffer name -GLuint ResourceManager::createBuffer() +GLuint BufferManager::createBuffer() { - GLuint handle = mBufferHandleAllocator.allocate(); + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); +} - mBufferMap[handle] = NULL; +Buffer *BufferManager::getBuffer(GLuint handle) const +{ + return mObjectMap.query(handle); +} - return handle; +// ShaderProgramManager Implementation. + +ShaderProgramManager::ShaderProgramManager() +{ } -// Returns an unused shader/program name -GLuint ResourceManager::createShader(const gl::Limitations &rendererLimitations, GLenum type) +ShaderProgramManager::~ShaderProgramManager() { - GLuint handle = mProgramShaderHandleAllocator.allocate(); + ASSERT(mPrograms.empty()); + ASSERT(mShaders.empty()); +} - if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER) +void ShaderProgramManager::reset(const Context *context) +{ + while (!mPrograms.empty()) { - mShaderMap[handle] = new Shader(this, mFactory, rendererLimitations, type, handle); + deleteProgram(context, mPrograms.begin()->first); } - else UNREACHABLE(); - - return handle; + mPrograms.clear(); + while (!mShaders.empty()) + { + deleteShader(context, mShaders.begin()->first); + } + mShaders.clear(); } -// Returns an unused program/shader name -GLuint ResourceManager::createProgram() +GLuint ShaderProgramManager::createShader(rx::GLImplFactory *factory, + const gl::Limitations &rendererLimitations, + GLenum type) { - GLuint handle = mProgramShaderHandleAllocator.allocate(); - - mProgramMap[handle] = new Program(mFactory, this, handle); - + ASSERT(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER || type == GL_COMPUTE_SHADER || + type == GL_GEOMETRY_SHADER_EXT); + GLuint handle = mHandleAllocator.allocate(); + mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle)); return handle; } -// Returns an unused texture name -GLuint ResourceManager::createTexture() +void ShaderProgramManager::deleteShader(const Context *context, GLuint shader) { - GLuint handle = mTextureHandleAllocator.allocate(); - - mTextureMap[handle] = NULL; - - return handle; + deleteObject(context, &mShaders, shader); } -// Returns an unused renderbuffer name -GLuint ResourceManager::createRenderbuffer() +Shader *ShaderProgramManager::getShader(GLuint handle) const { - GLuint handle = mRenderbufferHandleAllocator.allocate(); - - mRenderbufferMap[handle] = NULL; - - return handle; + return mShaders.query(handle); } -// Returns an unused sampler name -GLuint ResourceManager::createSampler() +GLuint ShaderProgramManager::createProgram(rx::GLImplFactory *factory) { - GLuint handle = mSamplerHandleAllocator.allocate(); - - mSamplerMap[handle] = NULL; - + GLuint handle = mHandleAllocator.allocate(); + mPrograms.assign(handle, new Program(factory, this, handle)); return handle; } -// Returns the next unused fence name, and allocates the fence -GLuint ResourceManager::createFenceSync() +void ShaderProgramManager::deleteProgram(const gl::Context *context, GLuint program) { - GLuint handle = mFenceSyncHandleAllocator.allocate(); - - FenceSync *fenceSync = new FenceSync(mFactory->createFenceSync(), handle); - fenceSync->addRef(); - mFenceSyncMap[handle] = fenceSync; + deleteObject(context, &mPrograms, program); +} - return handle; +Program *ShaderProgramManager::getProgram(GLuint handle) const +{ + return mPrograms.query(handle); } -void ResourceManager::deleteBuffer(GLuint buffer) +template <typename ObjectType> +void ShaderProgramManager::deleteObject(const Context *context, + ResourceMap<ObjectType> *objectMap, + GLuint id) { - BufferMap::iterator bufferObject = mBufferMap.find(buffer); + ObjectType *object = objectMap->query(id); + if (!object) + { + return; + } - if (bufferObject != mBufferMap.end()) + if (object->getRefCount() == 0) + { + mHandleAllocator.release(id); + object->onDestroy(context); + objectMap->erase(id, &object); + } + else { - mBufferHandleAllocator.release(bufferObject->first); - if (bufferObject->second) bufferObject->second->release(); - mBufferMap.erase(bufferObject); + object->flagForDeletion(); } } -void ResourceManager::deleteShader(GLuint shader) +// TextureManager Implementation. + +// static +Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle, GLenum target) { - ShaderMap::iterator shaderObject = mShaderMap.find(shader); + Texture *texture = new Texture(factory, handle, target); + texture->addRef(); + return texture; +} - if (shaderObject != mShaderMap.end()) - { - if (shaderObject->second->getRefCount() == 0) - { - mProgramShaderHandleAllocator.release(shaderObject->first); - delete shaderObject->second; - mShaderMap.erase(shaderObject); - } - else - { - shaderObject->second->flagForDeletion(); - } - } +// static +void TextureManager::DeleteObject(const Context *context, Texture *texture) +{ + texture->release(context); } -void ResourceManager::deleteProgram(GLuint program) +GLuint TextureManager::createTexture() { - ProgramMap::iterator programObject = mProgramMap.find(program); + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); +} + +Texture *TextureManager::getTexture(GLuint handle) const +{ + ASSERT(mObjectMap.query(0) == nullptr); + return mObjectMap.query(handle); +} - if (programObject != mProgramMap.end()) +void TextureManager::signalAllTexturesDirty() const +{ + for (const auto &texture : mObjectMap) { - if (programObject->second->getRefCount() == 0) + if (texture.second) { - mProgramShaderHandleAllocator.release(programObject->first); - delete programObject->second; - mProgramMap.erase(programObject); - } - else - { - programObject->second->flagForDeletion(); + // 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->signalDirty(InitState::MayNeedInit); } } } -void ResourceManager::deleteTexture(GLuint texture) -{ - TextureMap::iterator textureObject = mTextureMap.find(texture); +// RenderbufferManager Implementation. - if (textureObject != mTextureMap.end()) - { - mTextureHandleAllocator.release(textureObject->first); - if (textureObject->second) textureObject->second->release(); - mTextureMap.erase(textureObject); - } +// static +Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle) +{ + Renderbuffer *renderbuffer = new Renderbuffer(factory->createRenderbuffer(), handle); + renderbuffer->addRef(); + return renderbuffer; } -void ResourceManager::deleteRenderbuffer(GLuint renderbuffer) +// static +void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer) { - RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer); + renderbuffer->release(context); +} - if (renderbufferObject != mRenderbufferMap.end()) - { - mRenderbufferHandleAllocator.release(renderbufferObject->first); - if (renderbufferObject->second) renderbufferObject->second->release(); - mRenderbufferMap.erase(renderbufferObject); - } +GLuint RenderbufferManager::createRenderbuffer() +{ + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); } -void ResourceManager::deleteSampler(GLuint sampler) +Renderbuffer *RenderbufferManager::getRenderbuffer(GLuint handle) const { - auto samplerObject = mSamplerMap.find(sampler); + return mObjectMap.query(handle); +} - if (samplerObject != mSamplerMap.end()) - { - mSamplerHandleAllocator.release(samplerObject->first); - if (samplerObject->second) samplerObject->second->release(); - mSamplerMap.erase(samplerObject); - } +// SamplerManager Implementation. + +// static +Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle) +{ + Sampler *sampler = new Sampler(factory, handle); + sampler->addRef(); + return sampler; } -void ResourceManager::deleteFenceSync(GLuint fenceSync) +// static +void SamplerManager::DeleteObject(const Context *context, Sampler *sampler) { - auto fenceObjectIt = mFenceSyncMap.find(fenceSync); + sampler->release(context); +} - if (fenceObjectIt != mFenceSyncMap.end()) - { - mFenceSyncHandleAllocator.release(fenceObjectIt->first); - if (fenceObjectIt->second) fenceObjectIt->second->release(); - mFenceSyncMap.erase(fenceObjectIt); - } +GLuint SamplerManager::createSampler() +{ + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); } -Buffer *ResourceManager::getBuffer(unsigned int handle) +Sampler *SamplerManager::getSampler(GLuint handle) const { - BufferMap::iterator buffer = mBufferMap.find(handle); + return mObjectMap.query(handle); +} - if (buffer == mBufferMap.end()) - { - return NULL; - } - else - { - return buffer->second; - } +bool SamplerManager::isSampler(GLuint sampler) const +{ + return mObjectMap.contains(sampler); } -Shader *ResourceManager::getShader(unsigned int handle) +// SyncManager Implementation. + +// static +void SyncManager::DeleteObject(const Context *context, Sync *sync) { - ShaderMap::iterator shader = mShaderMap.find(handle); + sync->release(context); +} - if (shader == mShaderMap.end()) - { - return NULL; - } - else - { - return shader->second; - } +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; } -Texture *ResourceManager::getTexture(unsigned int handle) +Sync *SyncManager::getSync(GLuint handle) const { - if (handle == 0) return NULL; + return mObjectMap.query(handle); +} - TextureMap::iterator texture = mTextureMap.find(handle); +// PathManager Implementation. - if (texture == mTextureMap.end()) - { - return NULL; - } - else - { - return texture->second; - } +PathManager::PathManager() +{ } -Program *ResourceManager::getProgram(unsigned int handle) const +ErrorOrResult<GLuint> PathManager::createPaths(rx::GLImplFactory *factory, GLsizei range) { - ProgramMap::const_iterator program = mProgramMap.find(handle); + // Allocate client side handles. + const GLuint client = mHandleAllocator.allocateRange(static_cast<GLuint>(range)); + if (client == HandleRangeAllocator::kInvalidHandle) + return OutOfMemory() << "Failed to allocate path handle range."; - if (program == mProgramMap.end()) + const auto &paths = factory->createPaths(range); + if (paths.empty()) { - return NULL; + mHandleAllocator.releaseRange(client, range); + return OutOfMemory() << "Failed to allocate path objects."; } - else + + for (GLsizei i = 0; i < range; ++i) { - return program->second; + rx::PathImpl *impl = paths[static_cast<unsigned>(i)]; + const auto id = client + i; + mPaths.assign(id, new Path(impl)); } + return client; } -Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle) +void PathManager::deletePaths(GLuint first, GLsizei range) { - RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle); - - if (renderbuffer == mRenderbufferMap.end()) + for (GLsizei i = 0; i < range; ++i) { - return NULL; - } - else - { - return renderbuffer->second; + const auto id = first + i; + Path *p = nullptr; + if (!mPaths.erase(id, &p)) + continue; + delete p; } + mHandleAllocator.releaseRange(first, static_cast<GLuint>(range)); } -Sampler *ResourceManager::getSampler(unsigned int handle) +Path *PathManager::getPath(GLuint handle) const { - auto sampler = mSamplerMap.find(handle); + return mPaths.query(handle); +} - if (sampler == mSamplerMap.end()) - { - return NULL; - } - else - { - return sampler->second; - } +bool PathManager::hasPath(GLuint handle) const +{ + return mHandleAllocator.isUsed(handle); } -FenceSync *ResourceManager::getFenceSync(unsigned int handle) +PathManager::~PathManager() { - auto fenceObjectIt = mFenceSyncMap.find(handle); + ASSERT(mPaths.empty()); +} - if (fenceObjectIt == mFenceSyncMap.end()) - { - return NULL; - } - else +void PathManager::reset(const Context *context) +{ + for (auto path : mPaths) { - return fenceObjectIt->second; + SafeDelete(path.second); } + mPaths.clear(); } -void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer) +// FramebufferManager Implementation. + +// static +Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory, + GLuint handle, + const Caps &caps) { - mRenderbufferMap[handle] = buffer; + return new Framebuffer(caps, factory, handle); } -void ResourceManager::checkBufferAllocation(GLuint handle) +// static +void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer) { - if (handle != 0) + // Default framebuffer are owned by their respective Surface + if (framebuffer->id() != 0) { - auto bufferMapIt = mBufferMap.find(handle); - bool handleAllocated = (bufferMapIt != mBufferMap.end()); - - if (handleAllocated && bufferMapIt->second != nullptr) - { - return; - } - - Buffer *buffer = new Buffer(mFactory->createBuffer(), handle); - buffer->addRef(); - - if (handleAllocated) - { - bufferMapIt->second = buffer; - } - else - { - mBufferHandleAllocator.reserve(handle); - mBufferMap[handle] = buffer; - } + framebuffer->onDestroy(context); + delete framebuffer; } } -void ResourceManager::checkTextureAllocation(GLuint handle, GLenum type) +GLuint FramebufferManager::createFramebuffer() { - if (handle != 0) - { - auto textureMapIt = mTextureMap.find(handle); - bool handleAllocated = (textureMapIt != mTextureMap.end()); - - if (handleAllocated && textureMapIt->second != nullptr) - { - return; - } + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); +} - Texture *texture = new Texture(mFactory->createTexture(type), handle, type); - texture->addRef(); +Framebuffer *FramebufferManager::getFramebuffer(GLuint handle) const +{ + return mObjectMap.query(handle); +} - if (handleAllocated) - { - textureMapIt->second = texture; - } - else - { - mTextureHandleAllocator.reserve(handle); - mTextureMap[handle] = texture; - } - } +void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer) +{ + ASSERT(framebuffer == nullptr || framebuffer->id() == 0); + mObjectMap.assign(0, framebuffer); } -void ResourceManager::checkRenderbufferAllocation(GLuint handle) +void FramebufferManager::invalidateFramebufferComplenessCache() const { - if (handle != 0) + for (const auto &framebuffer : mObjectMap) { - auto renderbufferMapIt = mRenderbufferMap.find(handle); - bool handleAllocated = (renderbufferMapIt != mRenderbufferMap.end()); - - if (handleAllocated && renderbufferMapIt->second != nullptr) + if (framebuffer.second) { - return; + framebuffer.second->invalidateCompletenessCache(); } + } +} - Renderbuffer *renderbuffer = new Renderbuffer(mFactory->createRenderbuffer(), handle); - renderbuffer->addRef(); +// ProgramPipelineManager Implementation. - if (handleAllocated) - { - renderbufferMapIt->second = renderbuffer; - } - else - { - mRenderbufferHandleAllocator.reserve(handle); - mRenderbufferMap[handle] = renderbuffer; - } - } +// static +ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory, + GLuint handle) +{ + ProgramPipeline *pipeline = new ProgramPipeline(factory, handle); + pipeline->addRef(); + return pipeline; } -void ResourceManager::checkSamplerAllocation(GLuint sampler) +// static +void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline) { - if (sampler != 0 && !getSampler(sampler)) - { - Sampler *samplerObject = new Sampler(mFactory, sampler); - mSamplerMap[sampler] = samplerObject; - samplerObject->addRef(); - // Samplers cannot be created via Bind - } + pipeline->release(context); } -bool ResourceManager::isSampler(GLuint sampler) +GLuint ProgramPipelineManager::createProgramPipeline() { - return mSamplerMap.find(sampler) != mSamplerMap.end(); + return AllocateEmptyObject(&mHandleAllocator, &mObjectMap); } +ProgramPipeline *ProgramPipelineManager::getProgramPipeline(GLuint handle) const +{ + return mObjectMap.query(handle); } + +} // namespace gl |