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