Refactor ResourceManagers.

This makes ResourceManagers use more common code. It uses static
polymorphism to implement the various typed resource managers,
and unifies the FramebufferManager into a TypedResourceManager.
The lack of virtual calls and inlining in the header should keep
performance high.

This will make the upcoming refactor to add a destroy hook
for Vulkan objects simpler to implement.

TEST=manual performance testing of BindingPerf.
BUG=angleproject:1684
BUG=angleproject:1639

Change-Id: Ic2f102196020d1005e63a1b2cf0867577fc7c885
Reviewed-on: https://chromium-review.googlesource.com/439488
Commit-Queue: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/ResourceManager.cpp b/src/libANGLE/ResourceManager.cpp
index b3b598e..c7defac 100644
--- a/src/libANGLE/ResourceManager.cpp
+++ b/src/libANGLE/ResourceManager.cpp
@@ -33,37 +33,6 @@
     return handle;
 }
 
-template <typename ResourceType, typename CreationFunction>
-GLuint InsertObject(HandleAllocator *handleAllocator,
-                    ResourceMap<ResourceType> *objectMap,
-                    const CreationFunction &func)
-{
-    GLuint handle        = handleAllocator->allocate();
-    (*objectMap)[handle] = func(handle);
-    return handle;
-}
-
-template <typename ResourceType, typename DeletionFunction>
-void DeleteObject(HandleAllocator *handleAllocator,
-                  ResourceMap<ResourceType> *objectMap,
-                  GLuint handle,
-                  const DeletionFunction &deletionFunc)
-{
-    auto objectIter = objectMap->find(handle);
-    if (objectIter == objectMap->end())
-    {
-        return;
-    }
-
-    if (objectIter->second != nullptr)
-    {
-        deletionFunc(objectIter->second);
-    }
-
-    handleAllocator->release(objectIter->first);
-    objectMap->erase(objectIter);
-}
-
 template <typename ResourceType>
 ResourceType *GetObject(const ResourceMap<ResourceType> &objectMap, GLuint handle)
 {
@@ -93,8 +62,8 @@
     }
 }
 
-template <typename ResourceType, typename HandleAllocatorType>
-TypedResourceManager<ResourceType, HandleAllocatorType>::~TypedResourceManager()
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::~TypedResourceManager()
 {
     while (!mObjectMap.empty())
     {
@@ -102,73 +71,114 @@
     }
 }
 
-template <typename ResourceType, typename HandleAllocatorType>
-void TypedResourceManager<ResourceType, HandleAllocatorType>::deleteObject(GLuint handle)
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::deleteObject(GLuint handle)
 {
-    DeleteObject(&this->mHandleAllocator, &mObjectMap, handle,
-                 [](ResourceType *object) { object->release(); });
+    auto objectIter = mObjectMap.find(handle);
+    if (objectIter == mObjectMap.end())
+    {
+        return;
+    }
+
+    if (objectIter->second != nullptr)
+    {
+        ImplT::DeleteObject(objectIter->second);
+    }
+
+    // Requires an explicit this-> because of C++ template rules.
+    this->mHandleAllocator.release(objectIter->first);
+    mObjectMap.erase(objectIter);
 }
 
-// Instantiations of ResourceManager
+template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
+template <typename... ArgTypes>
+ResourceType *TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::allocateObject(
+    typename ResourceMap<ResourceType>::iterator &objectMapIter,
+    rx::GLImplFactory *factory,
+    GLuint handle,
+    ArgTypes... args)
+{
+    ResourceType *object = ImplT::AllocateNewObject(factory, handle, args...);
+
+    if (objectMapIter != mObjectMap.end())
+    {
+        objectMapIter->second = object;
+    }
+    else
+    {
+        this->mHandleAllocator.reserve(handle);
+        mObjectMap[handle] = object;
+    }
+
+    return object;
+}
+
 template class ResourceManagerBase<HandleAllocator>;
 template class ResourceManagerBase<HandleRangeAllocator>;
