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
271 // RenderbufferManager Implementation.
272
273 RenderbufferManager::~RenderbufferManager() = default;
274
275 // static
AllocateNewObject(rx::GLImplFactory * factory,RenderbufferID handle)276 Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory,
277 RenderbufferID handle)
278 {
279 Renderbuffer *renderbuffer = new Renderbuffer(factory, handle);
280 renderbuffer->addRef();
281 return renderbuffer;
282 }
283
284 // static
DeleteObject(const Context * context,Renderbuffer * renderbuffer)285 void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
286 {
287 renderbuffer->release(context);
288 }
289
createRenderbuffer()290 RenderbufferID RenderbufferManager::createRenderbuffer()
291 {
292 return {AllocateEmptyObject(&mHandleAllocator, &mObjectMap)};
293 }
294
getRenderbuffer(RenderbufferID handle) const295 Renderbuffer *RenderbufferManager::getRenderbuffer(RenderbufferID handle) const
296 {
297 return mObjectMap.query(handle);
298 }
299
300 // SamplerManager Implementation.
301
302 SamplerManager::~SamplerManager() = default;
303
304 // static
AllocateNewObject(rx::GLImplFactory * factory,SamplerID handle)305 Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, SamplerID handle)
306 {
307 Sampler *sampler = new Sampler(factory, handle);
308 sampler->addRef();
309 return sampler;
310 }
311
312 // static
DeleteObject(const Context * context,Sampler * sampler)313 void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
314 {
315 sampler->release(context);
316 }
317
createSampler()318 SamplerID SamplerManager::createSampler()
319 {
320 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
321 }
322
getSampler(SamplerID handle) const323 Sampler *SamplerManager::getSampler(SamplerID handle) const
324 {
325 return mObjectMap.query(handle);
326 }
327
isSampler(SamplerID sampler) const328 bool SamplerManager::isSampler(SamplerID sampler) const
329 {
330 return mObjectMap.contains(sampler);
331 }
332
333 // SyncManager Implementation.
334
335 SyncManager::~SyncManager() = default;
336
337 // static
DeleteObject(const Context * context,Sync * sync)338 void SyncManager::DeleteObject(const Context *context, Sync *sync)
339 {
340 sync->release(context);
341 }
342
createSync(rx::GLImplFactory * factory)343 SyncID SyncManager::createSync(rx::GLImplFactory *factory)
344 {
345 SyncID handle = {mHandleAllocator.allocate()};
346 Sync *sync = new Sync(factory, handle);
347 sync->addRef();
348 mObjectMap.assign(handle, sync);
349 return handle;
350 }
351
getSync(SyncID handle) const352 Sync *SyncManager::getSync(SyncID handle) const
353 {
354 return mObjectMap.query(handle);
355 }
356
357 // FramebufferManager Implementation.
358
359 FramebufferManager::~FramebufferManager() = default;
360
361 // static
AllocateNewObject(rx::GLImplFactory * factory,FramebufferID handle,const Context * context)362 Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
363 FramebufferID handle,
364 const Context *context)
365 {
366 // Make sure the caller isn't using a reserved handle.
367 ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle);
368 return new Framebuffer(context, factory, handle);
369 }
370
371 // static
DeleteObject(const Context * context,Framebuffer * framebuffer)372 void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
373 {
374 framebuffer->onDestroy(context);
375 delete framebuffer;
376 }
377
createFramebuffer()378 FramebufferID FramebufferManager::createFramebuffer()
379 {
380 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
381 }
382
getFramebuffer(FramebufferID handle) const383 Framebuffer *FramebufferManager::getFramebuffer(FramebufferID handle) const
384 {
385 return mObjectMap.query(handle);
386 }
387
setDefaultFramebuffer(Framebuffer * framebuffer)388 void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
389 {
390 ASSERT(framebuffer == nullptr || framebuffer->isDefault());
391 mObjectMap.assign(Framebuffer::kDefaultDrawFramebufferHandle, framebuffer);
392 }
393
getDefaultFramebuffer() const394 Framebuffer *FramebufferManager::getDefaultFramebuffer() const
395 {
396 return getFramebuffer(Framebuffer::kDefaultDrawFramebufferHandle);
397 }
398
invalidateFramebufferCompletenessCache() const399 void FramebufferManager::invalidateFramebufferCompletenessCache() const
400 {
401 // Note: framebuffer objects are private to context and so the map doesn't need locking
402 for (const auto &framebuffer : UnsafeResourceMapIter(mObjectMap))
403 {
404 if (framebuffer.second)
405 {
406 framebuffer.second->invalidateCompletenessCache();
407 }
408 }
409 }
410
411 // ProgramPipelineManager Implementation.
412
413 ProgramPipelineManager::~ProgramPipelineManager() = default;
414
415 // static
AllocateNewObject(rx::GLImplFactory * factory,ProgramPipelineID handle)416 ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
417 ProgramPipelineID handle)
418 {
419 ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
420 pipeline->addRef();
421 return pipeline;
422 }
423
424 // static
DeleteObject(const Context * context,ProgramPipeline * pipeline)425 void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
426 {
427 pipeline->release(context);
428 }
429
createProgramPipeline()430 ProgramPipelineID ProgramPipelineManager::createProgramPipeline()
431 {
432 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
433 }
434
getProgramPipeline(ProgramPipelineID handle) const435 ProgramPipeline *ProgramPipelineManager::getProgramPipeline(ProgramPipelineID handle) const
436 {
437 return mObjectMap.query(handle);
438 }
439
440 // MemoryObjectManager Implementation.
441
MemoryObjectManager()442 MemoryObjectManager::MemoryObjectManager() {}
443
~MemoryObjectManager()444 MemoryObjectManager::~MemoryObjectManager()
445 {
446 ASSERT(UnsafeResourceMapIter(mMemoryObjects).empty());
447 }
448
reset(const Context * context)449 void MemoryObjectManager::reset(const Context *context)
450 {
451 // Note: this function is called when the last context in the share group is destroyed. Thus
452 // there are no thread safety concerns.
453 mHandleAllocator.reset();
454 for (const auto &memoryObject : UnsafeResourceMapIter(mMemoryObjects))
455 {
456 if (memoryObject.second)
457 {
458 memoryObject.second->release(context);
459 }
460 }
461 mMemoryObjects.clear();
462 }
463
createMemoryObject(rx::GLImplFactory * factory)464 MemoryObjectID MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory)
465 {
466 MemoryObjectID handle = MemoryObjectID{mHandleAllocator.allocate()};
467 MemoryObject *memoryObject = new MemoryObject(factory, handle);
468 memoryObject->addRef();
469 mMemoryObjects.assign(handle, memoryObject);
470 return handle;
471 }
472
deleteMemoryObject(const Context * context,MemoryObjectID handle)473 void MemoryObjectManager::deleteMemoryObject(const Context *context, MemoryObjectID handle)
474 {
475 MemoryObject *memoryObject = nullptr;
476 if (!mMemoryObjects.erase(handle, &memoryObject))
477 {
478 return;
479 }
480
481 // Requires an explicit this-> because of C++ template rules.
482 this->mHandleAllocator.release(handle.value);
483
484 if (memoryObject)
485 {
486 memoryObject->release(context);
487 }
488 }
489
getMemoryObject(MemoryObjectID handle) const490 MemoryObject *MemoryObjectManager::getMemoryObject(MemoryObjectID handle) const
491 {
492 return mMemoryObjects.query(handle);
493 }
494
495 // SemaphoreManager Implementation.
496
SemaphoreManager()497 SemaphoreManager::SemaphoreManager() {}
498
~SemaphoreManager()499 SemaphoreManager::~SemaphoreManager()
500 {
501 ASSERT(UnsafeResourceMapIter(mSemaphores).empty());
502 }
503
reset(const Context * context)504 void SemaphoreManager::reset(const Context *context)
505 {
506 // Note: this function is called when the last context in the share group is destroyed. Thus
507 // there are no thread safety concerns.
508 mHandleAllocator.reset();
509 for (const auto &semaphore : UnsafeResourceMapIter(mSemaphores))
510 {
511 if (semaphore.second)
512 {
513 semaphore.second->release(context);
514 }
515 }
516 mSemaphores.clear();
517 }
518
createSemaphore(rx::GLImplFactory * factory)519 SemaphoreID SemaphoreManager::createSemaphore(rx::GLImplFactory *factory)
520 {
521 SemaphoreID handle = SemaphoreID{mHandleAllocator.allocate()};
522 Semaphore *semaphore = new Semaphore(factory, handle);
523 semaphore->addRef();
524 mSemaphores.assign(handle, semaphore);
525 return handle;
526 }
527
deleteSemaphore(const Context * context,SemaphoreID handle)528 void SemaphoreManager::deleteSemaphore(const Context *context, SemaphoreID handle)
529 {
530 Semaphore *semaphore = nullptr;
531 if (!mSemaphores.erase(handle, &semaphore))
532 {
533 return;
534 }
535
536 // Requires an explicit this-> because of C++ template rules.
537 this->mHandleAllocator.release(handle.value);
538
539 if (semaphore)
540 {
541 semaphore->release(context);
542 }
543 }
544
getSemaphore(SemaphoreID handle) const545 Semaphore *SemaphoreManager::getSemaphore(SemaphoreID handle) const
546 {
547 return mSemaphores.query(handle);
548 }
549 } // namespace gl
550