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