1 // Copyright 2018 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // This file contains various utility methods related to SDL and OpenGL, 16 // primarily RAII wrappers around the C types used by those. 17 18 #ifndef THIRD_PARTY_QUIC_TRACE_TOOLS_SDL_UTIL_H_ 19 #define THIRD_PARTY_QUIC_TRACE_TOOLS_SDL_UTIL_H_ 20 21 #include <GL/glew.h> 22 #include <SDL.h> 23 24 #include <memory> 25 26 #include "absl/log/check.h" 27 #include "absl/log/log.h" 28 #include "absl/memory/memory.h" 29 30 namespace quic_trace { 31 namespace render { 32 33 // Scoped global initialization for SDL. 34 class ScopedSDL { 35 public: ScopedSDL()36 ScopedSDL() { CHECK_EQ(0, SDL_Init(SDL_INIT_VIDEO)); } 37 ScopedSDL(const ScopedSDL&) = delete; 38 ScopedSDL& operator=(const ScopedSDL&) = delete; 39 ~ScopedSDL()40 ~ScopedSDL() { SDL_Quit(); } 41 }; 42 43 // A helper class to automatically delete SDL objects once they go out of scope. 44 template <typename T, void (*D)(T*)> 45 class ScopedSdlType { 46 public: ScopedSdlType()47 ScopedSdlType() : value_(nullptr, D) {} ScopedSdlType(T * value)48 ScopedSdlType(T* value) : value_(value, D) {} 49 get()50 T* get() const { return value_.get(); } 51 T* operator*() const { return value_.get(); } 52 T* operator->() const { return value_.get(); } 53 54 private: 55 std::unique_ptr<T, void (*)(T*)> value_; 56 }; 57 58 using ScopedSdlWindow = ScopedSdlType<SDL_Window, SDL_DestroyWindow>; 59 using ScopedSdlSurface = ScopedSdlType<SDL_Surface, SDL_FreeSurface>; 60 61 class OpenGlContext { 62 public: 63 OpenGlContext(SDL_Window* window); ~OpenGlContext()64 ~OpenGlContext() { SDL_GL_DeleteContext(context_); } 65 context()66 SDL_GLContext context() const { return context_; } 67 68 private: 69 SDL_GLContext context_; 70 }; 71 72 // Utility wrapper around an OpenGL shader. 73 class GlShader { 74 public: GlShader(GLenum type)75 GlShader(GLenum type) { shader_ = glCreateShader(type); } 76 ~GlShader()77 ~GlShader() { glDeleteShader(shader_); } 78 79 GlShader(const GlShader&) = delete; 80 GlShader& operator=(const GlShader&) = delete; 81 82 bool Compile(const char* source); 83 std::string GetCompileInfoLog(); 84 void CompileOrDie(const char* source); 85 86 GLuint operator*() const { return shader_; } 87 88 private: 89 GLuint shader_; 90 }; 91 92 class GlProgram { 93 public: GlProgram()94 GlProgram() { program_ = glCreateProgram(); } 95 ~GlProgram()96 ~GlProgram() { glDeleteProgram(program_); } 97 98 GlProgram(const GlProgram&) = delete; 99 GlProgram& operator=(const GlProgram&) = delete; 100 Attach(const GlShader & shader)101 void Attach(const GlShader& shader) { glAttachShader(program_, *shader); } 102 Link()103 bool Link() { 104 glLinkProgram(program_); 105 106 GLint link_status = GL_FALSE; 107 glGetProgramiv(program_, GL_LINK_STATUS, &link_status); 108 return link_status; 109 } 110 SetUniform(const char * name,float value)111 void SetUniform(const char* name, float value) const { 112 GLint var = glGetUniformLocation(program_, name); 113 DCHECK_NE(var, -1) << "Failed to locate a uniform " << name; 114 glUniform1f(var, value); 115 } 116 SetUniform(const char * name,float x,float y)117 void SetUniform(const char* name, float x, float y) const { 118 GLint var = glGetUniformLocation(program_, name); 119 DCHECK_NE(var, -1) << "Failed to locate a uniform " << name; 120 glUniform2f(var, x, y); 121 } 122 SetUniform(const char * name,int value)123 void SetUniform(const char* name, int value) const { 124 GLint var = glGetUniformLocation(program_, name); 125 DCHECK_NE(var, -1) << "Failed to locate a uniform " << name; 126 glUniform1i(var, value); 127 } 128 129 GLuint operator*() const { return program_; } 130 131 private: 132 GLuint program_; 133 }; 134 135 template <GLenum BufferType> 136 class GlBuffer { 137 public: GlBuffer()138 GlBuffer() { 139 glGenBuffers(1, &buffer_); 140 glBindBuffer(BufferType, buffer_); 141 } ~GlBuffer()142 ~GlBuffer() { glDeleteBuffers(1, &buffer_); } 143 144 GlBuffer(const GlBuffer&) = delete; 145 GlBuffer& operator=(const GlBuffer&) = delete; 146 147 GLuint operator*() const { return buffer_; } 148 149 private: 150 GLuint buffer_; 151 }; 152 153 using GlVertexBuffer = GlBuffer<GL_ARRAY_BUFFER>; 154 using GlUniformBuffer = GlBuffer<GL_UNIFORM_BUFFER>; 155 using GlElementBuffer = GlBuffer<GL_ELEMENT_ARRAY_BUFFER>; 156 157 class GlVertexArray { 158 public: GlVertexArray()159 GlVertexArray() { 160 glGenVertexArrays(1, &array_); 161 glBindVertexArray(array_); 162 } ~GlVertexArray()163 ~GlVertexArray() { glDeleteVertexArrays(1, &array_); } 164 165 GlVertexArray(const GlVertexArray&) = delete; 166 GlVertexArray& operator=(const GlVertexArray&) = delete; 167 168 GLuint operator*() const { return array_; } 169 170 private: 171 GLuint array_; 172 }; 173 174 class GlVertexArrayAttrib { 175 public: GlVertexArrayAttrib(const GlProgram & program,const char * name)176 GlVertexArrayAttrib(const GlProgram& program, const char* name) { 177 attribute_ = glGetAttribLocation(*program, name); 178 DCHECK_NE(attribute_, -1) << "Failed to locate attribute " << name; 179 glEnableVertexAttribArray(attribute_); 180 } 181 ~GlVertexArrayAttrib()182 ~GlVertexArrayAttrib() { glDisableVertexAttribArray(attribute_); } 183 184 GlVertexArrayAttrib(const GlVertexArrayAttrib&) = delete; 185 GlVertexArrayAttrib& operator=(const GlVertexArrayAttrib&) = delete; 186 187 GLint operator*() const { return attribute_; } 188 189 private: 190 GLint attribute_; 191 }; 192 193 class GlTexture { 194 public: GlTexture()195 GlTexture() { 196 glGenTextures(1, &texture_); 197 glBindTexture(GL_TEXTURE_2D, texture_); 198 } ~GlTexture()199 ~GlTexture() { glDeleteTextures(1, &texture_); } 200 201 GlTexture(const GlTexture&) = delete; 202 GlTexture& operator=(const GlTexture&) = delete; 203 204 GLuint operator*() const { return texture_; } 205 206 private: 207 GLuint texture_; 208 }; 209 210 } // namespace render 211 } // namespace quic_trace 212 213 #endif // THIRD_PARTY_QUIC_TRACE_TOOLS_SDL_UTIL_H_ 214