1// Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// ResourceManager.cpp: Implements the ResourceManager class, which tracks and
16// retrieves objects which may be shared by multiple Contexts.
17
18#include "ResourceManager.h"
19
20#include "Buffer.h"
21#include "Program.h"
22#include "Renderbuffer.h"
23#include "Shader.h"
24#include "Texture.h"
25
26namespace gl
27{
28ResourceManager::ResourceManager()
29{
30	mRefCount = 1;
31}
32
33ResourceManager::~ResourceManager()
34{
35	while(!mBufferMap.empty())
36	{
37		deleteBuffer(mBufferMap.begin()->first);
38	}
39
40	while(!mProgramMap.empty())
41	{
42		deleteProgram(mProgramMap.begin()->first);
43	}
44
45	while(!mShaderMap.empty())
46	{
47		deleteShader(mShaderMap.begin()->first);
48	}
49
50	while(!mRenderbufferMap.empty())
51	{
52		deleteRenderbuffer(mRenderbufferMap.begin()->first);
53	}
54
55	while(!mTextureMap.empty())
56	{
57		deleteTexture(mTextureMap.begin()->first);
58	}
59}
60
61void ResourceManager::addRef()
62{
63	mRefCount++;
64}
65
66void ResourceManager::release()
67{
68	if(--mRefCount == 0)
69	{
70		delete this;
71	}
72}
73
74// Returns an unused buffer name
75GLuint ResourceManager::createBuffer()
76{
77	//GLuint handle = mBufferNameSpace.allocate();
78	unsigned int handle = 1;
79
80	while (mBufferMap.find(handle) != mBufferMap.end())
81	{
82		handle++;
83	}
84
85	mBufferMap[handle] = nullptr;
86
87	return handle;
88}
89
90// Returns an unused shader/program name
91GLuint ResourceManager::createShader(GLenum type)
92{
93	//GLuint handle = mProgramShaderNameSpace.allocate();
94	unsigned int handle = 1;
95
96	while (mShaderMap.find(handle) != mShaderMap.end())
97	{
98		handle++;
99	}
100
101	if(type == GL_VERTEX_SHADER)
102	{
103		mShaderMap[handle] = new VertexShader(this, handle);
104	}
105	else if(type == GL_FRAGMENT_SHADER)
106	{
107		mShaderMap[handle] = new FragmentShader(this, handle);
108	}
109	else UNREACHABLE(type);
110
111	return handle;
112}
113
114// Returns an unused program/shader name
115GLuint ResourceManager::createProgram()
116{
117	//GLuint handle = mProgramShaderNameSpace.allocate();
118	unsigned int handle = 1;
119
120	while (mProgramMap.find(handle) != mProgramMap.end())
121	{
122		handle++;
123	}
124
125	mProgramMap[handle] = new Program(this, handle);
126
127	return handle;
128}
129
130// Returns an unused texture name
131GLuint ResourceManager::createTexture()
132{
133	//GLuint handle = mTextureNameSpace.allocate();
134	unsigned int handle = 1;
135
136	while (mTextureMap.find(handle) != mTextureMap.end())
137	{
138		handle++;
139	}
140
141	mTextureMap[handle] = nullptr;
142
143	return handle;
144}
145
146// Returns an unused renderbuffer name
147GLuint ResourceManager::createRenderbuffer()
148{
149	//GLuint handle = mRenderbufferNameSpace.allocate();
150	unsigned int handle = 1;
151
152	while (mRenderbufferMap.find(handle) != mRenderbufferMap.end())
153	{
154		handle++;
155	}
156
157	mRenderbufferMap[handle] = nullptr;
158
159	return handle;
160}
161
162void ResourceManager::deleteBuffer(GLuint buffer)
163{
164	BufferMap::iterator bufferObject = mBufferMap.find(buffer);
165
166	if(bufferObject != mBufferMap.end())
167	{
168		//mBufferNameSpace.release(bufferObject->first);
169		if(bufferObject->second) bufferObject->second->release();
170		mBufferMap.erase(bufferObject);
171	}
172}
173
174void ResourceManager::deleteShader(GLuint shader)
175{
176	ShaderMap::iterator shaderObject = mShaderMap.find(shader);
177
178	if(shaderObject != mShaderMap.end())
179	{
180		if(shaderObject->second->getRefCount() == 0)
181		{
182			//mProgramShaderNameSpace.release(shaderObject->first);
183			delete shaderObject->second;
184			mShaderMap.erase(shaderObject);
185		}
186		else
187		{
188			shaderObject->second->flagForDeletion();
189		}
190	}
191}
192
193void ResourceManager::deleteProgram(GLuint program)
194{
195	ProgramMap::iterator programObject = mProgramMap.find(program);
196
197	if(programObject != mProgramMap.end())
198	{
199		if(programObject->second->getRefCount() == 0)
200		{
201			//mProgramShaderNameSpace.release(programObject->first);
202			delete programObject->second;
203			mProgramMap.erase(programObject);
204		}
205		else
206		{
207			programObject->second->flagForDeletion();
208		}
209	}
210}
211
212void ResourceManager::deleteTexture(GLuint texture)
213{
214	TextureMap::iterator textureObject = mTextureMap.find(texture);
215
216	if(textureObject != mTextureMap.end())
217	{
218		//mTextureNameSpace.release(textureObject->first);
219		if(textureObject->second) textureObject->second->release();
220		mTextureMap.erase(textureObject);
221	}
222}
223
224void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
225{
226	RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
227
228	if(renderbufferObject != mRenderbufferMap.end())
229	{
230		//mRenderbufferNameSpace.release(renderbufferObject->first);
231		if(renderbufferObject->second) renderbufferObject->second->release();
232		mRenderbufferMap.erase(renderbufferObject);
233	}
234}
235
236Buffer *ResourceManager::getBuffer(unsigned int handle)
237{
238	BufferMap::iterator buffer = mBufferMap.find(handle);
239
240	if(buffer == mBufferMap.end())
241	{
242		return nullptr;
243	}
244	else
245	{
246		return buffer->second;
247	}
248}
249
250Shader *ResourceManager::getShader(unsigned int handle)
251{
252	ShaderMap::iterator shader = mShaderMap.find(handle);
253
254	if(shader == mShaderMap.end())
255	{
256		return nullptr;
257	}
258	else
259	{
260		return shader->second;
261	}
262}
263
264Texture *ResourceManager::getTexture(unsigned int handle)
265{
266	if(handle == 0) return nullptr;
267
268	TextureMap::iterator texture = mTextureMap.find(handle);
269
270	if(texture == mTextureMap.end())
271	{
272		return nullptr;
273	}
274	else
275	{
276		return texture->second;
277	}
278}
279
280Program *ResourceManager::getProgram(unsigned int handle)
281{
282	ProgramMap::iterator program = mProgramMap.find(handle);
283
284	if(program == mProgramMap.end())
285	{
286		return nullptr;
287	}
288	else
289	{
290		return program->second;
291	}
292}
293
294Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
295{
296	RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
297
298	if(renderbuffer == mRenderbufferMap.end())
299	{
300		return nullptr;
301	}
302	else
303	{
304		return renderbuffer->second;
305	}
306}
307
308void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
309{
310	mRenderbufferMap[handle] = buffer;
311}
312
313void ResourceManager::checkBufferAllocation(unsigned int buffer)
314{
315	if(buffer != 0 && !getBuffer(buffer))
316	{
317		Buffer *bufferObject = new Buffer(buffer);
318		mBufferMap[buffer] = bufferObject;
319		bufferObject->addRef();
320	}
321}
322
323void ResourceManager::checkTextureAllocation(GLuint texture, TextureType type)
324{
325	if(!getTexture(texture) && texture != 0)
326	{
327		Texture *textureObject;
328
329		if(type == TEXTURE_2D)
330		{
331			textureObject = new Texture2D(texture);
332		}
333		else if(type == TEXTURE_CUBE)
334		{
335			textureObject = new TextureCubeMap(texture);
336		}
337		else
338		{
339			UNREACHABLE(type);
340			return;
341		}
342
343		mTextureMap[texture] = textureObject;
344		textureObject->addRef();
345	}
346}
347
348void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer)
349{
350	if(renderbuffer != 0 && !getRenderbuffer(renderbuffer))
351	{
352		Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(0, 0, GL_RGBA4, 0));
353		mRenderbufferMap[renderbuffer] = renderbufferObject;
354		renderbufferObject->addRef();
355	}
356}
357
358}
359