summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2015-05-12 14:35:26 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2015-05-13 19:01:58 -0700
commita2344c36c372445ee230832a0b742ac5ee739eb1 (patch)
treec733e1fff4d4b7e7a914d19f0838aeaaf1ca3aa7
parent0f7c6b0b52ac76db3bb0064b4230229d9def62a8 (diff)
downloadqtlocation-mapboxgl-a2344c36c372445ee230832a0b742ac5ee739eb1.tar.gz
Extensible GL extension support
-rw-r--r--android/cpp/native_map_view.cpp87
-rw-r--r--include/mbgl/platform/gl.hpp147
-rw-r--r--platform/default/glfw_view.cpp81
-rw-r--r--platform/default/headless_view.cpp57
-rw-r--r--platform/ios/MGLMapView.mm24
-rw-r--r--src/mbgl/geometry/vao.cpp42
-rw-r--r--src/mbgl/geometry/vao.hpp3
-rw-r--r--src/mbgl/gl/debugging.cpp195
-rw-r--r--src/mbgl/gl/debugging.hpp21
-rw-r--r--src/mbgl/map/environment.cpp5
-rw-r--r--src/mbgl/map/source.cpp3
-rw-r--r--src/mbgl/platform/gl.cpp78
-rw-r--r--src/mbgl/renderer/painter.cpp36
-rw-r--r--src/mbgl/renderer/painter_clipping.cpp3
-rw-r--r--src/mbgl/renderer/painter_debug.cpp9
15 files changed, 352 insertions, 439 deletions
diff --git a/android/cpp/native_map_view.cpp b/android/cpp/native_map_view.cpp
index 4a2e4099a3..4cd1669ef9 100644
--- a/android/cpp/native_map_view.cpp
+++ b/android/cpp/native_map_view.cpp
@@ -585,90 +585,9 @@ EGLConfig NativeMapView::chooseConfig(const EGLConfig configs[], EGLint numConfi
}
void loadExtensions() {
- const GLubyte *str = glGetString(GL_EXTENSIONS);
- if (str == nullptr) {
- mbgl::Log::Error(mbgl::Event::OpenGL, "glGetString(GL_EXTENSIONS) returned error %d",
- glGetError());
- return;
- }
-
- std::string extensions(reinterpret_cast<const char *>(str));
-
- if (extensions.find("GL_OES_vertex_array_object") != std::string::npos) {
- mbgl::Log::Info(mbgl::Event::OpenGL, "Using GL_OES_vertex_array_object.");
- gl::BindVertexArray = reinterpret_cast<gl::PFNGLBINDVERTEXARRAYPROC>(
- eglGetProcAddress("glBindVertexArrayOES"));
- gl::DeleteVertexArrays = reinterpret_cast<gl::PFNGLDELETEVERTEXARRAYSPROC>(
- eglGetProcAddress("glDeleteVertexArraysOES"));
- gl::GenVertexArrays = reinterpret_cast<gl::PFNGLGENVERTEXARRAYSPROC>(
- eglGetProcAddress("glGenVertexArraysOES"));
- gl::IsVertexArray =
- reinterpret_cast<gl::PFNGLISVERTEXARRAYPROC>(eglGetProcAddress("glIsVertexArrayOES"));
- assert(gl::BindVertexArray != nullptr);
- assert(gl::DeleteVertexArrays != nullptr);
- assert(gl::GenVertexArrays != nullptr);
- assert(gl::IsVertexArray != nullptr);
- }
-
- if (extensions.find("GL_KHR_debug") != std::string::npos) {
- mbgl::Log::Info(mbgl::Event::OpenGL, "Using GL_KHR_debug.");
- gl::DebugMessageControl = reinterpret_cast<gl::PFNGLDEBUGMESSAGECONTROLPROC>(
- eglGetProcAddress("glDebugMessageControl"));
- gl::DebugMessageInsert = reinterpret_cast<gl::PFNGLDEBUGMESSAGEINSERTPROC>(
- eglGetProcAddress("glDebugMessageInsert"));
- gl::DebugMessageCallback = reinterpret_cast<gl::PFNGLDEBUGMESSAGECALLBACKPROC>(
- eglGetProcAddress("glDebugMessageCallback"));
- gl::GetDebugMessageLog = reinterpret_cast<gl::PFNGLGETDEBUGMESSAGELOGPROC>(
- eglGetProcAddress("glGetDebugMessageLog"));
- gl::GetPointerv =
- reinterpret_cast<gl::PFNGLGETPOINTERVPROC>(eglGetProcAddress("glGetPointerv"));
- gl::PushDebugGroup =
- reinterpret_cast<gl::PFNGLPUSHDEBUGGROUPPROC>(eglGetProcAddress("glPushDebugGroup"));
- gl::PopDebugGroup =
- reinterpret_cast<gl::PFNGLPOPDEBUGGROUPPROC>(eglGetProcAddress("glPopDebugGroup"));
- gl::ObjectLabel =
- reinterpret_cast<gl::PFNGLOBJECTLABELPROC>(eglGetProcAddress("glObjectLabel"));
- gl::GetObjectLabel =
- reinterpret_cast<gl::PFNGLGETOBJECTLABELPROC>(eglGetProcAddress("glGetObjectLabel"));
- gl::ObjectPtrLabel =
- reinterpret_cast<gl::PFNGLOBJECTPTRLABELPROC>(eglGetProcAddress("glObjectPtrLabel"));
- gl::GetObjectPtrLabel = reinterpret_cast<gl::PFNGLGETOBJECTPTRLABELPROC>(
- eglGetProcAddress("glGetObjectPtrLabel"));
- assert(gl::DebugMessageControl != nullptr);
- assert(gl::DebugMessageInsert != nullptr);
- assert(gl::DebugMessageCallback != nullptr);
- assert(gl::GetDebugMessageLog != nullptr);
- assert(gl::GetPointerv != nullptr);
- assert(gl::PushDebugGroup != nullptr);
- assert(gl::PopDebugGroup != nullptr);
- assert(gl::ObjectLabel != nullptr);
- assert(gl::GetObjectLabel != nullptr);
- assert(gl::ObjectPtrLabel != nullptr);
- assert(gl::GetObjectPtrLabel != nullptr);
- } else {
- if (extensions.find("GL_EXT_debug_marker") != std::string::npos) {
- mbgl::Log::Info(mbgl::Event::OpenGL, "Using GL_EXT_debug_marker.");
- gl::InsertEventMarkerEXT = reinterpret_cast<gl::PFNGLINSERTEVENTMARKEREXTPROC>(
- eglGetProcAddress("glInsertEventMarkerEXT"));
- gl::PushGroupMarkerEXT = reinterpret_cast<gl::PFNGLPUSHGROUPMARKEREXTPROC>(
- eglGetProcAddress("glPushGroupMarkerEXT"));
- gl::PopGroupMarkerEXT = reinterpret_cast<gl::PFNGLPOPGROUPMARKEREXTPROC>(
- eglGetProcAddress("glPopGroupMarkerEXT"));
- assert(gl::InsertEventMarkerEXT != nullptr);
- assert(gl::PushGroupMarkerEXT != nullptr);
- assert(gl::PopGroupMarkerEXT != nullptr);
- }
-
- if (extensions.find("GL_EXT_debug_label") != std::string::npos) {
- mbgl::Log::Info(mbgl::Event::OpenGL, "Using GL_EXT_debug_label.");
- gl::LabelObjectEXT = reinterpret_cast<gl::PFNGLLABELOBJECTEXTPROC>(
- eglGetProcAddress("glLabelObjectEXT"));
- gl::GetObjectLabelEXT = reinterpret_cast<gl::PFNGLGETOBJECTLABELEXTPROC>(
- eglGetProcAddress("glGetObjectLabelEXT"));
- assert(gl::LabelObjectEXT != nullptr);
- assert(gl::GetObjectLabelEXT != nullptr);
- }
- }
+ mbgl::gl::InitializeExtensions([] (const char * name) {
+ return reinterpret_cast<mbgl::gl::glProc>(eglGetProcAddress(name));
+ });
}
void NativeMapView::pause() {
diff --git a/include/mbgl/platform/gl.hpp b/include/mbgl/platform/gl.hpp
index 1b842b0804..73f0801fa5 100644
--- a/include/mbgl/platform/gl.hpp
+++ b/include/mbgl/platform/gl.hpp
@@ -3,6 +3,7 @@
#include <string>
#include <stdexcept>
+#include <vector>
#if __APPLE__
#include "TargetConditionals.h"
@@ -44,137 +45,37 @@ void checkError(const char *cmd, const char *file, int line);
#define MBGL_CHECK_ERROR(cmd) (cmd)
#endif
-// GL_KHR_debug / GL_ARB_debug_output
-#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
-#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
-#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
-#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
-#define GL_DEBUG_SOURCE_API 0x8246
-#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
-#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
-#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
-#define GL_DEBUG_SOURCE_APPLICATION 0x824A
-#define GL_DEBUG_SOURCE_OTHER 0x824B
-#define GL_DEBUG_TYPE_ERROR 0x824C
-#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
-#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
-#define GL_DEBUG_TYPE_PORTABILITY 0x824F
-#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
-#define GL_DEBUG_TYPE_OTHER 0x8251
-#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
-#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
-#define GL_DEBUG_LOGGED_MESSAGES 0x9145
-#define GL_DEBUG_SEVERITY_HIGH 0x9146
-#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
-#define GL_DEBUG_SEVERITY_LOW 0x9148
-#define GL_DEBUG_TYPE_MARKER 0x8268
-#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
-#define GL_DEBUG_TYPE_POP_GROUP 0x826A
-#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
-#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
-#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
-#define GL_BUFFER 0x82E0
-#define GL_SHADER 0x82E1
-#define GL_PROGRAM 0x82E2
-#define GL_QUERY 0x82E3
-#define GL_PROGRAM_PIPELINE 0x82E4
-#define GL_SAMPLER 0x82E6
-#define GL_MAX_LABEL_LENGTH 0x82E8
-#define GL_DEBUG_OUTPUT 0x92E0
-#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
-#define GL_DISPLAY_LIST 0x82E7
-#define GL_VERTEX_ARRAY 0x8074
-#define GL_TRANSFORM_FEEDBACK 0x8E22
-#define GL_TEXTURE 0x1702
-#define GL_RENDERBUFFER 0x8D41
-#define GL_FRAMEBUFFER 0x8D40
-typedef void (* GLDEBUGPROC)(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam);
-typedef void (* PFNGLDEBUGMESSAGECONTROLPROC) (GLenum source, GLenum type, GLenum severity, GLsizei count, const GLuint *ids, GLboolean enabled);
-typedef void (* PFNGLDEBUGMESSAGEINSERTPROC) (GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *buf);
-typedef void (* PFNGLDEBUGMESSAGECALLBACKPROC) (GLDEBUGPROC callback, const void *userParam);
-typedef GLuint (* PFNGLGETDEBUGMESSAGELOGPROC) (GLuint count, GLsizei bufSize, GLenum *sources, GLenum *types, GLuint *ids, GLenum *severities, GLsizei *lengths, GLchar *messageLog);
-typedef void (* PFNGLGETPOINTERVPROC) (GLenum pname, void **params);
-typedef void (* PFNGLPUSHDEBUGGROUPPROC) (GLenum source, GLuint id, GLsizei length, const GLchar *message);
-typedef void (* PFNGLPOPDEBUGGROUPPROC) (void);
-typedef void (* PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
-typedef void (* PFNGLGETOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei bufSize, GLsizei *length, GLchar *label);
-typedef void (* PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
-typedef void (* PFNGLGETOBJECTPTRLABELPROC) (const void *ptr, GLsizei bufSize, GLsizei *length, GLchar *label);
-extern PFNGLDEBUGMESSAGECONTROLPROC DebugMessageControl;
-extern PFNGLDEBUGMESSAGEINSERTPROC DebugMessageInsert;
-extern PFNGLDEBUGMESSAGECALLBACKPROC DebugMessageCallback;
-extern PFNGLGETDEBUGMESSAGELOGPROC GetDebugMessageLog;
-extern PFNGLGETPOINTERVPROC GetPointerv;
-extern PFNGLPUSHDEBUGGROUPPROC PushDebugGroup;
-extern PFNGLPOPDEBUGGROUPPROC PopDebugGroup;
-extern PFNGLOBJECTLABELPROC ObjectLabel;
-extern PFNGLGETOBJECTLABELPROC GetObjectLabel;
-extern PFNGLOBJECTPTRLABELPROC ObjectPtrLabel;
-extern PFNGLGETOBJECTPTRLABELPROC GetObjectPtrLabel;
-void debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar *message, const void *userParam);
-
-// GL_EXT_debug_marker
-typedef void (* PFNGLINSERTEVENTMARKEREXTPROC) (GLsizei length, const GLchar *marker);
-typedef void (* PFNGLPUSHGROUPMARKEREXTPROC) (GLsizei length, const GLchar *marker);
-typedef void (* PFNGLPOPGROUPMARKEREXTPROC) (void);
-extern PFNGLINSERTEVENTMARKEREXTPROC InsertEventMarkerEXT;
-extern PFNGLPUSHGROUPMARKEREXTPROC PushGroupMarkerEXT;
-extern PFNGLPOPGROUPMARKEREXTPROC PopGroupMarkerEXT;
-
-// GL_EXT_debug_label
-#define GL_PROGRAM_PIPELINE_OBJECT_EXT 0x8A4F
-#define GL_PROGRAM_OBJECT_EXT 0x8B40
-#define GL_SHADER_OBJECT_EXT 0x8B48
-#define GL_BUFFER_OBJECT_EXT 0x9151
-#define GL_QUERY_OBJECT_EXT 0x9153
-#define GL_VERTEX_ARRAY_OBJECT_EXT 0x9154
-typedef void (* PFNGLLABELOBJECTEXTPROC) (GLenum type, GLuint object, GLsizei length, const GLchar *label);
-typedef void (* PFNGLGETOBJECTLABELEXTPROC) (GLenum type, GLuint object, GLsizei bufSize, GLsizei *length, GLchar *label);
-extern PFNGLLABELOBJECTEXTPROC LabelObjectEXT;
-extern PFNGLGETOBJECTLABELEXTPROC GetObjectLabelEXT;
+class ExtensionFunctionBase {
+public:
+ static std::vector<ExtensionFunctionBase*>& functions();
+ typedef std::pair<const char *, const char *> Probe;
+ std::vector<Probe> probes;
+ void (*ptr)();
+};
-// GL_ARB_vertex_array_object / GL_OES_vertex_array_object
-#define GL_VERTEX_ARRAY_BINDING 0x85B5
-typedef void (* PFNGLBINDVERTEXARRAYPROC) (GLuint array);
-typedef void (* PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint* arrays);
-typedef void (* PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint* arrays);
-typedef GLboolean (* PFNGLISVERTEXARRAYPROC) (GLuint array);
-extern PFNGLBINDVERTEXARRAYPROC BindVertexArray;
-extern PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays;
-extern PFNGLGENVERTEXARRAYSPROC GenVertexArrays;
-extern PFNGLISVERTEXARRAYPROC IsVertexArray;
+template <class>
+class ExtensionFunction;
-// Debug group markers, useful for debugging on iOS
-#if defined(DEBUG)
-// static int indent = 0;
-inline void start_group(const std::string &str) {
- if (gl::PushDebugGroup != nullptr) {
- MBGL_CHECK_ERROR(gl::PushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, GLsizei(str.size()), str.c_str()));
- } else if (gl::PushGroupMarkerEXT != nullptr) {
- MBGL_CHECK_ERROR(gl::PushGroupMarkerEXT(GLsizei(str.size() + 1), str.c_str()));
+template <class R, class... Args>
+class ExtensionFunction<R (Args...)> : protected ExtensionFunctionBase {
+public:
+ ExtensionFunction(std::initializer_list<Probe> probes_) {
+ probes = probes_;
+ ExtensionFunctionBase::functions().push_back(this);
}
- // fprintf(stderr, "%s%s\n", std::string(indent * 4, ' ').c_str(), str.c_str());
- // indent++;
-}
-inline void end_group() {
- if (gl::PopDebugGroup != nullptr) {
- MBGL_CHECK_ERROR(gl::PopDebugGroup());
- } else if (gl::PopGroupMarkerEXT != nullptr) {
- MBGL_CHECK_ERROR(gl::PopGroupMarkerEXT());
+ explicit operator bool() const {
+ return ptr;
}
- // indent--;
-}
-#else
-inline void start_group(const std::string &) {}
-inline void end_group() {}
-#endif
-struct group {
- inline group(const std::string &str) { start_group(str); }
- ~group() { end_group(); };
+ R operator()(Args... args) const {
+ return (*reinterpret_cast<R (*)(Args...)>(ptr))(std::forward<Args>(args)...);
+ }
};
+using glProc = void (*)();
+void InitializeExtensions(glProc (*getProcAddress)(const char *));
+
}
}
diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp
index fa27c0880d..ed499d374b 100644
--- a/platform/default/glfw_view.cpp
+++ b/platform/default/glfw_view.cpp
@@ -14,10 +14,6 @@ void glfwError(int error, const char *description) {
}
GLFWView::GLFWView(bool fullscreen_) : fullscreen(fullscreen_) {
-#ifdef NVIDIA
- glDiscardFramebufferEXT = reinterpret_cast<PFNGLDISCARDFRAMEBUFFEREXTPROC>(glfwGetProcAddress("glDiscardFramebufferEXT"));
-#endif
-
glfwSetErrorCallback(glfwError);
if (!glfwInit()) {
@@ -66,82 +62,7 @@ GLFWView::GLFWView(bool fullscreen_) : fullscreen(fullscreen_) {
glfwSetKeyCallback(window, onKey);
pthread_once(&loadGLExtensions, [] {
- const std::string extensions = reinterpret_cast<const char *>(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)));
- using namespace mbgl;
-
- if (extensions.find("GL_KHR_debug") != std::string::npos) {
- gl::DebugMessageControl = reinterpret_cast<gl::PFNGLDEBUGMESSAGECONTROLPROC>(glfwGetProcAddress("glDebugMessageControl"));
- gl::DebugMessageInsert = reinterpret_cast<gl::PFNGLDEBUGMESSAGEINSERTPROC>(glfwGetProcAddress("glDebugMessageInsert"));
- gl::DebugMessageCallback = reinterpret_cast<gl::PFNGLDEBUGMESSAGECALLBACKPROC>(glfwGetProcAddress("glDebugMessageCallback"));
- gl::GetDebugMessageLog = reinterpret_cast<gl::PFNGLGETDEBUGMESSAGELOGPROC>(glfwGetProcAddress("glGetDebugMessageLog"));
- gl::GetPointerv = reinterpret_cast<gl::PFNGLGETPOINTERVPROC>(glfwGetProcAddress("glGetPointerv"));
- gl::PushDebugGroup = reinterpret_cast<gl::PFNGLPUSHDEBUGGROUPPROC>(glfwGetProcAddress("glPushDebugGroup"));
- gl::PopDebugGroup = reinterpret_cast<gl::PFNGLPOPDEBUGGROUPPROC>(glfwGetProcAddress("glPopDebugGroup"));
- gl::ObjectLabel = reinterpret_cast<gl::PFNGLOBJECTLABELPROC>(glfwGetProcAddress("glObjectLabel"));
- gl::GetObjectLabel = reinterpret_cast<gl::PFNGLGETOBJECTLABELPROC>(glfwGetProcAddress("glGetObjectLabel"));
- gl::ObjectPtrLabel = reinterpret_cast<gl::PFNGLOBJECTPTRLABELPROC>(glfwGetProcAddress("glObjectPtrLabel"));
- gl::GetObjectPtrLabel = reinterpret_cast<gl::PFNGLGETOBJECTPTRLABELPROC>(glfwGetProcAddress("glGetObjectPtrLabel"));
- assert(gl::DebugMessageControl != nullptr);
- assert(gl::DebugMessageInsert != nullptr);
- assert(gl::DebugMessageCallback != nullptr);
- assert(gl::GetDebugMessageLog != nullptr);
- assert(gl::GetPointerv != nullptr);
- assert(gl::PushDebugGroup != nullptr);
- assert(gl::PopDebugGroup != nullptr);
- assert(gl::ObjectLabel != nullptr);
- assert(gl::GetObjectLabel != nullptr);
- assert(gl::ObjectPtrLabel != nullptr);
- assert(gl::GetObjectPtrLabel != nullptr);
- } else {
- if (extensions.find("GL_ARB_debug_output") != std::string::npos) {
- gl::DebugMessageControl = reinterpret_cast<gl::PFNGLDEBUGMESSAGECONTROLPROC>(glfwGetProcAddress("glDebugMessageControlARB"));
- gl::DebugMessageInsert = reinterpret_cast<gl::PFNGLDEBUGMESSAGEINSERTPROC>(glfwGetProcAddress("glDebugMessageInsertARB"));
- gl::DebugMessageCallback = reinterpret_cast<gl::PFNGLDEBUGMESSAGECALLBACKPROC>(glfwGetProcAddress("glDebugMessageCallbackARB"));
- gl::GetDebugMessageLog = reinterpret_cast<gl::PFNGLGETDEBUGMESSAGELOGPROC>(glfwGetProcAddress("glGetDebugMessageLogARB"));
- gl::GetPointerv = reinterpret_cast<gl::PFNGLGETPOINTERVPROC>(glfwGetProcAddress("glGetPointerv"));
- assert(gl::DebugMessageControl != nullptr);
- assert(gl::DebugMessageInsert != nullptr);
- assert(gl::DebugMessageCallback != nullptr);
- assert(gl::GetDebugMessageLog != nullptr);
- assert(gl::GetPointerv != nullptr);
- }
-
- if (extensions.find("GL_EXT_debug_marker") != std::string::npos) {
- gl::InsertEventMarkerEXT = reinterpret_cast<gl::PFNGLINSERTEVENTMARKEREXTPROC>(glfwGetProcAddress("glInsertEventMarkerEXT"));
- gl::PushGroupMarkerEXT = reinterpret_cast<gl::PFNGLPUSHGROUPMARKEREXTPROC>(glfwGetProcAddress("glPushGroupMarkerEXT"));
- gl::PopGroupMarkerEXT = reinterpret_cast<gl::PFNGLPOPGROUPMARKEREXTPROC>(glfwGetProcAddress("glPopGroupMarkerEXT"));
- assert(gl::InsertEventMarkerEXT != nullptr);
- assert(gl::PushGroupMarkerEXT != nullptr);
- assert(gl::PopGroupMarkerEXT != nullptr);
- }
-
- if (extensions.find("GL_EXT_debug_label") != std::string::npos) {
- gl::LabelObjectEXT = reinterpret_cast<gl::PFNGLLABELOBJECTEXTPROC>(glfwGetProcAddress("glLabelObjectEXT"));
- gl::GetObjectLabelEXT = reinterpret_cast<gl::PFNGLGETOBJECTLABELEXTPROC>(glfwGetProcAddress("glGetObjectLabelEXT"));
- assert(gl::LabelObjectEXT != nullptr);
- assert(gl::GetObjectLabelEXT != nullptr);
- }
- }
-
- if (extensions.find("GL_ARB_vertex_array_object") != std::string::npos) {
- gl::BindVertexArray = reinterpret_cast<gl::PFNGLBINDVERTEXARRAYPROC>(glfwGetProcAddress("glBindVertexArray"));
- gl::DeleteVertexArrays = reinterpret_cast<gl::PFNGLDELETEVERTEXARRAYSPROC>(glfwGetProcAddress("glDeleteVertexArrays"));
- gl::GenVertexArrays = reinterpret_cast<gl::PFNGLGENVERTEXARRAYSPROC>(glfwGetProcAddress("glGenVertexArrays"));
- gl::IsVertexArray = reinterpret_cast<gl::PFNGLISVERTEXARRAYPROC>(glfwGetProcAddress("glIsVertexArray"));
- assert(gl::BindVertexArray != nullptr);
- assert(gl::DeleteVertexArrays != nullptr);
- assert(gl::GenVertexArrays != nullptr);
- assert(gl::IsVertexArray != nullptr);
- } else if (extensions.find("GL_APPLE_vertex_array_object") != std::string::npos) {
- gl::BindVertexArray = reinterpret_cast<gl::PFNGLBINDVERTEXARRAYPROC>(glfwGetProcAddress("glBindVertexArrayAPPLE"));
- gl::DeleteVertexArrays = reinterpret_cast<gl::PFNGLDELETEVERTEXARRAYSPROC>(glfwGetProcAddress("glDeleteVertexArraysAPPLE"));
- gl::GenVertexArrays = reinterpret_cast<gl::PFNGLGENVERTEXARRAYSPROC>(glfwGetProcAddress("glGenVertexArraysAPPLE"));
- gl::IsVertexArray = reinterpret_cast<gl::PFNGLISVERTEXARRAYPROC>(glfwGetProcAddress("glIsVertexArrayAPPLE"));
- assert(gl::BindVertexArray != nullptr);
- assert(gl::DeleteVertexArrays != nullptr);
- assert(gl::GenVertexArrays != nullptr);
- assert(gl::IsVertexArray != nullptr);
- }
+ mbgl::gl::InitializeExtensions(glfwGetProcAddress);
});
glfwMakeContextCurrent(nullptr);
diff --git a/platform/default/headless_view.cpp b/platform/default/headless_view.cpp
index 41584b9a99..357c6fac70 100644
--- a/platform/default/headless_view.cpp
+++ b/platform/default/headless_view.cpp
@@ -17,22 +17,6 @@ pthread_once_t loadGLExtensions = PTHREAD_ONCE_INIT;
#ifdef MBGL_USE_CGL
#include <CoreFoundation/CoreFoundation.h>
-
-typedef void (* CGLProc)(void);
-CGLProc CGLGetProcAddress(const char *proc) {
- static CFBundleRef framework = nullptr;
- if (!framework) {
- framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
- if (!framework) {
- throw std::runtime_error("Failed to load OpenGL framework.");
- }
- }
-
- CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, proc, kCFStringEncodingASCII);
- CGLProc symbol = reinterpret_cast<CGLProc>(CFBundleGetFunctionPointerForName(framework, name));
- CFRelease(name);
- return symbol;
-}
#elif MBGL_USE_GLX
#include <GL/glx.h>
#endif
@@ -62,36 +46,25 @@ void HeadlessView::loadExtensions() {
}
pthread_once(&loadGLExtensions, [] {
- const char *extensionPtr = reinterpret_cast<const char *>(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)));
+#ifdef MBGL_USE_CGL
+ gl::InitializeExtensions([](const char * name) {
+ static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
+ if (!framework) {
+ throw std::runtime_error("Failed to load OpenGL framework.");
+ }
- if (!extensionPtr) {
- return;
- }
- const std::string extensions = extensionPtr;
+ CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
+ void* symbol = CFBundleGetFunctionPointerForName(framework, str);
+ CFRelease(str);
-#ifdef MBGL_USE_CGL
- if (extensions.find("GL_APPLE_vertex_array_object") != std::string::npos) {
- gl::BindVertexArray = reinterpret_cast<gl::PFNGLBINDVERTEXARRAYPROC>(CGLGetProcAddress("glBindVertexArrayAPPLE"));
- gl::DeleteVertexArrays = reinterpret_cast<gl::PFNGLDELETEVERTEXARRAYSPROC>(CGLGetProcAddress("glDeleteVertexArraysAPPLE"));
- gl::GenVertexArrays = reinterpret_cast<gl::PFNGLGENVERTEXARRAYSPROC>(CGLGetProcAddress("glGenVertexArraysAPPLE"));
- gl::IsVertexArray = reinterpret_cast<gl::PFNGLISVERTEXARRAYPROC>(CGLGetProcAddress("glIsVertexArrayAPPLE"));
- assert(gl::BindVertexArray != nullptr);
- assert(gl::DeleteVertexArrays != nullptr);
- assert(gl::GenVertexArrays != nullptr);
- assert(gl::IsVertexArray != nullptr);
- }
+ return reinterpret_cast<gl::glProc>(symbol);
+ });
#endif
+
#ifdef MBGL_USE_GLX
- if (extensions.find("GL_ARB_vertex_array_object") != std::string::npos) {
- gl::BindVertexArray = reinterpret_cast<gl::PFNGLBINDVERTEXARRAYPROC>(glXGetProcAddress((const GLubyte *)"glBindVertexArray"));
- gl::DeleteVertexArrays = reinterpret_cast<gl::PFNGLDELETEVERTEXARRAYSPROC>(glXGetProcAddress((const GLubyte *)"glDeleteVertexArrays"));
- gl::GenVertexArrays = reinterpret_cast<gl::PFNGLGENVERTEXARRAYSPROC>(glXGetProcAddress((const GLubyte *)"glGenVertexArrays"));
- gl::IsVertexArray = reinterpret_cast<gl::PFNGLISVERTEXARRAYPROC>(glXGetProcAddress((const GLubyte *)"glIsVertexArray"));
- assert(gl::BindVertexArray != nullptr);
- assert(gl::DeleteVertexArrays != nullptr);
- assert(gl::GenVertexArrays != nullptr);
- assert(gl::IsVertexArray != nullptr);
- }
+ gl::InitializeExtensions([](const char * name) {
+ return glXGetProcAddress(reinterpret_cast<const GLubyte *>(name));
+ });
#endif
});
diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm
index 72f2d420c7..a2e55b337a 100644
--- a/platform/ios/MGLMapView.mm
+++ b/platform/ios/MGLMapView.mm
@@ -235,22 +235,18 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
//
dispatch_once(&loadGLExtensions, ^
{
- const std::string extensions = (char *)glGetString(GL_EXTENSIONS);
-
- using namespace mbgl;
+ mbgl::gl::InitializeExtensions([](const char * name) {
+ static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
+ if (!framework) {
+ throw std::runtime_error("Failed to load OpenGL framework.");
+ }
- if (extensions.find("GL_OES_vertex_array_object") != std::string::npos) {
- gl::BindVertexArray = glBindVertexArrayOES;
- gl::DeleteVertexArrays = glDeleteVertexArraysOES;
- gl::GenVertexArrays = glGenVertexArraysOES;
- gl::IsVertexArray = glIsVertexArrayOES;
- }
+ CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
+ void* symbol = CFBundleGetFunctionPointerForName(framework, str);
+ CFRelease(str);
- if (extensions.find("GL_EXT_debug_marker") != std::string::npos) {
- gl::InsertEventMarkerEXT = glInsertEventMarkerEXT;
- gl::PushGroupMarkerEXT = glPushGroupMarkerEXT;
- gl::PopGroupMarkerEXT = glPopGroupMarkerEXT;
- }
+ return reinterpret_cast<mbgl::gl::glProc>(symbol);
+ });
});
// setup mbgl map
diff --git a/src/mbgl/geometry/vao.cpp b/src/mbgl/geometry/vao.cpp
index fef74396a9..4f6e89332f 100644
--- a/src/mbgl/geometry/vao.cpp
+++ b/src/mbgl/geometry/vao.cpp
@@ -5,11 +5,45 @@
namespace mbgl {
+static gl::ExtensionFunction<
+ void (GLuint array)>
+ BindVertexArray({
+ {"GL_ARB_vertex_array_object", "glBindVertexArray"},
+ {"GL_OES_vertex_array_object", "glBindVertexArrayOES"},
+ {"GL_APPLE_vertex_array_object", "glBindVertexArrayAPPLE"}
+ });
+
+static gl::ExtensionFunction<
+ void (GLsizei n,
+ const GLuint* arrays)>
+ DeleteVertexArrays({
+ {"GL_ARB_vertex_array_object", "glDeleteVertexArrays"},
+ {"GL_OES_vertex_array_object", "glDeleteVertexArraysOES"},
+ {"GL_APPLE_vertex_array_object", "glDeleteVertexArraysAPPLE"}
+ });
+
+static gl::ExtensionFunction<
+ void (GLsizei n,
+ GLuint* arrays)>
+ GenVertexArrays({
+ {"GL_ARB_vertex_array_object", "glGenVertexArrays"},
+ {"GL_OES_vertex_array_object", "glGenVertexArraysOES"},
+ {"GL_APPLE_vertex_array_object", "glGenVertexArraysAPPLE"}
+ });
+
+void VertexArrayObject::Bind(GLuint array) {
+ MBGL_CHECK_ERROR(BindVertexArray(array));
+}
+
+void VertexArrayObject::Delete(GLsizei n, const GLuint* arrays) {
+ MBGL_CHECK_ERROR(DeleteVertexArrays(n, arrays));
+}
+
VertexArrayObject::VertexArrayObject() {
}
VertexArrayObject::~VertexArrayObject() {
- if (!gl::DeleteVertexArrays) return;
+ if (!DeleteVertexArrays) return;
if (vao) {
Environment::Get().abandonVAO(vao);
@@ -17,7 +51,7 @@ VertexArrayObject::~VertexArrayObject() {
}
void VertexArrayObject::bindVertexArrayObject() {
- if (!gl::GenVertexArrays || !gl::BindVertexArray) {
+ if (!GenVertexArrays || !BindVertexArray) {
static bool reported = false;
if (!reported) {
Log::Warning(Event::OpenGL, "Not using Vertex Array Objects");
@@ -27,9 +61,9 @@ void VertexArrayObject::bindVertexArrayObject() {
}
if (!vao) {
- MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &vao));
+ MBGL_CHECK_ERROR(GenVertexArrays(1, &vao));
}
- MBGL_CHECK_ERROR(gl::BindVertexArray(vao));
+ MBGL_CHECK_ERROR(BindVertexArray(vao));
}
void VertexArrayObject::verifyBinding(Shader &shader, GLuint vertexBuffer, GLuint elementsBuffer,
diff --git a/src/mbgl/geometry/vao.hpp b/src/mbgl/geometry/vao.hpp
index 72bacfd793..e35fcc9bf8 100644
--- a/src/mbgl/geometry/vao.hpp
+++ b/src/mbgl/geometry/vao.hpp
@@ -11,6 +11,9 @@ namespace mbgl {
class VertexArrayObject : public util::noncopyable {
public:
+ static void Bind(GLuint array);
+ static void Delete(GLsizei n, const GLuint* arrays);
+
VertexArrayObject();
~VertexArrayObject();
diff --git a/src/mbgl/gl/debugging.cpp b/src/mbgl/gl/debugging.cpp
new file mode 100644
index 0000000000..5fc90e8274
--- /dev/null
+++ b/src/mbgl/gl/debugging.cpp
@@ -0,0 +1,195 @@
+#include <mbgl/gl/debugging.hpp>
+#include <mbgl/platform/gl.hpp>
+#include <mbgl/platform/event.hpp>
+#include <mbgl/platform/log.hpp>
+
+#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
+#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243
+#define GL_DEBUG_CALLBACK_FUNCTION 0x8244
+#define GL_DEBUG_CALLBACK_USER_PARAM 0x8245
+#define GL_DEBUG_SOURCE_API 0x8246
+#define GL_DEBUG_SOURCE_WINDOW_SYSTEM 0x8247
+#define GL_DEBUG_SOURCE_SHADER_COMPILER 0x8248
+#define GL_DEBUG_SOURCE_THIRD_PARTY 0x8249
+#define GL_DEBUG_SOURCE_APPLICATION 0x824A
+#define GL_DEBUG_SOURCE_OTHER 0x824B
+#define GL_DEBUG_TYPE_ERROR 0x824C
+#define GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR 0x824D
+#define GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR 0x824E
+#define GL_DEBUG_TYPE_PORTABILITY 0x824F
+#define GL_DEBUG_TYPE_PERFORMANCE 0x8250
+#define GL_DEBUG_TYPE_OTHER 0x8251
+#define GL_MAX_DEBUG_MESSAGE_LENGTH 0x9143
+#define GL_MAX_DEBUG_LOGGED_MESSAGES 0x9144
+#define GL_DEBUG_LOGGED_MESSAGES 0x9145
+#define GL_DEBUG_SEVERITY_HIGH 0x9146
+#define GL_DEBUG_SEVERITY_MEDIUM 0x9147
+#define GL_DEBUG_SEVERITY_LOW 0x9148
+#define GL_DEBUG_TYPE_MARKER 0x8268
+#define GL_DEBUG_TYPE_PUSH_GROUP 0x8269
+#define GL_DEBUG_TYPE_POP_GROUP 0x826A
+#define GL_DEBUG_SEVERITY_NOTIFICATION 0x826B
+#define GL_MAX_DEBUG_GROUP_STACK_DEPTH 0x826C
+#define GL_DEBUG_GROUP_STACK_DEPTH 0x826D
+#define GL_BUFFER 0x82E0
+#define GL_SHADER 0x82E1
+#define GL_PROGRAM 0x82E2
+#define GL_QUERY 0x82E3
+#define GL_PROGRAM_PIPELINE 0x82E4
+#define GL_SAMPLER 0x82E6
+#define GL_MAX_LABEL_LENGTH 0x82E8
+#define GL_DEBUG_OUTPUT 0x92E0
+#define GL_CONTEXT_FLAG_DEBUG_BIT 0x00000002
+#define GL_DISPLAY_LIST 0x82E7
+#define GL_VERTEX_ARRAY 0x8074
+#define GL_TRANSFORM_FEEDBACK 0x8E22
+#define GL_TEXTURE 0x1702
+#define GL_RENDERBUFFER 0x8D41
+#define GL_FRAMEBUFFER 0x8D40
+
+namespace mbgl {
+namespace gl {
+namespace debugging {
+
+typedef void (*GLDEBUGPROC)(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei length,
+ const GLchar *message,
+ const void *userParam);
+
+static ExtensionFunction<
+ void (GLenum source,
+ GLenum type,
+ GLenum severity,
+ GLsizei count,
+ const GLuint *ids,
+ GLboolean enabled)>
+ DebugMessageControl({
+ {"GL_KHR_debug", "glDebugMessageControl"},
+ {"GL_ARB_debug_output", "glDebugMessageControlARB"}
+ });
+
+static ExtensionFunction<
+ void (GLDEBUGPROC callback,
+ const void *userParam)>
+ DebugMessageCallback({
+ {"GL_KHR_debug", "glDebugMessageCallback"},
+ {"GL_ARB_debug_output", "glDebugMessageCallbackARB"}
+ });
+
+static ExtensionFunction<
+ void (GLenum source,
+ GLuint id,
+ GLsizei length,
+ const GLchar *message)>
+ PushDebugGroup({
+ {"GL_KHR_debug", "glPushDebugGroup"}
+ });
+
+static ExtensionFunction<
+ void ()>
+ PopDebugGroup({
+ {"GL_KHR_debug", "glPopDebugGroup"}
+ });
+
+static ExtensionFunction<
+ void (GLsizei length,
+ const GLchar *marker)>
+ PushGroupMarkerEXT({
+ {"GL_EXT_debug_marker", "glPushGroupMarkerEXT"}
+ });
+
+static ExtensionFunction<
+ void ()>
+ PopGroupMarkerEXT({
+ {"GL_EXT_debug_marker", "glPopGroupMarkerEXT"}
+ });
+
+void debugCallback(GLenum source,
+ GLenum type,
+ GLuint id,
+ GLenum severity,
+ GLsizei /*length*/,
+ const GLchar* message,
+ const void* /*userParam*/)
+{
+ std::string strSource;
+ switch (source) {
+ case GL_DEBUG_SOURCE_API: strSource = "DEBUG_SOURCE_API"; break;
+ case GL_DEBUG_SOURCE_WINDOW_SYSTEM: strSource = "DEBUG_SOURCE_WINDOW_SYSTEM"; break;
+ case GL_DEBUG_SOURCE_SHADER_COMPILER: strSource = "DEBUG_SOURCE_SHADER_COMPILER"; break;
+ case GL_DEBUG_SOURCE_THIRD_PARTY: strSource = "DEBUG_SOURCE_THIRD_PARTY"; break;
+ case GL_DEBUG_SOURCE_APPLICATION: strSource = "DEBUG_SOURCE_APPLICATION"; break;
+ case GL_DEBUG_SOURCE_OTHER: strSource = "DEBUG_SOURCE_OTHER"; break;
+ default: strSource = "(unknown)"; break;
+ }
+
+ std::string strType;
+ switch (type) {
+ case GL_DEBUG_TYPE_ERROR: strType = "DEBUG_TYPE_ERROR"; break;
+ case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: strType = "DEBUG_TYPE_DEPRECATED_BEHAVIOR"; break;
+ case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: strType = "DEBUG_TYPE_UNDEFINED_BEHAVIOR"; break;
+ case GL_DEBUG_TYPE_PERFORMANCE: strType = "DEBUG_TYPE_PERFORMANCE"; break;
+ case GL_DEBUG_TYPE_PORTABILITY: strType = "DEBUG_TYPE_PORTABILITY"; break;
+ case GL_DEBUG_TYPE_OTHER: strType = "DEBUG_TYPE_OTHER"; break;
+ case GL_DEBUG_TYPE_MARKER: strType = "DEBUG_TYPE_MARKER"; break;
+ case GL_DEBUG_TYPE_PUSH_GROUP: strType = "DEBUG_TYPE_OTHER"; break;
+ case GL_DEBUG_TYPE_POP_GROUP: strType = "DEBUG_TYPE_POP_GROUP"; break;
+ default: strSource = "(unknown)"; break;
+ }
+
+ std::string strSeverity;
+ mbgl::EventSeverity evtSeverity;
+ switch (severity) {
+ case GL_DEBUG_SEVERITY_HIGH: strSeverity = "DEBUG_SEVERITY_HIGH"; evtSeverity = mbgl::EventSeverity::Error; break;
+ case GL_DEBUG_SEVERITY_MEDIUM: strSeverity = "DEBUG_SEVERITY_MEDIUM"; evtSeverity = mbgl::EventSeverity::Warning; break;
+ case GL_DEBUG_SEVERITY_LOW: strSeverity = "DEBUG_SEVERITY_LOW"; evtSeverity = mbgl::EventSeverity::Info; break;
+ case GL_DEBUG_SEVERITY_NOTIFICATION: strSeverity = "DEBUG_SEVERITY_NOTIFICATION"; evtSeverity = mbgl::EventSeverity::Debug; break;
+ default: strSource = "(unknown)"; evtSeverity = mbgl::EventSeverity::Debug; break;
+ }
+
+ mbgl::Log::Record(evtSeverity, mbgl::Event::OpenGL, "GL_%s GL_%s %u GL_%s - %s", strSource.c_str(), strType.c_str(), id, strSeverity.c_str(), message);
+}
+
+void enable() {
+ if (!DebugMessageControl || !DebugMessageCallback) {
+ return;
+ }
+
+ // This will enable all messages including performance hints
+ //MBGL_CHECK_ERROR(DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE));
+
+ // This will only enable high and medium severity messages
+ MBGL_CHECK_ERROR(DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr, GL_TRUE));
+ MBGL_CHECK_ERROR(DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr, GL_TRUE));
+ MBGL_CHECK_ERROR(DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr, GL_FALSE));
+
+ MBGL_CHECK_ERROR(DebugMessageCallback(debugCallback, nullptr));
+}
+
+#if defined(DEBUG)
+group::group(const std::string& str) {
+ if (PushDebugGroup) {
+ PushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, GLsizei(str.size()), str.c_str());
+ } else if (PushGroupMarkerEXT) {
+ PushGroupMarkerEXT(GLsizei(str.size()), str.c_str());
+ }
+}
+
+group::~group() {
+ if (PopDebugGroup) {
+ PopDebugGroup();
+ } else if (PopGroupMarkerEXT) {
+ PopGroupMarkerEXT();
+ }
+}
+#else
+group::group(const std::string&) {}
+group::~group() = default;
+#endif
+
+}
+}
+}
diff --git a/src/mbgl/gl/debugging.hpp b/src/mbgl/gl/debugging.hpp
new file mode 100644
index 0000000000..82d08a53fb
--- /dev/null
+++ b/src/mbgl/gl/debugging.hpp
@@ -0,0 +1,21 @@
+#ifndef MBGL_GL_DEBUG_MESSAGES
+#define MBGL_GL_DEBUG_MESSAGES
+
+#include <string>
+
+namespace mbgl {
+namespace gl {
+namespace debugging {
+
+void enable();
+
+struct group {
+ group(const std::string&);
+ ~group();
+};
+
+}
+}
+}
+
+#endif
diff --git a/src/mbgl/map/environment.cpp b/src/mbgl/map/environment.cpp
index 327efeecff..d121f96555 100644
--- a/src/mbgl/map/environment.cpp
+++ b/src/mbgl/map/environment.cpp
@@ -2,6 +2,7 @@
#include <mbgl/storage/file_source.hpp>
#include <mbgl/platform/gl.hpp>
#include <mbgl/util/run_loop.hpp>
+#include <mbgl/geometry/vao.hpp>
#include <uv.h>
@@ -155,8 +156,8 @@ void Environment::performCleanup() {
assert(currentlyOn(ThreadType::Map));
if (!abandonedVAOs.empty()) {
- MBGL_CHECK_ERROR(gl::DeleteVertexArrays(static_cast<GLsizei>(abandonedVAOs.size()),
- abandonedVAOs.data()));
+ MBGL_CHECK_ERROR(VertexArrayObject::Delete(static_cast<GLsizei>(abandonedVAOs.size()),
+ abandonedVAOs.data()));
abandonedVAOs.clear();
}
diff --git a/src/mbgl/map/source.cpp b/src/mbgl/map/source.cpp
index afe775be30..686b15c24e 100644
--- a/src/mbgl/map/source.cpp
+++ b/src/mbgl/map/source.cpp
@@ -21,6 +21,7 @@
#include <mbgl/map/raster_tile_data.hpp>
#include <mbgl/map/live_tile_data.hpp>
#include <mbgl/style/style.hpp>
+#include <mbgl/gl/debugging.hpp>
#include <algorithm>
@@ -179,7 +180,7 @@ void Source::updateMatrices(const mat4 &projMatrix, const TransformState &transf
void Source::drawClippingMasks(Painter &painter) {
for (const auto& pair : tiles) {
Tile &tile = *pair.second;
- gl::group group(std::string { "mask: " } + std::string(tile.id));
+ gl::debugging::group group(std::string { "mask: " } + std::string(tile.id));
painter.drawClippingMask(tile.matrix, tile.clip);
}
}
diff --git a/src/mbgl/platform/gl.cpp b/src/mbgl/platform/gl.cpp
index 096ec8393f..3d8a237c70 100644
--- a/src/mbgl/platform/gl.cpp
+++ b/src/mbgl/platform/gl.cpp
@@ -1,75 +1,31 @@
#include <mbgl/platform/gl.hpp>
-#include <mbgl/platform/log.hpp>
-
-#include <iostream>
-
namespace mbgl {
namespace gl {
-PFNGLDEBUGMESSAGECONTROLPROC DebugMessageControl = nullptr;
-PFNGLDEBUGMESSAGEINSERTPROC DebugMessageInsert = nullptr;
-PFNGLDEBUGMESSAGECALLBACKPROC DebugMessageCallback = nullptr;
-PFNGLGETDEBUGMESSAGELOGPROC GetDebugMessageLog = nullptr;
-PFNGLGETPOINTERVPROC GetPointerv = nullptr;
-PFNGLPUSHDEBUGGROUPPROC PushDebugGroup = nullptr;
-PFNGLPOPDEBUGGROUPPROC PopDebugGroup = nullptr;
-PFNGLOBJECTLABELPROC ObjectLabel = nullptr;
-PFNGLGETOBJECTLABELPROC GetObjectLabel = nullptr;
-PFNGLOBJECTPTRLABELPROC ObjectPtrLabel = nullptr;
-PFNGLGETOBJECTPTRLABELPROC GetObjectPtrLabel = nullptr;
+std::vector<ExtensionFunctionBase*>& ExtensionFunctionBase::functions() {
+ static std::vector<ExtensionFunctionBase*> functions;
+ return functions;
+}
-void debug_callback(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei, const GLchar *message, const void *) {
- std::string strSource;
- switch (source) {
- case GL_DEBUG_SOURCE_API: strSource = "DEBUG_SOURCE_API"; break;
- case GL_DEBUG_SOURCE_WINDOW_SYSTEM: strSource = "DEBUG_SOURCE_WINDOW_SYSTEM"; break;
- case GL_DEBUG_SOURCE_SHADER_COMPILER: strSource = "DEBUG_SOURCE_SHADER_COMPILER"; break;
- case GL_DEBUG_SOURCE_THIRD_PARTY: strSource = "DEBUG_SOURCE_THIRD_PARTY"; break;
- case GL_DEBUG_SOURCE_APPLICATION: strSource = "DEBUG_SOURCE_APPLICATION"; break;
- case GL_DEBUG_SOURCE_OTHER: strSource = "DEBUG_SOURCE_OTHER"; break;
- default: strSource = "(unknown)"; break;
- }
+void InitializeExtensions(glProc (*getProcAddress)(const char *)) {
+ const char * extensionsPtr = reinterpret_cast<const char *>(
+ MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)));
- std::string strType;
- switch (type) {
- case GL_DEBUG_TYPE_ERROR: strType = "DEBUG_TYPE_ERROR"; break;
- case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: strType = "DEBUG_TYPE_DEPRECATED_BEHAVIOR"; break;
- case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: strType = "DEBUG_TYPE_UNDEFINED_BEHAVIOR"; break;
- case GL_DEBUG_TYPE_PERFORMANCE: strType = "DEBUG_TYPE_PERFORMANCE"; break;
- case GL_DEBUG_TYPE_PORTABILITY: strType = "DEBUG_TYPE_PORTABILITY"; break;
- case GL_DEBUG_TYPE_OTHER: strType = "DEBUG_TYPE_OTHER"; break;
- case GL_DEBUG_TYPE_MARKER: strType = "DEBUG_TYPE_MARKER"; break;
- case GL_DEBUG_TYPE_PUSH_GROUP: strType = "DEBUG_TYPE_OTHER"; break;
- case GL_DEBUG_TYPE_POP_GROUP: strType = "DEBUG_TYPE_POP_GROUP"; break;
- default: strSource = "(unknown)"; break;
- }
+ if (!extensionsPtr)
+ return;
- std::string strSeverity;
- mbgl::EventSeverity evtSeverity;
- switch (severity) {
- case GL_DEBUG_SEVERITY_HIGH: strSeverity = "DEBUG_SEVERITY_HIGH"; evtSeverity = mbgl::EventSeverity::Error; break;
- case GL_DEBUG_SEVERITY_MEDIUM: strSeverity = "DEBUG_SEVERITY_MEDIUM"; evtSeverity = mbgl::EventSeverity::Warning; break;
- case GL_DEBUG_SEVERITY_LOW: strSeverity = "DEBUG_SEVERITY_LOW"; evtSeverity = mbgl::EventSeverity::Info; break;
- case GL_DEBUG_SEVERITY_NOTIFICATION: strSeverity = "DEBUG_SEVERITY_NOTIFICATION"; evtSeverity = mbgl::EventSeverity::Debug; break;
- default: strSource = "(unknown)"; evtSeverity = mbgl::EventSeverity::Debug; break;
+ const std::string extensions = extensionsPtr;
+ for (auto fn : ExtensionFunctionBase::functions()) {
+ for (auto probe : fn->probes) {
+ if (extensions.find(probe.first) != std::string::npos) {
+ fn->ptr = getProcAddress(probe.second);
+ break;
+ }
+ }
}
-
- mbgl::Log::Record(evtSeverity, mbgl::Event::OpenGL, "GL_%s GL_%s %u GL_%s - %s", strSource.c_str(), strType.c_str(), id, strSeverity.c_str(), message);
}
-PFNGLINSERTEVENTMARKEREXTPROC InsertEventMarkerEXT = nullptr;
-PFNGLPUSHGROUPMARKEREXTPROC PushGroupMarkerEXT = nullptr;
-PFNGLPOPGROUPMARKEREXTPROC PopGroupMarkerEXT = nullptr;
-
-PFNGLLABELOBJECTEXTPROC LabelObjectEXT = nullptr;
-PFNGLGETOBJECTLABELEXTPROC GetObjectLabelEXT = nullptr;
-
-PFNGLBINDVERTEXARRAYPROC BindVertexArray = nullptr;
-PFNGLDELETEVERTEXARRAYSPROC DeleteVertexArrays = nullptr;
-PFNGLGENVERTEXARRAYSPROC GenVertexArrays = nullptr;
-PFNGLISVERTEXARRAYPROC IsVertexArray = nullptr;
-
void checkError(const char *cmd, const char *file, int line) {
const GLenum err = glGetError();
if (err != GL_NO_ERROR) {
diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp
index 56d814c03a..f306dec2d3 100644
--- a/src/mbgl/renderer/painter.cpp
+++ b/src/mbgl/renderer/painter.cpp
@@ -4,6 +4,7 @@
#include <mbgl/map/tile.hpp>
#include <mbgl/platform/log.hpp>
+#include <mbgl/gl/debugging.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/style_layer.hpp>
@@ -56,18 +57,7 @@ bool Painter::needsAnimation() const {
}
void Painter::setup() {
- // Enable GL debugging
- if ((gl::DebugMessageControl != nullptr) && (gl::DebugMessageCallback != nullptr)) {
- // This will enable all messages including performance hints
- //MBGL_CHECK_ERROR(gl::DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, nullptr, GL_TRUE));
-
- // This will only enable high and medium severity messages
- MBGL_CHECK_ERROR(gl::DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr, GL_TRUE));
- MBGL_CHECK_ERROR(gl::DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr, GL_TRUE));
- MBGL_CHECK_ERROR(gl::DebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr, GL_FALSE));
-
- MBGL_CHECK_ERROR(gl::DebugMessageCallback(gl::debug_callback, nullptr));
- }
+ gl::debugging::enable();
setupShaders();
@@ -160,7 +150,7 @@ void Painter::changeMatrix() {
}
void Painter::clear() {
- gl::group group("clear");
+ gl::debugging::group group("clear");
config.stencilTest = true;
config.stencilMask = 0xFF;
config.depthTest = false;
@@ -212,7 +202,7 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time)
// - UPLOAD PASS -------------------------------------------------------------------------------
// Uploads all required buffers and images before we do any actual rendering.
{
- const gl::group upload("upload");
+ const gl::debugging::group upload("upload");
tileStencilBuffer.upload();
tileBorderBuffer.upload();
@@ -231,7 +221,7 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time)
// - CLIPPING MASKS ----------------------------------------------------------------------------
// Draws the clipping masks to the stencil buffer.
{
- const gl::group clip("clip");
+ const gl::debugging::group clip("clip");
// Update all clipping IDs.
ClipIDGenerator generator;
@@ -259,7 +249,7 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time)
// - OPAQUE PASS -------------------------------------------------------------------------------
// Render everything top-to-bottom by using reverse iterators. Render opaque objects first.
{
- const gl::group _("opaque");
+ const gl::debugging::group _("opaque");
if (debug::renderTree) {
Log::Info(Event::Render, "%*s%s", indent++ * 4, "", "OPAQUE {");
@@ -270,13 +260,13 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time)
const auto& item = *it;
if (item.bucket && item.tile) {
if (item.hasRenderPass(RenderPass::Opaque)) {
- const gl::group group(item.layer.id + " - " + std::string(item.tile->id));
+ const gl::debugging::group group(item.layer.id + " - " + std::string(item.tile->id));
setStrata(i * strata_thickness);
prepareTile(*item.tile);
item.bucket->render(*this, item.layer, item.tile->id, item.tile->matrix);
}
} else {
- const gl::group group("background");
+ const gl::debugging::group group("background");
setStrata(i * strata_thickness);
renderBackground(item.layer);
}
@@ -289,7 +279,7 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time)
// - TRANSLUCENT PASS --------------------------------------------------------------------------
// Make a second pass, rendering translucent objects. This time, we render bottom-to-top.
{
- const gl::group _("translucent");
+ const gl::debugging::group _("translucent");
if (debug::renderTree) {
Log::Info(Event::Render, "%*s%s", indent++ * 4, "", "TRANSLUCENT {");
@@ -300,7 +290,7 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time)
const auto& item = *it;
if (item.bucket && item.tile) {
if (item.hasRenderPass(RenderPass::Translucent)) {
- const gl::group group(item.layer.id + " - " + std::string(item.tile->id));
+ const gl::debugging::group group(item.layer.id + " - " + std::string(item.tile->id));
setStrata(i * strata_thickness);
prepareTile(*item.tile);
item.bucket->render(*this, item.layer, item.tile->id, item.tile->matrix);
@@ -317,7 +307,7 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time)
// - DEBUG PASS --------------------------------------------------------------------------------
// Renders debug overlays.
{
- const gl::group _("debug");
+ const gl::debugging::group _("debug");
// Finalize the rendering, e.g. by calling debug render calls per tile.
// This guarantees that we have at least one function per tile called.
@@ -331,10 +321,10 @@ void Painter::render(const Style& style, TransformState state_, TimePoint time)
// TODO: Find a better way to unbind VAOs after we're done with them without introducing
// unnecessary bind(0)/bind(N) sequences.
{
- const gl::group _("cleanup");
+ const gl::debugging::group _("cleanup");
MBGL_CHECK_ERROR(glBindTexture(GL_TEXTURE_2D, 0));
- MBGL_CHECK_ERROR(gl::BindVertexArray(0));
+ MBGL_CHECK_ERROR(VertexArrayObject::Bind(0));
}
}
diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp
index c495359282..c2a8e6f500 100644
--- a/src/mbgl/renderer/painter_clipping.cpp
+++ b/src/mbgl/renderer/painter_clipping.cpp
@@ -2,6 +2,7 @@
#include <mbgl/map/source.hpp>
#include <mbgl/shader/plain_shader.hpp>
#include <mbgl/util/clip_id.hpp>
+#include <mbgl/gl/debugging.hpp>
#ifndef BUFFER_OFFSET
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
@@ -10,7 +11,7 @@
using namespace mbgl;
void Painter::drawClippingMasks(const std::set<Source*>& sources) {
- gl::group group("clipping masks");
+ gl::debugging::group group("clipping masks");
useProgram(plainShader->program);
config.stencilTest = true;
diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp
index b252e2e835..d4306d3e1a 100644
--- a/src/mbgl/renderer/painter_debug.cpp
+++ b/src/mbgl/renderer/painter_debug.cpp
@@ -4,6 +4,7 @@
#include <mbgl/map/tile_data.hpp>
#include <mbgl/shader/plain_shader.hpp>
#include <mbgl/util/string.hpp>
+#include <mbgl/gl/debugging.hpp>
#ifndef BUFFER_OFFSET
#define BUFFER_OFFSET(i) ((char *)nullptr + (i))
@@ -12,7 +13,7 @@
using namespace mbgl;
void Painter::renderTileDebug(const Tile& tile) {
- gl::group group(std::string { "debug " } + std::string(tile.id));
+ gl::debugging::group group(std::string { "debug " } + std::string(tile.id));
assert(tile.data);
if (debug) {
prepareTile(tile);
@@ -22,7 +23,7 @@ void Painter::renderTileDebug(const Tile& tile) {
}
void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) {
- gl::group group("debug text");
+ gl::debugging::group group("debug text");
config.depthTest = false;
@@ -49,7 +50,7 @@ void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) {
}
void Painter::renderDebugFrame(const mat4 &matrix) {
- gl::group group("debug frame");
+ gl::debugging::group group("debug frame");
// Disable depth test and don't count this towards the depth buffer,
// but *don't* disable stencil test, as we want to clip the red tile border
@@ -72,7 +73,7 @@ void Painter::renderDebugText(const std::vector<std::string> &strings) {
return;
}
- gl::group group("debug text");
+ gl::debugging::group group("debug text");
config.depthTest = false;
config.stencilTest = true;