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