blob: c7defac5f1e993d7e58a7d395b9b3325063e5ad4 [file] [log] [blame]
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00001//
Geoff Lang4ddf5af2016-12-01 14:30:44 -05002// Copyright (c) 2002-2016 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
Geoff Lang4ddf5af2016-12-01 14:30:44 -05007// ResourceManager.cpp: Implements the the ResourceManager classes, which handle allocation and
8// lifetime of GL objects.
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +00009
Geoff Lang2b5420c2014-11-19 14:20:15 -050010#include "libANGLE/ResourceManager.h"
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000011
Geoff Lang2b5420c2014-11-19 14:20:15 -050012#include "libANGLE/Buffer.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040013#include "libANGLE/Fence.h"
Sami Väisänene45e53b2016-05-25 10:36:04 +030014#include "libANGLE/Path.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Program.h"
16#include "libANGLE/Renderbuffer.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040017#include "libANGLE/Sampler.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050018#include "libANGLE/Shader.h"
19#include "libANGLE/Texture.h"
Jamie Madill53ea9cc2016-05-17 10:12:52 -040020#include "libANGLE/renderer/GLImplFactory.h"
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000021
22namespace gl
23{
Geoff Lang4ddf5af2016-12-01 14:30:44 -050024
25namespace
26{
27
28template <typename ResourceType>
29GLuint AllocateEmptyObject(HandleAllocator *handleAllocator, ResourceMap<ResourceType> *objectMap)
30{
31 GLuint handle = handleAllocator->allocate();
32 (*objectMap)[handle] = nullptr;
33 return handle;
34}
35
Geoff Lang4ddf5af2016-12-01 14:30:44 -050036template <typename ResourceType>
37ResourceType *GetObject(const ResourceMap<ResourceType> &objectMap, GLuint handle)
38{
39 auto iter = objectMap.find(handle);
40 return iter != objectMap.end() ? iter->second : nullptr;
41}
42
43} // anonymous namespace
44
45template <typename HandleAllocatorType>
46ResourceManagerBase<HandleAllocatorType>::ResourceManagerBase() : mRefCount(1)
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000047{
48}
49
Geoff Lang4ddf5af2016-12-01 14:30:44 -050050template <typename HandleAllocatorType>
51void ResourceManagerBase<HandleAllocatorType>::addRef()
daniel@transgaming.com0d25b002010-07-28 19:21:07 +000052{
53 mRefCount++;
54}
55
Geoff Lang4ddf5af2016-12-01 14:30:44 -050056template <typename HandleAllocatorType>
57void ResourceManagerBase<HandleAllocatorType>::release()
daniel@transgaming.com0d25b002010-07-28 19:21:07 +000058{
59 if (--mRefCount == 0)
60 {
61 delete this;
62 }
63}
64
Jamie Madill5f45e7c2017-02-10 15:23:28 -080065template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
66TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::~TypedResourceManager()
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000067{
Geoff Lang4ddf5af2016-12-01 14:30:44 -050068 while (!mObjectMap.empty())
69 {
70 deleteObject(mObjectMap.begin()->first);
71 }
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +000072}
73
Jamie Madill5f45e7c2017-02-10 15:23:28 -080074template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
75void TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::deleteObject(GLuint handle)
Geoff Lang4ddf5af2016-12-01 14:30:44 -050076{
Jamie Madill5f45e7c2017-02-10 15:23:28 -080077 auto objectIter = mObjectMap.find(handle);
78 if (objectIter == mObjectMap.end())
79 {
80 return;
81 }
82
83 if (objectIter->second != nullptr)
84 {
85 ImplT::DeleteObject(objectIter->second);
86 }
87
88 // Requires an explicit this-> because of C++ template rules.
89 this->mHandleAllocator.release(objectIter->first);
90 mObjectMap.erase(objectIter);
Geoff Lang4ddf5af2016-12-01 14:30:44 -050091}
92
Jamie Madill5f45e7c2017-02-10 15:23:28 -080093template <typename ResourceType, typename HandleAllocatorType, typename ImplT>
94template <typename... ArgTypes>
95ResourceType *TypedResourceManager<ResourceType, HandleAllocatorType, ImplT>::allocateObject(
96 typename ResourceMap<ResourceType>::iterator &objectMapIter,
97 rx::GLImplFactory *factory,
98 GLuint handle,
99 ArgTypes... args)
100{
101 ResourceType *object = ImplT::AllocateNewObject(factory, handle, args...);
102
103 if (objectMapIter != mObjectMap.end())
104 {
105 objectMapIter->second = object;
106 }
107 else
108 {
109 this->mHandleAllocator.reserve(handle);
110 mObjectMap[handle] = object;
111 }
112
113 return object;
114}
115
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500116template class ResourceManagerBase<HandleAllocator>;
117template class ResourceManagerBase<HandleRangeAllocator>;
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800118template class TypedResourceManager<Buffer, HandleAllocator, BufferManager>;
119template Buffer *TypedResourceManager<Buffer, HandleAllocator, BufferManager>::allocateObject(
120 ResourceMap<Buffer>::iterator &,
121 rx::GLImplFactory *,
122 GLuint);
123template class TypedResourceManager<Texture, HandleAllocator, TextureManager>;
124template Texture *TypedResourceManager<Texture, HandleAllocator, TextureManager>::allocateObject(
125 ResourceMap<Texture>::iterator &,
126 rx::GLImplFactory *,
127 GLuint,
128 GLenum);
129template class TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>;
130template Renderbuffer *
131TypedResourceManager<Renderbuffer, HandleAllocator, RenderbufferManager>::allocateObject(
132 ResourceMap<Renderbuffer>::iterator &,
133 rx::GLImplFactory *,
134 GLuint);
135template class TypedResourceManager<Sampler, HandleAllocator, SamplerManager>;
136template Sampler *TypedResourceManager<Sampler, HandleAllocator, SamplerManager>::allocateObject(
137 ResourceMap<Sampler>::iterator &,
138 rx::GLImplFactory *,
139 GLuint);
140template class TypedResourceManager<FenceSync, HandleAllocator, FenceSyncManager>;
141template class TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>;
142template Framebuffer *
143TypedResourceManager<Framebuffer, HandleAllocator, FramebufferManager>::allocateObject(
144 ResourceMap<Framebuffer>::iterator &,
145 rx::GLImplFactory *,
146 GLuint,
147 const Caps &);
148
149// BufferManager Implementation.
150
151// static
152Buffer *BufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
153{
154 Buffer *buffer = new Buffer(factory, handle);
155 buffer->addRef();
156 return buffer;
157}
158
159// static
160void BufferManager::DeleteObject(Buffer *buffer)
161{
162 buffer->release();
163}
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500164
165GLuint BufferManager::createBuffer()
166{
167 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
168}
169
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500170Buffer *BufferManager::getBuffer(GLuint handle) const
171{
172 return GetObject(mObjectMap, handle);
173}
174
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500175bool BufferManager::isBufferGenerated(GLuint buffer) const
176{
177 return buffer == 0 || mObjectMap.find(buffer) != mObjectMap.end();
178}
179
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800180// ShaderProgramManager Implementation.
181
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500182ShaderProgramManager::~ShaderProgramManager()
183{
184 while (!mPrograms.empty())
185 {
186 deleteProgram(mPrograms.begin()->first);
187 }
188 while (!mShaders.empty())
189 {
190 deleteShader(mShaders.begin()->first);
191 }
192}
193
194GLuint ShaderProgramManager::createShader(rx::GLImplFactory *factory,
195 const gl::Limitations &rendererLimitations,
196 GLenum type)
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000197{
Martin Radev4c4c8e72016-08-04 12:25:34 +0300198 ASSERT(type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER || type == GL_COMPUTE_SHADER);
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500199 GLuint handle = mHandleAllocator.allocate();
200 mShaders[handle] = new Shader(this, factory, rendererLimitations, type, handle);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000201 return handle;
202}
203
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500204void ShaderProgramManager::deleteShader(GLuint shader)
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000205{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500206 deleteObject(&mShaders, shader);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000207}
208
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500209Shader *ShaderProgramManager::getShader(GLuint handle) const
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000210{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500211 return GetObject(mShaders, handle);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000212}
213
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500214GLuint ShaderProgramManager::createProgram(rx::GLImplFactory *factory)
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000215{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500216 GLuint handle = mHandleAllocator.allocate();
217 mPrograms[handle] = new Program(factory, this, handle);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000218 return handle;
219}
220
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500221void ShaderProgramManager::deleteProgram(GLuint program)
Jamie Madilldc356042013-07-19 16:36:57 -0400222{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500223 deleteObject(&mPrograms, program);
Jamie Madilldc356042013-07-19 16:36:57 -0400224}
225
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500226Program *ShaderProgramManager::getProgram(GLuint handle) const
Jamie Madillcd055f82013-07-26 11:55:15 -0400227{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500228 return GetObject(mPrograms, handle);
Jamie Madillcd055f82013-07-26 11:55:15 -0400229}
230
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500231template <typename ObjectType>
232void ShaderProgramManager::deleteObject(ResourceMap<ObjectType> *objectMap, GLuint id)
233{
234 auto iter = objectMap->find(id);
235 if (iter == objectMap->end())
236 {
237 return;
238 }
239
240 auto object = iter->second;
241 if (object->getRefCount() == 0)
242 {
243 mHandleAllocator.release(id);
244 SafeDelete(object);
245 objectMap->erase(iter);
246 }
247 else
248 {
249 object->flagForDeletion();
250 }
251}
252
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800253// TextureManager Implementation.
254
255// static
256Texture *TextureManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle, GLenum target)
257{
258 Texture *texture = new Texture(factory, handle, target);
259 texture->addRef();
260 return texture;
261}
262
263// static
264void TextureManager::DeleteObject(Texture *texture)
265{
266 texture->release();
267}
268
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500269GLuint TextureManager::createTexture()
270{
271 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
272}
273
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500274Texture *TextureManager::getTexture(GLuint handle) const
275{
276 ASSERT(GetObject(mObjectMap, 0) == nullptr);
277 return GetObject(mObjectMap, handle);
278}
279
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500280bool TextureManager::isTextureGenerated(GLuint texture) const
281{
282 return texture == 0 || mObjectMap.find(texture) != mObjectMap.end();
283}
284
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800285// RenderbufferManager Implementation.
286
287// static
288Renderbuffer *RenderbufferManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
289{
290 Renderbuffer *renderbuffer = new Renderbuffer(factory->createRenderbuffer(), handle);
291 renderbuffer->addRef();
292 return renderbuffer;
293}
294
295// static
296void RenderbufferManager::DeleteObject(Renderbuffer *renderbuffer)
297{
298 renderbuffer->release();
299}
300
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500301GLuint RenderbufferManager::createRenderbuffer()
302{
303 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
304}
305
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500306Renderbuffer *RenderbufferManager::getRenderbuffer(GLuint handle)
307{
308 return GetObject(mObjectMap, handle);
309}
310
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500311bool RenderbufferManager::isRenderbufferGenerated(GLuint renderbuffer) const
312{
313 return renderbuffer == 0 || mObjectMap.find(renderbuffer) != mObjectMap.end();
314}
315
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800316// SamplerManager Implementation.
317
318// static
319Sampler *SamplerManager::AllocateNewObject(rx::GLImplFactory *factory, GLuint handle)
320{
321 Sampler *sampler = new Sampler(factory, handle);
322 sampler->addRef();
323 return sampler;
324}
325
326// static
327void SamplerManager::DeleteObject(Sampler *sampler)
328{
329 sampler->release();
330}
331
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500332GLuint SamplerManager::createSampler()
333{
334 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
335}
336
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500337Sampler *SamplerManager::getSampler(GLuint handle)
338{
339 return GetObject(mObjectMap, handle);
340}
341
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500342bool SamplerManager::isSampler(GLuint sampler)
343{
344 return mObjectMap.find(sampler) != mObjectMap.end();
345}
346
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800347// FenceSyncManager Implementation.
348
349// static
350void FenceSyncManager::DeleteObject(FenceSync *fenceSync)
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500351{
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800352 fenceSync->release();
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500353}
354
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800355GLuint FenceSyncManager::createFenceSync(rx::GLImplFactory *factory)
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500356{
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800357 GLuint handle = mHandleAllocator.allocate();
358 FenceSync *fenceSync = new FenceSync(factory->createFenceSync(), handle);
359 fenceSync->addRef();
360 mObjectMap[handle] = fenceSync;
361 return handle;
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500362}
363
364FenceSync *FenceSyncManager::getFenceSync(GLuint handle)
365{
366 return GetObject(mObjectMap, handle);
367}
368
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800369// PathManager Implementation.
370
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500371ErrorOrResult<GLuint> PathManager::createPaths(rx::GLImplFactory *factory, GLsizei range)
Sami Väisänene45e53b2016-05-25 10:36:04 +0300372{
373 // Allocate client side handles.
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500374 const GLuint client = mHandleAllocator.allocateRange(static_cast<GLuint>(range));
Sami Väisänene45e53b2016-05-25 10:36:04 +0300375 if (client == HandleRangeAllocator::kInvalidHandle)
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500376 return Error(GL_OUT_OF_MEMORY, "Failed to allocate path handle range.");
Sami Väisänene45e53b2016-05-25 10:36:04 +0300377
378 const auto &paths = factory->createPaths(range);
379 if (paths.empty())
380 {
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500381 mHandleAllocator.releaseRange(client, range);
382 return Error(GL_OUT_OF_MEMORY, "Failed to allocate path objects.");
Sami Väisänene45e53b2016-05-25 10:36:04 +0300383 }
384
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500385 auto hint = mPaths.begin();
Sami Väisänene45e53b2016-05-25 10:36:04 +0300386
387 for (GLsizei i = 0; i < range; ++i)
388 {
389 const auto impl = paths[static_cast<unsigned>(i)];
390 const auto id = client + i;
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500391 hint = mPaths.insert(hint, std::make_pair(id, new Path(impl)));
Sami Väisänene45e53b2016-05-25 10:36:04 +0300392 }
393 return client;
394}
395
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500396void PathManager::deletePaths(GLuint first, GLsizei range)
Sami Väisänene45e53b2016-05-25 10:36:04 +0300397{
398 for (GLsizei i = 0; i < range; ++i)
399 {
400 const auto id = first + i;
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500401 const auto it = mPaths.find(id);
402 if (it == mPaths.end())
Sami Väisänene45e53b2016-05-25 10:36:04 +0300403 continue;
404 Path *p = it->second;
405 delete p;
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500406 mPaths.erase(it);
Sami Väisänene45e53b2016-05-25 10:36:04 +0300407 }
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500408 mHandleAllocator.releaseRange(first, static_cast<GLuint>(range));
Sami Väisänene45e53b2016-05-25 10:36:04 +0300409}
410
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500411Path *PathManager::getPath(GLuint handle) const
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000412{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500413 auto iter = mPaths.find(handle);
414 return iter != mPaths.end() ? iter->second : nullptr;
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000415}
416
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500417bool PathManager::hasPath(GLuint handle) const
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000418{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500419 return mHandleAllocator.isUsed(handle);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000420}
421
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500422PathManager::~PathManager()
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000423{
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500424 for (auto path : mPaths)
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000425 {
Geoff Lang4ddf5af2016-12-01 14:30:44 -0500426 SafeDelete(path.second);
daniel@transgaming.comda13f3e2010-07-28 19:20:56 +0000427 }
Geoff Langf41a7152016-09-19 15:11:17 -0400428}
429
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800430// FramebufferManager Implementation.
431
432// static
433Framebuffer *FramebufferManager::AllocateNewObject(rx::GLImplFactory *factory,
434 GLuint handle,
435 const Caps &caps)
Geoff Lang3bf8e3a2016-12-01 17:28:52 -0500436{
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800437 return new Framebuffer(caps, factory, handle);
438}
439
440// static
441void FramebufferManager::DeleteObject(Framebuffer *framebuffer)
442{
443 // Default framebuffer are owned by their respective Surface
444 if (framebuffer->id() != 0)
Geoff Lang3bf8e3a2016-12-01 17:28:52 -0500445 {
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800446 delete framebuffer;
Geoff Lang3bf8e3a2016-12-01 17:28:52 -0500447 }
448}
449
450GLuint FramebufferManager::createFramebuffer()
451{
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800452 return AllocateEmptyObject(&mHandleAllocator, &mObjectMap);
Geoff Lang3bf8e3a2016-12-01 17:28:52 -0500453}
454
455Framebuffer *FramebufferManager::getFramebuffer(GLuint handle) const
456{
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800457 return GetObject(mObjectMap, handle);
Geoff Lang3bf8e3a2016-12-01 17:28:52 -0500458}
459
460void FramebufferManager::setDefaultFramebuffer(Framebuffer *framebuffer)
461{
462 ASSERT(framebuffer == nullptr || framebuffer->id() == 0);
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800463 mObjectMap[0] = framebuffer;
Geoff Lang3bf8e3a2016-12-01 17:28:52 -0500464}
465
466bool FramebufferManager::isFramebufferGenerated(GLuint framebuffer)
467{
Jamie Madill5f45e7c2017-02-10 15:23:28 -0800468 ASSERT(mObjectMap.find(0) != mObjectMap.end());
469 return mObjectMap.find(framebuffer) != mObjectMap.end();
Geoff Lang3bf8e3a2016-12-01 17:28:52 -0500470}
471
Jamie Madill3f01e6c2016-03-08 13:53:02 -0500472} // namespace gl