Edit

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

Branch :

  • Show log

    Commit

  • Author : Peng Huang
    Date : 2021-01-07 13:23:57
    Hash : 043fcf18
    Message : Support create ANGLE EGLContext from an external EGLContext For Android WebView, Android creates an EGLContext, EGLSurface and FBO, and makeCurrent on them, and then calls WebView draw function to draw the WebView content on the current EGLSurface or binded FBO. So to use ANGLE in WebView, this CL adds a way to create ANGLE EGLContext from an external EGLContext, and save and restore GL state in eglMakeCurrent(). Bug: angleproject:5509 Change-Id: I874986813117f125e23e975ea1adc51ac5b3a631 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2615239 Commit-Queue: Peng Huang <penghuang@chromium.org> Reviewed-by: Geoff Lang <geofflang@chromium.org> Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>

  • src/libANGLE/ResourceManager.cpp
  • //
    // 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