//
// 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 = FromGL<IDType>(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, typename IDType>
TypedResourceManager<ResourceType, HandleAllocatorType, ImplT, IDType>::~TypedResourceManager()
{
    ASSERT(mObjectMap.empty());
}

template <typename ResourceType, typename HandleAllocatorType, typename ImplT, typename IDType>
void TypedResourceManager<ResourceType, HandleAllocatorType, 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 HandleAllocatorType, typename ImplT, typename IDType>
void TypedResourceManager<ResourceType, HandleAllocatorType, 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);
    }
}

template class ResourceManagerBase<HandleAllocator>;
template class TypedResourceManager<Buffer, HandleAllocator, BufferManager, BufferID>;
template class TypedResourceManager<Texture, HandleAllocator, TextureManager, TextureID>;
template class TypedResourceManager<Renderbuffer,
                                    HandleAllocator,
                                    RenderbufferManager,
                                    RenderbufferID>;
template class TypedResourceManager<Sampler, HandleAllocator, SamplerManager, SamplerID>;
template class TypedResourceManager<Sync, HandleAllocator, SyncManager, GLuint>;
template class TypedResourceManager<Framebuffer,
                                    HandleAllocator,
                                    FramebufferManager,
                                    FramebufferID>;
template class TypedResourceManager<ProgramPipeline,
                                    HandleAllocator,
                                    ProgramPipelineManager,
                                    ProgramPipelineID>;

// BufferManager Implementation.

// 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.

// 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.

// 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.

// 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.

// 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.

// static
Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
                                                   FramebufferID handle,
                                                   const Caps &caps,
                                                   ContextID owningContextID)
{
    // Make sure the caller isn't using a reserved handle.
    ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle);
    return new Framebuffer(caps, factory, handle, owningContextID);
}

// 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);
}

void FramebufferManager::invalidateFramebufferCompletenessCache() const
{
    for (const auto &framebuffer : mObjectMap)
    {
        if (framebuffer.second)
        {
            framebuffer.second->invalidateCompletenessCache();
        }
    }
}

// ProgramPipelineManager Implementation.

// 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
