From 7fc676ed417ab509374f59a1e081605495cadcb3 Mon Sep 17 00:00:00 2001 From: Ivo van Dongen Date: Mon, 19 Feb 2018 18:34:32 +0200 Subject: [android] custom layer example - add error checking to debug issues more easily --- platform/android/src/example_custom_layer.cpp | 170 +++++++++++++++++++++----- 1 file changed, 142 insertions(+), 28 deletions(-) diff --git a/platform/android/src/example_custom_layer.cpp b/platform/android/src/example_custom_layer.cpp index 4467cd5e23..4d1954f095 100644 --- a/platform/android/src/example_custom_layer.cpp +++ b/platform/android/src/example_custom_layer.cpp @@ -2,8 +2,111 @@ #include #include - +#include #include +#include + +// 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"); - - 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); + + // Debug info + int maxAttrib; + GL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttrib)); + mbgl::Log::Info(mbgl::Event::General, "Max vertex attributes: %i", maxAttrib); + + 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; -- cgit v1.2.1