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.h : Defines the ResourceManager classes, which handle allocation and lifetime of
8 // GL objects.
9 
10 #ifndef LIBANGLE_RESOURCEMANAGER_H_
11 #define LIBANGLE_RESOURCEMANAGER_H_
12 
13 #include "angle_gl.h"
14 #include "common/angleutils.h"
15 #include "libANGLE/Error.h"
16 #include "libANGLE/HandleAllocator.h"
17 #include "libANGLE/ResourceMap.h"
18 
19 namespace rx
20 {
21 class GLImplFactory;
22 }  // namespace rx
23 
24 namespace egl
25 {
26 class ShareGroup;
27 }  // namespace egl
28 
29 namespace gl
30 {
31 class Buffer;
32 struct Caps;
33 class Context;
34 class Framebuffer;
35 struct Limitations;
36 class MemoryObject;
37 class Path;
38 class Program;
39 class ProgramPipeline;
40 class Renderbuffer;
41 class Sampler;
42 class Semaphore;
43 class Shader;
44 class Sync;
45 class Texture;
46 
47 class ResourceManagerBase : angle::NonCopyable
48 {
49   public:
50     ResourceManagerBase();
51 
52     void addRef();
53     void release(const Context *context);
54 
55   protected:
56     virtual void reset(const Context *context) = 0;
57     virtual ~ResourceManagerBase();
58 
59     HandleAllocator mHandleAllocator;
60 
61   private:
62     size_t mRefCount;
63 };
64 
65 template <typename ResourceType, typename ImplT, typename IDType>
66 class TypedResourceManager : public ResourceManagerBase
67 {
68   public:
TypedResourceManager()69     TypedResourceManager() {}
70 
71     void deleteObject(const Context *context, IDType handle);
isHandleGenerated(IDType handle)72     ANGLE_INLINE bool isHandleGenerated(IDType handle) const
73     {
74         // Zero is always assumed to have been generated implicitly.
75         return GetIDValue(handle) == 0 || mObjectMap.contains(handle);
76     }
77 
begin()78     typename ResourceMap<ResourceType, IDType>::Iterator begin() const
79     {
80         return mObjectMap.begin();
81     }
end()82     typename ResourceMap<ResourceType, IDType>::Iterator end() const { return mObjectMap.end(); }
83 
84   protected:
85     ~TypedResourceManager() override;
86 
87     // Inlined in the header for performance.
88     template <typename... ArgTypes>
checkObjectAllocation(rx::GLImplFactory * factory,IDType handle,ArgTypes...args)89     ANGLE_INLINE ResourceType *checkObjectAllocation(rx::GLImplFactory *factory,
90                                                      IDType handle,
91                                                      ArgTypes... args)
92     {
93         ResourceType *value = mObjectMap.query(handle);
94         if (value)
95         {
96             return value;
97         }
98 
99         if (GetIDValue(handle) == 0)
100         {
101             return nullptr;
102         }
103 
104         return checkObjectAllocationImpl(factory, handle, args...);
105     }
106 
107     void reset(const Context *context) override;
108 
109     ResourceMap<ResourceType, IDType> mObjectMap;
110 
111   private:
112     template <typename... ArgTypes>
checkObjectAllocationImpl(rx::GLImplFactory * factory,IDType handle,ArgTypes...args)113     ResourceType *checkObjectAllocationImpl(rx::GLImplFactory *factory,
114                                             IDType handle,
115                                             ArgTypes... args)
116     {
117         ResourceType *object = ImplT::AllocateNewObject(factory, handle, args...);
118 
119         if (!mObjectMap.contains(handle))
120         {
121             this->mHandleAllocator.reserve(GetIDValue(handle));
122         }
123         mObjectMap.assign(handle, object);
124 
125         return object;
126     }
127 };
128 
129 class BufferManager : public TypedResourceManager<Buffer, BufferManager, BufferID>
130 {
131   public:
132     BufferID createBuffer();
133     Buffer *getBuffer(BufferID handle) const;
134 
checkBufferAllocation(rx::GLImplFactory * factory,BufferID handle)135     ANGLE_INLINE Buffer *checkBufferAllocation(rx::GLImplFactory *factory, BufferID handle)
136     {
137         return checkObjectAllocation(factory, handle);
138     }
139 
140     // TODO(jmadill): Investigate design which doesn't expose these methods publicly.
141     static Buffer *AllocateNewObject(rx::GLImplFactory *factory, BufferID handle);
142     static void DeleteObject(const Context *context, Buffer *buffer);
143 
144   protected:
145     ~BufferManager() override;
146 };
147 
148 class ShaderProgramManager : public ResourceManagerBase
149 {
150   public:
151     ShaderProgramManager();
152 
153     ShaderProgramID createShader(rx::GLImplFactory *factory,
154                                  const Limitations &rendererLimitations,
155                                  ShaderType type);
156     void deleteShader(const Context *context, ShaderProgramID shader);
157     Shader *getShader(ShaderProgramID handle) const;
158 
159     ShaderProgramID createProgram(rx::GLImplFactory *factory);
160     void deleteProgram(const Context *context, ShaderProgramID program);
161 
getProgram(ShaderProgramID handle)162     ANGLE_INLINE Program *getProgram(ShaderProgramID handle) const
163     {
164         return mPrograms.query(handle);
165     }
166 
167     // For capture and performance counters only.
getShadersForCapture()168     const ResourceMap<Shader, ShaderProgramID> &getShadersForCapture() const { return mShaders; }
getProgramsForCaptureAndPerf()169     const ResourceMap<Program, ShaderProgramID> &getProgramsForCaptureAndPerf() const
170     {
171         return mPrograms;
172     }
173 
174   protected:
175     ~ShaderProgramManager() override;
176 
177   private:
178     template <typename ObjectType, typename IDType>
179     void deleteObject(const Context *context,
180                       ResourceMap<ObjectType, IDType> *objectMap,
181                       IDType id);
182 
183     void reset(const Context *context) override;
184 
185     ResourceMap<Shader, ShaderProgramID> mShaders;
186     ResourceMap<Program, ShaderProgramID> mPrograms;
187 };
188 
189 class TextureManager : public TypedResourceManager<Texture, TextureManager, TextureID>
190 {
191   public:
192     TextureID createTexture();
getTexture(TextureID handle)193     ANGLE_INLINE Texture *getTexture(TextureID handle) const
194     {
195         ASSERT(mObjectMap.query({0}) == nullptr);
196         return mObjectMap.query(handle);
197     }
198 
199     void signalAllTexturesDirty() const;
200 
checkTextureAllocation(rx::GLImplFactory * factory,TextureID handle,TextureType type)201     ANGLE_INLINE Texture *checkTextureAllocation(rx::GLImplFactory *factory,
202                                                  TextureID handle,
203                                                  TextureType type)
204     {
205         return checkObjectAllocation(factory, handle, type);
206     }
207 
208     static Texture *AllocateNewObject(rx::GLImplFactory *factory,
209                                       TextureID handle,
210                                       TextureType type);
211     static void DeleteObject(const Context *context, Texture *texture);
212 
213     void enableHandleAllocatorLogging();
214 
215   protected:
216     ~TextureManager() override;
217 };
218 
219 class RenderbufferManager
220     : public TypedResourceManager<Renderbuffer, RenderbufferManager, RenderbufferID>
221 {
222   public:
223     RenderbufferID createRenderbuffer();
224     Renderbuffer *getRenderbuffer(RenderbufferID handle) const;
225 
checkRenderbufferAllocation(rx::GLImplFactory * factory,RenderbufferID handle)226     Renderbuffer *checkRenderbufferAllocation(rx::GLImplFactory *factory, RenderbufferID handle)
227     {
228         return checkObjectAllocation(factory, handle);
229     }
230 
231     static Renderbuffer *AllocateNewObject(rx::GLImplFactory *factory, RenderbufferID handle);
232     static void DeleteObject(const Context *context, Renderbuffer *renderbuffer);
233 
234   protected:
235     ~RenderbufferManager() override;
236 };
237 
238 class SamplerManager : public TypedResourceManager<Sampler, SamplerManager, SamplerID>
239 {
240   public:
241     SamplerID createSampler();
242     Sampler *getSampler(SamplerID handle) const;
243     bool isSampler(SamplerID sampler) const;
244 
checkSamplerAllocation(rx::GLImplFactory * factory,SamplerID handle)245     Sampler *checkSamplerAllocation(rx::GLImplFactory *factory, SamplerID handle)
246     {
247         return checkObjectAllocation(factory, handle);
248     }
249 
250     static Sampler *AllocateNewObject(rx::GLImplFactory *factory, SamplerID handle);
251     static void DeleteObject(const Context *context, Sampler *sampler);
252 
253   protected:
254     ~SamplerManager() override;
255 };
256 
257 class SyncManager : public TypedResourceManager<Sync, SyncManager, GLuint>
258 {
259   public:
260     GLuint createSync(rx::GLImplFactory *factory);
261     Sync *getSync(GLuint handle) const;
262 
263     static void DeleteObject(const Context *context, Sync *sync);
264 
265   protected:
266     ~SyncManager() override;
267 };
268 
269 class FramebufferManager
270     : public TypedResourceManager<Framebuffer, FramebufferManager, FramebufferID>
271 {
272   public:
273     FramebufferID createFramebuffer();
274     Framebuffer *getFramebuffer(FramebufferID handle) const;
275     void setDefaultFramebuffer(Framebuffer *framebuffer);
276     Framebuffer *getDefaultFramebuffer() const;
277 
278     void invalidateFramebufferCompletenessCache() const;
279 
checkFramebufferAllocation(rx::GLImplFactory * factory,const Caps & caps,FramebufferID handle,egl::ShareGroup * shareGroup)280     Framebuffer *checkFramebufferAllocation(rx::GLImplFactory *factory,
281                                             const Caps &caps,
282                                             FramebufferID handle,
283                                             egl::ShareGroup *shareGroup)
284     {
285         return checkObjectAllocation<const Caps &>(factory, handle, caps, shareGroup);
286     }
287 
288     static Framebuffer *AllocateNewObject(rx::GLImplFactory *factory,
289                                           FramebufferID handle,
290                                           const Caps &caps,
291                                           egl::ShareGroup *shareGroup);
292     static void DeleteObject(const Context *context, Framebuffer *framebuffer);
293 
294   protected:
295     ~FramebufferManager() override;
296 };
297 
298 class ProgramPipelineManager
299     : public TypedResourceManager<ProgramPipeline, ProgramPipelineManager, ProgramPipelineID>
300 {
301   public:
302     ProgramPipelineID createProgramPipeline();
303     ProgramPipeline *getProgramPipeline(ProgramPipelineID handle) const;
304 
checkProgramPipelineAllocation(rx::GLImplFactory * factory,ProgramPipelineID handle)305     ProgramPipeline *checkProgramPipelineAllocation(rx::GLImplFactory *factory,
306                                                     ProgramPipelineID handle)
307     {
308         return checkObjectAllocation(factory, handle);
309     }
310 
311     static ProgramPipeline *AllocateNewObject(rx::GLImplFactory *factory, ProgramPipelineID handle);
312     static void DeleteObject(const Context *context, ProgramPipeline *pipeline);
313 
314   protected:
315     ~ProgramPipelineManager() override;
316 };
317 
318 class MemoryObjectManager : public ResourceManagerBase
319 {
320   public:
321     MemoryObjectManager();
322 
323     MemoryObjectID createMemoryObject(rx::GLImplFactory *factory);
324     void deleteMemoryObject(const Context *context, MemoryObjectID handle);
325     MemoryObject *getMemoryObject(MemoryObjectID handle) const;
326 
327   protected:
328     ~MemoryObjectManager() override;
329 
330   private:
331     void reset(const Context *context) override;
332 
333     ResourceMap<MemoryObject, MemoryObjectID> mMemoryObjects;
334 };
335 
336 class SemaphoreManager : public ResourceManagerBase
337 {
338   public:
339     SemaphoreManager();
340 
341     SemaphoreID createSemaphore(rx::GLImplFactory *factory);
342     void deleteSemaphore(const Context *context, SemaphoreID handle);
343     Semaphore *getSemaphore(SemaphoreID handle) const;
344 
345   protected:
346     ~SemaphoreManager() override;
347 
348   private:
349     void reset(const Context *context) override;
350 
351     ResourceMap<Semaphore, SemaphoreID> mSemaphores;
352 };
353 }  // namespace gl
354 
355 #endif  // LIBANGLE_RESOURCEMANAGER_H_
356