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 class GLPerfMonitor : public GLWrapper 145 { 146 public: GLPerfMonitor()147 GLPerfMonitor() : GLWrapper(&glGenPerfMonitorsAMD, (GLDelete *)&glDeletePerfMonitorsAMD) {} 148 }; 149 150 class GLShader : angle::NonCopyable 151 { 152 public: 153 GLShader() = delete; GLShader(GLenum shaderType)154 explicit GLShader(GLenum shaderType) { mHandle = glCreateShader(shaderType); } 155 ~GLShader()156 ~GLShader() { glDeleteShader(mHandle); } 157 get()158 GLuint get() const { return mHandle; } 159 GLuint()160 operator GLuint() const { return get(); } 161 reset()162 void reset() 163 { 164 if (mHandle) 165 { 166 glDeleteShader(mHandle); 167 mHandle = 0; 168 } 169 } 170 171 private: 172 GLuint mHandle; 173 }; 174 175 // Prefer ANGLE_GL_PROGRAM for local variables. 176 class GLProgram : angle::NonCopyable 177 { 178 public: GLProgram()179 GLProgram() : mHandle(0) {} 180 ~GLProgram()181 ~GLProgram() { reset(); } 182 makeEmpty()183 void makeEmpty() { mHandle = glCreateProgram(); } 184 makeCompute(const char * computeShader)185 void makeCompute(const char *computeShader) { mHandle = CompileComputeProgram(computeShader); } 186 makeRaster(const char * vertexShader,const char * fragmentShader)187 void makeRaster(const char *vertexShader, const char *fragmentShader) 188 { 189 mHandle = CompileProgram(vertexShader, fragmentShader); 190 } 191 makeRaster(const char * vertexShader,const char * geometryShader,const char * fragmentShader)192 void makeRaster(const char *vertexShader, 193 const char *geometryShader, 194 const char *fragmentShader) 195 { 196 mHandle = CompileProgramWithGS(vertexShader, geometryShader, fragmentShader); 197 } 198 makeRaster(const char * vertexShader,const char * tessControlShader,const char * tessEvaluateShader,const char * fragmentShader)199 void makeRaster(const char *vertexShader, 200 const char *tessControlShader, 201 const char *tessEvaluateShader, 202 const char *fragmentShader) 203 { 204 mHandle = CompileProgramWithTESS(vertexShader, tessControlShader, tessEvaluateShader, 205 fragmentShader); 206 } 207 makeRasterWithTransformFeedback(const char * vertexShader,const char * fragmentShader,const std::vector<std::string> & tfVaryings,GLenum bufferMode)208 void makeRasterWithTransformFeedback(const char *vertexShader, 209 const char *fragmentShader, 210 const std::vector<std::string> &tfVaryings, 211 GLenum bufferMode) 212 { 213 mHandle = CompileProgramWithTransformFeedback(vertexShader, fragmentShader, tfVaryings, 214 bufferMode); 215 } 216 makeBinaryOES(const std::vector<uint8_t> & binary,GLenum binaryFormat)217 void makeBinaryOES(const std::vector<uint8_t> &binary, GLenum binaryFormat) 218 { 219 mHandle = LoadBinaryProgramOES(binary, binaryFormat); 220 } 221 makeBinaryES3(const std::vector<uint8_t> & binary,GLenum binaryFormat)222 void makeBinaryES3(const std::vector<uint8_t> &binary, GLenum binaryFormat) 223 { 224 mHandle = LoadBinaryProgramES3(binary, binaryFormat); 225 } 226 valid()227 bool valid() const { return mHandle != 0; } 228 get()229 GLuint get() 230 { 231 if (!mHandle) 232 { 233 makeEmpty(); 234 } 235 return mHandle; 236 } get()237 GLuint get() const 238 { 239 ASSERT(mHandle); 240 return mHandle; 241 } 242 reset()243 void reset() 244 { 245 if (mHandle) 246 { 247 glDeleteProgram(mHandle); 248 mHandle = 0; 249 } 250 } 251 GLuint()252 operator GLuint() { return get(); } GLuint()253 operator GLuint() const { return get(); } 254 255 private: 256 GLuint mHandle; 257 }; 258 259 #define ANGLE_GL_EMPTY_PROGRAM(name) \ 260 GLProgram name; \ 261 name.makeEmpty(); \ 262 ASSERT_TRUE(name.valid()) 263 264 #define ANGLE_GL_PROGRAM(name, vertex, fragment) \ 265 GLProgram name; \ 266 name.makeRaster(vertex, fragment); \ 267 ASSERT_TRUE(name.valid()) 268 269 #define ANGLE_GL_PROGRAM_WITH_GS(name, vertex, geometry, fragment) \ 270 GLProgram name; \ 271 name.makeRaster(vertex, geometry, fragment); \ 272 ASSERT_TRUE(name.valid()) 273 274 #define ANGLE_GL_PROGRAM_WITH_TESS(name, vertex, tcs, tes, fragment) \ 275 GLProgram name; \ 276 name.makeRaster(vertex, tcs, tes, fragment); \ 277 ASSERT_TRUE(name.valid()) 278 279 #define ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(name, vertex, fragment, tfVaryings, bufferMode) \ 280 GLProgram name; \ 281 name.makeRasterWithTransformFeedback(vertex, fragment, tfVaryings, bufferMode); \ 282 ASSERT_TRUE(name.valid()) 283 284 #define ANGLE_GL_COMPUTE_PROGRAM(name, compute) \ 285 GLProgram name; \ 286 name.makeCompute(compute); \ 287 ASSERT_TRUE(name.valid()) 288 289 #define ANGLE_GL_BINARY_OES_PROGRAM(name, binary, binaryFormat) \ 290 GLProgram name; \ 291 name.makeBinaryOES(binary, binaryFormat); \ 292 ASSERT_TRUE(name.valid()) 293 294 #define ANGLE_GL_BINARY_ES3_PROGRAM(name, binary, binaryFormat) \ 295 GLProgram name; \ 296 name.makeBinaryES3(binary, binaryFormat); \ 297 ASSERT_TRUE(name.valid()) 298 299 } // namespace angle 300 301 #endif // ANGLE_TESTS_GL_RAII_H_ 302