summaryrefslogtreecommitdiff
path: root/platform/android/src/example_custom_layer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/android/src/example_custom_layer.cpp')
-rw-r--r--platform/android/src/example_custom_layer.cpp200
1 files changed, 158 insertions, 42 deletions
diff --git a/platform/android/src/example_custom_layer.cpp b/platform/android/src/example_custom_layer.cpp
index 1ed68d0835..f7b425c40a 100644
--- a/platform/android/src/example_custom_layer.cpp
+++ b/platform/android/src/example_custom_layer.cpp
@@ -1,17 +1,121 @@
#include <jni.h>
#include <GLES2/gl2.h>
+#include <sstream>
+#include <android/log.h>
+#include <mbgl/style/layers/custom_layer.hpp>
-#include <mbgl/util/logging.hpp>
+// DEBUGGING
-#include <mbgl/style/layers/custom_layer.hpp>
+const char* LOG_TAG = "Custom Layer Example";
+
+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::ostringstream message;
+ message << cmd << ": Error " << stringFromError(err);
+
+ // Check for further errors
+ while ((err = glGetError()) != GL_NO_ERROR) {
+ message << ", " << stringFromError(err);
+ }
+
+ message << " at " << file << ":" << line;
+ __android_log_write(ANDROID_LOG_ERROR, LOG_TAG, message.str().c_str());
+ throw Error(message.str());
+ }
+}
+
+#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]);
+ __android_log_write(ANDROID_LOG_ERROR, LOG_TAG, &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]);
+ __android_log_write(ANDROID_LOG_ERROR, LOG_TAG, &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 vec4 fill_color; void main() { gl_FragColor = fill_color; }";
+static const GLchar * fragmentShaderSource = "uniform highp vec4 fill_color; void main() { gl_FragColor = fill_color; }";
class ExampleCustomLayer {
public:
~ExampleCustomLayer() {
- mbgl::Log::Info(mbgl::Event::General, "~ExampleCustomLayer");
+ __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "~ExampleCustomLayer");
if (program) {
glDeleteBuffers(1, &buffer);
glDetachShader(program, vertexShader);
@@ -23,38 +127,49 @@ 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);
+ __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "Initialize");
+
+ // Debug info
+ int maxAttrib;
+ GL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttrib));
+ __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "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);
+ __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "Render");
+
+ 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;
@@ -70,12 +185,12 @@ public:
GLfloat ExampleCustomLayer::color[] = { 0.0f, 1.0f, 0.0f, 1.0f };
jlong JNICALL nativeCreateContext(JNIEnv*, jobject) {
- mbgl::Log::Info(mbgl::Event::General, "nativeCreateContext");
+ __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeCreateContext");
return reinterpret_cast<jlong>(new ExampleCustomLayer());
}
void JNICALL nativeSetColor(JNIEnv*, jobject, jfloat red, jfloat green, jfloat blue, jfloat alpha) {
- mbgl::Log::Info(mbgl::Event::General, "nativeSetColor: %.2f, %.2f, %.2f, %.2f", red, green, blue, alpha);
+ __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "nativeSetColor: %.2f, %.2f, %.2f, %.2f", red, green, blue, alpha);
ExampleCustomLayer::color[0] = red;
ExampleCustomLayer::color[1] = green;
ExampleCustomLayer::color[2] = blue;
@@ -83,26 +198,27 @@ void JNICALL nativeSetColor(JNIEnv*, jobject, jfloat red, jfloat green, jfloat b
}
void nativeInitialize(void *context) {
- mbgl::Log::Info(mbgl::Event::General, "nativeInitialize");
+ __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeInitialize");
reinterpret_cast<ExampleCustomLayer*>(context)->initialize();
}
void nativeRender(void *context, const mbgl::style::CustomLayerRenderParameters& /*parameters*/) {
- mbgl::Log::Info(mbgl::Event::General, "nativeRender");
+ __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeRender");
reinterpret_cast<ExampleCustomLayer*>(context)->render();
}
void nativeContextLost(void */*context*/) {
- mbgl::Log::Info(mbgl::Event::General, "nativeContextLost");
+ __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeContextLost");
}
-void nativeDenitialize(void *context) {
- mbgl::Log::Info(mbgl::Event::General, "nativeDeinitialize");
+void nativeDeinitialize(void *context) {
+ __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeDeinitialize");
delete reinterpret_cast<ExampleCustomLayer*>(context);
}
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
- mbgl::Log::Info(mbgl::Event::General, "OnLoad");
+ __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "OnLoad");
+
JNIEnv *env = nullptr;
vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6);
@@ -132,7 +248,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
env->SetStaticLongField(customLayerClass,
env->GetStaticFieldID(customLayerClass, "DeinitializeFunction", "J"),
- reinterpret_cast<jlong>(nativeDenitialize));
+ reinterpret_cast<jlong>(nativeDeinitialize));
return JNI_VERSION_1_6;
}