• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 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 // gl_raii:
7 //   Helper methods for containing GL objects like buffers and textures.
8 
9 #ifndef ANGLE_TESTS_GL_RAII_H_
10 #define ANGLE_TESTS_GL_RAII_H_
11 
12 #include <functional>
13 
14 #include "common/debug.h"
15 #include "util/shader_utils.h"
16 
17 namespace angle
18 {
19 
20 // This is a bit of hack to work around a bug in MSVS intellisense, and make it very easy to
21 // use the correct function pointer type without worrying about the various definitions of
22 // GL_APICALL.
23 using GLGen    = decltype(glGenBuffers);
24 using GLDelete = decltype(glDeleteBuffers);
25 
26 class GLWrapper : angle::NonCopyable
27 {
28   public:
GLWrapper(GLGen * genFunc,GLDelete * deleteFunc)29     GLWrapper(GLGen *genFunc, GLDelete *deleteFunc) : mGenFunc(genFunc), mDeleteFunc(deleteFunc) {}
~GLWrapper()30     ~GLWrapper()
31     {
32         if (mHandle)
33         {
34             (*mDeleteFunc)(1, &mHandle);
35         }
36     }
37 
38     // The move-constructor and move-assignment operators are necessary so that the data within a
39     // GLWrapper object can be relocated.
GLWrapper(GLWrapper && rht)40     GLWrapper(GLWrapper &&rht)
41         : mGenFunc(rht.mGenFunc), mDeleteFunc(rht.mDeleteFunc), mHandle(rht.mHandle)
42     {
43         rht.mHandle = 0u;
44     }
45     GLWrapper &operator=(GLWrapper &&rht)
46     {
47         if (this != &rht)
48         {
49             mGenFunc    = rht.mGenFunc;
50             mDeleteFunc = rht.mDeleteFunc;
51             std::swap(mHandle, rht.mHandle);
52         }
53         return *this;
54     }
55 
reset()56     void reset()
57     {
58         if (mHandle != 0u)
59         {
60             (*mDeleteFunc)(1, &mHandle);
61             mHandle = 0u;
62         }
63     }
64 
get()65     GLuint get()
66     {
67         if (!mHandle)
68         {
69             (*mGenFunc)(1, &mHandle);
70         }
71         return mHandle;
72     }
get()73     GLuint get() const
74     {
75         ASSERT(mHandle);
76         return mHandle;
77     }
78 
GLuint()79     operator GLuint() { return get(); }
GLuint()80     operator GLuint() const { return get(); }
81 
82   private:
83     GLGen *mGenFunc;
84     GLDelete *mDeleteFunc;
85     GLuint mHandle = 0u;
86 };
87 
88 class GLVertexArray : public GLWrapper
89 {
90   public:
GLVertexArray()91     GLVertexArray() : GLWrapper(&glGenVertexArrays, &glDeleteVertexArrays) {}
92 };
93 class GLBuffer : public GLWrapper
94 {
95   public:
GLBuffer()96     GLBuffer() : GLWrapper(&glGenBuffers, &glDeleteBuffers) {}
97 };
98 class GLTexture : public GLWrapper
99 {
100   public:
GLTexture()101     GLTexture() : GLWrapper(&glGenTextures, &glDeleteTextures) {}
102 };
103 class GLFramebuffer : public GLWrapper
104 {
105   public:
GLFramebuffer()106     GLFramebuffer() : GLWrapper(&glGenFramebuffers, &glDeleteFramebuffers) {}
107 };
108 class GLMemoryObject : public GLWrapper
109 {
110   public:
GLMemoryObject()111     GLMemoryObject() : GLWrapper(&glCreateMemoryObjectsEXT, &glDeleteMemoryObjectsEXT) {}
112 };
113 class GLRenderbuffer : public GLWrapper
114 {
115   public:
GLRenderbuffer()116     GLRenderbuffer() : GLWrapper(&glGenRenderbuffers, &glDeleteRenderbuffers) {}
117 };
118 class GLSampler : public GLWrapper
119 {
120   public:
GLSampler()121     GLSampler() : GLWrapper(&glGenSamplers, &glDeleteSamplers) {}
122 };
123 class GLSemaphore : public GLWrapper
124 {
125   public:
GLSemaphore()126     GLSemaphore() : GLWrapper(&glGenSemaphoresEXT, &glDeleteSemaphoresEXT) {}
127 };
128 class GLTransformFeedback : public GLWrapper
129 {
130   public:
GLTransformFeedback()131     GLTransformFeedback() : GLWrapper(&glGenTransformFeedbacks, &glDeleteTransformFeedbacks) {}
132 };
133 class GLProgramPipeline : public GLWrapper
134 {
135   public:
GLProgramPipeline()136     GLProgramPipeline() : GLWrapper(&glGenProgramPipelines, &glDeleteProgramPipelines) {}
137 };
138 class GLQueryEXT : public GLWrapper
139 {
140   public:
GLQueryEXT()141     GLQueryEXT() : GLWrapper(&glGenQueriesEXT, &glDeleteQueriesEXT) {}
142 };
143 using GLQuery = GLQueryEXT;
144 
145 class GLShader : angle::NonCopyable
146 {
147   public:
148     GLShader() = delete;
GLShader(GLenum shaderType)149     explicit GLShader(GLenum shaderType) { mHandle = glCreateShader(shaderType); }
150 
~GLShader()151     ~GLShader() { glDeleteShader(mHandle); }
152 
get()153     GLuint get() const { return mHandle; }
154 
GLuint()155     operator GLuint() const { return get(); }
156 
reset()157     void reset()
158     {
159         if (mHandle)
160         {
161             glDeleteShader(mHandle);
162             mHandle = 0;
163         }
164     }
165 
166   private:
167     GLuint mHandle;
168 };
169 
170 // Prefer ANGLE_GL_PROGRAM for local variables.
171 class GLProgram
172 {
173   public:
GLProgram()174     GLProgram() : mHandle(0) {}
175 
~GLProgram()176     ~GLProgram() { reset(); }
177 
makeEmpty()178     void makeEmpty() { mHandle = glCreateProgram(); }
179 
makeCompute(const char * computeShader)180     void makeCompute(const char *computeShader) { mHandle = CompileComputeProgram(computeShader); }
181 
makeRaster(const char * vertexShader,const char * fragmentShader)182     void makeRaster(const char *vertexShader, const char *fragmentShader)
183     {
184         mHandle = CompileProgram(vertexShader, fragmentShader);
185     }
186 
makeRaster(const char * vertexShader,const char * geometryShader,const char * fragmentShader)187     void makeRaster(const char *vertexShader,
188                     const char *geometryShader,
189                     const char *fragmentShader)
190     {
191         mHandle = CompileProgramWithGS(vertexShader, geometryShader, fragmentShader);
192     }
193 
makeRaster(const char * vertexShader,const char * tessControlShader,const char * tessEvaluateShader,const char * fragmentShader)194     void makeRaster(const char *vertexShader,
195                     const char *tessControlShader,
196                     const char *tessEvaluateShader,
197                     const char *fragmentShader)
198     {
199         mHandle = CompileProgramWithTESS(vertexShader, tessControlShader, tessEvaluateShader,
200                                          fragmentShader);
201     }
202 
makeRasterWithTransformFeedback(const char * vertexShader,const char * fragmentShader,const std::vector<std::string> & tfVaryings,GLenum bufferMode)203     void makeRasterWithTransformFeedback(const char *vertexShader,
204                                          const char *fragmentShader,
205                                          const std::vector<std::string> &tfVaryings,
206                                          GLenum bufferMode)
207     {
208         mHandle = CompileProgramWithTransformFeedback(vertexShader, fragmentShader, tfVaryings,
209                                                       bufferMode);
210     }
211 
makeBinaryOES(const std::vector<uint8_t> & binary,GLenum binaryFormat)212     void makeBinaryOES(const std::vector<uint8_t> &binary, GLenum binaryFormat)
213     {
214         mHandle = LoadBinaryProgramOES(binary, binaryFormat);
215     }
216 
makeBinaryES3(const std::vector<uint8_t> & binary,GLenum binaryFormat)217     void makeBinaryES3(const std::vector<uint8_t> &binary, GLenum binaryFormat)
218     {
219         mHandle = LoadBinaryProgramES3(binary, binaryFormat);
220     }
221 
valid()222     bool valid() const { return mHandle != 0; }
223 
get()224     GLuint get()
225     {
226         if (!mHandle)
227         {
228             makeEmpty();
229         }
230         return mHandle;
231     }
get()232     GLuint get() const
233     {
234         ASSERT(mHandle);
235         return mHandle;
236     }
237 
reset()238     void reset()
239     {
240         if (mHandle)
241         {
242             glDeleteProgram(mHandle);
243             mHandle = 0;
244         }
245     }
246 
GLuint()247     operator GLuint() { return get(); }
GLuint()248     operator GLuint() const { return get(); }
249 
250   private:
251     GLuint mHandle;
252 };
253 
254 #define ANGLE_GL_EMPTY_PROGRAM(name) \
255     GLProgram name;                  \
256     name.makeEmpty();                \
257     ASSERT_TRUE(name.valid())
258 
259 #define ANGLE_GL_PROGRAM(name, vertex, fragment) \
260     GLProgram name;                              \
261     name.makeRaster(vertex, fragment);           \
262     ASSERT_TRUE(name.valid())
263 
264 #define ANGLE_GL_PROGRAM_WITH_GS(name, vertex, geometry, fragment) \
265     GLProgram name;                                                \
266     name.makeRaster(vertex, geometry, fragment);                   \
267     ASSERT_TRUE(name.valid())
268 
269 #define ANGLE_GL_PROGRAM_WITH_TESS(name, vertex, tcs, tes, fragment) \
270     GLProgram name;                                                  \
271     name.makeRaster(vertex, tcs, tes, fragment);                     \
272     ASSERT_TRUE(name.valid())
273 
274 #define ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(name, vertex, fragment, tfVaryings, bufferMode) \
275     GLProgram name;                                                                         \
276     name.makeRasterWithTransformFeedback(vertex, fragment, tfVaryings, bufferMode);         \
277     ASSERT_TRUE(name.valid())
278 
279 #define ANGLE_GL_COMPUTE_PROGRAM(name, compute) \
280     GLProgram name;                             \
281     name.makeCompute(compute);                  \
282     ASSERT_TRUE(name.valid())
283 
284 #define ANGLE_GL_BINARY_OES_PROGRAM(name, binary, binaryFormat) \
285     GLProgram name;                                             \
286     name.makeBinaryOES(binary, binaryFormat);                   \
287     ASSERT_TRUE(name.valid())
288 
289 #define ANGLE_GL_BINARY_ES3_PROGRAM(name, binary, binaryFormat) \
290     GLProgram name;                                             \
291     name.makeBinaryES3(binary, binaryFormat);                   \
292     ASSERT_TRUE(name.valid())
293 
294 }  // namespace angle
295 
296 #endif  // ANGLE_TESTS_GL_RAII_H_
297