1 //
2 // Copyright (c) 2002-2016 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/Fence.h"
14 #include "libANGLE/Path.h"
15 #include "libANGLE/Program.h"
16 #include "libANGLE/ProgramPipeline.h"
17 #include "libANGLE/Renderbuffer.h"
18 #include "libANGLE/Sampler.h"
19 #include "libANGLE/Shader.h"
20 #include "libANGLE/Texture.h"
21 #include "libANGLE/renderer/GLImplFactory.h"
22 
23 namespace gl
24 {
25 
26 namespace
27 {
28 
29 template <typename ResourceType>
AllocateEmptyObject(HandleAllocator * handleAllocator,ResourceMap<ResourceType> * objectMap)30 GLuint AllocateEmptyObject(HandleAllocator *handleAllocator, ResourceMap<ResourceType> *objectMap)
31 {
32     GLuint handle = handleAllocator->allocate();
33     objectMap->assign(handle, nullptr);
34     return handle;
35 }
36 
37 }  // anonymous namespace
38 
39 template <typename HandleAllocatorType>
ResourceManagerBase()40 ResourceManagerBase<HandleAllocatorType>::ResourceManagerBase() : mRefCount(1)
41 {
42 }
43 
44 template <typename HandleAllocatorType>
addRef()45 void ResourceManagerBase<HandleAllocatorType>::addRef()
46 {
47     mRefCount++;
48 }
49 
50 template <typename HandleAllocatorType>
release(const Context * context)51 void ResourceManagerBase<HandleAllocatorType>::release(const Context *context)
52 {
53     if (--mRefCount == 0)
54     {
55         reset(context);
56         delete this;
57     }
58 }
59 
60 template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
~TypedResourceManager()61 TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::~TypedResourceManager()
62 {
63     ASSERT(mObjectMap.empty());
64 }
65 
66 template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
reset(const Context * context)67 void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::reset(const Context *context)
68 {
69     this->mHandleAllocator.reset();
70     for (const auto &resource : mObjectMap)
71     {
72         if (resource.second)
73         {
74             ImplT::DeleteObject(context, resource.second);
75         }
76     }
77     mObjectMap.clear();
78 }
79 
80 template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
deleteObject(const Context * context,GLuint handle)81 void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::deleteObject(
82     const Context *context,
83     GLuint 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(handle);
93 
94     if (resource)
95     {
96         ImplT::DeleteObject(context, resource);
97     }
98 }
99 
100 template class ResourceManagerBase<HandleAllocator>;
101 template class ResourceManagerBase<HandleRangeAllocator>;
102 template class TypedResourceManager<Buffer, HandleAllocator, BufferManager>;
103 template class TypedResourceManager<Texture, HandleAllocator, TextureManager>;
104 template class TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>;
105 template class TypedResourceManager<Sampler, HandleAllocator, SamplerManager>;
106 template class TypedResourceManager<Sync, HandleAllocator, SyncManager>;
107 template class TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>;
108 template class TypedResourceManager<ProgramPipeline, HandleAllocator, ProgramPipelineManager>;
109 
110 // BufferManager Implementation.
111 
112 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle)113 Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
114 {
115     Buffer *buffer = new Buffer(factory, handle);
116     buffer->addRef();
117     return buffer;
118 }
119 
120 // static
DeleteObject(const Context * context,Buffer * buffer)121 void BufferManager::DeleteObject(const Context *context, Buffer *buffer)
122 {
123     buffer->release(context);
124 }
125 
createBuffer()126 GLuint BufferManager::createBuffer()
127 {
128     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
129 }
130 
getBuffer(GLuint handle) const131 Buffer *BufferManager::getBuffer(GLuint handle) const
132 {
133     return mObjectMap.query(handle);
134 }
135 
136 // ShaderProgramManager Implementation.
137 
ShaderProgramManager()138 ShaderProgramManager::ShaderProgramManager()
139 {
140 }
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,GLenum type)162 GLuint ShaderProgramManager::createShader(rx::GLImplFactory *factory,
163                                           const gl::Limitations &rendererLimitations,
164                                           GLenum type)
165 {
166     ASSERT(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER || type == GL_COMPUTE_SHADER ||
167            type == GL_GEOMETRY_SHADER_EXT);
168     GLuint handle    = mHandleAllocator.allocate();
169     mShaders.assign(handle, new Shader(this, factory, rendererLimitations, type, handle));
170     return handle;
171 }
172 
deleteShader(const Context * context,GLuint shader)173 void ShaderProgramManager::deleteShader(const Context *context, GLuint shader)
174 {
175     deleteObject(context, &mShaders, shader);
176 }
177 
getShader(GLuint handle) const178 Shader *ShaderProgramManager::getShader(GLuint handle) const
179 {
180     return mShaders.query(handle);
181 }
182 
createProgram(rx::GLImplFactory * factory)183 GLuint ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
184 {
185     GLuint handle = mHandleAllocator.allocate();
186     mPrograms.assign(handle, new Program(factory, this, handle));
187     return handle;
188 }
189 
deleteProgram(const gl::Context * context,GLuint program)190 void ShaderProgramManager::deleteProgram(const gl::Context *context, GLuint program)
191 {
192     deleteObject(context, &mPrograms, program);
193 }
194 
getProgram(GLuint handle) const195 Program *ShaderProgramManager::getProgram(GLuint handle) const
196 {
197     return mPrograms.query(handle);
198 }
199 
200 template <typename ObjectType>
deleteObject(const Context * context,ResourceMap<ObjectType> * objectMap,GLuint id)201 void ShaderProgramManager::deleteObject(const Context *context,
202                                         ResourceMap<ObjectType> *objectMap,
203                                         GLuint id)
204 {
205     ObjectType *object = objectMap->query(id);
206     if (!object)
207     {
208         return;
209     }
210 
211     if (object->getRefCount() == 0)
212     {
213         mHandleAllocator.release(id);
214         object->onDestroy(context);
215         objectMap->erase(id, &object);
216     }
217     else
218     {
219         object->flagForDeletion();
220     }
221 }
222 
223 // TextureManager Implementation.
224 
225 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle,GLenum target)226 Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle, GLenum target)
227 {
228     Texture *texture = new Texture(factory, handle, target);
229     texture->addRef();
230     return texture;
231 }
232 
233 // static
DeleteObject(const Context * context,Texture * texture)234 void TextureManager::DeleteObject(const Context *context, Texture *texture)
235 {
236     texture->release(context);
237 }
238 
createTexture()239 GLuint TextureManager::createTexture()
240 {
241     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
242 }
243 
getTexture(GLuint handle) const244 Texture *TextureManager::getTexture(GLuint handle) const
245 {
246     ASSERT(mObjectMap.query(0) == nullptr);
247     return mObjectMap.query(handle);
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->signalDirty(InitState::MayNeedInit);
259         }
260     }
261 }
262 
263 // RenderbufferManager Implementation.
264 
265 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle)266 Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
267 {
268     Renderbuffer *renderbuffer = new Renderbuffer(factory->createRenderbuffer(), 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 GLuint RenderbufferManager::createRenderbuffer()
280 {
281     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
282 }
283 
getRenderbuffer(GLuint handle) const284 Renderbuffer *RenderbufferManager::getRenderbuffer(GLuint handle) const
285 {
286     return mObjectMap.query(handle);
287 }
288 
289 // SamplerManager Implementation.
290 
291 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle)292 Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
293 {
294     Sampler *sampler = new Sampler(factory, handle);
295     sampler->addRef();
296     return sampler;
297 }
298 
299 // static
DeleteObject(const Context * context,Sampler * sampler)300 void SamplerManager::DeleteObject(const Context *context, Sampler *sampler)
301 {
302     sampler->release(context);
303 }
304 
createSampler()305 GLuint SamplerManager::createSampler()
306 {
307     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
308 }
309 
getSampler(GLuint handle) const310 Sampler *SamplerManager::getSampler(GLuint handle) const
311 {
312     return mObjectMap.query(handle);
313 }
314 
isSampler(GLuint sampler) const315 bool SamplerManager::isSampler(GLuint sampler) const
316 {
317     return mObjectMap.contains(sampler);
318 }
319 
320 // SyncManager Implementation.
321 
322 // static
DeleteObject(const Context * context,Sync * sync)323 void SyncManager::DeleteObject(const Context *context, Sync *sync)
324 {
325     sync->release(context);
326 }
327 
createSync(rx::GLImplFactory * factory)328 GLuint SyncManager::createSync(rx::GLImplFactory *factory)
329 {
330     GLuint handle = mHandleAllocator.allocate();
331     Sync *sync    = new Sync(factory->createSync(), handle);
332     sync->addRef();
333     mObjectMap.assign(handle, sync);
334     return handle;
335 }
336 
getSync(GLuint handle) const337 Sync *SyncManager::getSync(GLuint handle) const
338 {
339     return mObjectMap.query(handle);
340 }
341 
342 // PathManager Implementation.
343 
PathManager()344 PathManager::PathManager()
345 {
346 }
347 
createPaths(rx::GLImplFactory * factory,GLsizei range)348 ErrorOrResult<GLuint> PathManager::createPaths(rx::GLImplFactory *factory, GLsizei range)
349 {
350     // Allocate client side handles.
351     const GLuint client = mHandleAllocator.allocateRange(static_cast<GLuint>(range));
352     if (client == HandleRangeAllocator::kInvalidHandle)
353         return OutOfMemory() << "Failed to allocate path handle range.";
354 
355     const auto &paths = factory->createPaths(range);
356     if (paths.empty())
357     {
358         mHandleAllocator.releaseRange(client, range);
359         return OutOfMemory() << "Failed to allocate path objects.";
360     }
361 
362     for (GLsizei i = 0; i < range; ++i)
363     {
364         rx::PathImpl *impl = paths[static_cast<unsigned>(i)];
365         const auto id   = client + i;
366         mPaths.assign(id, new Path(impl));
367     }
368     return client;
369 }
370 
deletePaths(GLuint first,GLsizei range)371 void PathManager::deletePaths(GLuint first, GLsizei range)
372 {
373     for (GLsizei i = 0; i < range; ++i)
374     {
375         const auto id = first + i;
376         Path *p       = nullptr;
377         if (!mPaths.erase(id, &p))
378             continue;
379         delete p;
380     }
381     mHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
382 }
383 
getPath(GLuint handle) const384 Path *PathManager::getPath(GLuint handle) const
385 {
386     return mPaths.query(handle);
387 }
388 
hasPath(GLuint handle) const389 bool PathManager::hasPath(GLuint handle) const
390 {
391     return mHandleAllocator.isUsed(handle);
392 }
393 
~PathManager()394 PathManager::~PathManager()
395 {
396     ASSERT(mPaths.empty());
397 }
398 
reset(const Context * context)399 void PathManager::reset(const Context *context)
400 {
401     for (auto path : mPaths)
402     {
403         SafeDelete(path.second);
404     }
405     mPaths.clear();
406 }
407 
408 // FramebufferManager Implementation.
409 
410 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle,const Caps & caps)411 Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
412                                                    GLuint handle,
413                                                    const Caps &caps)
414 {
415     return new Framebuffer(caps, factory, handle);
416 }
417 
418 // static
DeleteObject(const Context * context,Framebuffer * framebuffer)419 void FramebufferManager::DeleteObject(const Context *context, Framebuffer *framebuffer)
420 {
421     // Default framebuffer are owned by their respective Surface
422     if (framebuffer->id() != 0)
423     {
424         framebuffer->onDestroy(context);
425         delete framebuffer;
426     }
427 }
428 
createFramebuffer()429 GLuint FramebufferManager::createFramebuffer()
430 {
431     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
432 }
433 
getFramebuffer(GLuint handle) const434 Framebuffer *FramebufferManager::getFramebuffer(GLuint handle) const
435 {
436     return mObjectMap.query(handle);
437 }
438 
setDefaultFramebuffer(Framebuffer * framebuffer)439 void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
440 {
441     ASSERT(framebuffer == nullptr || framebuffer->id() == 0);
442     mObjectMap.assign(0, framebuffer);
443 }
444 
invalidateFramebufferComplenessCache() const445 void FramebufferManager::invalidateFramebufferComplenessCache() const
446 {
447     for (const auto &framebuffer : mObjectMap)
448     {
449         if (framebuffer.second)
450         {
451             framebuffer.second->invalidateCompletenessCache();
452         }
453     }
454 }
455 
456 // ProgramPipelineManager Implementation.
457 
458 // static
AllocateNewObject(rx::GLImplFactory * factory,GLuint handle)459 ProgramPipeline *ProgramPipelineManager::AllocateNewObject(rx::GLImplFactory *factory,
460                                                            GLuint handle)
461 {
462     ProgramPipeline *pipeline = new ProgramPipeline(factory, handle);
463     pipeline->addRef();
464     return pipeline;
465 }
466 
467 // static
DeleteObject(const Context * context,ProgramPipeline * pipeline)468 void ProgramPipelineManager::DeleteObject(const Context *context, ProgramPipeline *pipeline)
469 {
470     pipeline->release(context);
471 }
472 
createProgramPipeline()473 GLuint ProgramPipelineManager::createProgramPipeline()
474 {
475     return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
476 }
477 
getProgramPipeline(GLuint handle) const478 ProgramPipeline *ProgramPipelineManager::getProgramPipeline(GLuint handle) const
479 {
480     return mObjectMap.query(handle);
481 }
482 
483 }  // namespace gl
484