• 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/Program.h"
17 #include "libANGLE/ProgramPipeline.h"
18 #include "libANGLE/Query.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 = PackParam<IDType>(handleAllocator->allocate());
37     objectMap->assign(handle, nullptr);
38     return handle;
39 }
40 
41 }  // anonymous namespace
42 
ResourceManagerBase()43 ResourceManagerBase::ResourceManagerBase() : mRefCount(1) {}
44 
45 ResourceManagerBase::~ResourceManagerBase() = default;
46 
addRef()47 void ResourceManagerBase::addRef()
48 {
49     mRefCount++;
50 }
51 
release(const Context * context)52 void ResourceManagerBase::release(const Context *context)
53 {
54     if (--mRefCount == 0)
55     {
56         reset(context);
57         delete this;
58     }
59 }
60 
61 template <typename ResourceType, typename ImplT, typename IDType>
~TypedResourceManager()62 TypedResourceManager<ResourceType, ImplT, IDType>::~TypedResourceManager()
63 {
64     using UnsafeResourceMapIterTyped = UnsafeResourceMapIter<ResourceType, IDType>;
65     ASSERT(UnsafeResourceMapIterTyped(mObjectMap).empty());
66 }
67 
68 template <typename ResourceType, typename ImplT, typename IDType>
reset(const Context * context)69 void TypedResourceManager<ResourceType, ImplT, IDType>::reset(const Context *context)
70 {
71     // Note: this function is called when the last context in the share group is destroyed.  Thus
72     // there are no thread safety concerns.
73     this->mHandleAllocator.reset();
74     for (const auto &resource : UnsafeResourceMapIter(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 ImplT, typename IDType>
deleteObject(const Context * context,IDType handle)85 void TypedResourceManager<ResourceType, ImplT, IDType>::deleteObject(const Context *context,
86                                                                      IDType handle)
87 {
88     ResourceType *resource = nullptr;
89     if (!mObjectMap.erase(handle, &resource))
90     {
91         return;
92     }
93 
94     // Requires an explicit this-> because of C++ template rules.
95     this->mHandleAllocator.release(GetIDValue(handle));
96 
97     if (resource)
98     {
99         ImplT::DeleteObject(context, resource);
100     }
101 }
102 
103 template class TypedResourceManager<Buffer, BufferManager, BufferID>;
104 template class TypedResourceManager<Texture, TextureManager, TextureID>;
105 template class TypedResourceManager<Renderbuffer, RenderbufferManager, RenderbufferID>;
106 template class TypedResourceManager<Sampler, SamplerManager, SamplerID>;
107 template class TypedResourceManager<Sync, SyncManager, SyncID>;
108 template class TypedResourceManager<Framebuffer, FramebufferManager, FramebufferID>;
109 template class TypedResourceManager<ProgramPipeline, ProgramPipelineManager, ProgramPipelineID>;
110 
111 // BufferManager Implementation.
112 BufferManager::~BufferManager() = default;
113 
114 // static
AllocateNewObject(rx::GLImplFactory * factory,BufferID handle)115 Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, BufferID handle)
116 {
117     Buffer *buffer = new Buffer(factory, handle);
118     buffer->addRef();
119     return buffer;
120 }
121 
122 // static
DeleteObject(const Context * context,Buffer * buffer)123 void BufferManager::DeleteObject(const Context *context, Buffer *buffer)
124 {
125     buffer->release(context);
126 }
127 
createBuffer()128 BufferID BufferManager::createBuffer()
129 {
130     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
131 }
132 
getBuffer(BufferID handle) const133 Buffer *BufferManager::getBuffer(BufferID handle) const
134 {
135     return mObjectMap.query(handle);
136 }
137 
138 // ShaderProgramManager Implementation.
139 
ShaderProgramManager()140 ShaderProgramManager::ShaderProgramManager() {}
141 
~ShaderProgramManager()142 ShaderProgramManager::~ShaderProgramManager()
143 {
144     ASSERT(UnsafeResourceMapIter(mPrograms).empty());
145     ASSERT(UnsafeResourceMapIter(mShaders).empty());
146 }
147 
reset(const Context * context)148 void ShaderProgramManager::reset(const Context *context)
149 {
150     // Note: this function is called when the last context in the share group is destroyed.  Thus
151     // there are no thread safety concerns.
152     mHandleAllocator.reset();
153     for (const auto &program : UnsafeResourceMapIter(mPrograms))
154     {
155         if (program.second)
156         {
157             program.second->onDestroy(context);
158         }
159     }
160     for (const auto &shader : UnsafeResourceMapIter(mShaders))
161     {
162         if (shader.second)
163         {
164             shader.second->onDestroy(context);
165         }
166     }
167     mPrograms.clear();
168     mShaders.clear();
169 }
170 
createShader(rx::GLImplFactory * factory,const gl::Limitations & rendererLimitations,ShaderType type)171 ShaderProgramID ShaderProgramManager::createShader(rx::GLImplFactory *factory,
172                                                    const gl::Limitations &rendererLimitations,
173                                                    ShaderType type)
174 {
175     ASSERT(type != ShaderType::InvalidEnum);
176     ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
177     mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
178     return handle;
179 }
180 
deleteShader(const Context * context,ShaderProgramID shader)181 void ShaderProgramManager::deleteShader(const Context *context, ShaderProgramID shader)
182 {
183     deleteObject(context, &mShaders, shader);
184 }
185 
getShader(ShaderProgramID handle) const186 Shader *ShaderProgramManager::getShader(ShaderProgramID handle) const
187 {
188     return mShaders.query(handle);
189 }
190 
createProgram(rx::GLImplFactory * factory)191 ShaderProgramID ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
192 {
193     ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
194     mPrograms.assign(handle, new Program(factory, this, handle));
195     return handle;
196 }
197 
deleteProgram(const gl::Context * context,ShaderProgramID program)198 void ShaderProgramManager::deleteProgram(const gl::Context *context, ShaderProgramID program)
199 {
200     deleteObject(context, &mPrograms, program);
201 }
202 
203 template <typename ObjectType, typename IDType>
deleteObject(const Context * context,ResourceMap<ObjectType,IDType> * objectMap,IDType id)204 void ShaderProgramManager::deleteObject(const Context *context,
205                                         ResourceMap<ObjectType, IDType> *objectMap,
206                                         IDType id)
207 {
208     ObjectType *object = objectMap->query(id);
209     if (!object)
210     {
211         return;
212     }
213 
214     if (object->getRefCount() == 0)
215     {
216         mHandleAllocator.release(id.value);
217         object->onDestroy(context);
218         objectMap->erase(id, &object);
219     }
220     else
221     {
222         object->flagForDeletion();
223     }
224 }
225 
226 // TextureManager Implementation.
227 
228 TextureManager::~TextureManager() = default;
229 
230 // static
AllocateNewObject(rx::GLImplFactory * factory,TextureID handle,TextureType type)231 Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory,
232                                            TextureID handle,
233                                            TextureType type)
234 {
235     Texture *texture = new Texture(factory, handle, type);
236     texture->addRef();
237     return texture;
238 }
239 
240 // static
DeleteObject(const Context * context,Texture * texture)241 void TextureManager::DeleteObject(const Context *context, Texture *texture)
242 {
243     texture->release(context);
244 }
245 
createTexture()246 TextureID TextureManager::createTexture()
247 {
248     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
249 }
250 
signalAllTexturesDirty() const251 void TextureManager::signalAllTexturesDirty() const
252 {
253     // Note: this function is called with glRequestExtensionANGLE and glDisableExtensionANGLE.  The
254     // GL_ANGLE_request_extension explicitly requires the application to ensure thread safety.
255     for (const auto &texture : UnsafeResourceMapIter(mObjectMap))
256     {
257         if (texture.second)
258         {
259             // We don't know if the Texture needs init, but that's ok, since it will only force
260             // a re-check, and will not initialize the pixels if it's not needed.
261             texture.second->signalDirtyStorage(InitState::MayNeedInit);
262         }
263     }
264 }
265 
enableHandleAllocatorLogging()266 void TextureManager::enableHandleAllocatorLogging()
267 {
268     mHandleAllocator.enableLogging(true);
269 }
270 
getTotalMemorySize() const271 size_t TextureManager::getTotalMemorySize() const
272 {
273     size_t totalBytes = 0;
274 
275     for (const auto &texture : UnsafeResourceMapIter(mObjectMap))
276     {
277         if (texture.second->getBoundSurface() || texture.second->isEGLImageTarget())
278         {
279             // Skip external texture
280             continue;
281         }
282         totalBytes += static_cast<size_t>(texture.second->getMemorySize());
283     }
284     return totalBytes;
285 }
286 
287 // RenderbufferManager Implementation.
288 
289 RenderbufferManager::~RenderbufferManager() = default;
290 
291 // static
AllocateNewObject(rx::GLImplFactory * factory,RenderbufferID handle)292 Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory,
293                                                      RenderbufferID handle)
294 {
295     Renderbuffer *renderbuffer = new Renderbuffer(factory, handle);
296     renderbuffer->addRef();
297     return renderbuffer;
298 }
299 
300 // static
DeleteObject(const Context * context,Renderbuffer * renderbuffer)301 void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
302 {
303     renderbuffer->release(context);
304 }
305 
createRenderbuffer()306 RenderbufferID RenderbufferManager::createRenderbuffer()
307 {
308     return {AllocateEmptyObject(&mHandleAllocator, &mObjectMap)};
309 }
310 
getRenderbuffer(RenderbufferID handle) const311 Renderbuffer *RenderbufferManager::getRenderbuffer(RenderbufferID handle) const
312 {
313     return mObjectMap.query(handle);
314 }
315 
316 // SamplerManager Implementation.
317 
318 SamplerManager::~SamplerManager() = default;
319 
320 // static
AllocateNewObject(rx::GLImplFactory * factory,SamplerID handle)321 Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, SamplerID handle)
322 {
323     Sampler *sampler = new Sampler(factory, handle);
324     sampler->addRef();
325     return sampler;
326 }
327 
328 // static
DeleteObject(const Context * context,Sampler * sampler)329 void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
330 {
331     sampler->release(context);
332 }
333 
createSampler()334 SamplerID SamplerManager::createSampler()
335 {
336     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
337 }
338 
339 // SyncManager Implementation.
340 
341 SyncManager::~SyncManager() = default;
342 
343 // static
DeleteObject(const Context * context,Sync * sync)344 void SyncManager::DeleteObject(const Context *context, Sync *sync)
345 {
346     sync->release(context);
347 }
348 
createSync(rx::GLImplFactory * factory)349 SyncID SyncManager::createSync(rx::GLImplFactory *factory)
350 {
351     SyncID handle = {mHandleAllocator.allocate()};
352     Sync *sync    = new Sync(factory, handle);
353     sync->addRef();
354     mObjectMap.assign(handle, sync);
355     return handle;
356 }
357 
getSync(SyncID handle) const358 Sync *SyncManager::getSync(SyncID handle) const
359 {
360     return mObjectMap.query(handle);
361 }
362 
363 // FramebufferManager Implementation.
364 
365 FramebufferManager::~FramebufferManager() = default;
366 
367 // static
AllocateNewObject(rx::GLImplFactory * factory,FramebufferID handle,const Context * context)368 Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
369                                                    FramebufferID handle,
370                                                    const Context *context)
371 {
372     // Make sure the caller isn't using a reserved handle.
373     ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle);
374     return new Framebuffer(context, factory, handle);
375 }
376 
377 // static
DeleteObject(const Context * context,Framebuffer * framebuffer)378 void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
379 {
380     framebuffer->onDestroy(context);
381     delete framebuffer;
382 }
383 
createFramebuffer()384 FramebufferID FramebufferManager::createFramebuffer()
385 {
386     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
387 }
388 
getFramebuffer(FramebufferID handle) const389 Framebuffer *FramebufferManager::getFramebuffer(FramebufferID handle) const
390 {
391     return mObjectMap.query(handle);
392 }
393 
setDefaultFramebuffer(Framebuffer * framebuffer)394 void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
395 {
396     ASSERT(framebuffer == nullptr || framebuffer->isDefault());
397     mObjectMap.assign(Framebuffer::kDefaultDrawFramebufferHandle, framebuffer);
398 }
399 
getDefaultFramebuffer() const400 Framebuffer *FramebufferManager::getDefaultFramebuffer() const
401 {
402     return getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);
403 }
404 
invalidateFramebufferCompletenessCache() const405 void FramebufferManager::invalidateFramebufferCompletenessCache() const
406 {
407     // Note: framebuffer objects are private to context and so the map doesn't need locking
408     for (const auto &framebuffer : UnsafeResourceMapIter(mObjectMap))
409     {
410         if (framebuffer.second)
411         {
412             framebuffer.second->invalidateCompletenessCache();
413         }
414     }
415 }
416 
417 // ProgramPipelineManager Implementation.
418 
419 ProgramPipelineManager::~ProgramPipelineManager() = default;
420 
421 // static
AllocateNewObject(rx::GLImplFactory * factory,ProgramPipelineID handle)422 ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
423                                                            ProgramPipelineID handle)
424 {
425     ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
426     pipeline->addRef();
427     return pipeline;
428 }
429 
430 // static
DeleteObject(const Context * context,ProgramPipeline * pipeline)431 void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
432 {
433     pipeline->release(context);
434 }
435 
createProgramPipeline()436 ProgramPipelineID ProgramPipelineManager::createProgramPipeline()
437 {
438     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
439 }
440 
getProgramPipeline(ProgramPipelineID handle) const441 ProgramPipeline *ProgramPipelineManager::getProgramPipeline(ProgramPipelineID handle) const
442 {
443     return mObjectMap.query(handle);
444 }
445 
446 // MemoryObjectManager Implementation.
447 
MemoryObjectManager()448 MemoryObjectManager::MemoryObjectManager() {}
449 
~MemoryObjectManager()450 MemoryObjectManager::~MemoryObjectManager()
451 {
452     ASSERT(UnsafeResourceMapIter(mMemoryObjects).empty());
453 }
454 
reset(const Context * context)455 void MemoryObjectManager::reset(const Context *context)
456 {
457     // Note: this function is called when the last context in the share group is destroyed.  Thus
458     // there are no thread safety concerns.
459     mHandleAllocator.reset();
460     for (const auto &memoryObject : UnsafeResourceMapIter(mMemoryObjects))
461     {
462         if (memoryObject.second)
463         {
464             memoryObject.second->release(context);
465         }
466     }
467     mMemoryObjects.clear();
468 }
469 
createMemoryObject(rx::GLImplFactory * factory)470 MemoryObjectID MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory)
471 {
472     MemoryObjectID handle      = MemoryObjectID{mHandleAllocator.allocate()};
473     MemoryObject *memoryObject = new MemoryObject(factory, handle);
474     memoryObject->addRef();
475     mMemoryObjects.assign(handle, memoryObject);
476     return handle;
477 }
478 
deleteMemoryObject(const Context * context,MemoryObjectID handle)479 void MemoryObjectManager::deleteMemoryObject(const Context *context, MemoryObjectID handle)
480 {
481     MemoryObject *memoryObject = nullptr;
482     if (!mMemoryObjects.erase(handle, &memoryObject))
483     {
484         return;
485     }
486 
487     // Requires an explicit this-> because of C++ template rules.
488     this->mHandleAllocator.release(handle.value);
489 
490     if (memoryObject)
491     {
492         memoryObject->release(context);
493     }
494 }
495 
getMemoryObject(MemoryObjectID handle) const496 MemoryObject *MemoryObjectManager::getMemoryObject(MemoryObjectID handle) const
497 {
498     return mMemoryObjects.query(handle);
499 }
500 
501 // SemaphoreManager Implementation.
502 
SemaphoreManager()503 SemaphoreManager::SemaphoreManager() {}
504 
~SemaphoreManager()505 SemaphoreManager::~SemaphoreManager()
506 {
507     ASSERT(UnsafeResourceMapIter(mSemaphores).empty());
508 }
509 
reset(const Context * context)510 void SemaphoreManager::reset(const Context *context)
511 {
512     // Note: this function is called when the last context in the share group is destroyed.  Thus
513     // there are no thread safety concerns.
514     mHandleAllocator.reset();
515     for (const auto &semaphore : UnsafeResourceMapIter(mSemaphores))
516     {
517         if (semaphore.second)
518         {
519             semaphore.second->release(context);
520         }
521     }
522     mSemaphores.clear();
523 }
524 
createSemaphore(rx::GLImplFactory * factory)525 SemaphoreID SemaphoreManager::createSemaphore(rx::GLImplFactory *factory)
526 {
527     SemaphoreID handle   = SemaphoreID{mHandleAllocator.allocate()};
528     Semaphore *semaphore = new Semaphore(factory, handle);
529     semaphore->addRef();
530     mSemaphores.assign(handle, semaphore);
531     return handle;
532 }
533 
deleteSemaphore(const Context * context,SemaphoreID handle)534 void SemaphoreManager::deleteSemaphore(const Context *context, SemaphoreID handle)
535 {
536     Semaphore *semaphore = nullptr;
537     if (!mSemaphores.erase(handle, &semaphore))
538     {
539         return;
540     }
541 
542     // Requires an explicit this-> because of C++ template rules.
543     this->mHandleAllocator.release(handle.value);
544 
545     if (semaphore)
546     {
547         semaphore->release(context);
548     }
549 }
550 
getSemaphore(SemaphoreID handle) const551 Semaphore *SemaphoreManager::getSemaphore(SemaphoreID handle) const
552 {
553     return mSemaphores.query(handle);
554 }
555 }  // namespace gl
556