• 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, GLuint>;
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 GLuint SyncManager::createSync(rx::GLImplFactory *factory)
330 {
331     GLuint handle = mHandleAllocator.allocate();
332     Sync *sync    = new Sync(factory, handle);
333     sync->addRef();
334     mObjectMap.assign(handle, sync);
335     return handle;
336 }
337 
getSync(GLuint handle) const338 Sync *SyncManager::getSync(GLuint 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 Caps & caps,egl::ShareGroup * shareGroup)348 Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
349                                                    FramebufferID handle,
350                                                    const Caps &caps,
351                                                    egl::ShareGroup *shareGroup)
352 {
353     // Make sure the caller isn't using a reserved handle.
354     ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle);
355     return new Framebuffer(caps, factory, handle, shareGroup);
356 }
357 
358 // static
DeleteObject(const Context * context,Framebuffer * framebuffer)359 void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
360 {
361     framebuffer->onDestroy(context);
362     delete framebuffer;
363 }
364 
createFramebuffer()365 FramebufferID FramebufferManager::createFramebuffer()
366 {
367     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
368 }
369 
getFramebuffer(FramebufferID handle) const370 Framebuffer *FramebufferManager::getFramebuffer(FramebufferID handle) const
371 {
372     return mObjectMap.query(handle);
373 }
374 
setDefaultFramebuffer(Framebuffer * framebuffer)375 void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
376 {
377     ASSERT(framebuffer == nullptr || framebuffer->isDefault());
378     mObjectMap.assign(Framebuffer::kDefaultDrawFramebufferHandle, framebuffer);
379 }
380 
getDefaultFramebuffer() const381 Framebuffer *FramebufferManager::getDefaultFramebuffer() const
382 {
383     return getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);
384 }
385 
invalidateFramebufferCompletenessCache() const386 void FramebufferManager::invalidateFramebufferCompletenessCache() const
387 {
388     for (const auto &framebuffer : mObjectMap)
389     {
390         if (framebuffer.second)
391         {
392             framebuffer.second->invalidateCompletenessCache();
393         }
394     }
395 }
396 
397 // ProgramPipelineManager Implementation.
398 
399 ProgramPipelineManager::~ProgramPipelineManager() = default;
400 
401 // static
AllocateNewObject(rx::GLImplFactory * factory,ProgramPipelineID handle)402 ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
403                                                            ProgramPipelineID handle)
404 {
405     ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
406     pipeline->addRef();
407     return pipeline;
408 }
409 
410 // static
DeleteObject(const Context * context,ProgramPipeline * pipeline)411 void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
412 {
413     pipeline->release(context);
414 }
415 
createProgramPipeline()416 ProgramPipelineID ProgramPipelineManager::createProgramPipeline()
417 {
418     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
419 }
420 
getProgramPipeline(ProgramPipelineID handle) const421 ProgramPipeline *ProgramPipelineManager::getProgramPipeline(ProgramPipelineID handle) const
422 {
423     return mObjectMap.query(handle);
424 }
425 
426 // MemoryObjectManager Implementation.
427 
MemoryObjectManager()428 MemoryObjectManager::MemoryObjectManager() {}
429 
~MemoryObjectManager()430 MemoryObjectManager::~MemoryObjectManager()
431 {
432     ASSERT(mMemoryObjects.empty());
433 }
434 
reset(const Context * context)435 void MemoryObjectManager::reset(const Context *context)
436 {
437     while (!mMemoryObjects.empty())
438     {
439         deleteMemoryObject(context, {mMemoryObjects.begin()->first});
440     }
441     mMemoryObjects.clear();
442 }
443 
createMemoryObject(rx::GLImplFactory * factory)444 MemoryObjectID MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory)
445 {
446     MemoryObjectID handle      = MemoryObjectID{mHandleAllocator.allocate()};
447     MemoryObject *memoryObject = new MemoryObject(factory, handle);
448     memoryObject->addRef();
449     mMemoryObjects.assign(handle, memoryObject);
450     return handle;
451 }
452 
deleteMemoryObject(const Context * context,MemoryObjectID handle)453 void MemoryObjectManager::deleteMemoryObject(const Context *context, MemoryObjectID handle)
454 {
455     MemoryObject *memoryObject = nullptr;
456     if (!mMemoryObjects.erase(handle, &memoryObject))
457     {
458         return;
459     }
460 
461     // Requires an explicit this-> because of C++ template rules.
462     this->mHandleAllocator.release(handle.value);
463 
464     if (memoryObject)
465     {
466         memoryObject->release(context);
467     }
468 }
469 
getMemoryObject(MemoryObjectID handle) const470 MemoryObject *MemoryObjectManager::getMemoryObject(MemoryObjectID handle) const
471 {
472     return mMemoryObjects.query(handle);
473 }
474 
475 // SemaphoreManager Implementation.
476 
SemaphoreManager()477 SemaphoreManager::SemaphoreManager() {}
478 
~SemaphoreManager()479 SemaphoreManager::~SemaphoreManager()
480 {
481     ASSERT(mSemaphores.empty());
482 }
483 
reset(const Context * context)484 void SemaphoreManager::reset(const Context *context)
485 {
486     while (!mSemaphores.empty())
487     {
488         deleteSemaphore(context, {mSemaphores.begin()->first});
489     }
490     mSemaphores.clear();
491 }
492 
createSemaphore(rx::GLImplFactory * factory)493 SemaphoreID SemaphoreManager::createSemaphore(rx::GLImplFactory *factory)
494 {
495     SemaphoreID handle   = SemaphoreID{mHandleAllocator.allocate()};
496     Semaphore *semaphore = new Semaphore(factory, handle);
497     semaphore->addRef();
498     mSemaphores.assign(handle, semaphore);
499     return handle;
500 }
501 
deleteSemaphore(const Context * context,SemaphoreID handle)502 void SemaphoreManager::deleteSemaphore(const Context *context, SemaphoreID handle)
503 {
504     Semaphore *semaphore = nullptr;
505     if (!mSemaphores.erase(handle, &semaphore))
506     {
507         return;
508     }
509 
510     // Requires an explicit this-> because of C++ template rules.
511     this->mHandleAllocator.release(handle.value);
512 
513     if (semaphore)
514     {
515         semaphore->release(context);
516     }
517 }
518 
getSemaphore(SemaphoreID handle) const519 Semaphore *SemaphoreManager::getSemaphore(SemaphoreID handle) const
520 {
521     return mSemaphores.query(handle);
522 }
523 }  // namespace gl
524