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/Path.h"
17 #include "libANGLE/Program.h"
18 #include "libANGLE/ProgramPipeline.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 ResourceManagerBase<HandleRangeAllocator>;
106 template class TypedResourceManager<Buffer, HandleAllocator, BufferManager, BufferID>;
107 template class TypedResourceManager<Texture, HandleAllocator, TextureManager, TextureID>;
108 template class TypedResourceManager<Renderbuffer,
109 HandleAllocator,
110 RenderbufferManager,
111 RenderbufferID>;
112 template class TypedResourceManager<Sampler, HandleAllocator, SamplerManager, GLuint>;
113 template class TypedResourceManager<Sync, HandleAllocator, SyncManager, GLuint>;
114 template class TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager, GLuint>;
115 template class TypedResourceManager<ProgramPipeline,
116 HandleAllocator,
117 ProgramPipelineManager,
118 GLuint>;
119
120 // BufferManager Implementation.
121
122 // static
AllocateNewObject(rx::GLImplFactory * factory,BufferID handle)123 Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, BufferID handle)
124 {
125 Buffer *buffer = new Buffer(factory, handle);
126 buffer->addRef();
127 return buffer;
128 }
129
130 // static
DeleteObject(const Context * context,Buffer * buffer)131 void BufferManager::DeleteObject(const Context *context, Buffer *buffer)
132 {
133 buffer->release(context);
134 }
135
createBuffer()136 BufferID BufferManager::createBuffer()
137 {
138 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
139 }
140
getBuffer(BufferID handle) const141 Buffer *BufferManager::getBuffer(BufferID handle) const
142 {
143 return mObjectMap.query(handle);
144 }
145
146 // ShaderProgramManager Implementation.
147
ShaderProgramManager()148 ShaderProgramManager::ShaderProgramManager() {}
149
~ShaderProgramManager()150 ShaderProgramManager::~ShaderProgramManager()
151 {
152 ASSERT(mPrograms.empty());
153 ASSERT(mShaders.empty());
154 }
155
reset(const Context * context)156 void ShaderProgramManager::reset(const Context *context)
157 {
158 while (!mPrograms.empty())
159 {
160 deleteProgram(context, mPrograms.begin()->first);
161 }
162 mPrograms.clear();
163 while (!mShaders.empty())
164 {
165 deleteShader(context, mShaders.begin()->first);
166 }
167 mShaders.clear();
168 }
169
createShader(rx::GLImplFactory * factory,const gl::Limitations & rendererLimitations,ShaderType type)170 GLuint ShaderProgramManager::createShader(rx::GLImplFactory *factory,
171 const gl::Limitations &rendererLimitations,
172 ShaderType type)
173 {
174 ASSERT(type != ShaderType::InvalidEnum);
175 GLuint handle = mHandleAllocator.allocate();
176 mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
177 return handle;
178 }
179
deleteShader(const Context * context,GLuint shader)180 void ShaderProgramManager::deleteShader(const Context *context, GLuint shader)
181 {
182 deleteObject(context, &mShaders, shader);
183 }
184
getShader(GLuint handle) const185 Shader *ShaderProgramManager::getShader(GLuint handle) const
186 {
187 return mShaders.query(handle);
188 }
189
createProgram(rx::GLImplFactory * factory)190 GLuint ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
191 {
192 GLuint handle = mHandleAllocator.allocate();
193 mPrograms.assign(handle, new Program(factory, this, handle));
194 return handle;
195 }
196
deleteProgram(const gl::Context * context,GLuint program)197 void ShaderProgramManager::deleteProgram(const gl::Context *context, GLuint program)
198 {
199 deleteObject(context, &mPrograms, program);
200 }
201
202 template <typename ObjectType>
deleteObject(const Context * context,ResourceMap<ObjectType> * objectMap,GLuint id)203 void ShaderProgramManager::deleteObject(const Context *context,
204 ResourceMap<ObjectType> *objectMap,
205 GLuint id)
206 {
207 ObjectType *object = objectMap->query(id);
208 if (!object)
209 {
210 return;
211 }
212
213 if (object->getRefCount() == 0)
214 {
215 mHandleAllocator.release(id);
216 object->onDestroy(context);
217 objectMap->erase(id, &object);
218 }
219 else
220 {
221 object->flagForDeletion();
222 }
223 }
224
225 // TextureManager Implementation.
226
227 // static
AllocateNewObject(rx::GLImplFactory * factory,TextureID handle,TextureType type)228 Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory,
229 TextureID handle,
230 TextureType type)
231 {
232 Texture *texture = new Texture(factory, handle, type);
233 texture->addRef();
234 return texture;
235 }
236
237 // static
DeleteObject(const Context * context,Texture * texture)238 void TextureManager::DeleteObject(const Context *context, Texture *texture)
239 {
240 texture->release(context);
241 }
242
createTexture()243 TextureID TextureManager::createTexture()
244 {
245 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
246 }
247
signalAllTexturesDirty() const248 void TextureManager::signalAllTexturesDirty() const
249 {
250 for (const auto &texture : mObjectMap)
251 {
252 if (texture.second)
253 {
254 // We don't know if the Texture needs init, but that's ok, since it will only force
255 // a re-check, and will not initialize the pixels if it's not needed.
256 texture.second->signalDirtyStorage(InitState::MayNeedInit);
257 }
258 }
259 }
260
enableHandleAllocatorLogging()261 void TextureManager::enableHandleAllocatorLogging()
262 {
263 mHandleAllocator.enableLogging(true);
264 }
265
266 // RenderbufferManager Implementation.
267
268 // static
AllocateNewObject(rx::GLImplFactory * factory,RenderbufferID handle)269 Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory,
270 RenderbufferID handle)
271 {
272 Renderbuffer *renderbuffer = new Renderbuffer(factory, handle);
273 renderbuffer->addRef();
274 return renderbuffer;
275 }
276
277 // static
DeleteObject(const Context * context,Renderbuffer * renderbuffer)278 void RenderbufferManager::DeleteObject(const Context *context, Renderbuffer *renderbuffer)
279 {
280 renderbuffer->release(context);
281 }
282
createRenderbuffer()283 RenderbufferID RenderbufferManager::createRenderbuffer()
284 {
285 return {AllocateEmptyObject(&mHandleAllocator, &mObjectMap)};
286 }
287
getRenderbuffer(RenderbufferID handle) const288 Renderbuffer *RenderbufferManager::getRenderbuffer(RenderbufferID handle) const
289 {
290 return mObjectMap.query(handle);
291 }
292
293 // SamplerManager Implementation.
294
295 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle)296 Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
297 {
298 Sampler *sampler = new Sampler(factory, handle);
299 sampler->addRef();
300 return sampler;
301 }
302
303 // static
DeleteObject(const Context * context,Sampler * sampler)304 void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
305 {
306 sampler->release(context);
307 }
308
createSampler()309 GLuint SamplerManager::createSampler()
310 {
311 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
312 }
313
getSampler(GLuint handle) const314 Sampler *SamplerManager::getSampler(GLuint handle) const
315 {
316 return mObjectMap.query(handle);
317 }
318
isSampler(GLuint sampler) const319 bool SamplerManager::isSampler(GLuint sampler) const
320 {
321 return mObjectMap.contains(sampler);
322 }
323
324 // SyncManager Implementation.
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->createSync(), 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 // PathManager Implementation.
347
348 PathManager::PathManager() = default;
349
createPaths(Context * context,GLsizei range,GLuint * createdOut)350 angle::Result PathManager::createPaths(Context *context, GLsizei range, GLuint *createdOut)
351 {
352 *createdOut = 0;
353
354 // Allocate client side handles.
355 const GLuint client = mHandleAllocator.allocateRange(static_cast<GLuint>(range));
356 if (client == HandleRangeAllocator::kInvalidHandle)
357 {
358 context->handleError(GL_OUT_OF_MEMORY, "Failed to allocate path handle range.", __FILE__,
359 ANGLE_FUNCTION, __LINE__);
360 return angle::Result::Stop;
361 }
362
363 const auto &paths = context->getImplementation()->createPaths(range);
364 if (paths.empty())
365 {
366 mHandleAllocator.releaseRange(client, range);
367 context->handleError(GL_OUT_OF_MEMORY, "Failed to allocate path objects.", __FILE__,
368 ANGLE_FUNCTION, __LINE__);
369 return angle::Result::Stop;
370 }
371
372 for (GLsizei i = 0; i < range; ++i)
373 {
374 rx::PathImpl *impl = paths[static_cast<unsigned>(i)];
375 const auto id = client + i;
376 mPaths.assign(id, new Path(impl));
377 }
378 *createdOut = client;
379 return angle::Result::Continue;
380 }
381
deletePaths(GLuint first,GLsizei range)382 void PathManager::deletePaths(GLuint first, GLsizei range)
383 {
384 for (GLsizei i = 0; i < range; ++i)
385 {
386 const auto id = first + i;
387 Path *p = nullptr;
388 if (!mPaths.erase(id, &p))
389 continue;
390 delete p;
391 }
392 mHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
393 }
394
getPath(GLuint handle) const395 Path *PathManager::getPath(GLuint handle) const
396 {
397 return mPaths.query(handle);
398 }
399
hasPath(GLuint handle) const400 bool PathManager::hasPath(GLuint handle) const
401 {
402 return mHandleAllocator.isUsed(handle);
403 }
404
~PathManager()405 PathManager::~PathManager()
406 {
407 ASSERT(mPaths.empty());
408 }
409
reset(const Context * context)410 void PathManager::reset(const Context *context)
411 {
412 for (auto path : mPaths)
413 {
414 SafeDelete(path.second);
415 }
416 mPaths.clear();
417 }
418
419 // FramebufferManager Implementation.
420
421 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle,const Caps & caps)422 Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
423 GLuint handle,
424 const Caps &caps)
425 {
426 return new Framebuffer(caps, factory, handle);
427 }
428
429 // static
DeleteObject(const Context * context,Framebuffer * framebuffer)430 void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
431 {
432 framebuffer->onDestroy(context);
433 delete framebuffer;
434 }
435
createFramebuffer()436 GLuint FramebufferManager::createFramebuffer()
437 {
438 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
439 }
440
getFramebuffer(GLuint handle) const441 Framebuffer *FramebufferManager::getFramebuffer(GLuint handle) const
442 {
443 return mObjectMap.query(handle);
444 }
445
setDefaultFramebuffer(Framebuffer * framebuffer)446 void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
447 {
448 ASSERT(framebuffer == nullptr || framebuffer->id() == 0);
449 mObjectMap.assign(0, framebuffer);
450 }
451
invalidateFramebufferComplenessCache() const452 void FramebufferManager::invalidateFramebufferComplenessCache() const
453 {
454 for (const auto &framebuffer : mObjectMap)
455 {
456 if (framebuffer.second)
457 {
458 framebuffer.second->invalidateCompletenessCache();
459 }
460 }
461 }
462
463 // ProgramPipelineManager Implementation.
464
465 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle)466 ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
467 GLuint handle)
468 {
469 ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
470 pipeline->addRef();
471 return pipeline;
472 }
473
474 // static
DeleteObject(const Context * context,ProgramPipeline * pipeline)475 void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
476 {
477 pipeline->release(context);
478 }
479
createProgramPipeline()480 GLuint ProgramPipelineManager::createProgramPipeline()
481 {
482 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
483 }
484
getProgramPipeline(GLuint handle) const485 ProgramPipeline *ProgramPipelineManager::getProgramPipeline(GLuint handle) const
486 {
487 return mObjectMap.query(handle);
488 }
489
490 // MemoryObjectManager Implementation.
491
MemoryObjectManager()492 MemoryObjectManager::MemoryObjectManager() {}
493
~MemoryObjectManager()494 MemoryObjectManager::~MemoryObjectManager()
495 {
496 ASSERT(mMemoryObjects.empty());
497 }
498
reset(const Context * context)499 void MemoryObjectManager::reset(const Context *context)
500 {
501 while (!mMemoryObjects.empty())
502 {
503 deleteMemoryObject(context, mMemoryObjects.begin()->first);
504 }
505 mMemoryObjects.clear();
506 }
507
createMemoryObject(rx::GLImplFactory * factory)508 GLuint MemoryObjectManager::createMemoryObject(rx::GLImplFactory *factory)
509 {
510 GLuint handle = mHandleAllocator.allocate();
511 MemoryObject *memoryObject = new MemoryObject(factory, handle);
512 memoryObject->addRef();
513 mMemoryObjects.assign(handle, memoryObject);
514 return handle;
515 }
516
deleteMemoryObject(const Context * context,GLuint handle)517 void MemoryObjectManager::deleteMemoryObject(const Context *context, GLuint handle)
518 {
519 MemoryObject *memoryObject = nullptr;
520 if (!mMemoryObjects.erase(handle, &memoryObject))
521 {
522 return;
523 }
524
525 // Requires an explicit this-> because of C++ template rules.
526 this->mHandleAllocator.release(handle);
527
528 if (memoryObject)
529 {
530 memoryObject->release(context);
531 }
532 }
533
getMemoryObject(GLuint handle) const534 MemoryObject *MemoryObjectManager::getMemoryObject(GLuint handle) const
535 {
536 return mMemoryObjects.query(handle);
537 }
538
539 // SemaphoreManager Implementation.
540
SemaphoreManager()541 SemaphoreManager::SemaphoreManager() {}
542
~SemaphoreManager()543 SemaphoreManager::~SemaphoreManager()
544 {
545 ASSERT(mSemaphores.empty());
546 }
547
reset(const Context * context)548 void SemaphoreManager::reset(const Context *context)
549 {
550 while (!mSemaphores.empty())
551 {
552 deleteSemaphore(context, mSemaphores.begin()->first);
553 }
554 mSemaphores.clear();
555 }
556
createSemaphore(rx::GLImplFactory * factory)557 GLuint SemaphoreManager::createSemaphore(rx::GLImplFactory *factory)
558 {
559 GLuint handle = mHandleAllocator.allocate();
560 Semaphore *semaphore = new Semaphore(factory, handle);
561 semaphore->addRef();
562 mSemaphores.assign(handle, semaphore);
563 return handle;
564 }
565
deleteSemaphore(const Context * context,GLuint handle)566 void SemaphoreManager::deleteSemaphore(const Context *context, GLuint handle)
567 {
568 Semaphore *semaphore = nullptr;
569 if (!mSemaphores.erase(handle, &semaphore))
570 {
571 return;
572 }
573
574 // Requires an explicit this-> because of C++ template rules.
575 this->mHandleAllocator.release(handle);
576
577 if (semaphore)
578 {
579 semaphore->release(context);
580 }
581 }
582
getSemaphore(GLuint handle) const583 Semaphore *SemaphoreManager::getSemaphore(GLuint handle) const
584 {
585 return mSemaphores.query(handle);
586 }
587
588 } // namespace gl
589