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