From 69fa8fe3c0cc2a53b9ba4bb9d31cdabd2cbd373e Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Sun, 14 Feb 2016 17:55:39 +0200 Subject: [PATCH] [gl] Added mbgl::gl::ProgramHolder --- src/mbgl/gl/gl_object_store.cpp | 15 ++++++++++++++- src/mbgl/gl/gl_object_store.hpp | 29 ++++++++++++++++++++++++++-- src/mbgl/shader/shader.cpp | 34 ++++++++++++++------------------- src/mbgl/shader/shader.hpp | 11 ++++------- 4 files changed, 59 insertions(+), 30 deletions(-) diff --git a/src/mbgl/gl/gl_object_store.cpp b/src/mbgl/gl/gl_object_store.cpp index a830b6d73..52cf03d04 100644 --- a/src/mbgl/gl/gl_object_store.cpp +++ b/src/mbgl/gl/gl_object_store.cpp @@ -1,5 +1,5 @@ #include - +#include #include #include #include @@ -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); diff --git a/src/mbgl/gl/gl_object_store.hpp b/src/mbgl/gl/gl_object_store.hpp index ac8ddd274..be2572866 100644 --- a/src/mbgl/gl/gl_object_store.hpp +++ b/src/mbgl/gl/gl_object_store.hpp @@ -4,15 +4,40 @@ #include #include +#include #include 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); diff --git a/src/mbgl/shader/shader.cpp b/src/mbgl/shader/shader.cpp index fbf758d3b..c0757b749 100644 --- a/src/mbgl/shader/shader.cpp +++ b/src/mbgl/shader/shader.cpp @@ -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(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)); diff --git a/src/mbgl/shader/shader.hpp b/src/mbgl/shader/shader.hpp index 0570b1c64..b3d694a04 100644 --- a/src/mbgl/shader/shader.hpp +++ b/src/mbgl/shader/shader.hpp @@ -2,12 +2,9 @@ #define MBGL_RENDERER_SHADER #include +#include #include -#include -#include -#include - 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; };