diff options
25 files changed, 102 insertions, 110 deletions
diff --git a/include/mbgl/map/backend.hpp b/include/mbgl/map/backend.hpp index cd756abe43..876c19261b 100644 --- a/include/mbgl/map/backend.hpp +++ b/include/mbgl/map/backend.hpp @@ -3,11 +3,13 @@ #include <mbgl/map/map_observer.hpp> #include <memory> +#include <mutex> namespace mbgl { namespace gl { class Context; +using ProcAddress = void (*)(); } // namespace gl class BackendScope; @@ -25,6 +27,11 @@ public: virtual void invalidate() = 0; protected: + // Called with the name of an OpenGL extension that should be loaded. Backend implementations + // must call the API-specific version that obtains the function pointer for this function, + // or a null pointer if unsupported/unavailable. + virtual gl::ProcAddress initializeExtension(const char*) = 0; + // Called when the backend's GL context needs to be made active or inactive. These are called, // as a matched pair, in four situations: // @@ -38,8 +45,12 @@ protected: virtual void activate() = 0; virtual void deactivate() = 0; +protected: std::unique_ptr<gl::Context> context; +private: + std::once_flag initialized; + friend class BackendScope; }; diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index c65c241458..eeb4620c2e 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -15,7 +15,6 @@ #include <jni/jni.hpp> #include <mbgl/gl/context.hpp> -#include <mbgl/gl/extension.hpp> #include <mbgl/map/backend_scope.hpp> #include <mbgl/util/constants.hpp> #include <mbgl/util/event.hpp> @@ -108,6 +107,10 @@ void NativeMapView::bind() { /** * From mbgl::Backend. */ +gl::ProcAddress NativeMapView::initializeExtension(const char* name) { + return eglGetProcAddress(name); +} + void NativeMapView::activate() { if (active++) { return; @@ -1394,10 +1397,6 @@ void NativeMapView::_createSurface(ANativeWindow *window_) { eglGetError()); throw std::runtime_error("eglMakeCurrent() failed"); } - - mbgl::gl::InitializeExtensions([] (const char * name) { - return reinterpret_cast<mbgl::gl::glProc>(eglGetProcAddress(name)); - }); } } diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp index 9a490ddbae..af8c7dd660 100755 --- a/platform/android/src/native_map_view.hpp +++ b/platform/android/src/native_map_view.hpp @@ -262,6 +262,7 @@ public: protected: // mbgl::Backend // + gl::ProcAddress initializeExtension(const char*) override; void activate() override; void deactivate() override; diff --git a/platform/darwin/src/headless_backend_cgl.cpp b/platform/darwin/src/headless_backend_cgl.cpp index 7069738fb1..6ad98f4326 100644 --- a/platform/darwin/src/headless_backend_cgl.cpp +++ b/platform/darwin/src/headless_backend_cgl.cpp @@ -36,7 +36,7 @@ struct CGLImpl : public HeadlessBackend::Impl { CGLContextObj glContext = nullptr; }; -gl::glProc HeadlessBackend::initializeExtension(const char* name) { +gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); if (!framework) { throw std::runtime_error("Failed to load OpenGL framework."); @@ -46,7 +46,7 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) { void* symbol = CFBundleGetFunctionPointerForName(framework, str); CFRelease(str); - return reinterpret_cast<gl::glProc>(symbol); + return reinterpret_cast<gl::ProcAddress>(symbol); } bool HeadlessBackend::hasDisplay() { diff --git a/platform/darwin/src/headless_backend_eagl.mm b/platform/darwin/src/headless_backend_eagl.mm index bd4a202ec5..1daaeaf54c 100644 --- a/platform/darwin/src/headless_backend_eagl.mm +++ b/platform/darwin/src/headless_backend_eagl.mm @@ -1,7 +1,5 @@ #include <mbgl/gl/headless_backend.hpp> -#include <mbgl/gl/extension.hpp> - #include <OpenGLES/EAGL.h> #include <stdexcept> @@ -29,7 +27,7 @@ struct EAGLImpl : public HeadlessBackend::Impl { EAGLContext* glContext = nullptr; }; -gl::glProc HeadlessBackend::initializeExtension(const char* name) { +gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles")); if (!framework) { throw std::runtime_error("Failed to load OpenGL framework."); @@ -39,7 +37,7 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) { void* symbol = CFBundleGetFunctionPointerForName(framework, str); CFRelease(str); - return reinterpret_cast<gl::glProc>(symbol); + return reinterpret_cast<gl::ProcAddress>(symbol); } bool HeadlessBackend::hasDisplay() { diff --git a/platform/default/headless_backend_osmesa.cpp b/platform/default/headless_backend_osmesa.cpp index 8ec6079bd0..5042f5ed10 100644 --- a/platform/default/headless_backend_osmesa.cpp +++ b/platform/default/headless_backend_osmesa.cpp @@ -25,7 +25,7 @@ struct OSMesaImpl : public HeadlessBackend::Impl { GLubyte fakeBuffer = 0; }; -gl::glProc HeadlessBackend::initializeExtension(const char* name) { +gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { return OSMesaGetProcAddress(name); } diff --git a/platform/default/mbgl/gl/headless_backend.cpp b/platform/default/mbgl/gl/headless_backend.cpp index 6ae19356fb..798c8fe680 100644 --- a/platform/default/mbgl/gl/headless_backend.cpp +++ b/platform/default/mbgl/gl/headless_backend.cpp @@ -33,11 +33,6 @@ void HeadlessBackend::activate() { assert(hasContext()); impl->activateContext(); - - if (!extensionsLoaded) { - gl::InitializeExtensions(initializeExtension); - extensionsLoaded = true; - } } void HeadlessBackend::deactivate() { diff --git a/platform/default/mbgl/gl/headless_backend.hpp b/platform/default/mbgl/gl/headless_backend.hpp index 63e3cec9ee..7e1749a253 100644 --- a/platform/default/mbgl/gl/headless_backend.hpp +++ b/platform/default/mbgl/gl/headless_backend.hpp @@ -1,7 +1,5 @@ #pragma once -#include <mbgl/gl/extension.hpp> - #include <mbgl/map/backend.hpp> #include <memory> @@ -27,7 +25,7 @@ public: private: // Implementation specific functions - static gl::glProc initializeExtension(const char*); + gl::ProcAddress initializeExtension(const char*) override; void activate() override; void deactivate() override; @@ -40,7 +38,6 @@ private: std::unique_ptr<Impl> impl; std::shared_ptr<HeadlessDisplay> display; - bool extensionsLoaded = false; bool active = false; }; diff --git a/platform/glfw/glfw_view.cpp b/platform/glfw/glfw_view.cpp index d73b147deb..812b0e32af 100644 --- a/platform/glfw/glfw_view.cpp +++ b/platform/glfw/glfw_view.cpp @@ -4,7 +4,6 @@ #include <mbgl/sprite/sprite_image.hpp> #include <mbgl/style/transition_options.hpp> #include <mbgl/gl/gl.hpp> -#include <mbgl/gl/extension.hpp> #include <mbgl/gl/context.hpp> #include <mbgl/util/logging.hpp> #include <mbgl/util/platform.hpp> @@ -86,8 +85,6 @@ GLFWView::GLFWView(bool fullscreen_, bool benchmark_) glfwSetScrollCallback(window, onScroll); glfwSetKeyCallback(window, onKey); - mbgl::gl::InitializeExtensions(glfwGetProcAddress); - glfwGetWindowSize(window, &width, &height); glfwGetFramebufferSize(window, &fbWidth, &fbHeight); pixelRatio = static_cast<float>(fbWidth) / width; @@ -499,6 +496,10 @@ mbgl::Size GLFWView::getFramebufferSize() const { return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) }; } +mbgl::gl::ProcAddress GLFWView::initializeExtension(const char* name) { + return glfwGetProcAddress(name); +} + void GLFWView::activate() { glfwMakeContextCurrent(window); } diff --git a/platform/glfw/glfw_view.hpp b/platform/glfw/glfw_view.hpp index bfabf6cc68..55f795cd34 100644 --- a/platform/glfw/glfw_view.hpp +++ b/platform/glfw/glfw_view.hpp @@ -44,9 +44,13 @@ public: mbgl::Size getFramebufferSize() const; // mbgl::Backend implementation + void invalidate() override; + +protected: + // mbgl::Backend implementation + mbgl::gl::ProcAddress initializeExtension(const char*) override; void activate() override; void deactivate() override; - void invalidate() override; private: // Window callbacks diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index 6bd3092445..e8bc1b4b2a 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -1,7 +1,6 @@ #import "MGLMapView_Private.h" #include <mbgl/util/logging.hpp> -#include <mbgl/gl/extension.hpp> #include <mbgl/gl/context.hpp> #import <GLKit/GLKit.h> @@ -610,21 +609,6 @@ public: [_glView bindDrawable]; [self insertSubview:_glView atIndex:0]; _glView.contentMode = UIViewContentModeCenter; - - // load extensions - // - 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."); - } - - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); - void* symbol = CFBundleGetFunctionPointerForName(framework, str); - CFRelease(str); - - return reinterpret_cast<mbgl::gl::glProc>(symbol); - }); } - (UIImage *)compassImage @@ -5436,6 +5420,20 @@ public: [nativeView didFinishLoadingStyle]; } + mbgl::gl::ProcAddress initializeExtension(const char* name) override { + static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles")); + if (!framework) { + throw std::runtime_error("Failed to load OpenGL framework."); + } + + CFStringRef str = + CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); + void* symbol = CFBundleGetFunctionPointerForName(framework, str); + CFRelease(str); + + return reinterpret_cast<mbgl::gl::ProcAddress>(symbol); + } + void invalidate() override { [nativeView setNeedsGLDisplay]; diff --git a/platform/linux/src/headless_backend_egl.cpp b/platform/linux/src/headless_backend_egl.cpp index df0ecc8dff..696fa3065c 100644 --- a/platform/linux/src/headless_backend_egl.cpp +++ b/platform/linux/src/headless_backend_egl.cpp @@ -60,7 +60,7 @@ struct EGLImpl : public HeadlessBackend::Impl { EGLSurface glSurface = EGL_NO_SURFACE; }; -gl::glProc HeadlessBackend::initializeExtension(const char* name) { +gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { return eglGetProcAddress(name); } diff --git a/platform/linux/src/headless_backend_glx.cpp b/platform/linux/src/headless_backend_glx.cpp index 5791f1892f..36a60ec06b 100644 --- a/platform/linux/src/headless_backend_glx.cpp +++ b/platform/linux/src/headless_backend_glx.cpp @@ -44,7 +44,7 @@ struct GLXImpl : public HeadlessBackend::Impl { GLXFBConfig* fbConfigs = nullptr; }; -gl::glProc HeadlessBackend::initializeExtension(const char* name) { +gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name)); } diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index ef1c0f3bc1..45ac7c5357 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -26,7 +26,6 @@ #import <mbgl/map/camera.hpp> #import <mbgl/storage/reachability.h> #import <mbgl/util/default_thread_pool.hpp> -#import <mbgl/gl/extension.hpp> #import <mbgl/gl/context.hpp> #import <mbgl/map/backend.hpp> #import <mbgl/map/backend_scope.hpp> @@ -768,19 +767,6 @@ public: - (void)renderSync { if (!self.dormant) { - // Enable vertex buffer objects. - mbgl::gl::InitializeExtensions([](const char *name) { - static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); - if (!framework) { - throw std::runtime_error("Failed to load OpenGL framework."); - } - - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); - void *symbol = CFBundleGetFunctionPointerForName(framework, str); - CFRelease(str); - - return reinterpret_cast<mbgl::gl::glProc>(symbol); - }); // The OpenGL implementation automatically enables the OpenGL context for us. mbgl::BackendScope scope { *_mbglView, mbgl::BackendScope::ScopeType::Implicit }; @@ -2846,6 +2832,19 @@ public: [nativeView sourceDidChange]; } + mbgl::gl::ProcAddress initializeExtension(const char* name) override { + static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); + if (!framework) { + throw std::runtime_error("Failed to load OpenGL framework."); + } + + CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); + void *symbol = CFBundleGetFunctionPointerForName(framework, str); + CFRelease(str); + + return reinterpret_cast<mbgl::gl::ProcAddress>(symbol); + } + void invalidate() override { [nativeView setNeedsGLDisplay]; } diff --git a/platform/qt/app/mapwindow.cpp b/platform/qt/app/mapwindow.cpp index 926d504904..345c5196ba 100644 --- a/platform/qt/app/mapwindow.cpp +++ b/platform/qt/app/mapwindow.cpp @@ -372,8 +372,6 @@ void MapWindow::wheelEvent(QWheelEvent *ev) void MapWindow::initializeGL() { - QMapbox::initializeGLExtensions(); - m_map.reset(new QMapboxGL(nullptr, m_settings, size(), pixelRatio())); connect(m_map.data(), SIGNAL(needsRendering()), this, SLOT(update())); diff --git a/platform/qt/include/qmapbox.hpp b/platform/qt/include/qmapbox.hpp index f2d96412a9..e69b37108d 100644 --- a/platform/qt/include/qmapbox.hpp +++ b/platform/qt/include/qmapbox.hpp @@ -97,8 +97,6 @@ typedef void (*CustomLayerInitializeFunction)(void* context) ; typedef void (*CustomLayerRenderFunction)(void* context, const CustomLayerRenderParameters&); typedef void (*CustomLayerDeinitializeFunction)(void* context); -Q_DECL_EXPORT void initializeGLExtensions(); - } // namespace QMapbox Q_DECLARE_METATYPE(QMapbox::Coordinate); diff --git a/platform/qt/src/qmapbox.cpp b/platform/qt/src/qmapbox.cpp index 126ece1efa..410e114690 100644 --- a/platform/qt/src/qmapbox.cpp +++ b/platform/qt/src/qmapbox.cpp @@ -1,6 +1,5 @@ #include "qmapbox.hpp" -#include <mbgl/gl/extension.hpp> #include <mbgl/storage/network_status.hpp> #include <mbgl/util/default_styles.hpp> #include <mbgl/util/geometry.hpp> @@ -255,26 +254,4 @@ Q_DECL_EXPORT QList<QPair<QString, QString> >& defaultStyles() return styles; } -/*! - \fn void QMapbox::initializeGLExtensions() - - Initializes the OpenGL extensions such as Vertex Array Objects (VAOs), - required by Mapbox GL Native engine. - - Should be called only once, after an OpenGL context is available. - Consecutive calls are ignored. -*/ -Q_DECL_EXPORT void initializeGLExtensions() -{ - mbgl::gl::InitializeExtensions([](const char* name) { -#if QT_VERSION >= 0x050000 - QOpenGLContext* thisContext = QOpenGLContext::currentContext(); - return thisContext->getProcAddress(name); -#else - const QGLContext* thisContext = QGLContext::currentContext(); - return reinterpret_cast<mbgl::gl::glProc>(thisContext->getProcAddress(name)); -#endif - }); -} - } // namespace QMapbox diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index 384bdc8ebf..5776502a5b 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -1678,6 +1678,20 @@ void QMapboxGLPrivate::onSourceChanged(mbgl::style::Source&) emit mapChanged(QMapboxGL::MapChangeSourceDidChange); } +/*! + Initializes an OpenGL extension function such as Vertex Array Objects (VAOs), + required by Mapbox GL Native engine. +*/ +mbgl::gl::ProcAddress QMapboxGLPrivate::initializeExtension(const char* name) { +#if QT_VERSION >= 0x050000 + QOpenGLContext* thisContext = QOpenGLContext::currentContext(); + return thisContext->getProcAddress(name); +#else + const QGLContext* thisContext = QGLContext::currentContext(); + return reinterpret_cast<mbgl::gl::ProcAddress>(thisContext->getProcAddress(name)); +#endif +} + void QMapboxGLPrivate::connectionEstablished() { mbgl::NetworkStatus::Reachable(); diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp index 4112542431..464b66bd73 100644 --- a/platform/qt/src/qmapboxgl_p.hpp +++ b/platform/qt/src/qmapboxgl_p.hpp @@ -58,6 +58,9 @@ public: bool dirty { false }; +private: + mbgl::gl::ProcAddress initializeExtension(const char*) override; + public slots: void connectionEstablished(); diff --git a/platform/qt/test/headless_backend_qt.cpp b/platform/qt/test/headless_backend_qt.cpp index 401ce55a7f..5f95b2f96a 100644 --- a/platform/qt/test/headless_backend_qt.cpp +++ b/platform/qt/test/headless_backend_qt.cpp @@ -24,13 +24,13 @@ struct QtImpl : public HeadlessBackend::Impl { QGLWidget widget; }; -gl::glProc HeadlessBackend::initializeExtension(const char* name) { +gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { #if QT_VERSION >= 0x050000 QOpenGLContext* thisContext = QOpenGLContext::currentContext(); return thisContext->getProcAddress(name); #else const QGLContext* thisContext = QGLContext::currentContext(); - return reinterpret_cast<mbgl::gl::glProc>(thisContext->getProcAddress(name)); + return reinterpret_cast<gl::ProcAddress>(thisContext->getProcAddress(name)); #endif } diff --git a/platform/qt/test/qmapboxgl.cpp b/platform/qt/test/qmapboxgl.cpp index 650c635b99..453604076e 100644 --- a/platform/qt/test/qmapboxgl.cpp +++ b/platform/qt/test/qmapboxgl.cpp @@ -20,8 +20,6 @@ public: this, SLOT(onMapChanged(QMapboxGL::MapChange))); connect(&map, SIGNAL(needsRendering()), this, SLOT(onNeedsRendering())); - QMapbox::initializeGLExtensions(); - map.resize(fbo.size(), fbo.size()); map.setFramebufferObject(fbo.handle()); map.setCoordinateZoom(QMapbox::Coordinate(60.170448, 24.942046), 14); diff --git a/src/mbgl/gl/extension.cpp b/src/mbgl/gl/extension.cpp index e6b4d9156e..41a5ea175e 100644 --- a/src/mbgl/gl/extension.cpp +++ b/src/mbgl/gl/extension.cpp @@ -1,7 +1,6 @@ #include <mbgl/gl/extension.hpp> #include <mbgl/gl/gl.hpp> -#include <mutex> #include <string> #include <vector> #include <cstring> @@ -11,7 +10,7 @@ namespace gl { namespace detail { using Probes = std::vector<ExtensionFunctionBase::Probe>; -using ExtensionFunctions = std::vector<std::pair<glProc*, Probes>>; +using ExtensionFunctions = std::vector<std::pair<ProcAddress*, Probes>>; ExtensionFunctions& extensionFunctions() { static ExtensionFunctions functions; return functions; @@ -23,22 +22,18 @@ ExtensionFunctionBase::ExtensionFunctionBase(std::initializer_list<Probe> probes } // namespace detail -static std::once_flag initializeExtensionsOnce; - -void InitializeExtensions(glProc (*getProcAddress)(const char*)) { - std::call_once(initializeExtensionsOnce, [getProcAddress] { - if (const char* extensions = - reinterpret_cast<const char*>(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; - } +void initializeExtensions(const std::function<ProcAddress(const char*)>& getProcAddress) { + if (const char* extensions = + reinterpret_cast<const char*>(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 diff --git a/src/mbgl/gl/extension.hpp b/src/mbgl/gl/extension.hpp index ea5a1ae5f5..7d1d9a4d7d 100644 --- a/src/mbgl/gl/extension.hpp +++ b/src/mbgl/gl/extension.hpp @@ -2,12 +2,13 @@ #include <initializer_list> #include <utility> +#include <functional> namespace mbgl { namespace gl { -using glProc = void (*)(); -void InitializeExtensions(glProc (*getProcAddress)(const char*)); +using ProcAddress = void (*)(); +void initializeExtensions(const std::function<ProcAddress(const char*)>&); namespace detail { @@ -15,7 +16,7 @@ class ExtensionFunctionBase { public: using Probe = std::pair<const char*, const char*>; ExtensionFunctionBase(std::initializer_list<Probe>); - glProc ptr; + ProcAddress ptr; }; } // namespace detail diff --git a/src/mbgl/map/backend.cpp b/src/mbgl/map/backend.cpp index a1a2f8f3a8..29f7522e4f 100644 --- a/src/mbgl/map/backend.cpp +++ b/src/mbgl/map/backend.cpp @@ -1,16 +1,23 @@ #include <mbgl/map/backend.hpp> #include <mbgl/map/backend_scope.hpp> #include <mbgl/gl/context.hpp> +#include <mbgl/gl/extension.hpp> +#include <mbgl/gl/debugging.hpp> #include <cassert> namespace mbgl { -Backend::Backend() : context(std::make_unique<gl::Context>()) { -} +Backend::Backend() = default; gl::Context& Backend::getContext() { assert(BackendScope::exists()); + std::call_once(initialized, [this] { + context = std::make_unique<gl::Context>(); + gl::debugging::enable(); + gl::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 754959438b..73a084c8c6 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -94,8 +94,6 @@ Painter::Painter(gl::Context& context_, tileBorderSegments.emplace_back(0, 0, 4, 5); rasterSegments.emplace_back(0, 0, 4, 6); - gl::debugging::enable(); - programs = std::make_unique<Programs>(context, ProgramParameters{ pixelRatio, false, programCacheDir }); #ifndef NDEBUG |