diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2015-05-12 14:35:26 -0700 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2015-05-13 19:01:58 -0700 |
commit | a2344c36c372445ee230832a0b742ac5ee739eb1 (patch) | |
tree | c733e1fff4d4b7e7a914d19f0838aeaaf1ca3aa7 | |
parent | 0f7c6b0b52ac76db3bb0064b4230229d9def62a8 (diff) | |
download | qtlocation-mapboxgl-a2344c36c372445ee230832a0b742ac5ee739eb1.tar.gz |
Extensible GL extension support
-rw-r--r-- | android/cpp/native_map_view.cpp | 87 | ||||
-rw-r--r-- | include/mbgl/platform/gl.hpp | 147 | ||||
-rw-r--r-- | platform/default/glfw_view.cpp | 81 | ||||
-rw-r--r-- | platform/default/headless_view.cpp | 57 | ||||
-rw-r--r-- | platform/ios/MGLMapView.mm | 24 | ||||
-rw-r--r-- | src/mbgl/geometry/vao.cpp | 42 | ||||
-rw-r--r-- | src/mbgl/geometry/vao.hpp | 3 | ||||
-rw-r--r-- | src/mbgl/gl/debugging.cpp | 195 | ||||
-rw-r--r-- | src/mbgl/gl/debugging.hpp | 21 | ||||
-rw-r--r-- | src/mbgl/map/environment.cpp | 5 | ||||
-rw-r--r-- | src/mbgl/map/source.cpp | 3 | ||||
-rw-r--r-- | src/mbgl/platform/gl.cpp | 78 | ||||
-rw-r--r-- | src/mbgl/renderer/painter.cpp | 36 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_clipping.cpp | 3 | ||||
-rw-r--r-- | src/mbgl/renderer/painter_debug.cpp | 9 |
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; |