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() { (*mDeleteFunc)(1, &mHandle); } 30 31 // The move-constructor and move-assignment operators are necessary so that the data within a 32 // GLWrapper object can be relocated. GLWrapper(GLWrapper && rht)33 GLWrapper(GLWrapper &&rht) 34 : mGenFunc(rht.mGenFunc), mDeleteFunc(rht.mDeleteFunc), mHandle(rht.mHandle) 35 { 36 rht.mHandle = 0u; 37 } 38 GLWrapper &operator=(GLWrapper &&rht) 39 { 40 if (this != &rht) 41 { 42 mGenFunc = rht.mGenFunc; 43 mDeleteFunc = rht.mDeleteFunc; 44 std::swap(mHandle, rht.mHandle); 45 } 46 return *this; 47 } 48 reset()49 void reset() 50 { 51 if (mHandle != 0u) 52 { 53 (*mDeleteFunc)(1, &mHandle); 54 mHandle = 0u; 55 } 56 } 57 get()58 GLuint get() 59 { 60 if (!mHandle) 61 { 62 (*mGenFunc)(1, &mHandle); 63 } 64 return mHandle; 65 } 66 GLuint()67 operator GLuint() { return get(); } 68 69 private: 70 GLGen *mGenFunc; 71 GLDelete *mDeleteFunc; 72 GLuint mHandle = 0u; 73 }; 74 75 class GLVertexArray : public GLWrapper 76 { 77 public: GLVertexArray()78 GLVertexArray() : GLWrapper(&glGenVertexArrays, &glDeleteVertexArrays) {} 79 }; 80 class GLBuffer : public GLWrapper 81 { 82 public: GLBuffer()83 GLBuffer() : GLWrapper(&glGenBuffers, &glDeleteBuffers) {} 84 }; 85 class GLTexture : public GLWrapper 86 { 87 public: GLTexture()88 GLTexture() : GLWrapper(&glGenTextures, &glDeleteTextures) {} 89 }; 90 class GLFramebuffer : public GLWrapper 91 { 92 public: GLFramebuffer()93 GLFramebuffer() : GLWrapper(&glGenFramebuffers, &glDeleteFramebuffers) {} 94 }; 95 class GLMemoryObject : public GLWrapper 96 { 97 public: GLMemoryObject()98 GLMemoryObject() : GLWrapper(&glCreateMemoryObjectsEXT, &glDeleteMemoryObjectsEXT) {} 99 }; 100 class GLRenderbuffer : public GLWrapper 101 { 102 public: GLRenderbuffer()103 GLRenderbuffer() : GLWrapper(&glGenRenderbuffers, &glDeleteRenderbuffers) {} 104 }; 105 class GLSampler : public GLWrapper 106 { 107 public: GLSampler()108 GLSampler() : GLWrapper(&glGenSamplers, &glDeleteSamplers) {} 109 }; 110 class GLSemaphore : public GLWrapper 111 { 112 public: GLSemaphore()113 GLSemaphore() : GLWrapper(&glGenSemaphoresEXT, &glDeleteSemaphoresEXT) {} 114 }; 115 class GLTransformFeedback : public GLWrapper 116 { 117 public: GLTransformFeedback()118 GLTransformFeedback() : GLWrapper(&glGenTransformFeedbacks, &glDeleteTransformFeedbacks) {} 119 }; 120 class GLProgramPipeline : public GLWrapper 121 { 122 public: GLProgramPipeline()123 GLProgramPipeline() : GLWrapper(&glGenProgramPipelines, &glDeleteProgramPipelines) {} 124 }; 125 class GLQueryEXT : public GLWrapper 126 { 127 public: GLQueryEXT()128 GLQueryEXT() : GLWrapper(&glGenQueriesEXT, &glDeleteQueriesEXT) {} 129 }; 130 131 class GLShader : angle::NonCopyable 132 { 133 public: 134 GLShader() = delete; GLShader(GLenum shaderType)135 explicit GLShader(GLenum shaderType) { mHandle = glCreateShader(shaderType); } 136 ~GLShader()137 ~GLShader() { glDeleteShader(mHandle); } 138 get()139 GLuint get() { return mHandle; } 140 GLuint()141 operator GLuint() { return get(); } 142 143 private: 144 GLuint mHandle; 145 }; 146 147 // Prefer ANGLE_GL_PROGRAM for local variables. 148 class GLProgram 149 { 150 public: GLProgram()151 GLProgram() : mHandle(0) {} 152 ~GLProgram()153 ~GLProgram() { glDeleteProgram(mHandle); } 154 makeEmpty()155 void makeEmpty() { mHandle = glCreateProgram(); } 156 makeCompute(const char * computeShader)157 void makeCompute(const char *computeShader) { mHandle = CompileComputeProgram(computeShader); } 158 makeRaster(const char * vertexShader,const char * fragmentShader)159 void makeRaster(const char *vertexShader, const char *fragmentShader) 160 { 161 mHandle = CompileProgram(vertexShader, fragmentShader); 162 } 163 makeRaster(const char * vertexShader,const char * geometryShader,const char * fragmentShader)164 void makeRaster(const char *vertexShader, 165 const char *geometryShader, 166 const char *fragmentShader) 167 { 168 mHandle = CompileProgramWithGS(vertexShader, geometryShader, fragmentShader); 169 } 170 makeRasterWithTransformFeedback(const char * vertexShader,const char * fragmentShader,const std::vector<std::string> & tfVaryings,GLenum bufferMode)171 void makeRasterWithTransformFeedback(const char *vertexShader, 172 const char *fragmentShader, 173 const std::vector<std::string> &tfVaryings, 174 GLenum bufferMode) 175 { 176 mHandle = CompileProgramWithTransformFeedback(vertexShader, fragmentShader, tfVaryings, 177 bufferMode); 178 } 179 makeBinaryOES(const std::vector<uint8_t> & binary,GLenum binaryFormat)180 void makeBinaryOES(const std::vector<uint8_t> &binary, GLenum binaryFormat) 181 { 182 mHandle = LoadBinaryProgramOES(binary, binaryFormat); 183 } 184 makeBinaryES3(const std::vector<uint8_t> & binary,GLenum binaryFormat)185 void makeBinaryES3(const std::vector<uint8_t> &binary, GLenum binaryFormat) 186 { 187 mHandle = LoadBinaryProgramES3(binary, binaryFormat); 188 } 189 valid()190 bool valid() const { return mHandle != 0; } 191 get()192 GLuint get() { return mHandle; } 193 GLuint()194 operator GLuint() { return get(); } 195 196 private: 197 GLuint mHandle; 198 }; 199 200 #define ANGLE_GL_EMPTY_PROGRAM(name) \ 201 GLProgram name; \ 202 name.makeEmpty(); \ 203 ASSERT_TRUE(name.valid()) 204 205 #define ANGLE_GL_PROGRAM(name, vertex, fragment) \ 206 GLProgram name; \ 207 name.makeRaster(vertex, fragment); \ 208 ASSERT_TRUE(name.valid()) 209 210 #define ANGLE_GL_PROGRAM_WITH_GS(name, vertex, geometry, fragment) \ 211 GLProgram name; \ 212 name.makeRaster(vertex, geometry, fragment); \ 213 ASSERT_TRUE(name.valid()) 214 215 #define ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(name, vertex, fragment, tfVaryings, bufferMode) \ 216 GLProgram name; \ 217 name.makeRasterWithTransformFeedback(vertex, fragment, tfVaryings, bufferMode); \ 218 ASSERT_TRUE(name.valid()) 219 220 #define ANGLE_GL_COMPUTE_PROGRAM(name, compute) \ 221 GLProgram name; \ 222 name.makeCompute(compute); \ 223 ASSERT_TRUE(name.valid()) 224 225 #define ANGLE_GL_BINARY_OES_PROGRAM(name, binary, binaryFormat) \ 226 GLProgram name; \ 227 name.makeBinaryOES(binary, binaryFormat); \ 228 ASSERT_TRUE(name.valid()) 229 230 #define ANGLE_GL_BINARY_ES3_PROGRAM(name, binary, binaryFormat) \ 231 GLProgram name; \ 232 name.makeBinaryES3(binary, binaryFormat); \ 233 ASSERT_TRUE(name.valid()) 234 235 } // namespace angle 236 237 #endif // ANGLE_TESTS_GL_RAII_H_ 238