-template class TypedResourceManager<Buffer, HandleAllocator>;
-template class TypedResourceManager<Texture, HandleAllocator>;
-template class TypedResourceManager<Renderbuffer, HandleAllocator>;
-template class TypedResourceManager<Sampler, HandleAllocator>;
-template class TypedResourceManager<FenceSync, HandleAllocator>;
+template class TypedResourceManager<Buffer, HandleAllocator, BufferManager>;
+template Buffer *TypedResourceManager<Buffer, HandleAllocator, BufferManager>::allocateObject(
+    ResourceMap<Buffer>::iterator &,
+    rx::GLImplFactory *,
+    GLuint);
+template class TypedResourceManager<Texture, HandleAllocator, TextureManager>;
+template Texture *TypedResourceManager<Texture, HandleAllocator, TextureManager>::allocateObject(
+    ResourceMap<Texture>::iterator &,
+    rx::GLImplFactory *,
+    GLuint,
+    GLenum);
+template class TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>;
+template Renderbuffer *
+TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>::allocateObject(
+    ResourceMap<Renderbuffer>::iterator &,
+    rx::GLImplFactory *,
+    GLuint);
+template class TypedResourceManager<Sampler, HandleAllocator, SamplerManager>;
+template Sampler *TypedResourceManager<Sampler, HandleAllocator, SamplerManager>::allocateObject(
+    ResourceMap<Sampler>::iterator &,
+    rx::GLImplFactory *,
+    GLuint);
+template class TypedResourceManager<FenceSync, HandleAllocator, FenceSyncManager>;
+template class TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>;
+template Framebuffer *
+TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>::allocateObject(
+    ResourceMap<Framebuffer>::iterator &,
+    rx::GLImplFactory *,
+    GLuint,
+    const Caps &);
+
+// 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(Buffer *buffer)
+{
+    buffer->release();
+}
 
 GLuint BufferManager::createBuffer()
 {
     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
 }
 
-void BufferManager::deleteBuffer(GLuint buffer)
-{
-    deleteObject(buffer);
-}
-
 Buffer *BufferManager::getBuffer(GLuint handle) const
 {
     return GetObject(mObjectMap, handle);
 }
 
-Buffer *BufferManager::checkBufferAllocation(rx::GLImplFactory *factory, GLuint handle)
-{
-    if (handle == 0)
-    {
-        return nullptr;
-    }
-
-    auto objectMapIter   = mObjectMap.find(handle);
-    bool handleAllocated = (objectMapIter != mObjectMap.end());
-
-    if (handleAllocated && objectMapIter->second != nullptr)
-    {
-        return objectMapIter->second;
-    }
-
-    Buffer *object = new Buffer(factory, handle);
-    object->addRef();
-
-    if (handleAllocated)
-    {
-        objectMapIter->second = object;
-    }
-    else
-    {
-        mHandleAllocator.reserve(handle);
-        mObjectMap[handle] = object;
-    }
-
-    return object;
-}
-
 bool BufferManager::isBufferGenerated(GLuint buffer) const
 {
     return buffer == 0 || mObjectMap.find(buffer) != mObjectMap.end();
 }
 
+// ShaderProgramManager Implementation.
+
 ShaderProgramManager::~ShaderProgramManager()
 {
     while (!mPrograms.empty())
@@ -240,185 +250,115 @@
     }
 }
 
+// TextureManager Implementation.
+
+// static
+Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle, GLenum target)
+{
+    Texture *texture = new Texture(factory, handle, target);
+    texture->addRef();
+    return texture;
+}
+
+// static
+void TextureManager::DeleteObject(Texture *texture)
+{
+    texture->release();
+}
+
 GLuint TextureManager::createTexture()
 {
     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
 }
 
-void TextureManager::deleteTexture(GLuint texture)
-{
-    deleteObject(texture);
-}
-
 Texture *TextureManager::getTexture(GLuint handle) const
 {
     ASSERT(GetObject(mObjectMap, 0) == nullptr);
     return GetObject(mObjectMap, handle);
 }
 
