[gl] Added mbgl::gl::ProgramHolder

This commit is contained in:
Bruno de Oliveira Abinader
2016-02-14 17:55:39 +02:00
parent bfafc360a7
commit 69fa8fe3c0
4 changed files with 59 additions and 30 deletions

View File

@@ -1,5 +1,5 @@
#include <mbgl/gl/gl_object_store.hpp>
#include <mbgl/util/thread_context.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/geometry/vao.hpp>
#include <mbgl/gl/gl.hpp>
@@ -9,6 +9,19 @@
namespace mbgl {
namespace gl {
void ProgramHolder::create() {
if (id) return;
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
id = MBGL_CHECK_ERROR(glCreateProgram());
}
void ProgramHolder::reset() {
if (!id) return;
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
MBGL_CHECK_ERROR(glDeleteProgram(id));
id = 0;
}
void GLObjectStore::abandonVAO(GLuint vao) {
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
abandonedVAOs.emplace_back(vao);

View File

@@ -4,15 +4,40 @@
#include <mbgl/gl/gl.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <memory>
#include <vector>
namespace mbgl {
namespace gl {
class GLHolder : private util::noncopyable {
public:
GLHolder() {}
GLHolder(GLHolder&& o) noexcept : id(o.id) { o.id = 0; }
GLHolder& operator=(GLHolder&& o) noexcept { id = o.id; o.id = 0; return *this; }
explicit operator bool() const { return id; }
GLuint getID() const { return id; }
protected:
GLuint id = 0;
};
class ProgramHolder : public GLHolder {
public:
ProgramHolder() = default;
~ProgramHolder() { reset(); }
ProgramHolder(ProgramHolder&& o) noexcept : GLHolder(std::move(o)) {}
ProgramHolder& operator=(ProgramHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; }
void create();
void reset();
};
class GLObjectStore : private util::noncopyable {
public:
GLObjectStore() = default;
// Mark OpenGL objects for deletion
void abandonVAO(GLuint vao);
void abandonBuffer(GLuint buffer);

View File

@@ -15,16 +15,14 @@ using namespace mbgl;
Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSource)
: name(name_)
, program(0)
{
util::stopwatch stopwatch("shader compilation", Event::Shader);
program = MBGL_CHECK_ERROR(glCreateProgram());
program.create();
if (!compileShader(&vertShader, GL_VERTEX_SHADER, &vertSource)) {
Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertSource);
MBGL_CHECK_ERROR(glDeleteProgram(program));
program = 0;
program.reset();
throw util::ShaderException(std::string { "Vertex shader " } + name + " failed to compile");
}
@@ -32,27 +30,26 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo
Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragSource);
MBGL_CHECK_ERROR(glDeleteShader(vertShader));
vertShader = 0;
MBGL_CHECK_ERROR(glDeleteProgram(program));
program = 0;
program.reset();
throw util::ShaderException(std::string { "Fragment shader " } + name + " failed to compile");
}
// Attach shaders
MBGL_CHECK_ERROR(glAttachShader(program, vertShader));
MBGL_CHECK_ERROR(glAttachShader(program, fragShader));
MBGL_CHECK_ERROR(glAttachShader(program.getID(), vertexShader));
MBGL_CHECK_ERROR(glAttachShader(program.getID(), fragmentShader));
{
// Link program
GLint status;
MBGL_CHECK_ERROR(glLinkProgram(program));
MBGL_CHECK_ERROR(glLinkProgram(program.getID()));
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status));
MBGL_CHECK_ERROR(glGetProgramiv(program.getID(), GL_LINK_STATUS, &status));
if (status == 0) {
GLint logLength;
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength));
MBGL_CHECK_ERROR(glGetProgramiv(program.getID(), GL_INFO_LOG_LENGTH, &logLength));
const auto log = std::make_unique<GLchar[]>(logLength);
if (logLength > 0) {
MBGL_CHECK_ERROR(glGetProgramInfoLog(program, logLength, &logLength, log.get()));
MBGL_CHECK_ERROR(glGetProgramInfoLog(program.getID(), logLength, &logLength, log.get()));
Log::Error(Event::Shader, "Program failed to link: %s", log.get());
}
@@ -60,13 +57,12 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo
vertShader = 0;
MBGL_CHECK_ERROR(glDeleteShader(fragShader));
fragShader = 0;
MBGL_CHECK_ERROR(glDeleteProgram(program));
program = 0;
throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get());
program.reset();
throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get());
}
}
a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program, "a_pos"));
a_pos = MBGL_CHECK_ERROR(glGetAttribLocation(program.getID(), "a_pos"));
}
@@ -107,10 +103,8 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source[])
Shader::~Shader() {
if (program) {
MBGL_CHECK_ERROR(glDetachShader(program, vertShader));
MBGL_CHECK_ERROR(glDetachShader(program, fragShader));
MBGL_CHECK_ERROR(glDeleteProgram(program));
program = 0;
MBGL_CHECK_ERROR(glDetachShader(program.getID(), vertexShader));
MBGL_CHECK_ERROR(glDetachShader(program.getID(), fragmentShader));
MBGL_CHECK_ERROR(glDeleteShader(vertShader));
vertShader = 0;
MBGL_CHECK_ERROR(glDeleteShader(fragShader));

View File

@@ -2,12 +2,9 @@
#define MBGL_RENDERER_SHADER
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/gl_object_store.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <cstdint>
#include <array>
#include <string>
namespace mbgl {
class Shader : private util::noncopyable {
@@ -16,10 +13,9 @@ public:
~Shader();
const GLchar *name;
GLuint program;
inline GLuint getID() const {
return program;
inline const GLuint& getID() const {
return program.getID();
}
virtual void bind(GLbyte *offset) = 0;
@@ -30,6 +26,7 @@ protected:
private:
bool compileShader(GLuint *shader, GLenum type, const GLchar *source[]);
gl::ProgramHolder program;
GLuint vertShader = 0;
GLuint fragShader = 0;
};