• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2002 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 the ResourceManager classes, which handle allocation and
8 // lifetime of GL objects.
9 
10 #include "libANGLE/ResourceManager.h"
11 
12 #include "libANGLE/Buffer.h"
13 #include "libANGLE/Context.h"
14 #include "libANGLE/Fence.h"
15 #include "libANGLE/MemoryObject.h"
16 #include "libANGLE/Path.h"
17 #include "libANGLE/Program.h"
18 #include "libANGLE/ProgramPipeline.h"
19 #include "libANGLE/Renderbuffer.h"
20 #include "libANGLE/Sampler.h"
21 #include "libANGLE/Semaphore.h"
22 #include "libANGLE/Shader.h"
23 #include "libANGLE/Texture.h"
24 #include "libANGLE/renderer/ContextImpl.h"
25 
26 namespace gl
27 {
28 
29 namespace
30 {
31 
32 template <typename ResourceType, typename IDType>
AllocateEmptyObject(HandleAllocator * handleAllocator,ResourceMap<ResourceType,IDType> * objectMap)33 IDType AllocateEmptyObject(HandleAllocator *handleAllocator,
34                            ResourceMap<ResourceType, IDType> *objectMap)
35 {
36     IDType handle = FromGL<IDType>(handleAllocator->allocate());
37     objectMap->assign(handle, nullptr);
38     return handle;
39 }
40 
41 }  // anonymous namespace
42 
43 template <typename HandleAllocatorType>
ResourceManagerBase()44 ResourceManagerBase<HandleAllocatorType>::ResourceManagerBase() : mRefCount(1)
45 {}
46 
47 template <typename HandleAllocatorType>
addRef()48 void ResourceManagerBase<HandleAllocatorType>::addRef()
49 {
50     mRefCount++;
51 }
52 
53 template <typename HandleAllocatorType>
release(const Context * context)54 void ResourceManagerBase<HandleAllocatorType>::release(const Context *context)
55 {
56     if (--mRefCount == 0)
57     {
58         reset(context);
59         delete this;
60     }
61 }
62 
63 template <typename ResourceType, typename HandleAllocatorType, typename ImplT, typename IDType>
~TypedResourceManager()64 TypedResourceManager<ResourceType, HandleAllocatorType, ImplT, IDType>::~TypedResourceManager()
65 {
66     ASSERT(mObjectMap.empty());
67 }
68 
69 template <typename ResourceType, typename HandleAllocatorType, typename ImplT, typename IDType>
reset(const Context * context)70 void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT, IDType>::reset(
71     const Context *context)
72 {
73     this->mHandleAllocator.reset();
74     for (const auto &resource : mObjectMap)
75     {
76         if (resource.second)
77         {
78             ImplT::DeleteObject(context, resource.second);
79         }
80     }
81     mObjectMap.clear();
82 }
83 
84 template <typename ResourceType, typename HandleAllocatorType, typename ImplT, typename IDType>
deleteObject(const Context * context,IDType handle)85 void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT, IDType>::deleteObject(
86     const Context *context,
87     IDType handle)
88 {
89     ResourceType *resource = nullptr;
90     if (!mObjectMap.erase(handle, &resource))
91     {
92         return;
93     }
94 
95     // Requires an explicit this-> because of C++ template rules.
96     this->mHandleAllocator.release(GetIDValue(handle));
97 
98     if (resource)
99     {
100         ImplT::DeleteObject(context, resource);
101     }
102 }
103 
104 template class ResourceManagerBase<HandleAllocator>;
105 template class ResourceManagerBase<HandleRangeAllocator>;
106 template class TypedResourceManager<Buffer, HandleAllocator, BufferManager, BufferID>;
107 template class TypedResourceManager<Texture, HandleAllocator, TextureManager, TextureID>;
108 template class TypedResourceManager<Renderbuffer,
109                                     HandleAllocator,
110                                     RenderbufferManager,
111                                     RenderbufferID>;
112 template class TypedResourceManager<Sampler, HandleAllocator, SamplerManager, GLuint>;
113 template class TypedResourceManager<Sync, HandleAllocator, SyncManager, GLuint>;
114 template class TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager, GLuint>;
115 template class TypedResourceManager<ProgramPipeline,
116                                     HandleAllocator,
117                                     ProgramPipelineManager,
118                                     GLuint>;
119 
120 // BufferManager Implementation.
121 
122 // static
AllocateNewObject(rx::GLImplFactory * factory,BufferID handle)123 Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, BufferID handle)
124 {
125     Buffer *buffer = new Buffer(factory, handle);
126     buffer->addRef();
127     return buffer;
128 }
129 
130 // static
DeleteObject(const Context * context,Buffer * buffer)131 void BufferManager::DeleteObject(const Context *context, Buffer *buffer)
132 {
133     buffer->release(context);
134 }
135 
createBuffer()136 BufferID BufferManager::createBuffer()
137 {
138     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
139 }
140 
getBuffer(BufferID handle) const141 Buffer *BufferManager::getBuffer(BufferID handle) const
142 {
143     return mObjectMap.query(handle);
144 }
145 
146 // ShaderProgramManager Implementation.
147 
ShaderProgramManager()148 ShaderProgramManager::ShaderProgramManager() {}
149 
~ShaderProgramManager()150 ShaderProgramManager::~ShaderProgramManager()
151 {
152     ASSERT(mPrograms.empty());
153     ASSERT(mShaders.empty());
154 }
155 
reset(const Context * context)156 void ShaderProgramManager::reset(const Context *context)
157 {
158     while (!mPrograms.empty())
159     {
160         deleteProgram(context, mPrograms.begin()->first);
161     }
162     mPrograms.clear();
163     while (!mShaders.empty())
164     {
165         deleteShader(context, mShaders.begin()->first);
166     }
167     mShaders.clear();
168 }
169 
createShader(rx::GLImplFactory * factory,const gl::Limitations & rendererLimitations,ShaderType type)170 GLuint ShaderProgramManager::createShader(rx::GLImplFactory *factory,
171                                           const gl::Limitations &rendererLimitations,
172                                           ShaderType type)
173 {
174     ASSERT(type != ShaderType::InvalidEnum);
175     GLuint handle = mHandleAllocator.allocate();
176     mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
177     return handle;
178 }
179 
deleteShader(const Context * context,GLuint shader)180 void ShaderProgramManager::deleteShader(const Context *context, GLuint shader)
181 {
182     deleteObject(context, &mShaders, shader);
183 }
184 
getShader(GLuint handle) const185 Shader *ShaderProgramManager::getShader(GLuint handle) const
186 {
187     return mShaders.query(handle);
188 }
189 
createProgram(rx::GLImplFactory * factory)190 GLuint ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
191 {
192     GLuint handle = mHandleAllocator.allocate();
193     mPrograms.assign(handle, new Program(factory, this, handle));
194     return handle;
195 }
196 
deleteProgram(const gl::Context * context,GLuint program)197 void ShaderProgramManager::deleteProgram(const gl::Context *context, GLuint program)
198 {
199     deleteObject(context, &mPrograms, program);
200 }
201 
202 template <typename ObjectType>
deleteObject(const Context * context,ResourceMap<ObjectType> * objectMap,GLuint id)203 void ShaderProgramManager::deleteObject(const Context *context,
204                                         ResourceMap<ObjectType> *objectMap,
205                                         GLuint id)
206 {
207     ObjectType *object = objectMap->query(id);
208     if (!object)
209     {
210         return;
211     }
212 
213     if (object->getRefCount() == 0)
214     {
215         mHandleAllocator.release(id);
216         object->onDestroy(context);
217         objectMap->erase(id, &object);
218     }
219     else
220     {
221         object->flagForDeletion();
222     }
223 }
224 
225 // TextureManager Implementation.
226 
227 // static
AllocateNewObject(rx::GLImplFactory * factory,TextureID handle,TextureType type)228 Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory,
229                                            TextureID handle,
230                                            TextureType type)
231 {
232     Texture *texture = new Texture(factory, handle, type);
233     texture->addRef();
234     return texture;
235 }
236 
237 // static
DeleteObject(const Context * context,Texture * texture)238 void TextureManager::DeleteObject(const Context *context, Texture *texture)
239 {
240     texture->release(context);
241 }
242 
createTexture()243 TextureID TextureManager::createTexture()
244 {
245     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
246 }
247 
signalAllTexturesDirty() const248 void TextureManager::signalAllTexturesDirty() const
249 {
250     for (const auto &texture : mObjectMap)
251     {
252         if (texture.second)
253         {
254             // We don't know if the Texture needs init, but that's ok, since it will only force
255             // a re-check, and will not initialize the pixels if it's not needed.
256             texture.second->signalDirtyStorage(InitState::MayNeedInit);
257         }
258     }
259 }
260 
enableHandleAllocatorLogging()261 void TextureManager::enableHandleAllocatorLogging()
262 {
263     mHandleAllocator.enableLogging(true);
264 }
265 
266 // RenderbufferManager Implementation.
267 
268 // static
AllocateNewObject(rx::GLImplFactory * factory,RenderbufferID handle)269 Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory,
270                                                      RenderbufferID handle)
271 {
272     Renderbuffer *renderbuffer = new Renderbuffer(factory, handle);
273     renderbuffer->addRef();
274     return renderbuffer;
275 }
276 
277 // static
DeleteObject(const Context * context,Renderbuffer * renderbuffer)278 void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
279 {
280     renderbuffer->release(context);
281 }
282 
createRenderbuffer()283 RenderbufferID RenderbufferManager::createRenderbuffer()
284 {
285     return {AllocateEmptyObject(&mHandleAllocator, &mObjectMap)};
286 }
287 
getRenderbuffer(RenderbufferID handle) const288 Renderbuffer *RenderbufferManager::getRenderbuffer(RenderbufferID handle) const
289 {
290     return mObjectMap.query(handle);
291 }
292 
293 // SamplerManager Implementation.
294 
295 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle)296 Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
297 {
298     Sampler *sampler = new Sampler(factory, handle);
299     sampler->addRef();
300     return sampler;
301 }
302 
303 // static
DeleteObject(const Context * context,Sampler * sampler)304 void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
305 {
306     sampler->release(context);
307 }
308 
createSampler()309 GLuint SamplerManager::createSampler()
310 {
311     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
312 }
313 
getSampler(GLuint handle) const314 Sampler *SamplerManager::getSampler(GLuint handle) const
315 {
316     return mObjectMap.query(handle);
317 }
318 
isSampler(GLuint sampler) const319 bool SamplerManager::isSampler(GLuint sampler) const
320 {
321     return mObjectMap.contains(sampler);
322 }
323 
324 // SyncManager Implementation.
325 
326 // static
DeleteObject(const Context * context,Sync * sync)327 void SyncManager::DeleteObject(const Context *context, Sync *sync)
328 {
329     sync->release(context);
330 }
331 
createSync(rx::GLImplFactory * factory)332 GLuint SyncManager::createSync(rx::GLImplFactory *factory)
333 {
334     GLuint handle = mHandleAllocator.allocate();
335     Sync *sync    = new Sync(factory->createSync(), handle);
336     sync->addRef();
337     mObjectMap.assign(handle, sync);
338     return handle;
339 }
340 
getSync(GLuint handle) const341 Sync *SyncManager::getSync(GLuint handle) const
342 {
343     return mObjectMap.query(handle);
344 }
345 
346 // PathManager Implementation.
347 
348 PathManager::PathManager() = default;
349 
createPaths(Context * context,GLsizei range,GLuint * createdOut)350 angle::Result PathManager::createPaths(Context *context, GLsizei range, GLuint *createdOut)
351 {
352     *createdOut = 0;
353 
354     // Allocate client side handles.
355     const GLuint client = mHandleAllocator.allocateRange(static_cast<GLuint>(range));
356     if (client == HandleRangeAllocator::kInvalidHandle)
357     {
358         context->handleError(GL_OUT_OF_MEMORY, "Failed to allocate path handle range.", __FILE__,
359                              ANGLE_FUNCTION, __LINE__);
360         return angle::Result::Stop;
361     }
362 
363     const auto &paths = context->getImplementation()->createPaths(range);
364     if (paths.empty())
365     {
366         mHandleAllocator.releaseRange(client, range);
367         context->handleError(GL_OUT_OF_MEMORY, "Failed to allocate path objects.", __FILE__,
368                              ANGLE_FUNCTION, __LINE__);
369         return angle::Result::Stop;
370     }
371 
372     for (GLsizei i = 0; i < range; ++i)
373     {
374         rx::PathImpl *impl = paths[static_cast<unsigned>(i)];
375         const auto id      = client + i;
376         mPaths.assign(id, new Path(impl));
377     }
378     *createdOut = client;
379     return angle::Result::Continue;
380 }
381 
deletePaths(GLuint first,GLsizei range)382 void PathManager::deletePaths(GLuint first, GLsizei range)
383 {
384     for (GLsizei i = 0; i < range; ++i)
385     {
386         const auto id = first + i;
387         Path *p       = nullptr;
388         if (!mPaths.erase(id, &p))
389             continue;
390         delete p;
391     }
392     mHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
393 }
394 
getPath(GLuint handle) const395 Path *PathManager::getPath(GLuint handle) const
396 {
397     return mPaths.query(handle);
398 }
399 
hasPath(GLuint handle) const400 bool PathManager::hasPath(GLuint handle) const
401 {
402     return mHandleAllocator.isUsed(handle);
403 }
404 
~PathManager()405 PathManager::~PathManager()
406 {
407     ASSERT(mPaths.empty());
408 }
409 
reset(const Context * context)410 void PathManager::reset(const Context *context)
411 {
412     for (auto path : mPaths)
413     {
414         SafeDelete(path.second);
415     }
416     mPaths.clear();
417 }
418 
419 // FramebufferManager Implementation.
420 
421 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle,const Caps & caps)422 Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
423                                                    GLuint handle,
424                                                    const Caps &caps)
425 {
426     return new Framebuffer(caps, factory, handle);
427 }
428 
429 // static
DeleteObject(const Context * context,Framebuffer * framebuffer)430 void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
431 {
432     framebuffer->onDestroy(context);
433     delete framebuffer;
434 }
435 
createFramebuffer()436 GLuint FramebufferManager::createFramebuffer()
437 {
438     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
439 }
440 
getFramebuffer(GLuint handle) const441 Framebuffer *FramebufferManager::getFramebuffer(GLuint handle) const
442 {
443     return mObjectMap.query(handle);
444 }
445 
setDefaultFramebuffer(Framebuffer * framebuffer)446 void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
447 {
448     ASSERT(framebuffer == nullptr || framebuffer->id() == 0);
449     mObjectMap.assign(0, framebuffer);
450 }
451 
invalidateFramebufferComplenessCache() const452 void FramebufferManager::invalidateFramebufferComplenessCache() const
453 {
454     for (const auto &framebuffer : mObjectMap)
455     {
456         if (framebuffer.second)
457         {
458             framebuffer.second->invalidateCompletenessCache();
459         }
460     }
461 }
462 
463 // ProgramPipelineManager Implementation.
464 
465 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle)466 ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
467                                                            GLuint handle)
468 {
469     ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
470     pipeline->addRef();
471     return pipeline;
472 }
473 
474 // static
DeleteObject(const Context * context,ProgramPipeline * pipeline)475 void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
476 {
477     pipeline->release(context);
478 }
479 
createProgramPipeline()480 GLuint ProgramPipelineManager::createProgramPipeline()
481 {
482     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
483 }
484 
getProgramPipeline(GLuint handle) const485 ProgramPipeline *ProgramPipelineManager::getProgramPipeline(GLuint handle) const
486 {
487     return mObjectMap.query(handle);
488 }
489 
490 // MemoryObjectManager Implementation.
491 
MemoryObjectManager()492 MemoryObjectManager::MemoryObjectManager() {}
493 
~MemoryObjectManager()494 MemoryObjectManager::~MemoryObjectManager()
495 {
496     ASSERT(mMemoryObjects.empty());
497 }
498 
reset(const Context * context)499 void MemoryObjectManager::reset(const Context *context)
500 {
501     while (!mMemoryObjects.empty())
502     {
503         deleteMemoryObject(context, mMemoryObjects.begin()->first);
504     }
505     mMemoryObjects.clear();
506 }
507 
createMemoryObject(rx::GLImplFactory * factory)508 GLuint MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory)
509 {
510     GLuint handle              = mHandleAllocator.allocate();
511     MemoryObject *memoryObject = new MemoryObject(factory, handle);
512     memoryObject->addRef();
513     mMemoryObjects.assign(handle, memoryObject);
514     return handle;
515 }
516 
deleteMemoryObject(const Context * context,GLuint handle)517 void MemoryObjectManager::deleteMemoryObject(const Context *context, GLuint handle)
518 {
519     MemoryObject *memoryObject = nullptr;
520     if (!mMemoryObjects.erase(handle, &memoryObject))
521     {
522         return;
523     }
524 
525     // Requires an explicit this-> because of C++ template rules.
526     this->mHandleAllocator.release(handle);
527 
528     if (memoryObject)
529     {
530         memoryObject->release(context);
531     }
532 }
533 
getMemoryObject(GLuint handle) const534 MemoryObject *MemoryObjectManager::getMemoryObject(GLuint handle) const
535 {
536     return mMemoryObjects.query(handle);
537 }
538 
539 // SemaphoreManager Implementation.
540 
SemaphoreManager()541 SemaphoreManager::SemaphoreManager() {}
542 
~SemaphoreManager()543 SemaphoreManager::~SemaphoreManager()
544 {
545     ASSERT(mSemaphores.empty());
546 }
547 
reset(const Context * context)548 void SemaphoreManager::reset(const Context *context)
549 {
550     while (!mSemaphores.empty())
551     {
552         deleteSemaphore(context, mSemaphores.begin()->first);
553     }
554     mSemaphores.clear();
555 }
556 
createSemaphore(rx::GLImplFactory * factory)557 GLuint SemaphoreManager::createSemaphore(rx::GLImplFactory *factory)
558 {
559     GLuint handle        = mHandleAllocator.allocate();
560     Semaphore *semaphore = new Semaphore(factory, handle);
561     semaphore->addRef();
562     mSemaphores.assign(handle, semaphore);
563     return handle;
564 }
565 
deleteSemaphore(const Context * context,GLuint handle)566 void SemaphoreManager::deleteSemaphore(const Context *context, GLuint handle)
567 {
568     Semaphore *semaphore = nullptr;
569     if (!mSemaphores.erase(handle, &semaphore))
570     {
571         return;
572     }
573 
574     // Requires an explicit this-> because of C++ template rules.
575     this->mHandleAllocator.release(handle);
576 
577     if (semaphore)
578     {
579         semaphore->release(context);
580     }
581 }
582 
getSemaphore(GLuint handle) const583 Semaphore *SemaphoreManager::getSemaphore(GLuint handle) const
584 {
585     return mSemaphores.query(handle);
586 }
587 
588 }  // namespace gl
589