// Copyright 2016 The SwiftShader Authors. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ResourceManager.cpp: Implements the ResourceManager class, which tracks and // retrieves objects which may be shared by multiple Contexts. #include "ResourceManager.h" #include "Buffer.h" #include "Fence.h" #include "Program.h" #include "Renderbuffer.h" #include "Sampler.h" #include "Shader.h" #include "Texture.h" namespace es2 { ResourceManager::ResourceManager() { mRefCount = 1; } ResourceManager::~ResourceManager() { while(!mBufferNameSpace.empty()) { deleteBuffer(mBufferNameSpace.firstName()); } while(!mProgramNameSpace.empty()) { deleteProgram(mProgramNameSpace.firstName()); } while(!mShaderNameSpace.empty()) { deleteShader(mShaderNameSpace.firstName()); } while(!mRenderbufferNameSpace.empty()) { deleteRenderbuffer(mRenderbufferNameSpace.firstName()); } while(!mTextureNameSpace.empty()) { deleteTexture(mTextureNameSpace.firstName()); } while(!mSamplerNameSpace.empty()) { deleteSampler(mSamplerNameSpace.firstName()); } while(!mFenceSyncNameSpace.empty()) { deleteFenceSync(mFenceSyncNameSpace.firstName()); } } void ResourceManager::addRef() { mRefCount++; } void ResourceManager::release() { if(--mRefCount == 0) { delete this; } } // Returns an unused buffer name GLuint ResourceManager::createBuffer() { return mBufferNameSpace.allocate(); } // Returns an unused shader name GLuint ResourceManager::createShader(GLenum type) { GLuint name = mProgramShaderNameSpace.allocate(); if(type == GL_VERTEX_SHADER) { mShaderNameSpace.insert(name, new VertexShader(this, name)); } else if(type == GL_FRAGMENT_SHADER) { mShaderNameSpace.insert(name, new FragmentShader(this, name)); } else UNREACHABLE(type); return name; } // Returns an unused program name GLuint ResourceManager::createProgram() { GLuint name = mProgramShaderNameSpace.allocate(); mProgramNameSpace.insert(name, new Program(this, name)); return name; } // Returns an unused texture name GLuint ResourceManager::createTexture() { return mTextureNameSpace.allocate(); } // Returns an unused renderbuffer name GLuint ResourceManager::createRenderbuffer() { return mRenderbufferNameSpace.allocate(); } // Returns an unused sampler name GLuint ResourceManager::createSampler() { return mSamplerNameSpace.allocate(); } // Returns the next unused fence name, and allocates the fence GLuint ResourceManager::createFenceSync(GLenum condition, GLbitfield flags) { GLuint name = mFenceSyncNameSpace.allocate(); FenceSync *fenceSync = new FenceSync(name, condition, flags); fenceSync->addRef(); mFenceSyncNameSpace.insert(name, fenceSync); return name; } void ResourceManager::deleteBuffer(GLuint buffer) { Buffer *bufferObject = mBufferNameSpace.remove(buffer); if(bufferObject) { bufferObject->release(); } } void ResourceManager::deleteShader(GLuint shader) { Shader *shaderObject = mShaderNameSpace.find(shader); if(shaderObject) { if(shaderObject->getRefCount() == 0) { delete shaderObject; mShaderNameSpace.remove(shader); mProgramShaderNameSpace.remove(shader); } else { shaderObject->flagForDeletion(); } } } void ResourceManager::deleteProgram(GLuint program) { Program *programObject = mProgramNameSpace.find(program); if(programObject) { if(programObject->getRefCount() == 0) { delete programObject; mProgramNameSpace.remove(program); mProgramShaderNameSpace.remove(program); } else { programObject->flagForDeletion(); } } } void ResourceManager::deleteTexture(GLuint texture) { Texture *textureObject = mTextureNameSpace.remove(texture); if(textureObject) { textureObject->release(); } } void ResourceManager::deleteRenderbuffer(GLuint renderbuffer) { Renderbuffer *renderbufferObject = mRenderbufferNameSpace.remove(renderbuffer); if(renderbufferObject) { renderbufferObject->release(); } } void ResourceManager::deleteSampler(GLuint sampler) { Sampler *samplerObject = mSamplerNameSpace.remove(sampler); if(samplerObject) { samplerObject->release(); } } void ResourceManager::deleteFenceSync(GLuint fenceSync) { FenceSync *fenceObject = mFenceSyncNameSpace.remove(fenceSync); if(fenceObject) { fenceObject->release(); } } Buffer *ResourceManager::getBuffer(unsigned int handle) { return mBufferNameSpace.find(handle); } Shader *ResourceManager::getShader(unsigned int handle) { return mShaderNameSpace.find(handle); } Texture *ResourceManager::getTexture(unsigned int handle) { return mTextureNameSpace.find(handle); } Program *ResourceManager::getProgram(unsigned int handle) { return mProgramNameSpace.find(handle); } Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle) { return mRenderbufferNameSpace.find(handle); } Sampler *ResourceManager::getSampler(unsigned int handle) { return mSamplerNameSpace.find(handle); } FenceSync *ResourceManager::getFenceSync(unsigned int handle) { return mFenceSyncNameSpace.find(handle); } void ResourceManager::checkBufferAllocation(unsigned int buffer) { if(buffer != 0 && !getBuffer(buffer)) { Buffer *bufferObject = new Buffer(buffer); bufferObject->addRef(); mBufferNameSpace.insert(buffer, bufferObject); } } void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type) { if(!getTexture(texture) && texture != 0) { Texture *textureObject; if(type == TEXTURE_2D) { textureObject = new Texture2D(texture); } else if(type == TEXTURE_CUBE) { textureObject = new TextureCubeMap(texture); } else if(type == TEXTURE_EXTERNAL) { textureObject = new TextureExternal(texture); } else if(type == TEXTURE_3D) { textureObject = new Texture3D(texture); } else if(type == TEXTURE_2D_ARRAY) { textureObject = new Texture2DArray(texture); } else if(type == TEXTURE_2D_RECT) { textureObject = new Texture2DRect(texture); } else { UNREACHABLE(type); return; } textureObject->addRef(); mTextureNameSpace.insert(texture, textureObject); } } void ResourceManager::checkRenderbufferAllocation(GLuint handle) { if(handle != 0 && !getRenderbuffer(handle)) { Renderbuffer *renderbufferObject = new Renderbuffer(handle, new Colorbuffer(0, 0, GL_NONE, 0)); renderbufferObject->addRef(); mRenderbufferNameSpace.insert(handle, renderbufferObject); } } void ResourceManager::checkSamplerAllocation(GLuint sampler) { if(sampler != 0 && !getSampler(sampler)) { Sampler *samplerObject = new Sampler(sampler); samplerObject->addRef(); mSamplerNameSpace.insert(sampler, samplerObject); } } bool ResourceManager::isSampler(GLuint sampler) { return mSamplerNameSpace.isReserved(sampler); } }