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