Edit

kc3-lang/angle/src/libANGLE/ResourceManager.cpp

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2016-11-03 16:45:34
    Hash : 8f775607
    Message : Introduce a gl::BufferState class. This state can share vital pieces of information with the impl. The most elementary state is the buffer size, which then the impl doesn't need to replicate. BUG=angleproject:1579 Change-Id: I341393c64a6e49de65c1d53b1bad2fa143209862 Reviewed-on: https://chromium-review.googlesource.com/406644 Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Jamie Madill <jmadill@chromium.org>

  • src/libANGLE/ResourceManager.cpp
  • //
    // Copyright (c) 2002-2013 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.
    
    #include "libANGLE/ResourceManager.h"
    
    #include "libANGLE/Buffer.h"
    #include "libANGLE/Fence.h"
    #include "libANGLE/Path.h"
    #include "libANGLE/Program.h"
    #include "libANGLE/Renderbuffer.h"
    #include "libANGLE/Sampler.h"
    #include "libANGLE/Shader.h"
    #include "libANGLE/Texture.h"
    #include "libANGLE/renderer/GLImplFactory.h"
    
    namespace gl
    {
    ResourceManager::ResourceManager() : mRefCount(1)
    {
    }
    
    ResourceManager::~ResourceManager()
    {
        while (!mBufferMap.empty())
        {
            deleteBuffer(mBufferMap.begin()->first);
        }
    
        while (!mProgramMap.empty())
        {
            deleteProgram(mProgramMap.begin()->first);
        }
    
        while (!mShaderMap.empty())
        {
            deleteShader(mShaderMap.begin()->first);
        }
    
        while (!mRenderbufferMap.empty())
        {
            deleteRenderbuffer(mRenderbufferMap.begin()->first);
        }
    
        while (!mTextureMap.empty())
        {
            deleteTexture(mTextureMap.begin()->first);
        }
    
        while (!mSamplerMap.empty())
        {
            deleteSampler(mSamplerMap.begin()->first);
        }
    
        while (!mFenceSyncMap.empty())
        {
            deleteFenceSync(mFenceSyncMap.begin()->first);
        }
    
        for (auto it = mPathMap.begin(); it != mPathMap.end(); ++it)
        {
            const auto *p = it->second;
            delete p;
        }
    }
    
    void ResourceManager::addRef()
    {
        mRefCount++;
    }
    
    void ResourceManager::release()
    {
        if (--mRefCount == 0)
        {
            delete this;
        }
    }
    
    // Returns an unused buffer name
    GLuint ResourceManager::createBuffer()
    {
        GLuint handle = mBufferHandleAllocator.allocate();
    
        mBufferMap[handle] = nullptr;
    
        return handle;
    }
    
    // Returns an unused shader/program name
    GLuint ResourceManager::createShader(rx::GLImplFactory *factory,
                                         const gl::Limitations &rendererLimitations,
                                         GLenum type)
    {
        ASSERT(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER || type == GL_COMPUTE_SHADER);
        GLuint handle = mProgramShaderHandleAllocator.allocate();
    
        mShaderMap[handle] = new Shader(this, factory, rendererLimitations, type, handle);
    
        return handle;
    }
    
    // Returns an unused program/shader name
    GLuint ResourceManager::createProgram(rx::GLImplFactory *factory)
    {
        GLuint handle = mProgramShaderHandleAllocator.allocate();
    
        mProgramMap[handle] = new Program(factory, this, handle);
    
        return handle;
    }
    
    // Returns an unused texture name
    GLuint ResourceManager::createTexture()
    {
        GLuint handle = mTextureHandleAllocator.allocate();
    
        mTextureMap[handle] = nullptr;
    
        return handle;
    }
    
    // Returns an unused renderbuffer name
    GLuint ResourceManager::createRenderbuffer()
    {
        GLuint handle = mRenderbufferHandleAllocator.allocate();
    
        mRenderbufferMap[handle] = nullptr;
    
        return handle;
    }
    
    // Returns an unused sampler name
    GLuint ResourceManager::createSampler()
    {
        GLuint handle = mSamplerHandleAllocator.allocate();
    
        mSamplerMap[handle] = nullptr;
    
        return handle;
    }
    
    // Returns the next unused fence name, and allocates the fence
    GLuint ResourceManager::createFenceSync(rx::GLImplFactory *factory)
    {
        GLuint handle = mFenceSyncHandleAllocator.allocate();
    
        FenceSync *fenceSync = new FenceSync(factory->createFenceSync(), handle);
        fenceSync->addRef();
        mFenceSyncMap[handle] = fenceSync;
    
        return handle;
    }
    
    ErrorOrResult<GLuint> ResourceManager::createPaths(rx::GLImplFactory *factory, GLsizei range)
    {
        // Allocate client side handles.
        const GLuint client = mPathHandleAllocator.allocateRange(static_cast<GLuint>(range));
        if (client == HandleRangeAllocator::kInvalidHandle)
            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate path handle range.");
    
        const auto &paths = factory->createPaths(range);
        if (paths.empty())
        {
            mPathHandleAllocator.releaseRange(client, range);
            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate path objects.");
        }
    
        auto hint = mPathMap.begin();
    
        for (GLsizei i = 0; i < range; ++i)
        {
            const auto impl = paths[static_cast<unsigned>(i)];
            const auto id   = client + i;
            hint            = mPathMap.insert(hint, std::make_pair(id, new Path(impl)));
        }
        return client;
    }
    
    void ResourceManager::deleteBuffer(GLuint buffer)
    {
        auto bufferObject = mBufferMap.find(buffer);
    
        if (bufferObject != mBufferMap.end())
        {
            mBufferHandleAllocator.release(bufferObject->first);
            if (bufferObject->second) bufferObject->second->release();
            mBufferMap.erase(bufferObject);
        }
    }
    
    void ResourceManager::deleteShader(GLuint shader)
    {
        auto shaderObject = mShaderMap.find(shader);
    
        if (shaderObject != mShaderMap.end())
        {
            if (shaderObject->second->getRefCount() == 0)
            {
                mProgramShaderHandleAllocator.release(shaderObject->first);
                delete shaderObject->second;
                mShaderMap.erase(shaderObject);
            }
            else
            {
                shaderObject->second->flagForDeletion();
            }
        }
    }
    
    void ResourceManager::deleteProgram(GLuint program)
    {
        auto programObject = mProgramMap.find(program);
    
        if (programObject != mProgramMap.end())
        {
            if (programObject->second->getRefCount() == 0)
            {
                mProgramShaderHandleAllocator.release(programObject->first);
                delete programObject->second;
                mProgramMap.erase(programObject);
            }
            else
            {
                programObject->second->flagForDeletion();
            }
        }
    }
    
    void ResourceManager::deleteTexture(GLuint texture)
    {
        auto textureObject = mTextureMap.find(texture);
    
        if (textureObject != mTextureMap.end())
        {
            mTextureHandleAllocator.release(textureObject->first);
            if (textureObject->second) textureObject->second->release();
            mTextureMap.erase(textureObject);
        }
    }
    
    void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
    {
        auto renderbufferObject = mRenderbufferMap.find(renderbuffer);
    
        if (renderbufferObject != mRenderbufferMap.end())
        {
            mRenderbufferHandleAllocator.release(renderbufferObject->first);
            if (renderbufferObject->second) renderbufferObject->second->release();
            mRenderbufferMap.erase(renderbufferObject);
        }
    }
    
    void ResourceManager::deleteSampler(GLuint sampler)
    {
        auto samplerObject = mSamplerMap.find(sampler);
    
        if (samplerObject != mSamplerMap.end())
        {
            mSamplerHandleAllocator.release(samplerObject->first);
            if (samplerObject->second) samplerObject->second->release();
            mSamplerMap.erase(samplerObject);
        }
    }
    
    void ResourceManager::deleteFenceSync(GLuint fenceSync)
    {
        auto fenceObjectIt = mFenceSyncMap.find(fenceSync);
    
        if (fenceObjectIt != mFenceSyncMap.end())
        {
            mFenceSyncHandleAllocator.release(fenceObjectIt->first);
            if (fenceObjectIt->second) fenceObjectIt->second->release();
            mFenceSyncMap.erase(fenceObjectIt);
        }
    }
    
    void ResourceManager::deletePaths(GLuint first, GLsizei range)
    {
        for (GLsizei i = 0; i < range; ++i)
        {
            const auto id = first + i;
            const auto it = mPathMap.find(id);
            if (it == mPathMap.end())
                continue;
            Path *p = it->second;
            delete p;
            mPathMap.erase(it);
        }
        mPathHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
    }
    
    Buffer *ResourceManager::getBuffer(unsigned int handle)
    {
        auto buffer = mBufferMap.find(handle);
    
        if (buffer == mBufferMap.end())
        {
            return nullptr;
        }
        else
        {
            return buffer->second;
        }
    }
    
    Shader *ResourceManager::getShader(unsigned int handle) const
    {
        auto shader = mShaderMap.find(handle);
    
        if (shader == mShaderMap.end())
        {
            return nullptr;
        }
        else
        {
            return shader->second;
        }
    }
    
    Texture *ResourceManager::getTexture(unsigned int handle)
    {
        if (handle == 0)
            return nullptr;
    
        auto texture = mTextureMap.find(handle);
    
        if (texture == mTextureMap.end())
        {
            return nullptr;
        }
        else
        {
            return texture->second;
        }
    }
    
    Program *ResourceManager::getProgram(unsigned int handle) const
    {
        auto program = mProgramMap.find(handle);
    
        if (program == mProgramMap.end())
        {
            return nullptr;
        }
        else
        {
            return program->second;
        }
    }
    
    Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
    {
        auto renderbuffer = mRenderbufferMap.find(handle);
    
        if (renderbuffer == mRenderbufferMap.end())
        {
            return nullptr;
        }
        else
        {
            return renderbuffer->second;
        }
    }
    
    Sampler *ResourceManager::getSampler(unsigned int handle)
    {
        auto sampler = mSamplerMap.find(handle);
    
        if (sampler == mSamplerMap.end())
        {
            return nullptr;
        }
        else
        {
            return sampler->second;
        }
    }
    
    FenceSync *ResourceManager::getFenceSync(unsigned int handle)
    {
        auto fenceObjectIt = mFenceSyncMap.find(handle);
    
        if (fenceObjectIt == mFenceSyncMap.end())
        {
            return nullptr;
        }
        else
        {
            return fenceObjectIt->second;
        }
    }
    
    const Path *ResourceManager::getPath(GLuint handle) const
    {
        auto it = mPathMap.find(handle);
        if (it == std::end(mPathMap))
            return nullptr;
        return it->second;
    }
    
    Path *ResourceManager::getPath(GLuint handle)
    {
        auto it = mPathMap.find(handle);
        if (it == std::end(mPathMap))
            return nullptr;
    
        return it->second;
    }
    
    bool ResourceManager::hasPath(GLuint handle) const
    {
        return mPathHandleAllocator.isUsed(handle);
    }
    
    void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
    {
        mRenderbufferMap[handle] = buffer;
    }
    
    Buffer *ResourceManager::checkBufferAllocation(rx::GLImplFactory *factory, GLuint handle)
    {
        if (handle == 0)
        {
            return nullptr;
        }
    
        auto bufferMapIt     = mBufferMap.find(handle);
        bool handleAllocated = (bufferMapIt != mBufferMap.end());
    
        if (handleAllocated && bufferMapIt->second != nullptr)
        {
            return bufferMapIt->second;
        }
    
        Buffer *buffer = new Buffer(factory, handle);
        buffer->addRef();
    
        if (handleAllocated)
        {
            bufferMapIt->second = buffer;
        }
        else
        {
            mBufferHandleAllocator.reserve(handle);
            mBufferMap[handle] = buffer;
        }
    
        return buffer;
    }
    
    Texture *ResourceManager::checkTextureAllocation(rx::GLImplFactory *factory,
                                                     GLuint handle,
                                                     GLenum type)
    {
        if (handle == 0)
        {
            return nullptr;
        }
    
        auto textureMapIt    = mTextureMap.find(handle);
        bool handleAllocated = (textureMapIt != mTextureMap.end());
    
        if (handleAllocated && textureMapIt->second != nullptr)
        {
            return textureMapIt->second;
        }
    
        Texture *texture = new Texture(factory, handle, type);
        texture->addRef();
    
        if (handleAllocated)
        {
            textureMapIt->second = texture;
        }
        else
        {
            mTextureHandleAllocator.reserve(handle);
            mTextureMap[handle] = texture;
        }
    
        return texture;
    }
    
    Renderbuffer *ResourceManager::checkRenderbufferAllocation(rx::GLImplFactory *factory,
                                                               GLuint handle)
    {
        if (handle == 0)
        {
            return nullptr;
        }
    
        auto renderbufferMapIt = mRenderbufferMap.find(handle);
        bool handleAllocated   = (renderbufferMapIt != mRenderbufferMap.end());
    
        if (handleAllocated && renderbufferMapIt->second != nullptr)
        {
            return renderbufferMapIt->second;
        }
    
        Renderbuffer *renderbuffer = new Renderbuffer(factory->createRenderbuffer(), handle);
        renderbuffer->addRef();
    
        if (handleAllocated)
        {
            renderbufferMapIt->second = renderbuffer;
        }
        else
        {
            mRenderbufferHandleAllocator.reserve(handle);
            mRenderbufferMap[handle] = renderbuffer;
        }
    
        return renderbuffer;
    }
    
    Sampler *ResourceManager::checkSamplerAllocation(rx::GLImplFactory *factory, GLuint samplerHandle)
    {
        // Samplers cannot be created via Bind
        if (samplerHandle == 0)
        {
            return nullptr;
        }
    
        Sampler *sampler = getSampler(samplerHandle);
    
        if (!sampler)
        {
            sampler                    = new Sampler(factory, samplerHandle);
            mSamplerMap[samplerHandle] = sampler;
            sampler->addRef();
        }
    
        return sampler;
    }
    
    bool ResourceManager::isSampler(GLuint sampler)
    {
        return mSamplerMap.find(sampler) != mSamplerMap.end();
    }
    
    bool ResourceManager::isTextureGenerated(GLuint texture) const
    {
        return texture == 0 || mTextureMap.find(texture) != mTextureMap.end();
    }
    
    bool ResourceManager::isBufferGenerated(GLuint buffer) const
    {
        return buffer == 0 || mBufferMap.find(buffer) != mBufferMap.end();
    }
    
    bool ResourceManager::isRenderbufferGenerated(GLuint renderbuffer) const
    {
        return renderbuffer == 0 || mRenderbufferMap.find(renderbuffer) != mRenderbufferMap.end();
    }
    
    }  // namespace gl