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