From bee77684bf6826515aa0254b6d00ff80552d4032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Mon, 27 Nov 2017 17:25:20 +0100 Subject: [core] move HeadlessBackend extension initialization code into Impl --- include/mbgl/renderer/renderer_backend.hpp | 2 +- platform/android/config.cmake | 10 ------ platform/android/src/android_renderer_backend.cpp | 2 +- platform/android/src/android_renderer_backend.hpp | 2 +- platform/darwin/src/headless_backend_cgl.cpp | 41 ++++++++++++----------- platform/darwin/src/headless_backend_eagl.mm | 40 +++++++++++----------- platform/default/headless_backend_osmesa.cpp | 21 ++++++------ platform/default/mbgl/gl/headless_backend.cpp | 13 ++++--- platform/default/mbgl/gl/headless_backend.hpp | 11 +++--- platform/glfw/glfw_view.cpp | 2 +- platform/glfw/glfw_view.hpp | 2 +- platform/ios/src/MGLMapView.mm | 2 +- platform/linux/src/headless_backend_egl.cpp | 21 ++++++------ platform/linux/src/headless_backend_glx.cpp | 21 ++++++------ platform/macos/src/MGLMapView.mm | 2 +- platform/qt/src/headless_backend_qt.cpp | 30 ++++++++--------- platform/qt/src/qmapboxgl.cpp | 2 +- platform/qt/src/qmapboxgl_p.hpp | 2 +- src/mbgl/renderer/renderer_backend.cpp | 2 +- test/renderer/backend_scope.test.cpp | 9 ++--- 20 files changed, 117 insertions(+), 120 deletions(-) diff --git a/include/mbgl/renderer/renderer_backend.hpp b/include/mbgl/renderer/renderer_backend.hpp index 295838c71b..b83c128169 100644 --- a/include/mbgl/renderer/renderer_backend.hpp +++ b/include/mbgl/renderer/renderer_backend.hpp @@ -41,7 +41,7 @@ protected: // Called with the name of an OpenGL extension that should be loaded. RendererBackend 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; + virtual gl::ProcAddress getExtensionFunctionPointer(const char*) = 0; // Called when the backend's GL context needs to be made active or inactive. These are called, // as a matched pair, exclusively through BackendScope, in two situations: diff --git a/platform/android/config.cmake b/platform/android/config.cmake index 0175fa7ca6..fb5a0d7c56 100644 --- a/platform/android/config.cmake +++ b/platform/android/config.cmake @@ -66,7 +66,6 @@ macro(mbgl_platform_core) PRIVATE platform/default/mbgl/map/map_snapshotter.cpp PRIVATE platform/default/mbgl/map/map_snapshotter.hpp PRIVATE platform/linux/src/headless_backend_egl.cpp - PRIVATE platform/linux/src/headless_display_egl.cpp ) target_include_directories(mbgl-core @@ -341,15 +340,6 @@ macro(mbgl_platform_test) # Main test entry point platform/android/src/test/main.jni.cpp - - # Headless view - platform/default/mbgl/gl/headless_frontend.cpp - platform/default/mbgl/gl/headless_frontend.hpp - platform/default/mbgl/gl/headless_backend.cpp - platform/default/mbgl/gl/headless_backend.hpp - - platform/linux/src/headless_backend_egl.cpp - platform/linux/src/headless_display_egl.cpp ) target_include_directories(mbgl-test diff --git a/platform/android/src/android_renderer_backend.cpp b/platform/android/src/android_renderer_backend.cpp index 9e49915650..ae35acc5da 100755 --- a/platform/android/src/android_renderer_backend.cpp +++ b/platform/android/src/android_renderer_backend.cpp @@ -21,7 +21,7 @@ void AndroidRendererBackend::bind() { /** * From mbgl::RendererBackend. */ -gl::ProcAddress AndroidRendererBackend::initializeExtension(const char* name) { +gl::ProcAddress AndroidRendererBackend::getExtensionFunctionPointer(const char* name) { assert(BackendScope::exists()); return eglGetProcAddress(name); } diff --git a/platform/android/src/android_renderer_backend.hpp b/platform/android/src/android_renderer_backend.hpp index c5c552459f..d2c100dcc1 100755 --- a/platform/android/src/android_renderer_backend.hpp +++ b/platform/android/src/android_renderer_backend.hpp @@ -24,7 +24,7 @@ public: protected: // mbgl::RendererBackend // - gl::ProcAddress initializeExtension(const char*) override; + gl::ProcAddress getExtensionFunctionPointer(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 6e19213f52..46a5beb870 100644 --- a/platform/darwin/src/headless_backend_cgl.cpp +++ b/platform/darwin/src/headless_backend_cgl.cpp @@ -65,8 +65,9 @@ public: CGLPixelFormatObj pixelFormat = nullptr; }; -struct CGLImpl : public HeadlessBackend::Impl { - CGLImpl() { +class CGLBackendImpl : public HeadlessBackend::Impl { +public: + CGLBackendImpl() { CGLError error = CGLCreateContext(cglDisplay->pixelFormat, nullptr, &glContext); if (error != kCGLNoError) { throw std::runtime_error(std::string("Error creating GL context object:") + @@ -80,10 +81,24 @@ struct CGLImpl : public HeadlessBackend::Impl { } } - ~CGLImpl() final { + ~CGLBackendImpl() final { CGLDestroyContext(glContext); } + gl::ProcAddress getExtensionFunctionPointer(const char* name) final { + 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(symbol); + } + void activateContext() final { CGLError error = CGLSetCurrentContext(glContext); if (error != kCGLNoError) { @@ -105,23 +120,9 @@ private: CGLContextObj glContext = nullptr; }; -gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { - assert(hasContext()); - 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(symbol); -} - -void HeadlessBackend::createContext() { - assert(!hasContext()); - impl = std::make_unique(); +void HeadlessBackend::createImpl() { + assert(!impl); + impl = std::make_unique(); } } // namespace mbgl diff --git a/platform/darwin/src/headless_backend_eagl.mm b/platform/darwin/src/headless_backend_eagl.mm index 6bf5787f60..050fa62c78 100644 --- a/platform/darwin/src/headless_backend_eagl.mm +++ b/platform/darwin/src/headless_backend_eagl.mm @@ -6,8 +6,9 @@ namespace mbgl { -struct EAGLImpl : public HeadlessBackend::Impl { - EAGLImpl() { +class EAGLBackendImpl : public HeadlessBackend::Impl { +public: + EAGLBackendImpl() { glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; if (glContext == nil) { throw std::runtime_error("Error creating GL context object"); @@ -16,7 +17,21 @@ struct EAGLImpl : public HeadlessBackend::Impl { } // Required for ARC to deallocate correctly. - ~EAGLImpl() final = default; + ~EAGLBackendImpl() final = default; + + gl::ProcAddress getExtensionFunctionPointer(const char* name) final { + 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(symbol); + } void activateContext() final { [EAGLContext setCurrentContext:glContext]; @@ -30,22 +45,9 @@ private: EAGLContext* glContext = nullptr; }; -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."); - } - - CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII); - void* symbol = CFBundleGetFunctionPointerForName(framework, str); - CFRelease(str); - - return reinterpret_cast(symbol); -} - -void HeadlessBackend::createContext() { - assert(!hasContext()); - impl = std::make_unique(); +void HeadlessBackend::createImpl() { + assert(!impl); + impl = std::make_unique(); } } // namespace mbgl diff --git a/platform/default/headless_backend_osmesa.cpp b/platform/default/headless_backend_osmesa.cpp index 4cb0bfc5c4..0da1caf9af 100644 --- a/platform/default/headless_backend_osmesa.cpp +++ b/platform/default/headless_backend_osmesa.cpp @@ -7,8 +7,9 @@ namespace mbgl { -struct OSMesaImpl : public HeadlessBackend::Impl { - OSMesaImpl() { +class OSMesaBackendImpl : public HeadlessBackend::Impl { +public: + OSMesaBackendImpl() { #if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305 glContext = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, nullptr); #else @@ -19,10 +20,14 @@ struct OSMesaImpl : public HeadlessBackend::Impl { } } - ~OSMesaImpl() final { + ~OSMesaBackendImpl() final { OSMesaDestroyContext(glContext); } + gl::ProcAddress getExtensionFunctionPointer(const char* name) final { + return OSMesaGetProcAddress(name); + } + void activateContext() final { if (!OSMesaMakeCurrent(glContext, &fakeBuffer, GL_UNSIGNED_BYTE, 1, 1)) { throw std::runtime_error("Switching OpenGL context failed.\n"); @@ -34,13 +39,9 @@ private: GLubyte fakeBuffer = 0; }; -gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { - return OSMesaGetProcAddress(name); -} - -void HeadlessBackend::createContext() { - assert(!hasContext()); - impl = std::make_unique(); +void HeadlessBackend::createImpl() { + assert(!impl); + impl = std::make_unique(); } } // namespace mbgl diff --git a/platform/default/mbgl/gl/headless_backend.cpp b/platform/default/mbgl/gl/headless_backend.cpp index 2c81005686..ba08aecab7 100644 --- a/platform/default/mbgl/gl/headless_backend.cpp +++ b/platform/default/mbgl/gl/headless_backend.cpp @@ -31,19 +31,24 @@ HeadlessBackend::~HeadlessBackend() { context.reset(); } +gl::ProcAddress HeadlessBackend::getExtensionFunctionPointer(const char* name) { + assert(impl); + return impl->getExtensionFunctionPointer(name); +} + void HeadlessBackend::activate() { active = true; - if (!hasContext()) { - createContext(); + if (!impl) { + createImpl(); } - assert(hasContext()); + assert(impl); impl->activateContext(); } void HeadlessBackend::deactivate() { - assert(hasContext()); + assert(impl); impl->deactivateContext(); active = false; } diff --git a/platform/default/mbgl/gl/headless_backend.hpp b/platform/default/mbgl/gl/headless_backend.hpp index f96b01300b..7757037533 100644 --- a/platform/default/mbgl/gl/headless_backend.hpp +++ b/platform/default/mbgl/gl/headless_backend.hpp @@ -19,23 +19,24 @@ public: void setSize(Size); PremultipliedImage readStillImage(); - struct Impl { + class Impl { + public: virtual ~Impl() = default; + virtual gl::ProcAddress getExtensionFunctionPointer(const char*) = 0; virtual void activateContext() = 0; virtual void deactivateContext() {} }; private: // Implementation specific functions - gl::ProcAddress initializeExtension(const char*) override; + gl::ProcAddress getExtensionFunctionPointer(const char*) override; void activate() override; void deactivate() override; - bool hasContext() const { return bool(impl); } - - void createContext(); + void createImpl(); +private: std::unique_ptr impl; Size size; diff --git a/platform/glfw/glfw_view.cpp b/platform/glfw/glfw_view.cpp index d591f897e0..8fc2fba283 100644 --- a/platform/glfw/glfw_view.cpp +++ b/platform/glfw/glfw_view.cpp @@ -540,7 +540,7 @@ mbgl::Size GLFWView::getFramebufferSize() const { return { static_cast(fbWidth), static_cast(fbHeight) }; } -mbgl::gl::ProcAddress GLFWView::initializeExtension(const char* name) { +mbgl::gl::ProcAddress GLFWView::getExtensionFunctionPointer(const char* name) { return glfwGetProcAddress(name); } diff --git a/platform/glfw/glfw_view.hpp b/platform/glfw/glfw_view.hpp index d3257f6b9a..35f17b723a 100644 --- a/platform/glfw/glfw_view.hpp +++ b/platform/glfw/glfw_view.hpp @@ -52,7 +52,7 @@ public: protected: // mbgl::Backend implementation - mbgl::gl::ProcAddress initializeExtension(const char*) override; + mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override; void activate() override; void deactivate() override; diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index b54dfc4e98..8154525334 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -6031,7 +6031,7 @@ public: [nativeView didFinishLoadingStyle]; } - mbgl::gl::ProcAddress initializeExtension(const char* name) override { + mbgl::gl::ProcAddress getExtensionFunctionPointer(const char* name) override { static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles")); if (!framework) { throw std::runtime_error("Failed to load OpenGL framework."); diff --git a/platform/linux/src/headless_backend_egl.cpp b/platform/linux/src/headless_backend_egl.cpp index 7d3a3d1ec1..089e344987 100644 --- a/platform/linux/src/headless_backend_egl.cpp +++ b/platform/linux/src/headless_backend_egl.cpp @@ -66,8 +66,9 @@ public: EGLConfig config = 0; }; -struct EGLImpl : public HeadlessBackend::Impl { - EGLImpl() { +class EGLBackendImpl : public HeadlessBackend::Impl { +public: + EGLBackendImpl() { // EGL initializes the context client version to 1 by default. We want to // use OpenGL ES 2.0 which has the ability to create shader and program // objects and also to write vertex and fragment shaders in the OpenGL ES @@ -101,7 +102,7 @@ struct EGLImpl : public HeadlessBackend::Impl { } } - ~EGLImpl() final { + ~EGLBackendImpl() final { if (eglSurface != EGL_NO_SURFACE) { if (!eglDestroySurface(eglDisplay->display, eglSurface)) { Log::Error(Event::OpenGL, "Failed to destroy EGL surface."); @@ -113,6 +114,10 @@ struct EGLImpl : public HeadlessBackend::Impl { } } + gl::ProcAddress getExtensionFunctionPointer(const char* name) final { + return eglGetProcAddress(name); + } + void activateContext() final { if (!eglMakeCurrent(eglDisplay->display, eglSurface, eglSurface, eglContext)) { throw std::runtime_error("Switching OpenGL context failed.\n"); @@ -131,13 +136,9 @@ private: EGLSurface eglSurface = EGL_NO_SURFACE; }; -gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { - return eglGetProcAddress(name); -} - -void HeadlessBackend::createContext() { - assert(!hasContext()); - impl = std::make_unique(); +void HeadlessBackend::createImpl() { + assert(!impl); + impl = std::make_unique(); } } // namespace mbgl diff --git a/platform/linux/src/headless_backend_glx.cpp b/platform/linux/src/headless_backend_glx.cpp index 6d2939da0f..27af98e70a 100644 --- a/platform/linux/src/headless_backend_glx.cpp +++ b/platform/linux/src/headless_backend_glx.cpp @@ -70,8 +70,9 @@ public: GLXFBConfig* fbConfigs = nullptr; }; -struct GLXImpl : public HeadlessBackend::Impl { - GLXImpl() { +class GLXBackendImpl : public HeadlessBackend::Impl { +public: + GLXBackendImpl() { // Try to create a legacy context. glContext = glXCreateNewContext(glxDisplay->xDisplay, glxDisplay->fbConfigs[0], GLX_RGBA_TYPE, None, True); @@ -91,13 +92,17 @@ struct GLXImpl : public HeadlessBackend::Impl { glXCreatePbuffer(glxDisplay->xDisplay, glxDisplay->fbConfigs[0], pbufferAttributes); } - ~GLXImpl() final { + ~GLXBackendImpl() final { if (glxPbuffer) { glXDestroyPbuffer(glxDisplay->xDisplay, glxPbuffer); } glXDestroyContext(glxDisplay->xDisplay, glContext); } + gl::ProcAddress getExtensionFunctionPointer(const char* name) final { + return glXGetProcAddress(reinterpret_cast(name)); + } + void activateContext() final { if (!glXMakeContextCurrent(glxDisplay->xDisplay, glxPbuffer, glxPbuffer, glContext)) { throw std::runtime_error("Switching OpenGL context failed.\n"); @@ -117,13 +122,9 @@ private: GLXPbuffer glxPbuffer = 0; }; -gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { - return glXGetProcAddress(reinterpret_cast(name)); -} - -void HeadlessBackend::createContext() { - assert(!hasContext()); - impl = std::make_unique(); +void HeadlessBackend::createImpl() { + assert(!impl); + impl = std::make_unique(); } } // namespace mbgl diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm index 8df6f4545d..60af0cd648 100644 --- a/platform/macos/src/MGLMapView.mm +++ b/platform/macos/src/MGLMapView.mm @@ -2887,7 +2887,7 @@ public: [nativeView sourceDidChange:nativeSource]; } - mbgl::gl::ProcAddress initializeExtension(const char* name) override { + mbgl::gl::ProcAddress getExtensionFunctionPointer(const char* name) override { static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); if (!framework) { throw std::runtime_error("Failed to load OpenGL framework."); diff --git a/platform/qt/src/headless_backend_qt.cpp b/platform/qt/src/headless_backend_qt.cpp index 7985ca9f2d..ad3fa42290 100644 --- a/platform/qt/src/headless_backend_qt.cpp +++ b/platform/qt/src/headless_backend_qt.cpp @@ -12,9 +12,19 @@ namespace mbgl { -class QtImpl : public HeadlessBackend::Impl { +class QtBackendImpl : public HeadlessBackend::Impl { public: - ~QtImpl() final = default; + ~QtBackendImpl() final = default; + + gl::ProcAddress getExtensionFunctionPointer(const char* name) final { +#if QT_VERSION >= 0x050000 + QOpenGLContext* thisContext = QOpenGLContext::currentContext(); + return thisContext->getProcAddress(name); +#else + const QGLContext* thisContext = QGLContext::currentContext(); + return reinterpret_cast(thisContext->getProcAddress(name)); +#endif + } void activateContext() final { widget.makeCurrent(); @@ -28,19 +38,9 @@ private: QGLWidget widget; }; -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(thisContext->getProcAddress(name)); -#endif -} - -void HeadlessBackend::createContext() { - assert(!hasContext()); - impl = std::make_unique(); +void HeadlessBackend::createImpl() { + assert(!impl); + impl = std::make_unique(); } } // namespace mbgl diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp index cc1d88e22f..2675d87862 100644 --- a/platform/qt/src/qmapboxgl.cpp +++ b/platform/qt/src/qmapboxgl.cpp @@ -1695,7 +1695,7 @@ void QMapboxGLPrivate::onSourceChanged(mbgl::style::Source&) 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) { +mbgl::gl::ProcAddress QMapboxGLPrivate::getExtensionFunctionPointer(const char* name) { #if QT_VERSION >= 0x050000 QOpenGLContext* thisContext = QOpenGLContext::currentContext(); return thisContext->getProcAddress(name); diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp index 5e12b44a20..f947c09f48 100644 --- a/platform/qt/src/qmapboxgl_p.hpp +++ b/platform/qt/src/qmapboxgl_p.hpp @@ -61,7 +61,7 @@ public: bool dirty { false }; private: - mbgl::gl::ProcAddress initializeExtension(const char*) override; + mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override; public slots: void connectionEstablished(); diff --git a/src/mbgl/renderer/renderer_backend.cpp b/src/mbgl/renderer/renderer_backend.cpp index 159ef432b3..22d263313c 100644 --- a/src/mbgl/renderer/renderer_backend.cpp +++ b/src/mbgl/renderer/renderer_backend.cpp @@ -16,7 +16,7 @@ gl::Context& RendererBackend::getContext() { context = std::make_unique(); context->enableDebugging(); context->initializeExtensions( - std::bind(&RendererBackend::initializeExtension, this, std::placeholders::_1)); + std::bind(&RendererBackend::getExtensionFunctionPointer, this, std::placeholders::_1)); }); return *context; } diff --git a/test/renderer/backend_scope.test.cpp b/test/renderer/backend_scope.test.cpp index 66cf88a9c6..05b82695b2 100644 --- a/test/renderer/backend_scope.test.cpp +++ b/test/renderer/backend_scope.test.cpp @@ -28,18 +28,13 @@ public: if (updateAssumedStateFunction) updateAssumedStateFunction(); } - gl::ProcAddress initializeExtension(const char* ext) override { - if (initializeExtensionFunction) { - return initializeExtensionFunction(ext); - } else { - return {}; - } + gl::ProcAddress getExtensionFunctionPointer(const char*) override { + return {}; } std::function activateFunction; std::function deactivateFunction; std::function updateAssumedStateFunction; - std::function initializeExtensionFunction; }; // A scope should activate on construction -- cgit v1.2.1