Edit

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

Branch :

  • Show log

    Commit

  • Author : Jamie Madill
    Date : 2018-08-01 11:34:51
    Hash : b983a4b2
    Message : Pass Context to Framebuffer::invalidateCompletenessCache. This will be useful for validation state caching. Bug: angleproject:2747 Change-Id: I0737adca7406f79b9e15429f30ae22e1299cd7e4 Reviewed-on: https://chromium-review.googlesource.com/1158611 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Frank Henigman <fjhenigman@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org>

  • src/libANGLE/ResourceManager.cpp
  • //
    // 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/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/renderer/GLImplFactory.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);
    }
    
    Program *ShaderProgramManager::getProgram(GLuint handle) const
    {
        return mPrograms.query(handle);
    }
    
    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);
    }
    
    Texture *TextureManager::getTexture(GLuint handle) const
    {
        ASSERT(mObjectMap.query(0) == nullptr);
        return mObjectMap.query(handle);
    }
    
    void TextureManager::signalAllTexturesDirty(const Context *context) 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->signalDirty(context, 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()
    {
    }
    
    ErrorOrResult<GLuint> PathManager::createPaths(rx::GLImplFactory *factory, GLsizei range)
    {
        // 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.";
    
        const auto &paths = factory->createPaths(range);
        if (paths.empty())
        {
            mHandleAllocator.releaseRange(client, range);
            return OutOfMemory() << "Failed to allocate path objects.";
        }
    
        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));
        }
        return client;
    }
    
    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 Context *context) const
    {
        for (const auto &framebuffer : mObjectMap)
        {
            if (framebuffer.second)
            {
                framebuffer.second->invalidateCompletenessCache(context);
            }
        }
    }
    
    // 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);
    }
    
    }  // namespace gl