blob: 2e7f2a8fe55d243564f0592d7a84421cdf1c7337 [file] [log] [blame]
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001//
Geoff Lang4ddf5af2016-12-01 14:30:44 -05002// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Geoff Lang4ddf5af2016-12-01 14:30:44 -05007// ResourceManager.cpp: Implements the the ResourceManager classes, which handle allocation and
8// lifetime of GL objects.
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00009
Geoff Lang2b5420c2014-11-19 14:20:15 -050010#include "libANGLE/ResourceManager.h"
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000011
Geoff Lang2b5420c2014-11-19 14:20:15 -050012#include "libANGLE/Buffer.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040013#include "libANGLE/Fence.h"
Sami Väisänene45e53b2016-05-25 10:36:04 +030014#include "libANGLE/Path.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Program.h"
16#include "libANGLE/Renderbuffer.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040017#include "libANGLE/Sampler.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050018#include "libANGLE/Shader.h"
19#include "libANGLE/Texture.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040020#include "libANGLE/renderer/GLImplFactory.h"
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000021
22namespace gl
23{
Geoff Lang4ddf5af2016-12-01 14:30:44 -050024
25namespace
26{
27
28template <typename ResourceType>
29GLuint AllocateEmptyObject(HandleAllocator *handleAllocator, ResourceMap<ResourceType> *objectMap)
30{
31 GLuint handle = handleAllocator->allocate();
32 (*objectMap)[handle] = nullptr;
33 return handle;
34}
35
36template <typename ResourceType, typename CreationFunction>
37GLuint InsertObject(HandleAllocator *handleAllocator,
38 ResourceMap<ResourceType> *objectMap,
39 const CreationFunction &func)
40{
41 GLuint handle = handleAllocator->allocate();
42 (*objectMap)[handle] = func(handle);
43 return handle;
44}
45
46template <typename ResourceType, typename DeletionFunction>
47void DeleteObject(HandleAllocator *handleAllocator,
48 ResourceMap<ResourceType> *objectMap,
49 GLuint handle,
50 const DeletionFunction &deletionFunc)
51{
52 auto objectIter = objectMap->find(handle);
53 if (objectIter == objectMap->end())
54 {
55 return;
56 }
57
58 if (objectIter->second != nullptr)
59 {
60 deletionFunc(objectIter->second);
61 }
62
63 handleAllocator->release(objectIter->first);
64 objectMap->erase(objectIter);
65}
66
67template <typename ResourceType>
68ResourceType *GetObject(const ResourceMap<ResourceType> &objectMap, GLuint handle)
69{
70 auto iter = objectMap.find(handle);
71 return iter != objectMap.end() ? iter->second : nullptr;
72}
73
74} // anonymous namespace
75
76template <typename HandleAllocatorType>
77ResourceManagerBase<HandleAllocatorType>::ResourceManagerBase() : mRefCount(1)
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000078{
79}
80
Geoff Lang4ddf5af2016-12-01 14:30:44 -050081template <typename HandleAllocatorType>
82void ResourceManagerBase<HandleAllocatorType>::addRef()
daniel@transgaming.com0d25b002010-07-28 19:21:07 +000083{
84 mRefCount++;
85}
86
Geoff Lang4ddf5af2016-12-01 14:30:44 -050087template <typename HandleAllocatorType>
88void ResourceManagerBase<HandleAllocatorType>::release()
daniel@transgaming.com0d25b002010-07-28 19:21:07 +000089{
90 if (--mRefCount == 0)
91 {
92 delete this;
93 }
94}
95
Geoff Lang4ddf5af2016-12-01 14:30:44 -050096template <typename ResourceType, typename HandleAllocatorType>
97TypedResourceManager<ResourceType, HandleAllocatorType>::~TypedResourceManager()
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000098{
Geoff Lang4ddf5af2016-12-01 14:30:44 -050099 while (!mObjectMap.empty())
100 {
101 deleteObject(mObjectMap.begin()->first);
102 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000103}
104
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500105template <typename ResourceType, typename HandleAllocatorType>
106void TypedResourceManager<ResourceType, HandleAllocatorType>::deleteObject(GLuint handle)
107{
108 DeleteObject(&this->mHandleAllocator, &mObjectMap, handle,
109 [](ResourceType *object) { object->release(); });
110}
111
112// Instantiations of ResourceManager
113template class ResourceManagerBase<HandleAllocator>;
114template class ResourceManagerBase<HandleRangeAllocator>;
115template class TypedResourceManager<Buffer, HandleAllocator>;
116template class TypedResourceManager<Texture, HandleAllocator>;
117template class TypedResourceManager<Renderbuffer, HandleAllocator>;
118template class TypedResourceManager<Sampler, HandleAllocator>;
119template class TypedResourceManager<FenceSync, HandleAllocator>;
120
121GLuint BufferManager::createBuffer()
122{
123 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
124}
125
126void BufferManager::deleteBuffer(GLuint buffer)
127{
128 deleteObject(buffer);
129}
130
131Buffer *BufferManager::getBuffer(GLuint handle) const
132{
133 return GetObject(mObjectMap, handle);
134}
135
136Buffer *BufferManager::checkBufferAllocation(rx::GLImplFactory *factory, GLuint handle)
137{
138 if (handle == 0)
139 {
140 return nullptr;
141 }
142
143 auto objectMapIter = mObjectMap.find(handle);
144 bool handleAllocated = (objectMapIter != mObjectMap.end());
145
146 if (handleAllocated && objectMapIter->second != nullptr)
147 {
148 return objectMapIter->second;
149 }
150
151 Buffer *object = new Buffer(factory, handle);
152 object->addRef();
153
154 if (handleAllocated)
155 {
156 objectMapIter->second = object;
157 }
158 else
159 {
160 mHandleAllocator.reserve(handle);
161 mObjectMap[handle] = object;
162 }
163
164 return object;
165}
166
167bool BufferManager::isBufferGenerated(GLuint buffer) const
168{
169 return buffer == 0 || mObjectMap.find(buffer) != mObjectMap.end();
170}
171
172ShaderProgramManager::~ShaderProgramManager()
173{
174 while (!mPrograms.empty())
175 {
176 deleteProgram(mPrograms.begin()->first);
177 }
178 while (!mShaders.empty())
179 {
180 deleteShader(mShaders.begin()->first);
181 }
182}
183
184GLuint ShaderProgramManager::createShader(rx::GLImplFactory *factory,
185 const gl::Limitations &rendererLimitations,
186 GLenum type)
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000187{
Martin Radev4c4c8e72016-08-04 12:25:34 +0300188 ASSERT(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER || type == GL_COMPUTE_SHADER);
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500189 GLuint handle = mHandleAllocator.allocate();
190 mShaders[handle] = new Shader(this, factory, rendererLimitations, type, handle);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000191 return handle;
192}
193
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500194void ShaderProgramManager::deleteShader(GLuint shader)
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000195{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500196 deleteObject(&mShaders, shader);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000197}
198
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500199Shader *ShaderProgramManager::getShader(GLuint handle) const
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000200{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500201 return GetObject(mShaders, handle);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000202}
203
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500204GLuint ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000205{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500206 GLuint handle = mHandleAllocator.allocate();
207 mPrograms[handle] = new Program(factory, this, handle);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000208 return handle;
209}
210
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500211void ShaderProgramManager::deleteProgram(GLuint program)
Jamie Madilldc356042013-07-19 16:36:57 -0400212{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500213 deleteObject(&mPrograms, program);
Jamie Madilldc356042013-07-19 16:36:57 -0400214}
215
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500216Program *ShaderProgramManager::getProgram(GLuint handle) const
Jamie Madillcd055f82013-07-26 11:55:15 -0400217{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500218 return GetObject(mPrograms, handle);
Jamie Madillcd055f82013-07-26 11:55:15 -0400219}
220
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500221template <typename ObjectType>
222void ShaderProgramManager::deleteObject(ResourceMap<ObjectType> *objectMap, GLuint id)
223{
224 auto iter = objectMap->find(id);
225 if (iter == objectMap->end())
226 {
227 return;
228 }
229
230 auto object = iter->second;
231 if (object->getRefCount() == 0)
232 {
233 mHandleAllocator.release(id);
234 SafeDelete(object);
235 objectMap->erase(iter);
236 }
237 else
238 {
239 object->flagForDeletion();
240 }
241}
242
243GLuint TextureManager::createTexture()
244{
245 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
246}
247
248void TextureManager::deleteTexture(GLuint texture)
249{
250 deleteObject(texture);
251}
252
253Texture *TextureManager::getTexture(GLuint handle) const
254{
255 ASSERT(GetObject(mObjectMap, 0) == nullptr);
256 return GetObject(mObjectMap, handle);
257}
258
259Texture *TextureManager::checkTextureAllocation(rx::GLImplFactory *factory,
260 GLuint handle,
261 GLenum type)
262{
263 if (handle == 0)
264 {
265 return nullptr;
266 }
267
268 auto objectMapIter = mObjectMap.find(handle);
269 bool handleAllocated = (objectMapIter != mObjectMap.end());
270
271 if (handleAllocated && objectMapIter->second != nullptr)
272 {
273 return objectMapIter->second;
274 }
275
276 Texture *object = new Texture(factory, handle, type);
277 object->addRef();
278
279 if (handleAllocated)
280 {
281 objectMapIter->second = object;
282 }
283 else
284 {
285 mHandleAllocator.reserve(handle);
286 mObjectMap[handle] = object;
287 }
288
289 return object;
290}
291
292bool TextureManager::isTextureGenerated(GLuint texture) const
293{
294 return texture == 0 || mObjectMap.find(texture) != mObjectMap.end();
295}
296
297GLuint RenderbufferManager::createRenderbuffer()
298{
299 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
300}
301
302void RenderbufferManager::deleteRenderbuffer(GLuint renderbuffer)
303{
304 deleteObject(renderbuffer);
305}
306
307Renderbuffer *RenderbufferManager::getRenderbuffer(GLuint handle)
308{
309 return GetObject(mObjectMap, handle);
310}
311
312Renderbuffer *RenderbufferManager::checkRenderbufferAllocation(rx::GLImplFactory *factory,
313 GLuint handle)
314{
315 if (handle == 0)
316 {
317 return nullptr;
318 }
319
320 auto objectMapIter = mObjectMap.find(handle);
321 bool handleAllocated = (objectMapIter != mObjectMap.end());
322
323 if (handleAllocated && objectMapIter->second != nullptr)
324 {
325 return objectMapIter->second;
326 }
327
328 Renderbuffer *object = new Renderbuffer(factory->createRenderbuffer(), handle);
329 object->addRef();
330
331 if (handleAllocated)
332 {
333 objectMapIter->second = object;
334 }
335 else
336 {
337 mHandleAllocator.reserve(handle);
338 mObjectMap[handle] = object;
339 }
340
341 return object;
342}
343
344bool RenderbufferManager::isRenderbufferGenerated(GLuint renderbuffer) const
345{
346 return renderbuffer == 0 || mObjectMap.find(renderbuffer) != mObjectMap.end();
347}
348
349GLuint SamplerManager::createSampler()
350{
351 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
352}
353
354void SamplerManager::deleteSampler(GLuint sampler)
355{
356 deleteObject(sampler);
357}
358
359Sampler *SamplerManager::getSampler(GLuint handle)
360{
361 return GetObject(mObjectMap, handle);
362}
363
364Sampler *SamplerManager::checkSamplerAllocation(rx::GLImplFactory *factory, GLuint handle)
365{
366 if (handle == 0)
367 {
368 return nullptr;
369 }
370
371 auto objectMapIter = mObjectMap.find(handle);
372 bool handleAllocated = (objectMapIter != mObjectMap.end());
373
374 if (handleAllocated && objectMapIter->second != nullptr)
375 {
376 return objectMapIter->second;
377 }
378
379 Sampler *object = new Sampler(factory, handle);
380 object->addRef();
381
382 if (handleAllocated)
383 {
384 objectMapIter->second = object;
385 }
386 else
387 {
388 mHandleAllocator.reserve(handle);
389 mObjectMap[handle] = object;
390 }
391
392 return object;
393}
394
395bool SamplerManager::isSampler(GLuint sampler)
396{
397 return mObjectMap.find(sampler) != mObjectMap.end();
398}
399
400GLuint FenceSyncManager::createFenceSync(rx::GLImplFactory *factory)
401{
402 struct fenceSyncAllocator
403 {
404 fenceSyncAllocator(rx::GLImplFactory *factory) : factory(factory) {}
405
406 rx::GLImplFactory *factory;
407
408 FenceSync *operator()(GLuint handle) const
409 {
410 FenceSync *fenceSync = new FenceSync(factory->createFenceSync(), handle);
411 fenceSync->addRef();
412 return fenceSync;
413 }
414 };
415
416 return InsertObject(&mHandleAllocator, &mObjectMap, fenceSyncAllocator(factory));
417}
418
419void FenceSyncManager::deleteFenceSync(GLuint fenceSync)
420{
421 deleteObject(fenceSync);
422}
423
424FenceSync *FenceSyncManager::getFenceSync(GLuint handle)
425{
426 return GetObject(mObjectMap, handle);
427}
428
429ErrorOrResult<GLuint> PathManager::createPaths(rx::GLImplFactory *factory, GLsizei range)
Sami Väisänene45e53b2016-05-25 10:36:04 +0300430{
431 // Allocate client side handles.
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500432 const GLuint client = mHandleAllocator.allocateRange(static_cast<GLuint>(range));
Sami Väisänene45e53b2016-05-25 10:36:04 +0300433 if (client == HandleRangeAllocator::kInvalidHandle)
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500434 return Error(GL_OUT_OF_MEMORY, "Failed to allocate path handle range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +0300435
436 const auto &paths = factory->createPaths(range);
437 if (paths.empty())
438 {
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500439 mHandleAllocator.releaseRange(client, range);
440 return Error(GL_OUT_OF_MEMORY, "Failed to allocate path objects.");
Sami Väisänene45e53b2016-05-25 10:36:04 +0300441 }
442
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500443 auto hint = mPaths.begin();
Sami Väisänene45e53b2016-05-25 10:36:04 +0300444
445 for (GLsizei i = 0; i < range; ++i)
446 {
447 const auto impl = paths[static_cast<unsigned>(i)];
448 const auto id = client + i;
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500449 hint = mPaths.insert(hint, std::make_pair(id, new Path(impl)));
Sami Väisänene45e53b2016-05-25 10:36:04 +0300450 }
451 return client;
452}
453
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500454void PathManager::deletePaths(GLuint first, GLsizei range)
Sami Väisänene45e53b2016-05-25 10:36:04 +0300455{
456 for (GLsizei i = 0; i < range; ++i)
457 {
458 const auto id = first + i;
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500459 const auto it = mPaths.find(id);
460 if (it == mPaths.end())
Sami Väisänene45e53b2016-05-25 10:36:04 +0300461 continue;
462 Path *p = it->second;
463 delete p;
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500464 mPaths.erase(it);
Sami Väisänene45e53b2016-05-25 10:36:04 +0300465 }
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500466 mHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
Sami Väisänene45e53b2016-05-25 10:36:04 +0300467}
468
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500469Path *PathManager::getPath(GLuint handle) const
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000470{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500471 auto iter = mPaths.find(handle);
472 return iter != mPaths.end() ? iter->second : nullptr;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000473}
474
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500475bool PathManager::hasPath(GLuint handle) const
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000476{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500477 return mHandleAllocator.isUsed(handle);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000478}
479
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500480PathManager::~PathManager()
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000481{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500482 for (auto path : mPaths)
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000483 {
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500484 SafeDelete(path.second);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000485 }
Geoff Langf41a7152016-09-19 15:11:17 -0400486}
487
Jamie Madill3f01e6c2016-03-08 13:53:02 -0500488} // namespace gl