• 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 // Unclear why Clang warns about weak vtables in this case.
101 ANGLE_DISABLE_WEAK_TEMPLATE_VTABLES_WARNING
102 template class TypedResourceManager<Buffer, BufferManager, BufferID>;
103 template class TypedResourceManager<Texture, TextureManager, TextureID>;
104 template class TypedResourceManager<Renderbuffer, RenderbufferManager, RenderbufferID>;
105 template class TypedResourceManager<Sampler, SamplerManager, SamplerID>;
106 template class TypedResourceManager<Sync, SyncManager, GLuint>;
107 template class TypedResourceManager<Framebuffer, FramebufferManager, FramebufferID>;
108 template class TypedResourceManager<ProgramPipeline, ProgramPipelineManager, ProgramPipelineID>;
109 ANGLE_REENABLE_WEAK_TEMPLATE_VTABLES_WARNING
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(mPrograms.empty());
145     ASSERT(mShaders.empty());
146 }
147 
reset(const Context * context)148 void ShaderProgramManager::reset(const Context *context)
149 {
150     while (!mPrograms.empty())
151     {
152         deleteProgram(context, {mPrograms.begin()->first});
153     }
154     mPrograms.clear();
155     while (!mShaders.empty())
156     {
157         deleteShader(context, {mShaders.begin()->first});
158     }
159     mShaders.clear();
160 }
161 
createShader(rx::GLImplFactory * factory,const gl::Limitations & rendererLimitations,ShaderType type)162 ShaderProgramID ShaderProgramManager::createShader(rx::GLImplFactory *factory,
163                                                    const gl::Limitations &rendererLimitations,
164                                                    ShaderType type)
165 {
166     ASSERT(type != ShaderType::InvalidEnum);
167     ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
168     mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
169     return handle;
170 }
171 
deleteShader(const Context * context,ShaderProgramID shader)172 void ShaderProgramManager::deleteShader(const Context *context, ShaderProgramID shader)
173 {
174     deleteObject(context, &mShaders, shader);
175 }
176 
getShader(ShaderProgramID handle) const177 Shader *ShaderProgramManager::getShader(ShaderProgramID handle) const
178 {
179     return mShaders.query(handle);
180 }
181 
createProgram(rx::GLImplFactory * factory)182 ShaderProgramID ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
183 {
184     ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
185     mPrograms.assign(handle, new Program(factory, this, handle));
186     return handle;
187 }
188 
deleteProgram(const gl::Context * context,ShaderProgramID program)189 void ShaderProgramManager::deleteProgram(const gl::Context *context, ShaderProgramID program)
190 {
191     deleteObject(context, &mPrograms, program);
192 }
193 
194 template <typename ObjectType, typename IDType>
deleteObject(const Context * context,ResourceMap<ObjectType,IDType> * objectMap,IDType id)195 void ShaderProgramManager::deleteObject(const Context *context,
196                                         ResourceMap<ObjectType, IDType> *objectMap,
197                                         IDType id)
198 {
199     ObjectType *object = objectMap->query(id);
200     if (!object)
201     {
202         return;
203     }
204 
205     if (object->getRefCount() == 0)
206     {
207         mHandleAllocator.release(id.value);
208         object->onDestroy(context);
209         objectMap->erase(id, &object);
210     }
211     else
212     {
213         object->flagForDeletion();
214     }
215 }
216 
217 // TextureManager Implementation.
218 
219 TextureManager::~TextureManager() = default;
220 
221 // static
AllocateNewObject(rx::GLImplFactory * factory,TextureID handle,TextureType type)222 Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory,
223                                            TextureID handle,
224                                            TextureType type)
225 {
226     Texture *texture = new Texture(factory, handle, type);
227     texture->addRef();
228     return texture;
229 }
230 
231 // static
DeleteObject(const Context * context,Texture * texture)232 void TextureManager::DeleteObject(const Context *context, Texture *texture)
233 {
234     texture->release(context);
235 }
236 
createTexture()237 TextureID TextureManager::createTexture()
238 {
239     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
240 }
241 
signalAllTexturesDirty() const242 void TextureManager::signalAllTexturesDirty() const
243 {
244     for (const auto &texture : mObjectMap)
245     {
246         if (texture.second)
247         {
248             // We don't know if the Texture needs init, but that's ok, since it will only force
249             // a re-check, and will not initialize the pixels if it's not needed.
250             texture.second->signalDirtyStorage(InitState::MayNeedInit);
251         }
252     }
253 }
254 
enableHandleAllocatorLogging()255 void TextureManager::enableHandleAllocatorLogging()
256 {
257     mHandleAllocator.enableLogging(true);
258 }
259 
260 // RenderbufferManager Implementation.
261 
262 RenderbufferManager::~RenderbufferManager() = default;
263 
264 // static
AllocateNewObject(rx::GLImplFactory * factory,RenderbufferID handle)265 Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory,
266                                                      RenderbufferID handle)
267 {
268     Renderbuffer *renderbuffer = new Renderbuffer(factory, handle);
269     renderbuffer->addRef();
270     return renderbuffer;
271 }
272 
273 // static
DeleteObject(const Context * context,Renderbuffer * renderbuffer)274 void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
275 {
276     renderbuffer->release(context);
277 }
278 
createRenderbuffer()279 RenderbufferID RenderbufferManager::createRenderbuffer()
280 {
281     return {AllocateEmptyObject(&mHandleAllocator, &mObjectMap)};
282 }
283 
getRenderbuffer(RenderbufferID handle) const284 Renderbuffer *RenderbufferManager::getRenderbuffer(RenderbufferID handle) const
285 {
286     return mObjectMap.query(handle);
287 }
288 
289 // SamplerManager Implementation.
290 
291 SamplerManager::~SamplerManager() = default;
292 
293 // static
AllocateNewObject(rx::GLImplFactory * factory,SamplerID handle)294 Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, SamplerID handle)
295 {
296     Sampler *sampler = new Sampler(factory, handle);
297     sampler->addRef();
298     return sampler;
299 }
300 
301 // static
DeleteObject(const Context * context,Sampler * sampler)302 void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
303 {
304     sampler->release(context);
305 }
306 
createSampler()307 SamplerID SamplerManager::createSampler()
308 {
309     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
310 }
311 
getSampler(SamplerID handle) const312 Sampler *SamplerManager::getSampler(SamplerID handle) const
313 {
314     return mObjectMap.query(handle);
315 }
316 
isSampler(SamplerID sampler) const317 bool SamplerManager::isSampler(SamplerID sampler) const
318 {
319     return mObjectMap.contains(sampler);
320 }
321 
322 // SyncManager Implementation.
323 
324 SyncManager::~SyncManager() = default;
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, 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 // FramebufferManager Implementation.
347 
348 FramebufferManager::~FramebufferManager() = default;
349 
350 // static
AllocateNewObject(rx::GLImplFactory * factory,FramebufferID handle,const Caps & caps,egl::ShareGroup * shareGroup)351 Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
352                                                    FramebufferID handle,
353                                                    const Caps &caps,
354                                                    egl::ShareGroup *shareGroup)
355 {
356     // Make sure the caller isn't using a reserved handle.
357     ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle);
358     return new Framebuffer(caps, factory, handle, shareGroup);
359 }
360 
361 // static
DeleteObject(const Context * context,Framebuffer * framebuffer)362 void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
363 {
364     framebuffer->onDestroy(context);
365     delete framebuffer;
366 }
367 
createFramebuffer()368 FramebufferID FramebufferManager::createFramebuffer()
369 {
370     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
371 }
372 
getFramebuffer(FramebufferID handle) const373 Framebuffer *FramebufferManager::getFramebuffer(FramebufferID handle) const
374 {
375     return mObjectMap.query(handle);
376 }
377 
setDefaultFramebuffer(Framebuffer * framebuffer)378 void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
379 {
380     ASSERT(framebuffer == nullptr || framebuffer->isDefault());
381     mObjectMap.assign(Framebuffer::kDefaultDrawFramebufferHandle, framebuffer);
382 }
383 
getDefaultFramebuffer() const384 Framebuffer *FramebufferManager::getDefaultFramebuffer() const
385 {
386     return getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);
387 }
388 
invalidateFramebufferCompletenessCache() const389 void FramebufferManager::invalidateFramebufferCompletenessCache() const
390 {
391     for (const auto &framebuffer : mObjectMap)
392     {
393         if (framebuffer.second)
394         {
395             framebuffer.second->invalidateCompletenessCache();
396         }
397     }
398 }
399 
400 // ProgramPipelineManager Implementation.
401 
402 ProgramPipelineManager::~ProgramPipelineManager() = default;
403 
404 // static
AllocateNewObject(rx::GLImplFactory * factory,ProgramPipelineID handle)405 ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
406                                                            ProgramPipelineID handle)
407 {
408     ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
409     pipeline->addRef();
410     return pipeline;
411 }
412 
413 // static
DeleteObject(const Context * context,ProgramPipeline * pipeline)414 void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
415 {
416     pipeline->release(context);
417 }
418 
createProgramPipeline()419 ProgramPipelineID ProgramPipelineManager::createProgramPipeline()
420 {
421     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
422 }
423 
getProgramPipeline(ProgramPipelineID handle) const424 ProgramPipeline *ProgramPipelineManager::getProgramPipeline(ProgramPipelineID handle) const
425 {
426     return mObjectMap.query(handle);
427 }
428 
429 // MemoryObjectManager Implementation.
430 
MemoryObjectManager()431 MemoryObjectManager::MemoryObjectManager() {}
432 
~MemoryObjectManager()433 MemoryObjectManager::~MemoryObjectManager()
434 {
435     ASSERT(mMemoryObjects.empty());
436 }
437 
reset(const Context * context)438 void MemoryObjectManager::reset(const Context *context)
439 {
440     while (!mMemoryObjects.empty())
441     {
442         deleteMemoryObject(context, {mMemoryObjects.begin()->first});
443     }
444     mMemoryObjects.clear();
445 }
446 
createMemoryObject(rx::GLImplFactory * factory)447 MemoryObjectID MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory)
448 {
449     MemoryObjectID handle      = MemoryObjectID{mHandleAllocator.allocate()};
450     MemoryObject *memoryObject = new MemoryObject(factory, handle);
451     memoryObject->addRef();
452     mMemoryObjects.assign(handle, memoryObject);
453     return handle;
454 }
455 
deleteMemoryObject(const Context * context,MemoryObjectID handle)456 void MemoryObjectManager::deleteMemoryObject(const Context *context, MemoryObjectID handle)
457 {
458     MemoryObject *memoryObject = nullptr;
459     if (!mMemoryObjects.erase(handle, &memoryObject))
460     {
461         return;
462     }
463 
464     // Requires an explicit this-> because of C++ template rules.
465     this->mHandleAllocator.release(handle.value);
466 
467     if (memoryObject)
468     {
469         memoryObject->release(context);
470     }
471 }
472 
getMemoryObject(MemoryObjectID handle) const473 MemoryObject *MemoryObjectManager::getMemoryObject(MemoryObjectID handle) const
474 {
475     return mMemoryObjects.query(handle);
476 }
477 
478 // SemaphoreManager Implementation.
479 
SemaphoreManager()480 SemaphoreManager::SemaphoreManager() {}
481 
~SemaphoreManager()482 SemaphoreManager::~SemaphoreManager()
483 {
484     ASSERT(mSemaphores.empty());
485 }
486 
reset(const Context * context)487 void SemaphoreManager::reset(const Context *context)
488 {
489     while (!mSemaphores.empty())
490     {
491         deleteSemaphore(context, {mSemaphores.begin()->first});
492     }
493     mSemaphores.clear();
494 }
495 
createSemaphore(rx::GLImplFactory * factory)496 SemaphoreID SemaphoreManager::createSemaphore(rx::GLImplFactory *factory)
497 {
498     SemaphoreID handle   = SemaphoreID{mHandleAllocator.allocate()};
499     Semaphore *semaphore = new Semaphore(factory, handle);
500     semaphore->addRef();
501     mSemaphores.assign(handle, semaphore);
502     return handle;
503 }
504 
deleteSemaphore(const Context * context,SemaphoreID handle)505 void SemaphoreManager::deleteSemaphore(const Context *context, SemaphoreID handle)
506 {
507     Semaphore *semaphore = nullptr;
508     if (!mSemaphores.erase(handle, &semaphore))
509     {
510         return;
511     }
512 
513     // Requires an explicit this-> because of C++ template rules.
514     this->mHandleAllocator.release(handle.value);
515 
516     if (semaphore)
517     {
518         semaphore->release(context);
519     }
520 }
521 
getSemaphore(SemaphoreID handle) const522 Semaphore *SemaphoreManager::getSemaphore(SemaphoreID handle) const
523 {
524     return mSemaphores.query(handle);
525 }
526 }  // namespace gl
527