• 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     ASSERT(mObjectMap.empty());
65 }
66 
67 template <typename ResourceType, typename ImplT, typename IDType>
reset(const Context * context)68 void TypedResourceManager<ResourceType, ImplT, IDType>::reset(const Context *context)
69 {
70     this->mHandleAllocator.reset();
71     for (const auto &resource : mObjectMap)
72     {
73         if (resource.second)
74         {
75             ImplT::DeleteObject(context, resource.second);
76         }
77     }
78     mObjectMap.clear();
79 }
80 
81 template <typename ResourceType, typename ImplT, typename IDType>
deleteObject(const Context * context,IDType handle)82 void TypedResourceManager<ResourceType, ImplT, IDType>::deleteObject(const Context *context,
83                                                                      IDType handle)
84 {
85     ResourceType *resource = nullptr;
86     if (!mObjectMap.erase(handle, &resource))
87     {
88         return;
89     }
90 
91     // Requires an explicit this-> because of C++ template rules.
92     this->mHandleAllocator.release(GetIDValue(handle));
93 
94     if (resource)
95     {
96         ImplT::DeleteObject(context, resource);
97     }
98 }
99 
100 template class TypedResourceManager<Buffer, BufferManager, BufferID>;
101 template class TypedResourceManager<Texture, TextureManager, TextureID>;
102 template class TypedResourceManager<Renderbuffer, RenderbufferManager, RenderbufferID>;
103 template class TypedResourceManager<Sampler, SamplerManager, SamplerID>;
104 template class TypedResourceManager<Sync, SyncManager, SyncID>;
105 template class TypedResourceManager<Framebuffer, FramebufferManager, FramebufferID>;
106 template class TypedResourceManager<ProgramPipeline, ProgramPipelineManager, ProgramPipelineID>;
107 
108 // BufferManager Implementation.
109 BufferManager::~BufferManager() = default;
110 
111 // static
AllocateNewObject(rx::GLImplFactory * factory,BufferID handle)112 Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, BufferID handle)
113 {
114     Buffer *buffer = new Buffer(factory, handle);
115     buffer->addRef();
116     return buffer;
117 }
118 
119 // static
DeleteObject(const Context * context,Buffer * buffer)120 void BufferManager::DeleteObject(const Context *context, Buffer *buffer)
121 {
122     buffer->release(context);
123 }
124 
createBuffer()125 BufferID BufferManager::createBuffer()
126 {
127     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
128 }
129 
getBuffer(BufferID handle) const130 Buffer *BufferManager::getBuffer(BufferID handle) const
131 {
132     return mObjectMap.query(handle);
133 }
134 
135 // ShaderProgramManager Implementation.
136 
ShaderProgramManager()137 ShaderProgramManager::ShaderProgramManager() {}
138 
~ShaderProgramManager()139 ShaderProgramManager::~ShaderProgramManager()
140 {
141     ASSERT(mPrograms.empty());
142     ASSERT(mShaders.empty());
143 }
144 
reset(const Context * context)145 void ShaderProgramManager::reset(const Context *context)
146 {
147     while (!mPrograms.empty())
148     {
149         deleteProgram(context, {mPrograms.begin()->first});
150     }
151     mPrograms.clear();
152     while (!mShaders.empty())
153     {
154         deleteShader(context, {mShaders.begin()->first});
155     }
156     mShaders.clear();
157 }
158 
createShader(rx::GLImplFactory * factory,const gl::Limitations & rendererLimitations,ShaderType type)159 ShaderProgramID ShaderProgramManager::createShader(rx::GLImplFactory *factory,
160                                                    const gl::Limitations &rendererLimitations,
161                                                    ShaderType type)
162 {
163     ASSERT(type != ShaderType::InvalidEnum);
164     ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
165     mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
166     return handle;
167 }
168 
deleteShader(const Context * context,ShaderProgramID shader)169 void ShaderProgramManager::deleteShader(const Context *context, ShaderProgramID shader)
170 {
171     deleteObject(context, &mShaders, shader);
172 }
173 
getShader(ShaderProgramID handle) const174 Shader *ShaderProgramManager::getShader(ShaderProgramID handle) const
175 {
176     return mShaders.query(handle);
177 }
178 
createProgram(rx::GLImplFactory * factory)179 ShaderProgramID ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
180 {
181     ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
182     mPrograms.assign(handle, new Program(factory, this, handle));
183     return handle;
184 }
185 
deleteProgram(const gl::Context * context,ShaderProgramID program)186 void ShaderProgramManager::deleteProgram(const gl::Context *context, ShaderProgramID program)
187 {
188     deleteObject(context, &mPrograms, program);
189 }
190 
191 template <typename ObjectType, typename IDType>
deleteObject(const Context * context,ResourceMap<ObjectType,IDType> * objectMap,IDType id)192 void ShaderProgramManager::deleteObject(const Context *context,
193                                         ResourceMap<ObjectType, IDType> *objectMap,
194                                         IDType id)
195 {
196     ObjectType *object = objectMap->query(id);
197     if (!object)
198     {
199         return;
200     }
201 
202     if (object->getRefCount() == 0)
203     {
204         mHandleAllocator.release(id.value);
205         object->onDestroy(context);
206         objectMap->erase(id, &object);
207     }
208     else
209     {
210         object->flagForDeletion();
211     }
212 }
213 
214 // TextureManager Implementation.
215 
216 TextureManager::~TextureManager() = default;
217 
218 // static
AllocateNewObject(rx::GLImplFactory * factory,TextureID handle,TextureType type)219 Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory,
220                                            TextureID handle,
221                                            TextureType type)
222 {
223     Texture *texture = new Texture(factory, handle, type);
224     texture->addRef();
225     return texture;
226 }
227 
228 // static
DeleteObject(const Context * context,Texture * texture)229 void TextureManager::DeleteObject(const Context *context, Texture *texture)
230 {
231     texture->release(context);
232 }
233 
createTexture()234 TextureID TextureManager::createTexture()
235 {
236     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
237 }
238 
signalAllTexturesDirty() const239 void TextureManager::signalAllTexturesDirty() const
240 {
241     for (const auto &texture : mObjectMap)
242     {
243         if (texture.second)
244         {
245             // We don't know if the Texture needs init, but that's ok, since it will only force
246             // a re-check, and will not initialize the pixels if it's not needed.
247             texture.second->signalDirtyStorage(InitState::MayNeedInit);
248         }
249     }
250 }
251 
enableHandleAllocatorLogging()252 void TextureManager::enableHandleAllocatorLogging()
253 {
254     mHandleAllocator.enableLogging(true);
255 }
256 
257 // RenderbufferManager Implementation.
258 
259 RenderbufferManager::~RenderbufferManager() = default;
260 
261 // static
AllocateNewObject(rx::GLImplFactory * factory,RenderbufferID handle)262 Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory,
263                                                      RenderbufferID handle)
264 {
265     Renderbuffer *renderbuffer = new Renderbuffer(factory, handle);
266     renderbuffer->addRef();
267     return renderbuffer;
268 }
269 
270 // static
DeleteObject(const Context * context,Renderbuffer * renderbuffer)271 void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
272 {
273     renderbuffer->release(context);
274 }
275 
createRenderbuffer()276 RenderbufferID RenderbufferManager::createRenderbuffer()
277 {
278     return {AllocateEmptyObject(&mHandleAllocator, &mObjectMap)};
279 }
280 
getRenderbuffer(RenderbufferID handle) const281 Renderbuffer *RenderbufferManager::getRenderbuffer(RenderbufferID handle) const
282 {
283     return mObjectMap.query(handle);
284 }
285 
286 // SamplerManager Implementation.
287 
288 SamplerManager::~SamplerManager() = default;
289 
290 // static
AllocateNewObject(rx::GLImplFactory * factory,SamplerID handle)291 Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, SamplerID handle)
292 {
293     Sampler *sampler = new Sampler(factory, handle);
294     sampler->addRef();
295     return sampler;
296 }
297 
298 // static
DeleteObject(const Context * context,Sampler * sampler)299 void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
300 {
301     sampler->release(context);
302 }
303 
createSampler()304 SamplerID SamplerManager::createSampler()
305 {
306     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
307 }
308 
getSampler(SamplerID handle) const309 Sampler *SamplerManager::getSampler(SamplerID handle) const
310 {
311     return mObjectMap.query(handle);
312 }
313 
isSampler(SamplerID sampler) const314 bool SamplerManager::isSampler(SamplerID sampler) const
315 {
316     return mObjectMap.contains(sampler);
317 }
318 
319 // SyncManager Implementation.
320 
321 SyncManager::~SyncManager() = default;
322 
323 // static
DeleteObject(const Context * context,Sync * sync)324 void SyncManager::DeleteObject(const Context *context, Sync *sync)
325 {
326     sync->release(context);
327 }
328 
createSync(rx::GLImplFactory * factory)329 SyncID SyncManager::createSync(rx::GLImplFactory *factory)
330 {
331     SyncID handle = {mHandleAllocator.allocate()};
332     Sync *sync    = new Sync(factory, handle);
333     sync->addRef();
334     mObjectMap.assign(handle, sync);
335     return handle;
336 }
337 
getSync(SyncID handle) const338 Sync *SyncManager::getSync(SyncID handle) const
339 {
340     return mObjectMap.query(handle);
341 }
342 
343 // FramebufferManager Implementation.
344 
345 FramebufferManager::~FramebufferManager() = default;
346 
347 // static
AllocateNewObject(rx::GLImplFactory * factory,FramebufferID handle,const Context * context)348 Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
349                                                    FramebufferID handle,
350                                                    const Context *context)
351 {
352     // Make sure the caller isn't using a reserved handle.
353     ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle);
354     return new Framebuffer(context, factory, handle);
355 }
356 
357 // static
DeleteObject(const Context * context,Framebuffer * framebuffer)358 void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
359 {
360     framebuffer->onDestroy(context);
361     delete framebuffer;
362 }
363 
createFramebuffer()364 FramebufferID FramebufferManager::createFramebuffer()
365 {
366     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
367 }
368 
getFramebuffer(FramebufferID handle) const369 Framebuffer *FramebufferManager::getFramebuffer(FramebufferID handle) const
370 {
371     return mObjectMap.query(handle);
372 }
373 
setDefaultFramebuffer(Framebuffer * framebuffer)374 void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
375 {
376     ASSERT(framebuffer == nullptr || framebuffer->isDefault());
377     mObjectMap.assign(Framebuffer::kDefaultDrawFramebufferHandle, framebuffer);
378 }
379 
getDefaultFramebuffer() const380 Framebuffer *FramebufferManager::getDefaultFramebuffer() const
381 {
382     return getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);
383 }
384 
invalidateFramebufferCompletenessCache() const385 void FramebufferManager::invalidateFramebufferCompletenessCache() const
386 {
387     for (const auto &framebuffer : mObjectMap)
388     {
389         if (framebuffer.second)
390         {
391             framebuffer.second->invalidateCompletenessCache();
392         }
393     }
394 }
395 
396 // ProgramPipelineManager Implementation.
397 
398 ProgramPipelineManager::~ProgramPipelineManager() = default;
399 
400 // static
AllocateNewObject(rx::GLImplFactory * factory,ProgramPipelineID handle)401 ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
402                                                            ProgramPipelineID handle)
403 {
404     ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
405     pipeline->addRef();
406     return pipeline;
407 }
408 
409 // static
DeleteObject(const Context * context,ProgramPipeline * pipeline)410 void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
411 {
412     pipeline->release(context);
413 }
414 
createProgramPipeline()415 ProgramPipelineID ProgramPipelineManager::createProgramPipeline()
416 {
417     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
418 }
419 
getProgramPipeline(ProgramPipelineID handle) const420 ProgramPipeline *ProgramPipelineManager::getProgramPipeline(ProgramPipelineID handle) const
421 {
422     return mObjectMap.query(handle);
423 }
424 
425 // MemoryObjectManager Implementation.
426 
MemoryObjectManager()427 MemoryObjectManager::MemoryObjectManager() {}
428 
~MemoryObjectManager()429 MemoryObjectManager::~MemoryObjectManager()
430 {
431     ASSERT(mMemoryObjects.empty());
432 }
433 
reset(const Context * context)434 void MemoryObjectManager::reset(const Context *context)
435 {
436     while (!mMemoryObjects.empty())
437     {
438         deleteMemoryObject(context, {mMemoryObjects.begin()->first});
439     }
440     mMemoryObjects.clear();
441 }
442 
createMemoryObject(rx::GLImplFactory * factory)443 MemoryObjectID MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory)
444 {
445     MemoryObjectID handle      = MemoryObjectID{mHandleAllocator.allocate()};
446     MemoryObject *memoryObject = new MemoryObject(factory, handle);
447     memoryObject->addRef();
448     mMemoryObjects.assign(handle, memoryObject);
449     return handle;
450 }
451 
deleteMemoryObject(const Context * context,MemoryObjectID handle)452 void MemoryObjectManager::deleteMemoryObject(const Context *context, MemoryObjectID handle)
453 {
454     MemoryObject *memoryObject = nullptr;
455     if (!mMemoryObjects.erase(handle, &memoryObject))
456     {
457         return;
458     }
459 
460     // Requires an explicit this-> because of C++ template rules.
461     this->mHandleAllocator.release(handle.value);
462 
463     if (memoryObject)
464     {
465         memoryObject->release(context);
466     }
467 }
468 
getMemoryObject(MemoryObjectID handle) const469 MemoryObject *MemoryObjectManager::getMemoryObject(MemoryObjectID handle) const
470 {
471     return mMemoryObjects.query(handle);
472 }
473 
474 // SemaphoreManager Implementation.
475 
SemaphoreManager()476 SemaphoreManager::SemaphoreManager() {}
477 
~SemaphoreManager()478 SemaphoreManager::~SemaphoreManager()
479 {
480     ASSERT(mSemaphores.empty());
481 }
482 
reset(const Context * context)483 void SemaphoreManager::reset(const Context *context)
484 {
485     while (!mSemaphores.empty())
486     {
487         deleteSemaphore(context, {mSemaphores.begin()->first});
488     }
489     mSemaphores.clear();
490 }
491 
createSemaphore(rx::GLImplFactory * factory)492 SemaphoreID SemaphoreManager::createSemaphore(rx::GLImplFactory *factory)
493 {
494     SemaphoreID handle   = SemaphoreID{mHandleAllocator.allocate()};
495     Semaphore *semaphore = new Semaphore(factory, handle);
496     semaphore->addRef();
497     mSemaphores.assign(handle, semaphore);
498     return handle;
499 }
500 
deleteSemaphore(const Context * context,SemaphoreID handle)501 void SemaphoreManager::deleteSemaphore(const Context *context, SemaphoreID handle)
502 {
503     Semaphore *semaphore = nullptr;
504     if (!mSemaphores.erase(handle, &semaphore))
505     {
506         return;
507     }
508 
509     // Requires an explicit this-> because of C++ template rules.
510     this->mHandleAllocator.release(handle.value);
511 
512     if (semaphore)
513     {
514         semaphore->release(context);
515     }
516 }
517 
getSemaphore(SemaphoreID handle) const518 Semaphore *SemaphoreManager::getSemaphore(SemaphoreID handle) const
519 {
520     return mSemaphores.query(handle);
521 }
522 }  // namespace gl
523