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 = FromGL<IDType>(handleAllocator->allocate());
37 objectMap->assign(handle, nullptr);
38 return handle;
39 }
40
41 } // anonymous namespace
42
43 template <typename HandleAllocatorType>
ResourceManagerBase()44 ResourceManagerBase<HandleAllocatorType>::ResourceManagerBase() : mRefCount(1)
45 {}
46
47 template <typename HandleAllocatorType>
addRef()48 void ResourceManagerBase<HandleAllocatorType>::addRef()
49 {
50 mRefCount++;
51 }
52
53 template <typename HandleAllocatorType>
release(const Context * context)54 void ResourceManagerBase<HandleAllocatorType>::release(const Context *context)
55 {
56 if (--mRefCount == 0)
57 {
58 reset(context);
59 delete this;
60 }
61 }
62
63 template <typename ResourceType, typename HandleAllocatorType, typename ImplT, typename IDType>
~TypedResourceManager()64 TypedResourceManager<ResourceType, HandleAllocatorType, ImplT, IDType>::~TypedResourceManager()
65 {
66 ASSERT(mObjectMap.empty());
67 }
68
69 template <typename ResourceType, typename HandleAllocatorType, typename ImplT, typename IDType>
reset(const Context * context)70 void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT, IDType>::reset(
71 const Context *context)
72 {
73 this->mHandleAllocator.reset();
74 for (const auto &resource : 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 HandleAllocatorType, typename ImplT, typename IDType>
deleteObject(const Context * context,IDType handle)85 void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT, IDType>::deleteObject(
86 const Context *context,
87 IDType handle)
88 {
89 ResourceType *resource = nullptr;
90 if (!mObjectMap.erase(handle, &resource))
91 {
92 return;
93 }
94
95 // Requires an explicit this-> because of C++ template rules.
96 this->mHandleAllocator.release(GetIDValue(handle));
97
98 if (resource)
99 {
100 ImplT::DeleteObject(context, resource);
101 }
102 }
103
104 template class ResourceManagerBase<HandleAllocator>;
105 template class TypedResourceManager<Buffer, HandleAllocator, BufferManager, BufferID>;
106 template class TypedResourceManager<Texture, HandleAllocator, TextureManager, TextureID>;
107 template class TypedResourceManager<Renderbuffer,
108 HandleAllocator,
109 RenderbufferManager,
110 RenderbufferID>;
111 template class TypedResourceManager<Sampler, HandleAllocator, SamplerManager, SamplerID>;
112 template class TypedResourceManager<Sync, HandleAllocator, SyncManager, GLuint>;
113 template class TypedResourceManager<Framebuffer,
114 HandleAllocator,
115 FramebufferManager,
116 FramebufferID>;
117 template class TypedResourceManager<ProgramPipeline,
118 HandleAllocator,
119 ProgramPipelineManager,
120 ProgramPipelineID>;
121
122 // BufferManager Implementation.
123
124 // static
AllocateNewObject(rx::GLImplFactory * factory,BufferID handle)125 Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, BufferID handle)
126 {
127 Buffer *buffer = new Buffer(factory, handle);
128 buffer->addRef();
129 return buffer;
130 }
131
132 // static
DeleteObject(const Context * context,Buffer * buffer)133 void BufferManager::DeleteObject(const Context *context, Buffer *buffer)
134 {
135 buffer->release(context);
136 }
137
createBuffer()138 BufferID BufferManager::createBuffer()
139 {
140 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
141 }
142
getBuffer(BufferID handle) const143 Buffer *BufferManager::getBuffer(BufferID handle) const
144 {
145 return mObjectMap.query(handle);
146 }
147
148 // ShaderProgramManager Implementation.
149
ShaderProgramManager()150 ShaderProgramManager::ShaderProgramManager() {}
151
~ShaderProgramManager()152 ShaderProgramManager::~ShaderProgramManager()
153 {
154 ASSERT(mPrograms.empty());
155 ASSERT(mShaders.empty());
156 }
157
reset(const Context * context)158 void ShaderProgramManager::reset(const Context *context)
159 {
160 while (!mPrograms.empty())
161 {
162 deleteProgram(context, {mPrograms.begin()->first});
163 }
164 mPrograms.clear();
165 while (!mShaders.empty())
166 {
167 deleteShader(context, {mShaders.begin()->first});
168 }
169 mShaders.clear();
170 }
171
createShader(rx::GLImplFactory * factory,const gl::Limitations & rendererLimitations,ShaderType type)172 ShaderProgramID ShaderProgramManager::createShader(rx::GLImplFactory *factory,
173 const gl::Limitations &rendererLimitations,
174 ShaderType type)
175 {
176 ASSERT(type != ShaderType::InvalidEnum);
177 ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
178 mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
179 return handle;
180 }
181
deleteShader(const Context * context,ShaderProgramID shader)182 void ShaderProgramManager::deleteShader(const Context *context, ShaderProgramID shader)
183 {
184 deleteObject(context, &mShaders, shader);
185 }
186
getShader(ShaderProgramID handle) const187 Shader *ShaderProgramManager::getShader(ShaderProgramID handle) const
188 {
189 return mShaders.query(handle);
190 }
191
createProgram(rx::GLImplFactory * factory)192 ShaderProgramID ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
193 {
194 ShaderProgramID handle = ShaderProgramID{mHandleAllocator.allocate()};
195 mPrograms.assign(handle, new Program(factory, this, handle));
196 return handle;
197 }
198
deleteProgram(const gl::Context * context,ShaderProgramID program)199 void ShaderProgramManager::deleteProgram(const gl::Context *context, ShaderProgramID program)
200 {
201 deleteObject(context, &mPrograms, program);
202 }
203
204 template <typename ObjectType, typename IDType>
deleteObject(const Context * context,ResourceMap<ObjectType,IDType> * objectMap,IDType id)205 void ShaderProgramManager::deleteObject(const Context *context,
206 ResourceMap<ObjectType, IDType> *objectMap,
207 IDType id)
208 {
209 ObjectType *object = objectMap->query(id);
210 if (!object)
211 {
212 return;
213 }
214
215 if (object->getRefCount() == 0)
216 {
217 mHandleAllocator.release(id.value);
218 object->onDestroy(context);
219 objectMap->erase(id, &object);
220 }
221 else
222 {
223 object->flagForDeletion();
224 }
225 }
226
227 // TextureManager Implementation.
228
229 // static
AllocateNewObject(rx::GLImplFactory * factory,TextureID handle,TextureType type)230 Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory,
231 TextureID handle,
232 TextureType type)
233 {
234 Texture *texture = new Texture(factory, handle, type);
235 texture->addRef();
236 return texture;
237 }
238
239 // static
DeleteObject(const Context * context,Texture * texture)240 void TextureManager::DeleteObject(const Context *context, Texture *texture)
241 {
242 texture->release(context);
243 }
244
createTexture()245 TextureID TextureManager::createTexture()
246 {
247 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
248 }
249
signalAllTexturesDirty() const250 void TextureManager::signalAllTexturesDirty() const
251 {
252 for (const auto &texture : mObjectMap)
253 {
254 if (texture.second)
255 {
256 // We don't know if the Texture needs init, but that's ok, since it will only force
257 // a re-check, and will not initialize the pixels if it's not needed.
258 texture.second->signalDirtyStorage(InitState::MayNeedInit);
259 }
260 }
261 }
262
enableHandleAllocatorLogging()263 void TextureManager::enableHandleAllocatorLogging()
264 {
265 mHandleAllocator.enableLogging(true);
266 }
267
268 // RenderbufferManager Implementation.
269
270 // static
AllocateNewObject(rx::GLImplFactory * factory,RenderbufferID handle)271 Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory,
272 RenderbufferID handle)
273 {
274 Renderbuffer *renderbuffer = new Renderbuffer(factory, handle);
275 renderbuffer->addRef();
276 return renderbuffer;
277 }
278
279 // static
DeleteObject(const Context * context,Renderbuffer * renderbuffer)280 void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
281 {
282 renderbuffer->release(context);
283 }
284
createRenderbuffer()285 RenderbufferID RenderbufferManager::createRenderbuffer()
286 {
287 return {AllocateEmptyObject(&mHandleAllocator, &mObjectMap)};
288 }
289
getRenderbuffer(RenderbufferID handle) const290 Renderbuffer *RenderbufferManager::getRenderbuffer(RenderbufferID handle) const
291 {
292 return mObjectMap.query(handle);
293 }
294
295 // SamplerManager Implementation.
296
297 // static
AllocateNewObject(rx::GLImplFactory * factory,SamplerID handle)298 Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, SamplerID handle)
299 {
300 Sampler *sampler = new Sampler(factory, handle);
301 sampler->addRef();
302 return sampler;
303 }
304
305 // static
DeleteObject(const Context * context,Sampler * sampler)306 void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
307 {
308 sampler->release(context);
309 }
310
createSampler()311 SamplerID SamplerManager::createSampler()
312 {
313 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
314 }
315
getSampler(SamplerID handle) const316 Sampler *SamplerManager::getSampler(SamplerID handle) const
317 {
318 return mObjectMap.query(handle);
319 }
320
isSampler(SamplerID sampler) const321 bool SamplerManager::isSampler(SamplerID sampler) const
322 {
323 return mObjectMap.contains(sampler);
324 }
325
326 // SyncManager Implementation.
327
328 // static
DeleteObject(const Context * context,Sync * sync)329 void SyncManager::DeleteObject(const Context *context, Sync *sync)
330 {
331 sync->release(context);
332 }
333
createSync(rx::GLImplFactory * factory)334 GLuint SyncManager::createSync(rx::GLImplFactory *factory)
335 {
336 GLuint handle = mHandleAllocator.allocate();
337 Sync *sync = new Sync(factory, handle);
338 sync->addRef();
339 mObjectMap.assign(handle, sync);
340 return handle;
341 }
342
getSync(GLuint handle) const343 Sync *SyncManager::getSync(GLuint handle) const
344 {
345 return mObjectMap.query(handle);
346 }
347
348 // FramebufferManager Implementation.
349
350 // static
AllocateNewObject(rx::GLImplFactory * factory,FramebufferID handle,const Caps & caps,ContextID owningContextID)351 Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
352 FramebufferID handle,
353 const Caps &caps,
354 ContextID owningContextID)
355 {
356 // Make sure the caller isn't using a reserved handle.
357 ASSERT(handle != Framebuffer::kDefaultDrawFramebufferHandle);
358 return new Framebuffer(caps, factory, handle, owningContextID);
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
invalidateFramebufferCompletenessCache() const384 void FramebufferManager::invalidateFramebufferCompletenessCache() const
385 {
386 for (const auto &framebuffer : mObjectMap)
387 {
388 if (framebuffer.second)
389 {
390 framebuffer.second->invalidateCompletenessCache();
391 }
392 }
393 }
394
395 // ProgramPipelineManager Implementation.
396
397 // static
AllocateNewObject(rx::GLImplFactory * factory,ProgramPipelineID handle)398 ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
399 ProgramPipelineID handle)
400 {
401 ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
402 pipeline->addRef();
403 return pipeline;
404 }
405
406 // static
DeleteObject(const Context * context,ProgramPipeline * pipeline)407 void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
408 {
409 pipeline->release(context);
410 }
411
createProgramPipeline()412 ProgramPipelineID ProgramPipelineManager::createProgramPipeline()
413 {
414 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
415 }
416
getProgramPipeline(ProgramPipelineID handle) const417 ProgramPipeline *ProgramPipelineManager::getProgramPipeline(ProgramPipelineID handle) const
418 {
419 return mObjectMap.query(handle);
420 }
421
422 // MemoryObjectManager Implementation.
423
MemoryObjectManager()424 MemoryObjectManager::MemoryObjectManager() {}
425
~MemoryObjectManager()426 MemoryObjectManager::~MemoryObjectManager()
427 {
428 ASSERT(mMemoryObjects.empty());
429 }
430
reset(const Context * context)431 void MemoryObjectManager::reset(const Context *context)
432 {
433 while (!mMemoryObjects.empty())
434 {
435 deleteMemoryObject(context, {mMemoryObjects.begin()->first});
436 }
437 mMemoryObjects.clear();
438 }
439
createMemoryObject(rx::GLImplFactory * factory)440 MemoryObjectID MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory)
441 {
442 MemoryObjectID handle = MemoryObjectID{mHandleAllocator.allocate()};
443 MemoryObject *memoryObject = new MemoryObject(factory, handle);
444 memoryObject->addRef();
445 mMemoryObjects.assign(handle, memoryObject);
446 return handle;
447 }
448
deleteMemoryObject(const Context * context,MemoryObjectID handle)449 void MemoryObjectManager::deleteMemoryObject(const Context *context, MemoryObjectID handle)
450 {
451 MemoryObject *memoryObject = nullptr;
452 if (!mMemoryObjects.erase(handle, &memoryObject))
453 {
454 return;
455 }
456
457 // Requires an explicit this-> because of C++ template rules.
458 this->mHandleAllocator.release(handle.value);
459
460 if (memoryObject)
461 {
462 memoryObject->release(context);
463 }
464 }
465
getMemoryObject(MemoryObjectID handle) const466 MemoryObject *MemoryObjectManager::getMemoryObject(MemoryObjectID handle) const
467 {
468 return mMemoryObjects.query(handle);
469 }
470
471 // SemaphoreManager Implementation.
472
SemaphoreManager()473 SemaphoreManager::SemaphoreManager() {}
474
~SemaphoreManager()475 SemaphoreManager::~SemaphoreManager()
476 {
477 ASSERT(mSemaphores.empty());
478 }
479
reset(const Context * context)480 void SemaphoreManager::reset(const Context *context)
481 {
482 while (!mSemaphores.empty())
483 {
484 deleteSemaphore(context, {mSemaphores.begin()->first});
485 }
486 mSemaphores.clear();
487 }
488
createSemaphore(rx::GLImplFactory * factory)489 SemaphoreID SemaphoreManager::createSemaphore(rx::GLImplFactory *factory)
490 {
491 SemaphoreID handle = SemaphoreID{mHandleAllocator.allocate()};
492 Semaphore *semaphore = new Semaphore(factory, handle);
493 semaphore->addRef();
494 mSemaphores.assign(handle, semaphore);
495 return handle;
496 }
497
deleteSemaphore(const Context * context,SemaphoreID handle)498 void SemaphoreManager::deleteSemaphore(const Context *context, SemaphoreID handle)
499 {
500 Semaphore *semaphore = nullptr;
501 if (!mSemaphores.erase(handle, &semaphore))
502 {
503 return;
504 }
505
506 // Requires an explicit this-> because of C++ template rules.
507 this->mHandleAllocator.release(handle.value);
508
509 if (semaphore)
510 {
511 semaphore->release(context);
512 }
513 }
514
getSemaphore(SemaphoreID handle) const515 Semaphore *SemaphoreManager::getSemaphore(SemaphoreID handle) const
516 {
517 return mSemaphores.query(handle);
518 }
519 } // namespace gl
520