summaryrefslogtreecommitdiff
path: root/src/mbgl/gl
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-09-30 12:20:29 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-10-05 10:52:19 -0700
commit73334ac8fa330af05dd91906a4e5d1bbda7d5c34 (patch)
treeaeba3681352926e5837d2d68b70a08f52d6ed026 /src/mbgl/gl
parent7a3bef091e7390fa57bf33f1a704c893768b5625 (diff)
downloadqtlocation-mapboxgl-73334ac8fa330af05dd91906a4e5d1bbda7d5c34.tar.gz
[core] Move shader and uniform to gl directory
Diffstat (limited to 'src/mbgl/gl')
-rw-r--r--src/mbgl/gl/shader.cpp116
-rw-r--r--src/mbgl/gl/shader.hpp51
-rw-r--r--src/mbgl/gl/uniform.cpp57
-rw-r--r--src/mbgl/gl/uniform.hpp61
-rw-r--r--src/mbgl/gl/vao.cpp4
-rw-r--r--src/mbgl/gl/vao.hpp6
6 files changed, 290 insertions, 5 deletions
diff --git a/src/mbgl/gl/shader.cpp b/src/mbgl/gl/shader.cpp
new file mode 100644
index 0000000000..5b3712e80d
--- /dev/null
+++ b/src/mbgl/gl/shader.cpp
@@ -0,0 +1,116 @@
+#include <mbgl/gl/shader.hpp>
+#include <mbgl/gl/gl.hpp>
+#include <mbgl/gl/context.hpp>
+#include <mbgl/util/stopwatch.hpp>
+#include <mbgl/util/exception.hpp>
+#include <mbgl/platform/log.hpp>
+#include <mbgl/platform/platform.hpp>
+
+#include <cstring>
+#include <cassert>
+#include <iostream>
+#include <string>
+#include <fstream>
+#include <cstdio>
+#include <cassert>
+
+namespace mbgl {
+namespace gl {
+
+Shader::Shader(const char* name_,
+ const char* vertexSource,
+ const char* fragmentSource,
+ Context& context,
+ Defines defines)
+ : name(name_),
+ program(context.createProgram()),
+ vertexShader(context.createVertexShader()),
+ fragmentShader(context.createFragmentShader()) {
+ util::stopwatch stopwatch("shader compilation", Event::Shader);
+
+ if (!compileShader(vertexShader, vertexSource)) {
+ Log::Error(Event::Shader, "Vertex shader %s failed to compile: %s", name, vertexSource);
+ throw util::ShaderException(std::string { "Vertex shader " } + name + " failed to compile");
+ }
+
+ std::string fragment(fragmentSource);
+ if (defines & Defines::Overdraw) {
+ assert(fragment.find("#ifdef OVERDRAW_INSPECTOR") != std::string::npos);
+ fragment.replace(fragment.find_first_of('\n'), 1, "\n#define OVERDRAW_INSPECTOR\n");
+ }
+
+ if (!compileShader(fragmentShader, fragment.c_str())) {
+ Log::Error(Event::Shader, "Fragment shader %s failed to compile: %s", name, fragmentSource);
+ throw util::ShaderException(std::string { "Fragment shader " } + name + " failed to compile");
+ }
+
+ // Attach shaders
+ MBGL_CHECK_ERROR(glAttachShader(program.get(), vertexShader.get()));
+ MBGL_CHECK_ERROR(glAttachShader(program.get(), fragmentShader.get()));
+
+ // Bind attribute variables
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_pos, "a_pos"));
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_extrude, "a_extrude"));
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_offset, "a_offset"));
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_data, "a_data"));
+ MBGL_CHECK_ERROR(glBindAttribLocation(program.get(), a_texture_pos, "a_texture_pos"));
+
+ // Link program
+ GLint status;
+ MBGL_CHECK_ERROR(glLinkProgram(program.get()));
+
+ MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_LINK_STATUS, &status));
+ if (status == 0) {
+ GLint logLength;
+ MBGL_CHECK_ERROR(glGetProgramiv(program.get(), GL_INFO_LOG_LENGTH, &logLength));
+ const auto log = std::make_unique<GLchar[]>(logLength);
+ if (logLength > 0) {
+ MBGL_CHECK_ERROR(glGetProgramInfoLog(program.get(), logLength, &logLength, log.get()));
+ Log::Error(Event::Shader, "Program failed to link: %s", log.get());
+ }
+ throw util::ShaderException(std::string { "Program " } + name + " failed to link: " + log.get());
+ }
+}
+
+bool Shader::compileShader(UniqueShader& shader, const GLchar *source) {
+ GLint status = 0;
+
+ const GLsizei lengths = static_cast<GLsizei>(std::strlen(source));
+ MBGL_CHECK_ERROR(glShaderSource(shader.get(), 1, &source, &lengths));
+
+ MBGL_CHECK_ERROR(glCompileShader(shader.get()));
+
+ MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_COMPILE_STATUS, &status));
+ if (status == 0) {
+ GLint logLength;
+ MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_INFO_LOG_LENGTH, &logLength));
+ if (logLength > 0) {
+ const auto log = std::make_unique<GLchar[]>(logLength);
+ MBGL_CHECK_ERROR(glGetShaderInfoLog(shader.get(), logLength, &logLength, log.get()));
+ Log::Error(Event::Shader, "Shader failed to compile: %s", log.get());
+ }
+ return false;
+ }
+
+ MBGL_CHECK_ERROR(glGetShaderiv(shader.get(), GL_COMPILE_STATUS, &status));
+ if (status == GL_FALSE) {
+ Log::Error(Event::Shader, "Shader %s failed to compile.", name);
+ return false;
+ }
+
+ return true;
+}
+
+Shader::~Shader() {
+ if (program.get()) {
+ MBGL_CHECK_ERROR(glDetachShader(program.get(), vertexShader.get()));
+ MBGL_CHECK_ERROR(glDetachShader(program.get(), fragmentShader.get()));
+ }
+}
+
+UniformLocation Shader::getUniformLocation(const char* uniform) const {
+ return MBGL_CHECK_ERROR(glGetUniformLocation(program.get(), uniform));
+}
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/shader.hpp b/src/mbgl/gl/shader.hpp
new file mode 100644
index 0000000000..f73400bc15
--- /dev/null
+++ b/src/mbgl/gl/shader.hpp
@@ -0,0 +1,51 @@
+#pragma once
+
+#include <mbgl/gl/types.hpp>
+#include <mbgl/gl/object.hpp>
+#include <mbgl/util/noncopyable.hpp>
+
+namespace mbgl {
+namespace gl {
+
+class Context;
+
+class Shader : private util::noncopyable {
+public:
+ ~Shader();
+ const char* name;
+
+ ProgramID getID() const {
+ return program.get();
+ }
+
+ UniformLocation getUniformLocation(const char* uniform) const;
+
+ enum Defines : bool {
+ None = false,
+ Overdraw = true,
+ };
+
+protected:
+ Shader(const char* name_,
+ const char* vertex,
+ const char* fragment,
+ Context&,
+ Defines defines = Defines::None);
+
+public:
+ static constexpr AttributeLocation a_pos = 0;
+ static constexpr AttributeLocation a_extrude = 1;
+ static constexpr AttributeLocation a_offset = 2;
+ static constexpr AttributeLocation a_data = 3;
+ static constexpr AttributeLocation a_texture_pos = 4;
+
+private:
+ bool compileShader(UniqueShader&, const char *source);
+
+ UniqueProgram program;
+ UniqueShader vertexShader;
+ UniqueShader fragmentShader;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/uniform.cpp b/src/mbgl/gl/uniform.cpp
new file mode 100644
index 0000000000..07a27963d9
--- /dev/null
+++ b/src/mbgl/gl/uniform.cpp
@@ -0,0 +1,57 @@
+#include <mbgl/gl/uniform.hpp>
+#include <mbgl/gl/gl.hpp>
+#include <mbgl/util/color.hpp>
+
+namespace mbgl {
+namespace gl {
+
+template <>
+void Uniform<float>::bind(const float& t) {
+ MBGL_CHECK_ERROR(glUniform1f(location, t));
+}
+
+template <>
+void Uniform<int32_t>::bind(const int32_t& t) {
+ MBGL_CHECK_ERROR(glUniform1i(location, t));
+}
+
+template <>
+void Uniform<std::array<float, 2>>::bind(const std::array<float, 2>& t) {
+ MBGL_CHECK_ERROR(glUniform2fv(location, 1, t.data()));
+}
+
+template <>
+void Uniform<std::array<float, 3>>::bind(const std::array<float, 3>& t) {
+ MBGL_CHECK_ERROR(glUniform3fv(location, 1, t.data()));
+}
+
+template <>
+void Uniform<std::array<float, 4>>::bind(const std::array<float, 4>& t) {
+ MBGL_CHECK_ERROR(glUniform4fv(location, 1, t.data()));
+}
+
+template <>
+void Uniform<Color>::bind(const Color& t) {
+ std::array<float, 4> a = {{ t.r, t.g, t.b, t.a }};
+ MBGL_CHECK_ERROR(glUniform4fv(location, 1, a.data()));
+}
+
+template <>
+void UniformMatrix<2>::bind(const std::array<float, 4>& t) {
+ MBGL_CHECK_ERROR(glUniformMatrix2fv(location, 1, GL_FALSE, t.data()));
+}
+
+template <>
+void UniformMatrix<3>::bind(const std::array<float, 9>& t) {
+ MBGL_CHECK_ERROR(glUniformMatrix3fv(location, 1, GL_FALSE, t.data()));
+}
+
+template <>
+void UniformMatrix<4>::bind(const std::array<float, 16>& t) {
+ MBGL_CHECK_ERROR(glUniformMatrix4fv(location, 1, GL_FALSE, t.data()));
+}
+
+// Add more as needed.
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/uniform.hpp b/src/mbgl/gl/uniform.hpp
new file mode 100644
index 0000000000..5af781043d
--- /dev/null
+++ b/src/mbgl/gl/uniform.hpp
@@ -0,0 +1,61 @@
+#pragma once
+
+#include <mbgl/gl/shader.hpp>
+
+#include <array>
+
+namespace mbgl {
+namespace gl {
+
+template <typename T>
+class Uniform {
+public:
+ Uniform(const char* name, const Shader& shader)
+ : current(), location(shader.getUniformLocation(name)) {
+ }
+
+ void operator=(const T& t) {
+ if (current != t) {
+ current = t;
+ bind(t);
+ }
+ }
+
+private:
+ void bind(const T&);
+
+ T current;
+ UniformLocation location;
+};
+
+template <size_t C, size_t R = C>
+class UniformMatrix {
+public:
+ typedef std::array<float, C*R> T;
+
+ UniformMatrix(const char* name, const Shader& shader)
+ : current(), location(shader.getUniformLocation(name)) {
+ }
+
+ void operator=(const std::array<double, C*R>& t) {
+ bool dirty = false;
+ for (unsigned int i = 0; i < C*R; i++) {
+ if (current[i] != t[i]) {
+ current[i] = t[i];
+ dirty = true;
+ }
+ }
+ if (dirty) {
+ bind(current);
+ }
+ }
+
+private:
+ void bind(const T&);
+
+ T current;
+ UniformLocation location;
+};
+
+} // namespace gl
+} // namespace mbgl
diff --git a/src/mbgl/gl/vao.cpp b/src/mbgl/gl/vao.cpp
index 527dd214fb..26a03a8a16 100644
--- a/src/mbgl/gl/vao.cpp
+++ b/src/mbgl/gl/vao.cpp
@@ -30,7 +30,7 @@ void VertexArrayObject::bindVertexArrayObject(gl::Context& context) {
context.vertexArrayObject = *vertexArray;
}
-void VertexArrayObject::verifyBinding(Shader& shader,
+void VertexArrayObject::verifyBinding(gl::Shader& shader,
gl::BufferID vertexBuffer,
gl::BufferID elementsBuffer,
int8_t* offset) {
@@ -47,7 +47,7 @@ void VertexArrayObject::verifyBinding(Shader& shader,
}
}
-void VertexArrayObject::storeBinding(Shader& shader,
+void VertexArrayObject::storeBinding(gl::Shader& shader,
gl::BufferID vertexBuffer,
gl::BufferID elementsBuffer,
int8_t* offset) {
diff --git a/src/mbgl/gl/vao.hpp b/src/mbgl/gl/vao.hpp
index c2e3470367..bedc3abbc7 100644
--- a/src/mbgl/gl/vao.hpp
+++ b/src/mbgl/gl/vao.hpp
@@ -1,6 +1,6 @@
#pragma once
-#include <mbgl/shader/shader.hpp>
+#include <mbgl/gl/shader.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/vertex_buffer.hpp>
#include <mbgl/util/noncopyable.hpp>
@@ -57,11 +57,11 @@ public:
private:
void bindVertexArrayObject(gl::Context&);
- void storeBinding(Shader& shader,
+ void storeBinding(gl::Shader& shader,
gl::BufferID vertexBuffer,
gl::BufferID elementsBuffer,
int8_t* offset);
- void verifyBinding(Shader& shader,
+ void verifyBinding(gl::Shader& shader,
gl::BufferID vertexBuffer,
gl::BufferID elementsBuffer,
int8_t* offset);