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