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 137 class GLShader : angle::NonCopyable 138 { 139 public: 140 GLShader() = delete; GLShader(GLenum shaderType)141 explicit GLShader(GLenum shaderType) { mHandle = glCreateShader(shaderType); } 142 ~GLShader()143 ~GLShader() { glDeleteShader(mHandle); } 144 get()145 GLuint get() { return mHandle; } 146 GLuint()147 operator GLuint() { return get(); } 148 149 private: 150 GLuint mHandle; 151 }; 152 153 // Prefer ANGLE_GL_PROGRAM for local variables. 154 class GLProgram 155 { 156 public: GLProgram()157 GLProgram() : mHandle(0) {} 158 ~GLProgram()159 ~GLProgram() 160 { 161 if (mHandle) 162 { 163 glDeleteProgram(mHandle); 164 } 165 } 166 makeEmpty()167 void makeEmpty() { mHandle = glCreateProgram(); } 168 makeCompute(const char * computeShader)169 void makeCompute(const char *computeShader) { mHandle = CompileComputeProgram(computeShader); } 170 makeRaster(const char * vertexShader,const char * fragmentShader)171 void makeRaster(const char *vertexShader, const char *fragmentShader) 172 { 173 mHandle = CompileProgram(vertexShader, fragmentShader); 174 } 175 makeRaster(const char * vertexShader,const char * geometryShader,const char * fragmentShader)176 void makeRaster(const char *vertexShader, 177 const char *geometryShader, 178 const char *fragmentShader) 179 { 180 mHandle = CompileProgramWithGS(vertexShader, geometryShader, fragmentShader); 181 } 182 makeRasterWithTransformFeedback(const char * vertexShader,const char * fragmentShader,const std::vector<std::string> & tfVaryings,GLenum bufferMode)183 void makeRasterWithTransformFeedback(const char *vertexShader, 184 const char *fragmentShader, 185 const std::vector<std::string> &tfVaryings, 186 GLenum bufferMode) 187 { 188 mHandle = CompileProgramWithTransformFeedback(vertexShader, fragmentShader, tfVaryings, 189 bufferMode); 190 } 191 makeBinaryOES(const std::vector<uint8_t> & binary,GLenum binaryFormat)192 void makeBinaryOES(const std::vector<uint8_t> &binary, GLenum binaryFormat) 193 { 194 mHandle = LoadBinaryProgramOES(binary, binaryFormat); 195 } 196 makeBinaryES3(const std::vector<uint8_t> & binary,GLenum binaryFormat)197 void makeBinaryES3(const std::vector<uint8_t> &binary, GLenum binaryFormat) 198 { 199 mHandle = LoadBinaryProgramES3(binary, binaryFormat); 200 } 201 valid()202 bool valid() const { return mHandle != 0; } 203 get()204 GLuint get() { return mHandle; } 205 GLuint()206 operator GLuint() { return get(); } 207 208 private: 209 GLuint mHandle; 210 }; 211 212 #define ANGLE_GL_EMPTY_PROGRAM(name) \ 213 GLProgram name; \ 214 name.makeEmpty(); \ 215 ASSERT_TRUE(name.valid()) 216 217 #define ANGLE_GL_PROGRAM(name, vertex, fragment) \ 218 GLProgram name; \ 219 name.makeRaster(vertex, fragment); \ 220 ASSERT_TRUE(name.valid()) 221 222 #define ANGLE_GL_PROGRAM_WITH_GS(name, vertex, geometry, fragment) \ 223 GLProgram name; \ 224 name.makeRaster(vertex, geometry, fragment); \ 225 ASSERT_TRUE(name.valid()) 226 227 #define ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(name, vertex, fragment, tfVaryings, bufferMode) \ 228 GLProgram name; \ 229 name.makeRasterWithTransformFeedback(vertex, fragment, tfVaryings, bufferMode); \ 230 ASSERT_TRUE(name.valid()) 231 232 #define ANGLE_GL_COMPUTE_PROGRAM(name, compute) \ 233 GLProgram name; \ 234 name.makeCompute(compute); \ 235 ASSERT_TRUE(name.valid()) 236 237 #define ANGLE_GL_BINARY_OES_PROGRAM(name, binary, binaryFormat) \ 238 GLProgram name; \ 239 name.makeBinaryOES(binary, binaryFormat); \ 240 ASSERT_TRUE(name.valid()) 241 242 #define ANGLE_GL_BINARY_ES3_PROGRAM(name, binary, binaryFormat) \ 243 GLProgram name; \ 244 name.makeBinaryES3(binary, binaryFormat); \ 245 ASSERT_TRUE(name.valid()) 246 247 } // namespace angle 248 249 #endif // ANGLE_TESTS_GL_RAII_H_ 250