diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index e98f99911..8fc71bf28 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -58,10 +58,11 @@ set(MBGL_CORE_FILES src/mbgl/gl/context.hpp src/mbgl/gl/debugging.cpp src/mbgl/gl/debugging.hpp + src/mbgl/gl/debugging_extension.cpp + src/mbgl/gl/debugging_extension.hpp src/mbgl/gl/depth_mode.cpp src/mbgl/gl/depth_mode.hpp src/mbgl/gl/draw_mode.hpp - src/mbgl/gl/extension.cpp src/mbgl/gl/extension.hpp src/mbgl/gl/features.hpp src/mbgl/gl/framebuffer.hpp @@ -71,8 +72,7 @@ set(MBGL_CORE_FILES src/mbgl/gl/object.hpp src/mbgl/gl/primitives.hpp src/mbgl/gl/program.hpp - src/mbgl/gl/program_binary.cpp - src/mbgl/gl/program_binary.hpp + src/mbgl/gl/program_binary_extension.hpp src/mbgl/gl/renderbuffer.hpp src/mbgl/gl/segment.cpp src/mbgl/gl/segment.hpp @@ -85,8 +85,7 @@ set(MBGL_CORE_FILES src/mbgl/gl/uniform.hpp src/mbgl/gl/value.cpp src/mbgl/gl/value.hpp - src/mbgl/gl/vertex_array.cpp - src/mbgl/gl/vertex_array.hpp + src/mbgl/gl/vertex_array_extension.hpp src/mbgl/gl/vertex_buffer.hpp # layout diff --git a/platform/glfw/glfw_view.cpp b/platform/glfw/glfw_view.cpp index 812b0e32a..82f075fd6 100644 --- a/platform/glfw/glfw_view.cpp +++ b/platform/glfw/glfw_view.cpp @@ -459,7 +459,7 @@ void GLFWView::run() { if (dirty) { const double started = glfwGetTime(); - glfwMakeContextCurrent(window); + activate(); mbgl::BackendScope scope { *this, mbgl::BackendScope::ScopeType::Implicit }; updateViewBinding(); diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 97ebf687f..75931dc9d 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -1,8 +1,9 @@ #include #include #include -#include -#include +#include +#include +#include #include #include #include @@ -37,10 +38,58 @@ static_assert(underlying_type(TextureFormat::Alpha) == GL_ALPHA, "OpenGL type mi static_assert(std::is_same::value, "OpenGL type mismatch"); +Context::Context() = default; + Context::~Context() { reset(); } +void Context::initializeExtensions(const std::function& getProcAddress) { + if (const char* extensions = + reinterpret_cast(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)))) { + + auto fn = [&]( + std::initializer_list> probes) -> ProcAddress { + for (auto probe : probes) { + if (strstr(extensions, probe.first) != nullptr) { + if (ProcAddress ptr = getProcAddress(probe.second)) { + return ptr; + } + } + } + return nullptr; + }; + + debugging = std::make_unique(fn); + if (!disableVAOExtension) { + vertexArray = std::make_unique(fn); + } +#if MBGL_HAS_BINARY_PROGRAMS + programBinary = std::make_unique(fn); +#endif + + if (!supportsVertexArrays()) { + Log::Warning(Event::OpenGL, "Not using Vertex Array Objects"); + } + } +} + +void Context::enableDebugging() { + if (!debugging || !debugging->debugMessageControl || !debugging->debugMessageCallback) { + return; + } + + // This will enable all messages including performance hints + // MBGL_CHECK_ERROR(debugging->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(debugging->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_HIGH, 0, nullptr, GL_TRUE)); + MBGL_CHECK_ERROR(debugging->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_MEDIUM, 0, nullptr, GL_TRUE)); + MBGL_CHECK_ERROR(debugging->debugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DEBUG_SEVERITY_NOTIFICATION, 0, nullptr, GL_FALSE)); + + MBGL_CHECK_ERROR(debugging->debugMessageCallback(extension::Debugging::DebugCallback, nullptr)); +} + UniqueShader Context::createShader(ShaderType type, const std::string& source) { UniqueShader result { MBGL_CHECK_ERROR(glCreateShader(static_cast(type))), { this } }; @@ -78,9 +127,11 @@ UniqueProgram Context::createProgram(ShaderID vertexShader, ShaderID fragmentSha #if MBGL_HAS_BINARY_PROGRAMS UniqueProgram Context::createProgram(BinaryProgramFormat binaryFormat, const std::string& binaryProgram) { + assert(supportsProgramBinaries()); UniqueProgram result{ MBGL_CHECK_ERROR(glCreateProgram()), { this } }; - MBGL_CHECK_ERROR(ProgramBinary(result, static_cast(binaryFormat), binaryProgram.data(), - static_cast(binaryProgram.size()))); + MBGL_CHECK_ERROR(programBinary->programBinary(result, static_cast(binaryFormat), + binaryProgram.data(), + static_cast(binaryProgram.size()))); verifyProgramLinkage(result); return result; } @@ -144,15 +195,15 @@ UniqueTexture Context::createTexture() { } bool Context::supportsVertexArrays() const { - return gl::GenVertexArrays && - gl::BindVertexArray && - gl::DeleteVertexArrays && - !disableVAOExtension; + return vertexArray && + vertexArray->genVertexArrays && + vertexArray->bindVertexArray && + vertexArray->deleteVertexArrays; } #if MBGL_HAS_BINARY_PROGRAMS bool Context::supportsProgramBinaries() const { - return gl::ProgramBinary && gl::GetProgramBinary; + return programBinary && programBinary->programBinary && programBinary->getProgramBinary; } optional> @@ -165,8 +216,8 @@ Context::getBinaryProgram(ProgramID program_) const { std::string binary; binary.resize(binaryLength); GLenum binaryFormat; - MBGL_CHECK_ERROR(GetProgramBinary(program_, binaryLength, &binaryLength, &binaryFormat, - const_cast(binary.data()))); + MBGL_CHECK_ERROR(programBinary->getProgramBinary( + program_, binaryLength, &binaryLength, &binaryFormat, const_cast(binary.data()))); if (size_t(binaryLength) != binary.size()) { return {}; } @@ -181,7 +232,7 @@ optional> Context::getBinaryProgram( UniqueVertexArray Context::createVertexArray() { assert(supportsVertexArrays()); VertexArrayID id = 0; - MBGL_CHECK_ERROR(gl::GenVertexArrays(1, &id)); + MBGL_CHECK_ERROR(vertexArray->genVertexArrays(1, &id)); return UniqueVertexArray(std::move(id), { this }); } @@ -584,8 +635,8 @@ void Context::performCleanup() { vertexArrayObject.setDirty(); } } - MBGL_CHECK_ERROR(gl::DeleteVertexArrays(int(abandonedVertexArrays.size()), - abandonedVertexArrays.data())); + MBGL_CHECK_ERROR(vertexArray->deleteVertexArrays(int(abandonedVertexArrays.size()), + abandonedVertexArrays.data())); abandonedVertexArrays.clear(); } diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index 10ff4360d..14af299ba 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -30,11 +30,23 @@ class View; namespace gl { constexpr size_t TextureMax = 64; +using ProcAddress = void (*)(); + +namespace extension { +class VertexArray; +class Debugging; +class ProgramBinary; +} // namespace extension class Context : private util::noncopyable { public: + Context(); ~Context(); + void initializeExtensions(const std::function&); + + void enableDebugging(); + UniqueShader createShader(ShaderType type, const std::string& source); UniqueProgram createProgram(ShaderID vertexShader, ShaderID fragmentShader); UniqueProgram createProgram(BinaryProgramFormat binaryFormat, const std::string& binaryProgram); @@ -164,11 +176,27 @@ public: void setDirtyState(); + extension::Debugging* getDebuggingExtension() const { + return debugging.get(); + } + + extension::VertexArray* getVertexArrayExtension() const { + return vertexArray.get(); + } + +private: + std::unique_ptr debugging; + std::unique_ptr vertexArray; +#if MBGL_HAS_BINARY_PROGRAMS + std::unique_ptr programBinary; +#endif + +public: State activeTexture; State bindFramebuffer; State viewport; std::array, 2> texture; - State vertexArrayObject; + State vertexArrayObject { *this }; State program; State vertexBuffer; State elementBuffer; diff --git a/src/mbgl/gl/debugging.cpp b/src/mbgl/gl/debugging.cpp index 5ce3e606e..0d69d58be 100644 --- a/src/mbgl/gl/debugging.cpp +++ b/src/mbgl/gl/debugging.cpp @@ -1,193 +1,33 @@ #include -#include -#include -#include -#include - -#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 +#include +#include 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"} - }); - -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)); -} #ifndef NDEBUG -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"} - }); - -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() + 1), str.c_str()); +DebugGroup::DebugGroup(const Context& context_, const std::string& name) : context(context_) { + if (auto debugging = context.getDebuggingExtension()) { + if (debugging->pushDebugGroup) { + debugging->pushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, GLsizei(name.size()), name.c_str()); + } else if (debugging->pushGroupMarkerEXT) { + debugging->pushGroupMarkerEXT(GLsizei(name.size() + 1), name.c_str()); + } } } -group::~group() { - if (PopDebugGroup) { - PopDebugGroup(); - } else if (PopGroupMarkerEXT) { - PopGroupMarkerEXT(); +DebugGroup::~DebugGroup() { + if (auto debugging = context.getDebuggingExtension()) { + if (debugging->popDebugGroup) { + debugging->popDebugGroup(); + } else if (debugging->popGroupMarkerEXT) { + debugging->popGroupMarkerEXT(); + } } } + #endif -} // namespace debugging } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/debugging.hpp b/src/mbgl/gl/debugging.hpp index fe363701a..d24b72729 100644 --- a/src/mbgl/gl/debugging.hpp +++ b/src/mbgl/gl/debugging.hpp @@ -1,26 +1,34 @@ #pragma once +#include + #include namespace mbgl { namespace gl { -namespace debugging { -void enable(); +class Context; #ifndef NDEBUG -struct group { - group(const std::string&); - ~group(); + +class DebugGroup : private util::noncopyable { +public: + DebugGroup(const Context&, const std::string&); + ~DebugGroup(); + +private: + const Context& context; }; #define __MBGL_DEBUG_GROUP_NAME2(counter) __MBGL_DEBUG_GROUP_##counter #define __MBGL_DEBUG_GROUP_NAME(counter) __MBGL_DEBUG_GROUP_NAME2(counter) -#define MBGL_DEBUG_GROUP(string) ::mbgl::gl::debugging::group __MBGL_DEBUG_GROUP_NAME(__LINE__)(string); +#define MBGL_DEBUG_GROUP(context, name) const ::mbgl::gl::DebugGroup __MBGL_DEBUG_GROUP_NAME(__LINE__)(context, name); + #else -#define MBGL_DEBUG_GROUP(string) + +#define MBGL_DEBUG_GROUP(context, name) + #endif -} // namespace debugging } // namespace gl } // namespace mbgl diff --git a/src/mbgl/gl/debugging_extension.cpp b/src/mbgl/gl/debugging_extension.cpp new file mode 100644 index 000000000..5afa4f50f --- /dev/null +++ b/src/mbgl/gl/debugging_extension.cpp @@ -0,0 +1,55 @@ +#include +#include + +namespace mbgl { +namespace gl { +namespace extension { + +void Debugging::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); +} + +} // namespace extension +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/debugging_extension.hpp b/src/mbgl/gl/debugging_extension.hpp new file mode 100644 index 000000000..c1835cfcd --- /dev/null +++ b/src/mbgl/gl/debugging_extension.hpp @@ -0,0 +1,120 @@ +#pragma once + +#include +#include + +#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 extension { + +class Debugging { +public: + typedef void (*Callback)(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei length, + const GLchar* message, + const void* userParam); + + static void DebugCallback(GLenum source, + GLenum type, + GLuint id, + GLenum severity, + GLsizei /* length */, + const GLchar* message, + const void* /* userParam */); + + template + Debugging(const Fn& loadExtension) + : +#ifndef NDEBUG + pushDebugGroup( + loadExtension({ { "GL_KHR_debug", "glPushDebugGroup" } })), + popDebugGroup( + loadExtension({ { "GL_KHR_debug", "glPopDebugGroup" } })), + pushGroupMarkerEXT( + loadExtension({ { "GL_EXT_debug_marker", "glPushGroupMarkerEXT" } })), + popGroupMarkerEXT( + loadExtension({ { "GL_EXT_debug_marker", "glPopGroupMarkerEXT" } })), +#endif + debugMessageControl( + loadExtension({ { "GL_KHR_debug", "glDebugMessageControl" }, + { "GL_ARB_debug_output", "glDebugMessageControlARB" } })), + debugMessageCallback( + loadExtension({ { "GL_KHR_debug", "glDebugMessageCallback" }, + { "GL_ARB_debug_output", "glDebugMessageCallbackARB" } })) { + } + +#ifndef NDEBUG + const ExtensionFunction pushDebugGroup; + + const ExtensionFunction popDebugGroup; + + const ExtensionFunction pushGroupMarkerEXT; + + const ExtensionFunction popGroupMarkerEXT; +#endif + + const ExtensionFunction debugMessageControl; + + const ExtensionFunction debugMessageCallback; +}; + +} // namespace extension +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/gl/extension.cpp b/src/mbgl/gl/extension.cpp deleted file mode 100644 index 41a5ea175..000000000 --- a/src/mbgl/gl/extension.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include -#include - -#include -#include -#include - -namespace mbgl { -namespace gl { -namespace detail { - -using Probes = std::vector; -using ExtensionFunctions = std::vector>; -ExtensionFunctions& extensionFunctions() { - static ExtensionFunctions functions; - return functions; -} - -ExtensionFunctionBase::ExtensionFunctionBase(std::initializer_list probes) { - extensionFunctions().emplace_back(&ptr, probes); -} - -} // namespace detail - -void initializeExtensions(const std::function& getProcAddress) { - if (const char* extensions = - reinterpret_cast(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)))) { - for (auto fn : detail::extensionFunctions()) { - for (auto probe : fn.second) { - if (strstr(extensions, probe.first) != nullptr) { - *fn.first = getProcAddress(probe.second); - break; - } - } - } - } -} - -} // namespace gl -} // namespace mbgl diff --git a/src/mbgl/gl/extension.hpp b/src/mbgl/gl/extension.hpp index 7d1d9a4d7..8710314ef 100644 --- a/src/mbgl/gl/extension.hpp +++ b/src/mbgl/gl/extension.hpp @@ -8,26 +8,15 @@ namespace mbgl { namespace gl { using ProcAddress = void (*)(); -void initializeExtensions(const std::function&); - -namespace detail { - -class ExtensionFunctionBase { -public: - using Probe = std::pair; - ExtensionFunctionBase(std::initializer_list); - ProcAddress ptr; -}; - -} // namespace detail template class ExtensionFunction; template -class ExtensionFunction : protected detail::ExtensionFunctionBase { +class ExtensionFunction { public: - using detail::ExtensionFunctionBase::ExtensionFunctionBase; + ExtensionFunction(const ProcAddress ptr_) : ptr(ptr_) { + } explicit operator bool() const { return ptr; @@ -36,6 +25,9 @@ public: R operator()(Args... args) const { return (*reinterpret_cast(ptr))(std::forward(args)...); } + +private: + const ProcAddress ptr; }; } // namespace gl diff --git a/src/mbgl/gl/program_binary.cpp b/src/mbgl/gl/program_binary.cpp deleted file mode 100644 index ad147c819..000000000 --- a/src/mbgl/gl/program_binary.cpp +++ /dev/null @@ -1,24 +0,0 @@ -#include - -#if MBGL_HAS_BINARY_PROGRAMS - -namespace mbgl { -namespace gl { - -ExtensionFunction< - void(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)> - GetProgramBinary({ - { "GL_OES_get_program_binary", "glGetProgramBinaryOES" }, - { "GL_ARB_get_program_binary", "glGetProgramBinary" }, - }); - -ExtensionFunction - ProgramBinary({ - { "GL_OES_get_program_binary", "glProgramBinaryOES" }, - { "GL_ARB_get_program_binary", "glProgramBinary" }, - }); - -} // namespace gl -} // namespace mbgl - -#endif diff --git a/src/mbgl/gl/program_binary.hpp b/src/mbgl/gl/program_binary.hpp deleted file mode 100644 index e888ed3d4..000000000 --- a/src/mbgl/gl/program_binary.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include -#include - -#if MBGL_HAS_BINARY_PROGRAMS - -#define GL_PROGRAM_BINARY_LENGTH 0x8741 -#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE -#define GL_PROGRAM_BINARY_FORMATS 0x87FF - -namespace mbgl { -namespace gl { - -extern ExtensionFunction - GetProgramBinary; - -extern ExtensionFunction - ProgramBinary; - -} // namespace gl -} // namespace mbgl - -#endif diff --git a/src/mbgl/gl/program_binary_extension.hpp b/src/mbgl/gl/program_binary_extension.hpp new file mode 100644 index 000000000..a4aa1eeef --- /dev/null +++ b/src/mbgl/gl/program_binary_extension.hpp @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include + +#if MBGL_HAS_BINARY_PROGRAMS + +#define GL_PROGRAM_BINARY_LENGTH 0x8741 +#define GL_NUM_PROGRAM_BINARY_FORMATS 0x87FE +#define GL_PROGRAM_BINARY_FORMATS 0x87FF + +namespace mbgl { +namespace gl { +namespace extension { + +class ProgramBinary { +public: + template + ProgramBinary(const Fn& loadExtension) + : getProgramBinary(loadExtension({ + { "GL_OES_get_program_binary", "glGetProgramBinaryOES" }, + { "GL_ARB_get_program_binary", "glGetProgramBinary" }, + })), + programBinary(loadExtension({ + { "GL_OES_get_program_binary", "glProgramBinaryOES" }, + { "GL_ARB_get_program_binary", "glProgramBinary" }, + })) { + } + + const ExtensionFunction + getProgramBinary; + + const ExtensionFunction + programBinary; +}; + +} // namespace extension +} // namespace gl +} // namespace mbgl + +#endif diff --git a/src/mbgl/gl/segment.hpp b/src/mbgl/gl/segment.hpp index bd4926476..45c81973f 100644 --- a/src/mbgl/gl/segment.hpp +++ b/src/mbgl/gl/segment.hpp @@ -5,7 +5,6 @@ #include #include -#include #include #include @@ -47,10 +46,6 @@ public: } } else { // No VAO support. Force attributes to be rebound. - static std::once_flag reportedOnce; - std::call_once(reportedOnce, [] { - Log::Warning(Event::OpenGL, "Not using Vertex Array Objects"); - }); context.elementBuffer = indexBuffer_; variableBindings = {}; } diff --git a/src/mbgl/gl/state.hpp b/src/mbgl/gl/state.hpp index efe869e5b..f3268229d 100644 --- a/src/mbgl/gl/state.hpp +++ b/src/mbgl/gl/state.hpp @@ -1,5 +1,7 @@ #pragma once +#include + namespace mbgl { namespace gl { @@ -12,13 +14,16 @@ namespace gl { // static void Set(const Type& value); // static Type Get(); // }; -template +template class State { public: + State(Args&&... args) : params(std::forward_as_tuple(::std::forward(args)...)) { + } + void operator=(const typename T::Type& value) { if (*this != value) { setCurrentValue(value); - T::Set(currentValue); + set(std::index_sequence_for{}); } } @@ -49,23 +54,44 @@ public: return dirty; } +private: + template + void set(std::index_sequence) { + T::Set(currentValue, std::get(params)...); + } + private: typename T::Type currentValue = T::Default; bool dirty = true; + const std::tuple params; }; // Helper struct that stores the current state and restores it upon destruction. You should not use // this code normally, except for debugging purposes. -template +template class PreserveState { public: - PreserveState() : value(T::Get()) { + PreserveState(Args&&... args) + : params(std::forward_as_tuple(std::forward(args)...)), + value(get(std::index_sequence_for{})) { } ~PreserveState() { - T::Set(value); + set(std::index_sequence_for{}); } private: + template + typename T::Type get(std::index_sequence) { + return T::Get(std::get(params)...); + } + + template + void set(std::index_sequence) { + T::Set(value, std::get(params)...); + } + +private: + const std::tuple params; const typename T::Type value; }; diff --git a/src/mbgl/gl/value.cpp b/src/mbgl/gl/value.cpp index 603d82dfd..c081c941f 100644 --- a/src/mbgl/gl/value.cpp +++ b/src/mbgl/gl/value.cpp @@ -1,6 +1,7 @@ #include #include -#include +#include +#include namespace mbgl { namespace gl { @@ -328,15 +329,17 @@ BindElementBuffer::Type BindElementBuffer::Get() { const constexpr BindVertexArray::Type BindVertexArray::Default; -void BindVertexArray::Set(const Type& value) { - if (gl::BindVertexArray) { - MBGL_CHECK_ERROR(gl::BindVertexArray(value)); +void BindVertexArray::Set(const Type& value, const Context& context) { + if (auto vertexArray = context.getVertexArrayExtension()) { + if (vertexArray->bindVertexArray) { + MBGL_CHECK_ERROR(vertexArray->bindVertexArray(value)); + } } } -BindVertexArray::Type BindVertexArray::Get() { +BindVertexArray::Type BindVertexArray::Get(const Context& context) { GLint binding = 0; - if (gl::BindVertexArray) { + if (context.getVertexArrayExtension()) { #ifdef GL_VERTEX_ARRAY_BINDING MBGL_CHECK_ERROR(glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &binding)); #elif GL_VERTEX_ARRAY_BINDING_OES diff --git a/src/mbgl/gl/value.hpp b/src/mbgl/gl/value.hpp index eccd3e737..aa5cca6fe 100644 --- a/src/mbgl/gl/value.hpp +++ b/src/mbgl/gl/value.hpp @@ -10,6 +10,9 @@ namespace mbgl { namespace gl { + +class Context; + namespace value { struct ClearDepth { @@ -225,8 +228,8 @@ struct BindElementBuffer { struct BindVertexArray { using Type = gl::VertexArrayID; static const constexpr Type Default = 0; - static void Set(const Type&); - static Type Get(); + static void Set(const Type&, const Context&); + static Type Get(const Context&); }; #if not MBGL_USE_GLES2 diff --git a/src/mbgl/gl/vertex_array.cpp b/src/mbgl/gl/vertex_array.cpp deleted file mode 100644 index df63bbc4b..000000000 --- a/src/mbgl/gl/vertex_array.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include - -namespace mbgl { -namespace gl { - -ExtensionFunction - BindVertexArray({ { "GL_ARB_vertex_array_object", "glBindVertexArray" }, - { "GL_OES_vertex_array_object", "glBindVertexArrayOES" }, - { "GL_APPLE_vertex_array_object", "glBindVertexArrayAPPLE" } }); - -ExtensionFunction - DeleteVertexArrays({ { "GL_ARB_vertex_array_object", "glDeleteVertexArrays" }, - { "GL_OES_vertex_array_object", "glDeleteVertexArraysOES" }, - { "GL_APPLE_vertex_array_object", "glDeleteVertexArraysAPPLE" } }); - -ExtensionFunction - GenVertexArrays({ { "GL_ARB_vertex_array_object", "glGenVertexArrays" }, - { "GL_OES_vertex_array_object", "glGenVertexArraysOES" }, - { "GL_APPLE_vertex_array_object", "glGenVertexArraysAPPLE" } }); - -} // namespace gl -} // namespace mbgl diff --git a/src/mbgl/gl/vertex_array.hpp b/src/mbgl/gl/vertex_array.hpp deleted file mode 100644 index 6b6e11324..000000000 --- a/src/mbgl/gl/vertex_array.hpp +++ /dev/null @@ -1,14 +0,0 @@ -#pragma once - -#include -#include - -namespace mbgl { -namespace gl { - -extern ExtensionFunction BindVertexArray; -extern ExtensionFunction DeleteVertexArrays; -extern ExtensionFunction GenVertexArrays; - -} // namespace gl -} // namespace mbgl diff --git a/src/mbgl/gl/vertex_array_extension.hpp b/src/mbgl/gl/vertex_array_extension.hpp new file mode 100644 index 000000000..707a20e6f --- /dev/null +++ b/src/mbgl/gl/vertex_array_extension.hpp @@ -0,0 +1,37 @@ +#pragma once + +#include +#include + +namespace mbgl { +namespace gl { +namespace extension { + +class VertexArray { +public: + template + VertexArray(const Fn& loadExtension) + : bindVertexArray( + loadExtension({ { "GL_ARB_vertex_array_object", "glBindVertexArray" }, + { "GL_OES_vertex_array_object", "glBindVertexArrayOES" }, + { "GL_APPLE_vertex_array_object", "glBindVertexArrayAPPLE" } })), + deleteVertexArrays( + loadExtension({ { "GL_ARB_vertex_array_object", "glDeleteVertexArrays" }, + { "GL_OES_vertex_array_object", "glDeleteVertexArraysOES" }, + { "GL_APPLE_vertex_array_object", "glDeleteVertexArraysAPPLE" } })), + genVertexArrays( + loadExtension({ { "GL_ARB_vertex_array_object", "glGenVertexArrays" }, + { "GL_OES_vertex_array_object", "glGenVertexArraysOES" }, + { "GL_APPLE_vertex_array_object", "glGenVertexArraysAPPLE" } })) { + } + + const ExtensionFunction bindVertexArray; + + const ExtensionFunction deleteVertexArrays; + + const ExtensionFunction genVertexArrays; +}; + +} // namespace extension +} // namespace gl +} // namespace mbgl diff --git a/src/mbgl/map/backend.cpp b/src/mbgl/map/backend.cpp index 29f7522e4..c228719ba 100644 --- a/src/mbgl/map/backend.cpp +++ b/src/mbgl/map/backend.cpp @@ -14,8 +14,8 @@ gl::Context& Backend::getContext() { assert(BackendScope::exists()); std::call_once(initialized, [this] { context = std::make_unique(); - gl::debugging::enable(); - gl::initializeExtensions( + context->enableDebugging(); + context->initializeExtensions( std::bind(&Backend::initializeExtension, this, std::placeholders::_1)); }); return *context; diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 73a084c8c..f7a498eca 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -150,7 +150,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp // - UPLOAD PASS ------------------------------------------------------------------------------- // Uploads all required buffers and images before we do any actual rendering. { - MBGL_DEBUG_GROUP("upload"); + MBGL_DEBUG_GROUP(context, "upload"); spriteAtlas->upload(context, 0); @@ -170,7 +170,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp // Renders the backdrop of the OpenGL view. This also paints in areas where we don't have any // tiles whatsoever. { - MBGL_DEBUG_GROUP("clear"); + MBGL_DEBUG_GROUP(context, "clear"); view.bind(); context.clear(paintMode() == PaintMode::Overdraw ? Color::black() @@ -182,7 +182,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp // - CLIPPING MASKS ---------------------------------------------------------------------------- // Draws the clipping masks to the stencil buffer. { - MBGL_DEBUG_GROUP("clip"); + MBGL_DEBUG_GROUP(context, "clip"); // Update all clipping IDs. algorithm::ClipIDGenerator generator; @@ -190,10 +190,10 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp source->baseImpl->startRender(generator, projMatrix, state); } - MBGL_DEBUG_GROUP("clipping masks"); + MBGL_DEBUG_GROUP(context, "clipping masks"); for (const auto& stencil : generator.getStencils()) { - MBGL_DEBUG_GROUP(std::string{ "mask: " } + util::toString(stencil.first)); + MBGL_DEBUG_GROUP(context, std::string{ "mask: " } + util::toString(stencil.first)); renderClippingMask(stencil.first, stencil.second); } } @@ -230,7 +230,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp // - DEBUG PASS -------------------------------------------------------------------------------- // Renders debug overlays. { - MBGL_DEBUG_GROUP("debug"); + MBGL_DEBUG_GROUP(context, "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. @@ -250,7 +250,7 @@ void Painter::render(const Style& style, const FrameData& frame_, View& view, Sp // TODO: Find a better way to unbind VAOs after we're done with them without introducing // unnecessary bind(0)/bind(N) sequences. { - MBGL_DEBUG_GROUP("cleanup"); + MBGL_DEBUG_GROUP(context, "cleanup"); context.activeTexture = 1; context.texture[1] = 0; @@ -268,7 +268,7 @@ void Painter::renderPass(PaintParameters& parameters, uint32_t i, int8_t increment) { pass = pass_; - MBGL_DEBUG_GROUP(pass == RenderPass::Opaque ? "opaque" : "translucent"); + MBGL_DEBUG_GROUP(context, pass == RenderPass::Opaque ? "opaque" : "translucent"); if (debug::renderTree) { Log::Info(Event::Render, "%*s%s {", indent++ * 4, "", @@ -285,10 +285,10 @@ void Painter::renderPass(PaintParameters& parameters, continue; if (layer.is()) { - MBGL_DEBUG_GROUP("background"); + MBGL_DEBUG_GROUP(context, "background"); renderBackground(parameters, *layer.as()); } else if (layer.is()) { - MBGL_DEBUG_GROUP(layer.baseImpl->id + " - custom"); + MBGL_DEBUG_GROUP(context, layer.baseImpl->id + " - custom"); // Reset GL state to a known state so the CustomLayer always has a clean slate. context.vertexArrayObject = 0; @@ -303,7 +303,7 @@ void Painter::renderPass(PaintParameters& parameters, parameters.view.bind(); context.setDirtyState(); } else { - MBGL_DEBUG_GROUP(layer.baseImpl->id + " - " + util::toString(item.tile->id)); + MBGL_DEBUG_GROUP(context, layer.baseImpl->id + " - " + util::toString(item.tile->id)); item.bucket->render(*this, parameters, layer, *item.tile); } } diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp index 5b347884b..37fa3bcb1 100644 --- a/src/mbgl/renderer/painter_debug.cpp +++ b/src/mbgl/renderer/painter_debug.cpp @@ -18,7 +18,7 @@ void Painter::renderTileDebug(const RenderTile& renderTile) { if (frame.debugOptions == MapDebugOptions::NoDebug) return; - MBGL_DEBUG_GROUP(std::string { "debug " } + util::toString(renderTile.id)); + MBGL_DEBUG_GROUP(context, std::string { "debug " } + util::toString(renderTile.id)); static const style::PaintProperties<>::Evaluated properties {}; static const DebugProgram::PaintPropertyBinders paintAttibuteData(properties, 0);