[android] custom layer example - add error checking to debug issues more easily
This commit is contained in:
committed by
Ivo van Dongen
parent
5fc3d4ab1e
commit
9a3eb808cf
@@ -2,8 +2,111 @@
|
||||
#include <GLES2/gl2.h>
|
||||
|
||||
#include <mbgl/util/logging.hpp>
|
||||
|
||||
#include <mbgl/util/string.hpp>
|
||||
#include <mbgl/style/layers/custom_layer.hpp>
|
||||
#include <vector>
|
||||
|
||||
// DEBUGGING
|
||||
|
||||
const char* stringFromError(GLenum err) {
|
||||
switch (err) {
|
||||
case GL_INVALID_ENUM:
|
||||
return "GL_INVALID_ENUM";
|
||||
|
||||
case GL_INVALID_VALUE:
|
||||
return "GL_INVALID_VALUE";
|
||||
|
||||
case GL_INVALID_OPERATION:
|
||||
return "GL_INVALID_OPERATION";
|
||||
|
||||
case GL_INVALID_FRAMEBUFFER_OPERATION:
|
||||
return "GL_INVALID_FRAMEBUFFER_OPERATION";
|
||||
|
||||
case GL_OUT_OF_MEMORY:
|
||||
return "GL_OUT_OF_MEMORY";
|
||||
|
||||
#ifdef GL_TABLE_TOO_LARGE
|
||||
case GL_TABLE_TOO_LARGE:
|
||||
return "GL_TABLE_TOO_LARGE";
|
||||
#endif
|
||||
|
||||
#ifdef GL_STACK_OVERFLOW
|
||||
case GL_STACK_OVERFLOW:
|
||||
return "GL_STACK_OVERFLOW";
|
||||
#endif
|
||||
|
||||
#ifdef GL_STACK_UNDERFLOW
|
||||
case GL_STACK_UNDERFLOW:
|
||||
return "GL_STACK_UNDERFLOW";
|
||||
#endif
|
||||
|
||||
#ifdef GL_CONTEXT_LOST
|
||||
case GL_CONTEXT_LOST:
|
||||
return "GL_CONTEXT_LOST";
|
||||
#endif
|
||||
|
||||
default:
|
||||
return "GL_UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
struct Error : std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
};
|
||||
|
||||
void checkError(const char *cmd, const char *file, int line) {
|
||||
|
||||
GLenum err = GL_NO_ERROR;
|
||||
if ((err = glGetError()) != GL_NO_ERROR) {
|
||||
std::string message = std::string(cmd) + ": Error " + stringFromError(err);
|
||||
|
||||
// Check for further errors
|
||||
while ((err = glGetError()) != GL_NO_ERROR) {
|
||||
message += ", ";
|
||||
message += stringFromError(err);
|
||||
}
|
||||
|
||||
mbgl::Log::Error(mbgl::Event::General, message + " at " + file + ":" + mbgl::util::toString(line));
|
||||
throw Error(message + " at " + file + ":" + mbgl::util::toString(line));
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define GL_CHECK_ERROR(cmd) ([&]() { struct __MBGL_C_E { ~__MBGL_C_E() noexcept(false) { checkError(#cmd, __FILE__, __LINE__); } } __MBGL_C_E; return cmd; }())
|
||||
#else
|
||||
#define GL_CHECK_ERROR(cmd) (cmd)
|
||||
#endif
|
||||
|
||||
void checkLinkStatus(GLuint program) {
|
||||
GLint isLinked = 0;
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &isLinked);
|
||||
if (isLinked == GL_FALSE) {
|
||||
GLint maxLength = 0;
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &maxLength);
|
||||
GLchar infoLog[maxLength];
|
||||
glGetProgramInfoLog(program, maxLength, &maxLength, &infoLog[0]);
|
||||
mbgl::Log::Info(mbgl::Event::General, &infoLog[0]);
|
||||
throw Error(infoLog);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void checkCompileStatus(GLuint shader) {
|
||||
GLint isCompiled = 0;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &isCompiled);
|
||||
if (isCompiled == GL_FALSE) {
|
||||
GLint maxLength = 0;
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &maxLength);
|
||||
|
||||
// The maxLength includes the NULL character
|
||||
GLchar errorLog[maxLength];
|
||||
glGetShaderInfoLog(shader, maxLength, &maxLength, &errorLog[0]);
|
||||
mbgl::Log::Error(mbgl::Event::General, &errorLog[0]);
|
||||
throw Error(errorLog);
|
||||
}
|
||||
}
|
||||
|
||||
// /DEBUGGING
|
||||
|
||||
static const GLchar * vertexShaderSource = "attribute vec2 a_pos; void main() { gl_Position = vec4(a_pos, 0, 1); }";
|
||||
static const GLchar * fragmentShaderSource = "uniform highp vec4 fill_color; void main() { gl_FragColor = fill_color; }";
|
||||
@@ -24,37 +127,48 @@ public:
|
||||
|
||||
void initialize() {
|
||||
mbgl::Log::Info(mbgl::Event::General, "Initialize");
|
||||
program = glCreateProgram();
|
||||
vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr);
|
||||
glCompileShader(vertexShader);
|
||||
glAttachShader(program, vertexShader);
|
||||
glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr);
|
||||
glCompileShader(fragmentShader);
|
||||
glAttachShader(program, fragmentShader);
|
||||
glLinkProgram(program);
|
||||
a_pos = glGetAttribLocation(program, "a_pos");
|
||||
fill_color = glGetUniformLocation(program, "fill_color");
|
||||
// Debug info
|
||||
int maxAttrib;
|
||||
GL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttrib));
|
||||
mbgl::Log::Info(mbgl::Event::General, "Max vertex attributes: %i", maxAttrib);
|
||||
|
||||
GLfloat background[] = { -1,-1, 1,-1, -1,1, 1,1 };
|
||||
glGenBuffers(1, &buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), background, GL_STATIC_DRAW);
|
||||
program = GL_CHECK_ERROR(glCreateProgram());
|
||||
vertexShader = GL_CHECK_ERROR(glCreateShader(GL_VERTEX_SHADER));
|
||||
fragmentShader = GL_CHECK_ERROR(glCreateShader(GL_FRAGMENT_SHADER));
|
||||
|
||||
GL_CHECK_ERROR(glShaderSource(vertexShader, 1, &vertexShaderSource, nullptr));
|
||||
GL_CHECK_ERROR(glCompileShader(vertexShader));
|
||||
checkCompileStatus(vertexShader);
|
||||
GL_CHECK_ERROR(glAttachShader(program, vertexShader));
|
||||
GL_CHECK_ERROR(glShaderSource(fragmentShader, 1, &fragmentShaderSource, nullptr));
|
||||
GL_CHECK_ERROR(glCompileShader(fragmentShader));
|
||||
checkCompileStatus(fragmentShader);
|
||||
GL_CHECK_ERROR(glAttachShader(program, fragmentShader));
|
||||
GL_CHECK_ERROR(glLinkProgram(program));
|
||||
checkLinkStatus(program);
|
||||
|
||||
a_pos = GL_CHECK_ERROR(glGetAttribLocation(program, "a_pos"));
|
||||
fill_color = GL_CHECK_ERROR(glGetUniformLocation(program, "fill_color"));
|
||||
|
||||
GLfloat background[] = { -1, -1, 1, -1, -1, 1, 1, 1 };
|
||||
GL_CHECK_ERROR(glGenBuffers(1, &buffer));
|
||||
GL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, buffer));
|
||||
GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), background, GL_STATIC_DRAW));
|
||||
}
|
||||
|
||||
void render() {
|
||||
mbgl::Log::Info(mbgl::Event::General, "Render");
|
||||
glUseProgram(program);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
glEnableVertexAttribArray(a_pos);
|
||||
glVertexAttribPointer(a_pos, 2, GL_FLOAT, GL_FALSE, 0, NULL);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glUniform4fv(fill_color, 1, color);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
GL_CHECK_ERROR(glUseProgram(program));
|
||||
GL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, buffer));
|
||||
GL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
|
||||
GL_CHECK_ERROR(glVertexAttribPointer(a_pos, 2, GL_FLOAT, GL_FALSE, 0, NULL));
|
||||
GL_CHECK_ERROR(glDisable(GL_STENCIL_TEST));
|
||||
GL_CHECK_ERROR(glDisable(GL_DEPTH_TEST));
|
||||
GL_CHECK_ERROR(glUniform4fv(fill_color, 1, color));
|
||||
GL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
|
||||
|
||||
}
|
||||
|
||||
GLuint program = 0;
|
||||
|
||||
Reference in New Issue
Block a user