-Texture *TextureManager::checkTextureAllocation(rx::GLImplFactory *factory,
-                                                GLuint handle,
-                                                GLenum type)
-{
-    if (handle == 0)
-    {
-        return nullptr;
-    }
-
-    auto objectMapIter   = mObjectMap.find(handle);
-    bool handleAllocated = (objectMapIter != mObjectMap.end());
-
-    if (handleAllocated && objectMapIter->second != nullptr)
-    {
-        return objectMapIter->second;
-    }
-
-    Texture *object = new Texture(factory, handle, type);
-    object->addRef();
-
-    if (handleAllocated)
-    {
-        objectMapIter->second = object;
-    }
-    else
-    {
-        mHandleAllocator.reserve(handle);
-        mObjectMap[handle] = object;
-    }
-
-    return object;
-}
-
 bool TextureManager::isTextureGenerated(GLuint texture) const
 {
     return texture == 0 || mObjectMap.find(texture) != mObjectMap.end();
 }
 
+// RenderbufferManager Implementation.
+
+// static
+Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
+{
+    Renderbuffer *renderbuffer = new Renderbuffer(factory->createRenderbuffer(), handle);
+    renderbuffer->addRef();
+    return renderbuffer;
+}
+
+// static
+void RenderbufferManager::DeleteObject(Renderbuffer *renderbuffer)
+{
+    renderbuffer->release();
+}
+
 GLuint RenderbufferManager::createRenderbuffer()
 {
     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
 }
 
-void RenderbufferManager::deleteRenderbuffer(GLuint renderbuffer)
-{
-    deleteObject(renderbuffer);
-}
-
 Renderbuffer *RenderbufferManager::getRenderbuffer(GLuint handle)
 {
     return GetObject(mObjectMap, handle);
 }
 
-Renderbuffer *RenderbufferManager::checkRenderbufferAllocation(rx::GLImplFactory *factory,
-                                                               GLuint handle)
-{
-    if (handle == 0)
-    {
-        return nullptr;
-    }
-
-    auto objectMapIter   = mObjectMap.find(handle);
-    bool handleAllocated = (objectMapIter != mObjectMap.end());
-
-    if (handleAllocated && objectMapIter->second != nullptr)
-    {
-        return objectMapIter->second;
-    }
-
-    Renderbuffer *object = new Renderbuffer(factory->createRenderbuffer(), handle);
-    object->addRef();
-
-    if (handleAllocated)
-    {
-        objectMapIter->second = object;
-    }
-    else
-    {
-        mHandleAllocator.reserve(handle);
-        mObjectMap[handle] = object;
-    }
-
-    return object;
-}
-
 bool RenderbufferManager::isRenderbufferGenerated(GLuint renderbuffer) const
 {
     return renderbuffer == 0 || mObjectMap.find(renderbuffer) != mObjectMap.end();
 }
 
+// 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(Sampler *sampler)
+{
+    sampler->release();
+}
+
 GLuint SamplerManager::createSampler()
 {
     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
 }
 
-void SamplerManager::deleteSampler(GLuint sampler)
-{
-    deleteObject(sampler);
-}
-
 Sampler *SamplerManager::getSampler(GLuint handle)
 {
     return GetObject(mObjectMap, handle);
 }
 
-Sampler *SamplerManager::checkSamplerAllocation(rx::GLImplFactory *factory, GLuint handle)
-{
-    if (handle == 0)
-    {
-        return nullptr;
-    }
-
-    auto objectMapIter   = mObjectMap.find(handle);
-    bool handleAllocated = (objectMapIter != mObjectMap.end());
-
-    if (handleAllocated && objectMapIter->second != nullptr)
-    {
-        return objectMapIter->second;
-    }
-
-    Sampler *object = new Sampler(factory, handle);
-    object->addRef();
-
-    if (handleAllocated)
-    {
-        objectMapIter->second = object;
-    }
-    else
-    {
-        mHandleAllocator.reserve(handle);
-        mObjectMap[handle] = object;
-    }
-
-    return object;
-}
-
 bool SamplerManager::isSampler(GLuint sampler)
 {
     return mObjectMap.find(sampler) != mObjectMap.end();
 }
 
-GLuint FenceSyncManager::createFenceSync(rx::GLImplFactory *factory)
+// FenceSyncManager Implementation.
+
+// static
+void FenceSyncManager::DeleteObject(FenceSync *fenceSync)
 {
-    struct fenceSyncAllocator
-    {
-        fenceSyncAllocator(rx::GLImplFactory *factory) : factory(factory) {}
-
-        rx::GLImplFactory *factory;
-
-        FenceSync *operator()(GLuint handle) const
-        {
-            FenceSync *fenceSync = new FenceSync(factory->createFenceSync(), handle);
-            fenceSync->addRef();
-            return fenceSync;
-        }
-    };
-
-    return InsertObject(&mHandleAllocator, &mObjectMap, fenceSyncAllocator(factory));
+    fenceSync->release();
 }
 
