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