blob: a465418bc66bc4b20e017aaf2691b4536819c078 [file] [log] [blame]
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file contains various utility methods related to SDL and OpenGL,
// primarily RAII wrappers around the C types used by those.
#ifndef THIRD_PARTY_QUIC_TRACE_TOOLS_SDL_UTIL_H_
#define THIRD_PARTY_QUIC_TRACE_TOOLS_SDL_UTIL_H_
#include <GL/glew.h>
#include <SDL.h>
#include <memory>
#include <glog/logging.h>
#include <glog/stl_logging.h>
#include "absl/memory/memory.h"
namespace quic_trace {
namespace render {
// Scoped global initialization for SDL.
class ScopedSDL {
public:
ScopedSDL() { CHECK_EQ(0, SDL_Init(SDL_INIT_VIDEO)); }
ScopedSDL(const ScopedSDL&) = delete;
ScopedSDL& operator=(const ScopedSDL&) = delete;
~ScopedSDL() { SDL_Quit(); }
};
// A helper class to automatically delete SDL objects once they go out of scope.
template <typename T, void (*D)(T*)>
class ScopedSdlType {
public:
ScopedSdlType() : value_(nullptr, D) {}
ScopedSdlType(T* value) : value_(value, D) {}
T* get() const { return value_.get(); }
T* operator*() const { return value_.get(); }
T* operator->() const { return value_.get(); }
private:
std::unique_ptr<T, void (*)(T*)> value_;
};
using ScopedSdlWindow = ScopedSdlType<SDL_Window, SDL_DestroyWindow>;
using ScopedSdlSurface = ScopedSdlType<SDL_Surface, SDL_FreeSurface>;
class OpenGlContext {
public:
OpenGlContext(SDL_Window* window);
~OpenGlContext() { SDL_GL_DeleteContext(context_); }
SDL_GLContext context() const { return context_; }
private:
SDL_GLContext context_;
};
// Utility wrapper around an OpenGL shader.
class GlShader {
public:
GlShader(GLenum type) { shader_ = glCreateShader(type); }
~GlShader() { glDeleteShader(shader_); }
GlShader(const GlShader&) = delete;
GlShader& operator=(const GlShader&) = delete;
bool Compile(const char* source);
std::string GetCompileInfoLog();
void CompileOrDie(const char* source);
GLuint operator*() const { return shader_; }
private:
GLuint shader_;
};
class GlProgram {
public:
GlProgram() { program_ = glCreateProgram(); }
~GlProgram() { glDeleteProgram(program_); }
GlProgram(const GlProgram&) = delete;
GlProgram& operator=(const GlProgram&) = delete;
void Attach(const GlShader& shader) { glAttachShader(program_, *shader); }
bool Link() {
glLinkProgram(program_);
GLint link_status = GL_FALSE;
glGetProgramiv(program_, GL_LINK_STATUS, &link_status);
return link_status;
}
void SetUniform(const char* name, float value) const {
GLint var = glGetUniformLocation(program_, name);
DCHECK_NE(var, -1) << "Failed to locate a uniform " << name;
glUniform1f(var, value);
}
void SetUniform(const char* name, float x, float y) const {
GLint var = glGetUniformLocation(program_, name);
DCHECK_NE(var, -1) << "Failed to locate a uniform " << name;
glUniform2f(var, x, y);
}
void SetUniform(const char* name, int value) const {
GLint var = glGetUniformLocation(program_, name);
DCHECK_NE(var, -1) << "Failed to locate a uniform " << name;
glUniform1i(var, value);
}
GLuint operator*() const { return program_; }
private:
GLuint program_;
};
template <GLenum BufferType>
class GlBuffer {
public:
GlBuffer() {
glGenBuffers(1, &buffer_);
glBindBuffer(BufferType, buffer_);
}
~GlBuffer() { glDeleteBuffers(1, &buffer_); }
GlBuffer(const GlBuffer&) = delete;
GlBuffer& operator=(const GlBuffer&) = delete;
GLuint operator*() const { return buffer_; }
private:
GLuint buffer_;
};
using GlVertexBuffer = GlBuffer<GL_ARRAY_BUFFER>;
using GlUniformBuffer = GlBuffer<GL_UNIFORM_BUFFER>;
using GlElementBuffer = GlBuffer<GL_ELEMENT_ARRAY_BUFFER>;
class GlVertexArray {
public:
GlVertexArray() {
glGenVertexArrays(1, &array_);
glBindVertexArray(array_);
}
~GlVertexArray() { glDeleteVertexArrays(1, &array_); }
GlVertexArray(const GlVertexArray&) = delete;
GlVertexArray& operator=(const GlVertexArray&) = delete;
GLuint operator*() const { return array_; }
private:
GLuint array_;
};
class GlVertexArrayAttrib {
public:
GlVertexArrayAttrib(const GlProgram& program, const char* name) {
attribute_ = glGetAttribLocation(*program, name);
DCHECK_NE(attribute_, -1) << "Failed to locate attribute " << name;
glEnableVertexAttribArray(attribute_);
}
~GlVertexArrayAttrib() { glDisableVertexAttribArray(attribute_); }
GlVertexArrayAttrib(const GlVertexArrayAttrib&) = delete;
GlVertexArrayAttrib& operator=(const GlVertexArrayAttrib&) = delete;
GLint operator*() const { return attribute_; }
private:
GLint attribute_;
};
class GlTexture {
public:
GlTexture() {
glGenTextures(1, &texture_);
glBindTexture(GL_TEXTURE_2D, texture_);
}
~GlTexture() { glDeleteTextures(1, &texture_); }
GlTexture(const GlTexture&) = delete;
GlTexture& operator=(const GlTexture&) = delete;
GLuint operator*() const { return texture_; }
private:
GLuint texture_;
};
} // namespace render
} // namespace quic_trace
#endif // THIRD_PARTY_QUIC_TRACE_TOOLS_SDL_UTIL_H_