-void FenceSyncManager::deleteFenceSync(GLuint fenceSync)
+GLuint FenceSyncManager::createFenceSync(rx::GLImplFactory *factory)
 {
-    deleteObject(fenceSync);
+    GLuint handle        = mHandleAllocator.allocate();
+    FenceSync *fenceSync = new FenceSync(factory->createFenceSync(), handle);
+    fenceSync->addRef();
+    mObjectMap[handle] = fenceSync;
+    return handle;
 }
 
 FenceSync *FenceSyncManager::getFenceSync(GLuint handle)
@@ -426,6 +366,8 @@
     return GetObject(mObjectMap, handle);
 }
 
+// PathManager Implementation.
+
 ErrorOrResult<GLuint> PathManager::createPaths(rx::GLImplFactory *factory, GLsizei range)
 {
     // Allocate client side handles.
@@ -485,70 +427,46 @@
     }
 }
 
-FramebufferManager::~FramebufferManager()
+// FramebufferManager Implementation.
+
+// static
+Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
+                                                   GLuint handle,
+                                                   const Caps &caps)
 {
-    for (auto framebuffer : mFramebuffers)
+    return new Framebuffer(caps, factory, handle);
+}
+
+// static
+void FramebufferManager::DeleteObject(Framebuffer *framebuffer)
+{
+    // Default framebuffer are owned by their respective Surface
+    if (framebuffer->id() != 0)
     {
-        // Default framebuffer are owned by their respective Surface
-        if (framebuffer.second != nullptr && framebuffer.second->id() != 0)
-        {
-            SafeDelete(framebuffer.second);
-        }
+        delete framebuffer;
     }
 }
 
 GLuint FramebufferManager::createFramebuffer()
 {
-    return AllocateEmptyObject(&mHandleAllocator, &mFramebuffers);
-}
-
-void FramebufferManager::deleteFramebuffer(GLuint framebuffer)
-{
-    DeleteObject(&mHandleAllocator, &mFramebuffers, framebuffer, [](Framebuffer *framebuffer) {
-        ASSERT(framebuffer->id() != 0);
-        delete framebuffer;
-    });
-}
-
-Framebuffer *FramebufferManager::checkFramebufferAllocation(rx::GLImplFactory *factory,
-                                                            const Caps &caps,
-                                                            GLuint handle)
-{
-    // Can be called from Bind without a prior call to Gen.
-    auto framebufferIt = mFramebuffers.find(handle);
-    bool neverCreated  = framebufferIt == mFramebuffers.end();
-    if (neverCreated || framebufferIt->second == nullptr)
-    {
-        ASSERT(handle != 0);
-        Framebuffer *newFBO = new Framebuffer(caps, factory, handle);
-        if (neverCreated)
-        {
-            mHandleAllocator.reserve(handle);
-            mFramebuffers[handle] = newFBO;
-            return newFBO;
-        }
-
-        framebufferIt->second = newFBO;
-    }
-
-    return framebufferIt->second;
+    return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
 }
 
 Framebuffer *FramebufferManager::getFramebuffer(GLuint handle) const
 {
-    return GetObject(mFramebuffers, handle);
+    return GetObject(mObjectMap, handle);
 }
 
 void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
 {
     ASSERT(framebuffer == nullptr || framebuffer->id() == 0);
-    mFramebuffers[0] = framebuffer;
+    mObjectMap[0] = framebuffer;
 }
 
 bool FramebufferManager::isFramebufferGenerated(GLuint framebuffer)
 {
-    ASSERT(mFramebuffers.find(0) != mFramebuffers.end());
-    return mFramebuffers.find(framebuffer) != mFramebuffers.end();
+    ASSERT(mObjectMap.find(0) != mObjectMap.end());
+    return mObjectMap.find(framebuffer) != mObjectMap.end();
 }
 
 }  // namespace gl