1//
2// Copyright (c) 2002-2013 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#include "libGLESv2/Sampler.h"
18#include "libGLESv2/Fence.h"
19#include "libGLESv2/renderer/Renderer.h"
20
21namespace gl
22{
23ResourceManager::ResourceManager(rx::Renderer *renderer)
24{
25    mRefCount = 1;
26    mRenderer = renderer;
27}
28
29ResourceManager::~ResourceManager()
30{
31    while (!mBufferMap.empty())
32    {
33        deleteBuffer(mBufferMap.begin()->first);
34    }
35
36    while (!mProgramMap.empty())
37    {
38        deleteProgram(mProgramMap.begin()->first);
39    }
40
41    while (!mShaderMap.empty())
42    {
43        deleteShader(mShaderMap.begin()->first);
44    }
45
46    while (!mRenderbufferMap.empty())
47    {
48        deleteRenderbuffer(mRenderbufferMap.begin()->first);
49    }
50
51    while (!mTextureMap.empty())
52    {
53        deleteTexture(mTextureMap.begin()->first);
54    }
55
56    while (!mSamplerMap.empty())
57    {
58        deleteSampler(mSamplerMap.begin()->first);
59    }
60
61    while (!mFenceSyncMap.empty())
62    {
63        deleteFenceSync(mFenceSyncMap.begin()->first);
64    }
65}
66
67void ResourceManager::addRef()
68{
69    mRefCount++;
70}
71
72void ResourceManager::release()
73{
74    if (--mRefCount == 0)
75    {
76        delete this;
77    }
78}
79
80// Returns an unused buffer name
81GLuint ResourceManager::createBuffer()
82{
83    GLuint handle = mBufferHandleAllocator.allocate();
84
85    mBufferMap[handle] = NULL;
86
87    return handle;
88}
89
90// Returns an unused shader/program name
91GLuint ResourceManager::createShader(GLenum type)
92{
93    GLuint handle = mProgramShaderHandleAllocator.allocate();
94
95    if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER)
96    {
97        mShaderMap[handle] = new Shader(this, mRenderer->createShader(type), type, handle);
98    }
99    else UNREACHABLE();
100
101    return handle;
102}
103
104// Returns an unused program/shader name
105GLuint ResourceManager::createProgram()
106{
107    GLuint handle = mProgramShaderHandleAllocator.allocate();
108
109    mProgramMap[handle] = new Program(mRenderer, this, handle);
110
111    return handle;
112}
113
114// Returns an unused texture name
115GLuint ResourceManager::createTexture()
116{
117    GLuint handle = mTextureHandleAllocator.allocate();
118
119    mTextureMap[handle] = NULL;
120
121    return handle;
122}
123
124// Returns an unused renderbuffer name
125GLuint ResourceManager::createRenderbuffer()
126{
127    GLuint handle = mRenderbufferHandleAllocator.allocate();
128
129    mRenderbufferMap[handle] = NULL;
130
131    return handle;
132}
133
134// Returns an unused sampler name
135GLuint ResourceManager::createSampler()
136{
137    GLuint handle = mSamplerHandleAllocator.allocate();
138
139    mSamplerMap[handle] = NULL;
140
141    return handle;
142}
143
144// Returns the next unused fence name, and allocates the fence
145GLuint ResourceManager::createFenceSync()
146{
147    GLuint handle = mFenceSyncHandleAllocator.allocate();
148
149    FenceSync *fenceSync = new FenceSync(mRenderer, handle);
150    fenceSync->addRef();
151    mFenceSyncMap[handle] = fenceSync;
152
153    return handle;
154}
155
156void ResourceManager::deleteBuffer(GLuint buffer)
157{
158    BufferMap::iterator bufferObject = mBufferMap.find(buffer);
159
160    if (bufferObject != mBufferMap.end())
161    {
162        mBufferHandleAllocator.release(bufferObject->first);
163        if (bufferObject->second) bufferObject->second->release();
164        mBufferMap.erase(bufferObject);
165    }
166}
167
168void ResourceManager::deleteShader(GLuint shader)
169{
170    ShaderMap::iterator shaderObject = mShaderMap.find(shader);
171
172    if (shaderObject != mShaderMap.end())
173    {
174        if (shaderObject->second->getRefCount() == 0)
175        {
176            mProgramShaderHandleAllocator.release(shaderObject->first);
177            delete shaderObject->second;
178            mShaderMap.erase(shaderObject);
179        }
180        else
181        {
182            shaderObject->second->flagForDeletion();
183        }
184    }
185}
186
187void ResourceManager::deleteProgram(GLuint program)
188{
189    ProgramMap::iterator programObject = mProgramMap.find(program);
190
191    if (programObject != mProgramMap.end())
192    {
193        if (programObject->second->getRefCount() == 0)
194        {
195            mProgramShaderHandleAllocator.release(programObject->first);
196            delete programObject->second;
197            mProgramMap.erase(programObject);
198        }
199        else
200        {
201            programObject->second->flagForDeletion();
202        }
203    }
204}
205
206void ResourceManager::deleteTexture(GLuint texture)
207{
208    TextureMap::iterator textureObject = mTextureMap.find(texture);
209
210    if (textureObject != mTextureMap.end())
211    {
212        mTextureHandleAllocator.release(textureObject->first);
213        if (textureObject->second) textureObject->second->release();
214        mTextureMap.erase(textureObject);
215    }
216}
217
218void ResourceManager::deleteRenderbuffer(GLuint renderbuffer)
219{
220    RenderbufferMap::iterator renderbufferObject = mRenderbufferMap.find(renderbuffer);
221
222    if (renderbufferObject != mRenderbufferMap.end())
223    {
224        mRenderbufferHandleAllocator.release(renderbufferObject->first);
225        if (renderbufferObject->second) renderbufferObject->second->release();
226        mRenderbufferMap.erase(renderbufferObject);
227    }
228}
229
230void ResourceManager::deleteSampler(GLuint sampler)
231{
232    auto samplerObject = mSamplerMap.find(sampler);
233
234    if (samplerObject != mSamplerMap.end())
235    {
236        mSamplerHandleAllocator.release(samplerObject->first);
237        if (samplerObject->second) samplerObject->second->release();
238        mSamplerMap.erase(samplerObject);
239    }
240}
241
242void ResourceManager::deleteFenceSync(GLuint fenceSync)
243{
244    auto fenceObjectIt = mFenceSyncMap.find(fenceSync);
245
246    if (fenceObjectIt != mFenceSyncMap.end())
247    {
248        mFenceSyncHandleAllocator.release(fenceObjectIt->first);
249        if (fenceObjectIt->second) fenceObjectIt->second->release();
250        mFenceSyncMap.erase(fenceObjectIt);
251    }
252}
253
254Buffer *ResourceManager::getBuffer(unsigned int handle)
255{
256    BufferMap::iterator buffer = mBufferMap.find(handle);
257
258    if (buffer == mBufferMap.end())
259    {
260        return NULL;
261    }
262    else
263    {
264        return buffer->second;
265    }
266}
267
268Shader *ResourceManager::getShader(unsigned int handle)
269{
270    ShaderMap::iterator shader = mShaderMap.find(handle);
271
272    if (shader == mShaderMap.end())
273    {
274        return NULL;
275    }
276    else
277    {
278        return shader->second;
279    }
280}
281
282Texture *ResourceManager::getTexture(unsigned int handle)
283{
284    if (handle == 0) return NULL;
285
286    TextureMap::iterator texture = mTextureMap.find(handle);
287
288    if (texture == mTextureMap.end())
289    {
290        return NULL;
291    }
292    else
293    {
294        return texture->second;
295    }
296}
297
298Program *ResourceManager::getProgram(unsigned int handle)
299{
300    ProgramMap::iterator program = mProgramMap.find(handle);
301
302    if (program == mProgramMap.end())
303    {
304        return NULL;
305    }
306    else
307    {
308        return program->second;
309    }
310}
311
312Renderbuffer *ResourceManager::getRenderbuffer(unsigned int handle)
313{
314    RenderbufferMap::iterator renderbuffer = mRenderbufferMap.find(handle);
315
316    if (renderbuffer == mRenderbufferMap.end())
317    {
318        return NULL;
319    }
320    else
321    {
322        return renderbuffer->second;
323    }
324}
325
326Sampler *ResourceManager::getSampler(unsigned int handle)
327{
328    auto sampler = mSamplerMap.find(handle);
329
330    if (sampler == mSamplerMap.end())
331    {
332        return NULL;
333    }
334    else
335    {
336        return sampler->second;
337    }
338}
339
340FenceSync *ResourceManager::getFenceSync(unsigned int handle)
341{
342    auto fenceObjectIt = mFenceSyncMap.find(handle);
343
344    if (fenceObjectIt == mFenceSyncMap.end())
345    {
346        return NULL;
347    }
348    else
349    {
350        return fenceObjectIt->second;
351    }
352}
353
354void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
355{
356    mRenderbufferMap[handle] = buffer;
357}
358
359void ResourceManager::checkBufferAllocation(unsigned int buffer)
360{
361    if (buffer != 0 && !getBuffer(buffer))
362    {
363        Buffer *bufferObject = new Buffer(mRenderer->createBuffer(), buffer);
364        mBufferMap[buffer] = bufferObject;
365        bufferObject->addRef();
366    }
367}
368
369void ResourceManager::checkTextureAllocation(GLuint texture, GLenum type)
370{
371    if (!getTexture(texture) && texture != 0)
372    {
373        Texture *textureObject;
374
375        if (type == GL_TEXTURE_2D)
376        {
377            textureObject = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), texture);
378        }
379        else if (type == GL_TEXTURE_CUBE_MAP)
380        {
381            textureObject = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), texture);
382        }
383        else if (type == GL_TEXTURE_3D)
384        {
385            textureObject = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), texture);
386        }
387        else if (type == GL_TEXTURE_2D_ARRAY)
388        {
389            textureObject = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), texture);
390        }
391        else
392        {
393            UNREACHABLE();
394            return;
395        }
396
397        mTextureMap[texture] = textureObject;
398        textureObject->addRef();
399    }
400}
401
402void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer)
403{
404    if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
405    {
406        Renderbuffer *renderbufferObject = new Renderbuffer(renderbuffer, new Colorbuffer(mRenderer, 0, 0, GL_RGBA4, 0));
407        mRenderbufferMap[renderbuffer] = renderbufferObject;
408        renderbufferObject->addRef();
409    }
410}
411
412void ResourceManager::checkSamplerAllocation(GLuint sampler)
413{
414    if (sampler != 0 && !getSampler(sampler))
415    {
416        Sampler *samplerObject = new Sampler(sampler);
417        mSamplerMap[sampler] = samplerObject;
418        samplerObject->addRef();
419    }
420}
421
422bool ResourceManager::isSampler(GLuint sampler)
423{
424    return mSamplerMap.find(sampler) != mSamplerMap.end();
425}
426
427}
428