summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2016-10-06 13:23:50 +0200
committerKonstantin Käfer <mail@kkaefer.com>2016-10-25 13:52:36 -0700
commit5cc390d694fc7510d445310d8eb9e32429a5e67b (patch)
tree7a24706f919ac3e8154be8b4ce33aed5bf42188d /platform
parent45f4dc0166f2d609d014d2174209fdbe1994c943 (diff)
downloadqtlocation-mapboxgl-5cc390d694fc7510d445310d8eb9e32429a5e67b.tar.gz
[core] separate Backend from View for headless rendering
Diffstat (limited to 'platform')
-rwxr-xr-xplatform/android/src/native_map_view.cpp12
-rwxr-xr-xplatform/android/src/native_map_view.hpp7
-rw-r--r--platform/darwin/src/headless_backend_cgl.cpp58
-rw-r--r--platform/darwin/src/headless_backend_eagl.mm46
-rw-r--r--platform/darwin/src/headless_view_cgl.cpp51
-rw-r--r--platform/darwin/src/headless_view_eagl.cpp (renamed from platform/darwin/src/headless_view_eagl.mm)43
-rw-r--r--platform/default/glfw_view.cpp4
-rw-r--r--platform/default/headless_backend.cpp56
-rw-r--r--platform/default/headless_backend_glx.cpp67
-rw-r--r--platform/default/headless_display.cpp7
-rw-r--r--platform/default/headless_view.cpp72
-rw-r--r--platform/default/headless_view_glx.cpp64
-rw-r--r--platform/ios/config.cmake6
-rw-r--r--platform/ios/src/MGLMapView.mm22
-rw-r--r--platform/linux/config.cmake4
-rw-r--r--platform/macos/config.cmake2
-rw-r--r--platform/macos/src/MGLMapView.mm29
-rw-r--r--platform/node/src/node_map.cpp7
-rw-r--r--platform/node/src/node_map.hpp2
-rw-r--r--platform/qt/config.cmake2
-rw-r--r--platform/qt/src/qmapboxgl.cpp7
-rw-r--r--platform/qt/src/qmapboxgl_p.hpp6
-rw-r--r--platform/qt/test/headless_backend_qt.cpp46
-rw-r--r--platform/qt/test/headless_view_qt.cpp38
24 files changed, 382 insertions, 276 deletions
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 5bd2694932..fe201ac069 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -55,10 +55,8 @@ void log_gl_string(GLenum name, const char *label) {
}
}
-NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio_, int availableProcessors_, size_t totalMemory_)
- : mbgl::View(*this),
- env(env_),
- pixelRatio(pixelRatio_),
+NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio, int availableProcessors_, size_t totalMemory_)
+ : env(env_),
availableProcessors(availableProcessors_),
totalMemory(totalMemory_),
threadPool(4) {
@@ -82,7 +80,7 @@ NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio_, int
mbgl::android::cachePath + "/mbgl-offline.db",
mbgl::android::apkPath);
- map = std::make_unique<mbgl::Map>(*this, *fileSource, threadPool, MapMode::Continuous);
+ map = std::make_unique<mbgl::Map>(*this, *this, pixelRatio, *fileSource, threadPool, MapMode::Continuous);
float zoomFactor = map->getMaxZoom() - map->getMinZoom() + 1;
float cpuFactor = availableProcessors;
@@ -114,8 +112,8 @@ NativeMapView::~NativeMapView() {
vm = nullptr;
}
-float NativeMapView::getPixelRatio() const {
- return pixelRatio;
+void NativeMapView::bind() {
+ MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
}
std::array<uint16_t, 2> NativeMapView::getSize() const {
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index d42890dae2..42a9a10ad4 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -2,6 +2,7 @@
#include <mbgl/map/map.hpp>
#include <mbgl/map/view.hpp>
+#include <mbgl/map/backend.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
@@ -14,12 +15,13 @@
namespace mbgl {
namespace android {
-class NativeMapView : public mbgl::View, private mbgl::util::noncopyable {
+class NativeMapView : public mbgl::View, public mbgl::Backend {
public:
NativeMapView(JNIEnv *env, jobject obj, float pixelRatio, int availableProcessors, size_t totalMemory);
virtual ~NativeMapView();
- float getPixelRatio() const override;
+ void bind() override;
+
std::array<uint16_t, 2> getSize() const override;
std::array<uint16_t, 2> getFramebufferSize() const override;
void activate() override;
@@ -89,7 +91,6 @@ private:
int height = 0;
int fbWidth = 0;
int fbHeight = 0;
- const float pixelRatio;
int availableProcessors = 0;
size_t totalMemory = 0;
diff --git a/platform/darwin/src/headless_backend_cgl.cpp b/platform/darwin/src/headless_backend_cgl.cpp
new file mode 100644
index 0000000000..4ca567f55c
--- /dev/null
+++ b/platform/darwin/src/headless_backend_cgl.cpp
@@ -0,0 +1,58 @@
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/headless_display.hpp>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <string>
+#include <stdexcept>
+
+namespace mbgl {
+
+gl::glProc HeadlessBackend::initializeExtension(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<gl::glProc>(symbol);
+}
+
+void HeadlessBackend::createContext() {
+ CGLError error = CGLCreateContext(display->pixelFormat, nullptr, &glContext);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Error creating GL context object:") +
+ CGLErrorString(error) + "\n");
+ }
+
+ error = CGLEnable(glContext, kCGLCEMPEngine);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Error enabling OpenGL multithreading:") +
+ CGLErrorString(error) + "\n");
+ }
+}
+
+void HeadlessBackend::destroyContext() {
+ CGLDestroyContext(glContext);
+}
+
+void HeadlessBackend::activateContext() {
+ CGLError error = CGLSetCurrentContext(glContext);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Switching OpenGL context failed:") +
+ CGLErrorString(error) + "\n");
+ }
+}
+
+void HeadlessBackend::deactivateContext() {
+ CGLError error = CGLSetCurrentContext(nullptr);
+ if (error != kCGLNoError) {
+ throw std::runtime_error(std::string("Removing OpenGL context failed:") +
+ CGLErrorString(error) + "\n");
+ }
+}
+
+} // namespace mbgl
diff --git a/platform/darwin/src/headless_backend_eagl.mm b/platform/darwin/src/headless_backend_eagl.mm
new file mode 100644
index 0000000000..0a1ae706b8
--- /dev/null
+++ b/platform/darwin/src/headless_backend_eagl.mm
@@ -0,0 +1,46 @@
+#include <mbgl/platform/default/headless_backend.hpp>
+
+#include <mbgl/gl/extension.hpp>
+
+#include <OpenGLES/EAGL.h>
+
+#include <stdexcept>
+
+namespace mbgl {
+
+gl::glProc 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<gl::glProc>(symbol);
+}
+
+void HeadlessBackend::createContext() {
+ glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
+ if (glContext == nil) {
+ throw std::runtime_error("Error creating GL context object");
+ }
+ [reinterpret_cast<EAGLContext*>(glContext) retain];
+ reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES;
+}
+
+void HeadlessBackend::destroyContext() {
+ [reinterpret_cast<EAGLContext*>(glContext) release];
+ glContext = nil;
+}
+
+void HeadlessBackend::activateContext() {
+ [EAGLContext setCurrentContext:reinterpret_cast<EAGLContext*>(glContext)];
+}
+
+void HeadlessBackend::deactivateContext() {
+ [EAGLContext setCurrentContext:nil];
+}
+
+} // namespace mbgl
diff --git a/platform/darwin/src/headless_view_cgl.cpp b/platform/darwin/src/headless_view_cgl.cpp
index dc58463b5d..08f0da8751 100644
--- a/platform/darwin/src/headless_view_cgl.cpp
+++ b/platform/darwin/src/headless_view_cgl.cpp
@@ -1,37 +1,14 @@
#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-#include <CoreFoundation/CoreFoundation.h>
+#include <mbgl/gl/gl.hpp>
-namespace mbgl {
-
-gl::glProc HeadlessView::initializeExtension(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<gl::glProc>(symbol);
-}
-
-void HeadlessView::createContext() {
- CGLError error = CGLCreateContext(display->pixelFormat, nullptr, &glContext);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Error creating GL context object:") + CGLErrorString(error) + "\n");
- }
+#include <cassert>
- error = CGLEnable(glContext, kCGLCEMPEngine);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Error enabling OpenGL multithreading:") + CGLErrorString(error) + "\n");
- }
-}
+namespace mbgl {
-void HeadlessView::destroyContext() {
- CGLDestroyContext(glContext);
+void HeadlessView::bindFramebuffer() {
+ assert(fbo);
+ MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo));
}
void HeadlessView::resizeFramebuffer() {
@@ -76,8 +53,6 @@ void HeadlessView::resizeFramebuffer() {
}
void HeadlessView::clearBuffers() {
- assert(active);
-
MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
if (fbo) {
@@ -96,18 +71,4 @@ void HeadlessView::clearBuffers() {
}
}
-void HeadlessView::activateContext() {
- CGLError error = CGLSetCurrentContext(glContext);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Switching OpenGL context failed:") + CGLErrorString(error) + "\n");
- }
-}
-
-void HeadlessView::deactivateContext() {
- CGLError error = CGLSetCurrentContext(nullptr);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Removing OpenGL context failed:") + CGLErrorString(error) + "\n");
- }
-}
-
} // namespace mbgl
diff --git a/platform/darwin/src/headless_view_eagl.mm b/platform/darwin/src/headless_view_eagl.cpp
index a1f335fc6e..cc378912f9 100644
--- a/platform/darwin/src/headless_view_eagl.mm
+++ b/platform/darwin/src/headless_view_eagl.cpp
@@ -1,35 +1,14 @@
#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-#include <OpenGLES/EAGL.h>
+#include <mbgl/gl/gl.hpp>
-namespace mbgl {
-
-gl::glProc HeadlessView::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);
+#include <cassert>
- return reinterpret_cast<gl::glProc>(symbol);
-}
-
-void HeadlessView::createContext() {
- glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
- if (glContext == nil) {
- throw std::runtime_error("Error creating GL context object");
- }
- [reinterpret_cast<EAGLContext*>(glContext) retain];
- reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES;
-}
+namespace mbgl {
-void HeadlessView::destroyContext() {
- [reinterpret_cast<EAGLContext*>(glContext) release];
- glContext = nil;
+void HeadlessView::bindFramebuffer() {
+ assert(fbo);
+ MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo));
}
void HeadlessView::resizeFramebuffer() {
@@ -72,8 +51,6 @@ void HeadlessView::resizeFramebuffer() {
}
void HeadlessView::clearBuffers() {
- assert(active);
-
MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
if (fbo) {
@@ -92,12 +69,4 @@ void HeadlessView::clearBuffers() {
}
}
-void HeadlessView::activateContext() {
- [EAGLContext setCurrentContext:reinterpret_cast<EAGLContext*>(glContext)];
-}
-
-void HeadlessView::deactivateContext() {
- [EAGLContext setCurrentContext:nil];
-}
-
} // namespace mbgl
diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp
index 9c54fc4ebf..044181e8c8 100644
--- a/platform/default/glfw_view.cpp
+++ b/platform/default/glfw_view.cpp
@@ -129,6 +129,10 @@ void GLFWView::initialize(mbgl::Map *map_) {
map->addAnnotationIcon("default_marker", makeSpriteImage(22, 22, 1));
}
+void GLFWView::bind() {
+ MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
+}
+
void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, int mods) {
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
diff --git a/platform/default/headless_backend.cpp b/platform/default/headless_backend.cpp
new file mode 100644
index 0000000000..279a7973c9
--- /dev/null
+++ b/platform/default/headless_backend.cpp
@@ -0,0 +1,56 @@
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/headless_display.hpp>
+
+#include <cassert>
+#include <stdexcept>
+
+namespace mbgl {
+
+HeadlessBackend::HeadlessBackend() : display(std::make_shared<HeadlessDisplay>()) {
+ activate();
+}
+
+HeadlessBackend::HeadlessBackend(std::shared_ptr<HeadlessDisplay> display_)
+ : display(std::move(display_)) {
+ activate();
+}
+
+HeadlessBackend::~HeadlessBackend() {
+ deactivate();
+ destroyContext();
+}
+
+void HeadlessBackend::activate() {
+ active = true;
+
+ if (!glContext) {
+ if (!display) {
+ throw std::runtime_error("Display is not set");
+ }
+ createContext();
+ }
+
+ activateContext();
+
+ if (!extensionsLoaded) {
+ gl::InitializeExtensions(initializeExtension);
+ extensionsLoaded = true;
+ }
+}
+
+void HeadlessBackend::deactivate() {
+ deactivateContext();
+ active = false;
+}
+
+void HeadlessBackend::invalidate() {
+ assert(false);
+}
+
+void HeadlessBackend::notifyMapChange(MapChange change) {
+ if (mapChangeCallback) {
+ mapChangeCallback(change);
+ }
+}
+
+} // namespace mbgl
diff --git a/platform/default/headless_backend_glx.cpp b/platform/default/headless_backend_glx.cpp
new file mode 100644
index 0000000000..bbfd19345b
--- /dev/null
+++ b/platform/default/headless_backend_glx.cpp
@@ -0,0 +1,67 @@
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/headless_display.hpp>
+
+#include <mbgl/platform/log.hpp>
+
+// #include <cassert>
+
+#include <GL/glx.h>
+
+namespace mbgl {
+
+gl::glProc HeadlessBackend::initializeExtension(const char* name) {
+ return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
+}
+
+void HeadlessBackend::createContext() {
+ xDisplay = display->xDisplay;
+ fbConfigs = display->fbConfigs;
+
+ if (!glContext) {
+ // Try to create a legacy context
+ glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True);
+ if (glContext) {
+ if (!glXIsDirect(xDisplay, glContext)) {
+ Log::Error(Event::OpenGL, "failed to create direct OpenGL Legacy context");
+ glXDestroyContext(xDisplay, glContext);
+ glContext = nullptr;
+ }
+ }
+ }
+
+ if (glContext == nullptr) {
+ throw std::runtime_error("Error creating GL context object.");
+ }
+
+ // Create a dummy pbuffer. We will render to framebuffers anyway, but we need a pbuffer to
+ // activate the context.
+ int pbufferAttributes[] = {
+ GLX_PBUFFER_WIDTH, 8,
+ GLX_PBUFFER_HEIGHT, 8,
+ None
+ };
+ glxPbuffer = glXCreatePbuffer(xDisplay, fbConfigs[0], pbufferAttributes);
+}
+
+void HeadlessBackend::destroyContext() {
+ if (glxPbuffer) {
+ glXDestroyPbuffer(xDisplay, glxPbuffer);
+ glxPbuffer = 0;
+ }
+
+ glXDestroyContext(xDisplay, glContext);
+}
+
+void HeadlessBackend::activateContext() {
+ if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) {
+ throw std::runtime_error("Switching OpenGL context failed.\n");
+ }
+}
+
+void HeadlessBackend::deactivateContext() {
+ if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) {
+ throw std::runtime_error("Removing OpenGL context failed.\n");
+ }
+}
+
+} // namespace mbgl
diff --git a/platform/default/headless_display.cpp b/platform/default/headless_display.cpp
index 8b9f3fe04b..b98aef7903 100644
--- a/platform/default/headless_display.cpp
+++ b/platform/default/headless_display.cpp
@@ -1,12 +1,13 @@
#include <mbgl/platform/default/headless_display.hpp>
-#include <cstring>
-#include <stdexcept>
-
#if MBGL_USE_GLX
#include <GL/glx.h>
#endif
+#include <cstring>
+#include <stdexcept>
+#include <string>
+
namespace mbgl {
HeadlessDisplay::HeadlessDisplay() {
diff --git a/platform/default/headless_view.cpp b/platform/default/headless_view.cpp
index 95b196b746..f96b0a7f6d 100644
--- a/platform/default/headless_view.cpp
+++ b/platform/default/headless_view.cpp
@@ -1,34 +1,27 @@
#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-#include <cassert>
+#include <mbgl/gl/gl.hpp>
+
#include <cstring>
namespace mbgl {
HeadlessView::HeadlessView(float pixelRatio_, uint16_t width, uint16_t height)
- : display(std::make_shared<HeadlessDisplay>())
- , pixelRatio(pixelRatio_)
- , dimensions({{ width, height }})
- , needsResize(true) {
-}
-
-HeadlessView::HeadlessView(std::shared_ptr<HeadlessDisplay> display_,
- float pixelRatio_,
- uint16_t width,
- uint16_t height)
- : display(std::move(display_))
- , pixelRatio(pixelRatio_)
- , dimensions({{ width, height }})
- , needsResize(true) {
+ : pixelRatio(pixelRatio_), dimensions({ { width, height } }), needsResize(true) {
}
HeadlessView::~HeadlessView() {
- activate();
clearBuffers();
- deactivate();
+}
- destroyContext();
+void HeadlessView::bind() {
+ if (needsResize) {
+ clearBuffers();
+ resizeFramebuffer();
+ needsResize = false;
+ } else {
+ bindFramebuffer();
+ }
}
void HeadlessView::resize(const uint16_t width, const uint16_t height) {
@@ -41,8 +34,6 @@ void HeadlessView::resize(const uint16_t width, const uint16_t height) {
}
PremultipliedImage HeadlessView::readStillImage(std::array<uint16_t, 2> size) {
- assert(active);
-
if (!size[0] || !size[1]) {
size[0] = dimensions[0] * pixelRatio;
size[1] = dimensions[1] * pixelRatio;
@@ -76,43 +67,4 @@ std::array<uint16_t, 2> HeadlessView::getFramebufferSize() const {
static_cast<uint16_t>(dimensions[1] * pixelRatio) }};
}
-void HeadlessView::activate() {
- active = true;
-
- if (!glContext) {
- if (!display) {
- throw std::runtime_error("Display is not set");
- }
- createContext();
- }
-
- activateContext();
-
- if (!extensionsLoaded) {
- gl::InitializeExtensions(initializeExtension);
- extensionsLoaded = true;
- }
-
- if (needsResize) {
- clearBuffers();
- resizeFramebuffer();
- needsResize = false;
- }
-}
-
-void HeadlessView::deactivate() {
- deactivateContext();
- active = false;
-}
-
-void HeadlessView::invalidate() {
- assert(false);
-}
-
-void HeadlessView::notifyMapChange(MapChange change) {
- if (mapChangeCallback) {
- mapChangeCallback(change);
- }
-}
-
} // namespace mbgl
diff --git a/platform/default/headless_view_glx.cpp b/platform/default/headless_view_glx.cpp
index 55d9313f99..08f0da8751 100644
--- a/platform/default/headless_view_glx.cpp
+++ b/platform/default/headless_view_glx.cpp
@@ -1,54 +1,14 @@
#include <mbgl/platform/default/headless_view.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
-#include <mbgl/platform/log.hpp>
-#include <cassert>
+#include <mbgl/gl/gl.hpp>
-#include <GL/glx.h>
+#include <cassert>
namespace mbgl {
-gl::glProc HeadlessView::initializeExtension(const char* name) {
- return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
-}
-
-void HeadlessView::createContext() {
- xDisplay = display->xDisplay;
- fbConfigs = display->fbConfigs;
-
- if (!glContext) {
- // Try to create a legacy context
- glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True);
- if (glContext) {
- if (!glXIsDirect(xDisplay, glContext)) {
- Log::Error(Event::OpenGL, "failed to create direct OpenGL Legacy context");
- glXDestroyContext(xDisplay, glContext);
- glContext = nullptr;
- }
- }
- }
-
- if (glContext == nullptr) {
- throw std::runtime_error("Error creating GL context object.");
- }
-
- // Create a dummy pbuffer. We will render to framebuffers anyway, but we need a pbuffer to
- // activate the context.
- int pbufferAttributes[] = {
- GLX_PBUFFER_WIDTH, 8,
- GLX_PBUFFER_HEIGHT, 8,
- None
- };
- glxPbuffer = glXCreatePbuffer(xDisplay, fbConfigs[0], pbufferAttributes);
-}
-
-void HeadlessView::destroyContext() {
- if (glxPbuffer) {
- glXDestroyPbuffer(xDisplay, glxPbuffer);
- glxPbuffer = 0;
- }
-
- glXDestroyContext(xDisplay, glContext);
+void HeadlessView::bindFramebuffer() {
+ assert(fbo);
+ MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo));
}
void HeadlessView::resizeFramebuffer() {
@@ -93,8 +53,6 @@ void HeadlessView::resizeFramebuffer() {
}
void HeadlessView::clearBuffers() {
- assert(active);
-
MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
if (fbo) {
@@ -113,16 +71,4 @@ void HeadlessView::clearBuffers() {
}
}
-void HeadlessView::activateContext() {
- if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) {
- throw std::runtime_error("Switching OpenGL context failed.\n");
- }
-}
-
-void HeadlessView::deactivateContext() {
- if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) {
- throw std::runtime_error("Removing OpenGL context failed.\n");
- }
-}
-
} // namespace mbgl
diff --git a/platform/ios/config.cmake b/platform/ios/config.cmake
index e5480e37df..db75d7a4de 100644
--- a/platform/ios/config.cmake
+++ b/platform/ios/config.cmake
@@ -37,7 +37,9 @@ macro(mbgl_platform_core)
PRIVATE platform/darwin/src/image.mm
# Headless view
- PRIVATE platform/darwin/src/headless_view_eagl.mm
+ PRIVATE platform/darwin/src/headless_backend_eagl.mm
+ PRIVATE platform/darwin/src/headless_view_eagl.cpp
+ PRIVATE platform/default/headless_backend.cpp
PRIVATE platform/default/headless_display.cpp
PRIVATE platform/default/headless_view.cpp
@@ -53,7 +55,7 @@ macro(mbgl_platform_core)
# TODO: Remove this by converting to ARC
set_source_files_properties(
- platform/darwin/src/headless_view_eagl.mm
+ platform/darwin/src/headless_backend_eagl.mm
PROPERTIES
COMPILE_FLAGS -fno-objc-arc
)
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 194f1a88d4..3d93dc8fc9 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -18,6 +18,7 @@
#include <mbgl/storage/network_status.hpp>
#include <mbgl/style/transition_options.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
+#include <mbgl/map/backend.hpp>
#include <mbgl/math/wrap.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/constants.hpp>
@@ -389,8 +390,7 @@ public:
self.clipsToBounds = YES;
// setup mbgl view
- const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
- _mbglView = new MBGLView(self, scaleFactor);
+ _mbglView = new MBGLView(self);
// Delete the pre-offline ambient cache at ~/Library/Caches/cache.db.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
@@ -398,9 +398,10 @@ public:
[[NSFileManager defaultManager] removeItemAtPath:fileCachePath error:NULL];
// setup mbgl map
+ const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
_mbglThreadPool = new mbgl::ThreadPool(4);
- _mbglMap = new mbgl::Map(*_mbglView, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
+ _mbglMap = new mbgl::Map(*_mbglView, *_mbglView, scaleFactor, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
[self validateTileCacheSize];
// start paused if in IB
@@ -4938,15 +4939,11 @@ public:
return _annotationViewReuseQueueByIdentifier[identifier];
}
-class MBGLView : public mbgl::View
+class MBGLView : public mbgl::View, public mbgl::Backend
{
public:
- MBGLView(MGLMapView* nativeView_, const float scaleFactor_)
- : nativeView(nativeView_), scaleFactor(scaleFactor_) {
- }
-
- float getPixelRatio() const override {
- return scaleFactor;
+ MBGLView(MGLMapView* nativeView_)
+ : nativeView(nativeView_) {
}
std::array<uint16_t, 2> getSize() const override {
@@ -4959,6 +4956,10 @@ public:
static_cast<uint16_t>([[nativeView glView] drawableHeight]) }};
}
+ void bind() override {
+ [nativeView.glView bindDrawable];
+ }
+
void notifyMapChange(mbgl::MapChange change) override
{
[nativeView notifyMapChange:change];
@@ -4981,7 +4982,6 @@ public:
private:
__weak MGLMapView *nativeView = nullptr;
- const float scaleFactor;
};
@end
diff --git a/platform/linux/config.cmake b/platform/linux/config.cmake
index 86e8697f8c..d033f9df21 100644
--- a/platform/linux/config.cmake
+++ b/platform/linux/config.cmake
@@ -41,9 +41,11 @@ macro(mbgl_platform_core)
PRIVATE platform/default/webp_reader.cpp
# Headless view
+ PRIVATE platform/default/headless_backend_glx.cpp
+ PRIVATE platform/default/headless_view_glx.cpp
+ PRIVATE platform/default/headless_backend.cpp
PRIVATE platform/default/headless_display.cpp
PRIVATE platform/default/headless_view.cpp
- PRIVATE platform/default/headless_view_glx.cpp
# Thread pool
PRIVATE platform/default/thread_pool.cpp
diff --git a/platform/macos/config.cmake b/platform/macos/config.cmake
index 645feb90c3..198dfc7083 100644
--- a/platform/macos/config.cmake
+++ b/platform/macos/config.cmake
@@ -35,7 +35,9 @@ macro(mbgl_platform_core)
PRIVATE platform/darwin/src/image.mm
# Headless view
+ PRIVATE platform/darwin/src/headless_backend_cgl.cpp
PRIVATE platform/darwin/src/headless_view_cgl.cpp
+ PRIVATE platform/default/headless_backend.cpp
PRIVATE platform/default/headless_display.cpp
PRIVATE platform/default/headless_view.cpp
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index 46766b573b..475ca2d259 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -25,6 +25,7 @@
#import <mbgl/platform/default/thread_pool.hpp>
#import <mbgl/gl/extension.hpp>
#import <mbgl/gl/gl.hpp>
+#import <mbgl/map/backend.hpp>
#import <mbgl/sprite/sprite_image.hpp>
#import <mbgl/storage/default_file_source.hpp>
#import <mbgl/storage/network_status.hpp>
@@ -248,7 +249,7 @@ public:
_isTargetingInterfaceBuilder = NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent;
// Set up cross-platform controllers and resources.
- _mbglView = new MGLMapViewImpl(self, [NSScreen mainScreen].backingScaleFactor);
+ _mbglView = new MGLMapViewImpl(self);
// Delete the pre-offline ambient cache at
// ~/Library/Caches/com.mapbox.sdk.ios/cache.db.
@@ -264,7 +265,7 @@ public:
mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
_mbglThreadPool = new mbgl::ThreadPool(4);
- _mbglMap = new mbgl::Map(*_mbglView, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
+ _mbglMap = new mbgl::Map(*_mbglView, *_mbglView, [NSScreen mainScreen].backingScaleFactor, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
[self validateTileCacheSize];
// Install the OpenGL layer. Interface Builder’s synchronous drawing means
@@ -745,6 +746,8 @@ public:
return reinterpret_cast<mbgl::gl::glProc>(symbol);
});
+ _mbglView->updateFramebufferBinding();
+
_mbglMap->render();
if (_isPrinting) {
@@ -2531,14 +2534,10 @@ public:
}
/// Adapter responsible for bridging calls from mbgl to MGLMapView and Cocoa.
-class MGLMapViewImpl : public mbgl::View {
+class MGLMapViewImpl : public mbgl::View, public mbgl::Backend {
public:
- MGLMapViewImpl(MGLMapView *nativeView_, const float scaleFactor_)
- : nativeView(nativeView_), scaleFactor(scaleFactor_) {}
-
- float getPixelRatio() const override {
- return scaleFactor;
- }
+ MGLMapViewImpl(MGLMapView *nativeView_)
+ : nativeView(nativeView_) {}
std::array<uint16_t, 2> getSize() const override {
return {{ static_cast<uint16_t>(nativeView.bounds.size.width),
@@ -2568,6 +2567,14 @@ public:
[NSOpenGLContext clearCurrentContext];
}
+ void updateFramebufferBinding() {
+ MBGL_CHECK_ERROR(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo));
+ }
+
+ void bind() override {
+ MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo));
+ }
+
mbgl::PremultipliedImage readStillImage(std::array<uint16_t, 2> size = {{ 0, 0 }}) override {
if (!size[0] || !size[1]) {
size = getFramebufferSize();
@@ -2592,8 +2599,8 @@ private:
/// Cocoa map view that this adapter bridges to.
__weak MGLMapView *nativeView = nullptr;
- /// Backing scale factor of the view.
- const float scaleFactor;
+ /// The current framebuffer of the NSOpenGLLayer we are painting to.
+ GLint fbo = 0;
};
@end
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index a13adbc417..ebdf8d62c3 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -773,15 +773,16 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&
}
NodeMap::NodeMap(v8::Local<v8::Object> options) :
- view(sharedDisplay(), [&] {
+ backend(sharedDisplay()),
+ view([&] {
Nan::HandleScope scope;
return Nan::Has(options, Nan::New("ratio").ToLocalChecked()).FromJust() ? Nan::Get(options, Nan::New("ratio").ToLocalChecked()).ToLocalChecked()->NumberValue() : 1.0;
}()),
threadpool(),
- map(std::make_unique<mbgl::Map>(view, *this, threadpool, mbgl::MapMode::Still)),
+ map(std::make_unique<mbgl::Map>(backend, view, view.getPixelRatio(), *this, threadpool, mbgl::MapMode::Still)),
async(new uv_async_t) {
- view.setMapChangeCallback([&](mbgl::MapChange change) {
+ backend.setMapChangeCallback([&](mbgl::MapChange change) {
if (change == mbgl::MapChangeDidFailLoadingMap) {
throw std::runtime_error("Requires a map style to be a valid style JSON");
}
diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp
index 588ece2c74..48ff2caab1 100644
--- a/platform/node/src/node_map.hpp
+++ b/platform/node/src/node_map.hpp
@@ -4,6 +4,7 @@
#include <mbgl/map/map.hpp>
#include <mbgl/storage/file_source.hpp>
+#include <mbgl/platform/default/headless_backend.hpp>
#include <mbgl/platform/default/headless_view.hpp>
#pragma GCC diagnostic push
@@ -53,6 +54,7 @@ public:
std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback);
+ mbgl::HeadlessBackend backend;
mbgl::HeadlessView view;
NodeThreadPool threadpool;
std::unique_ptr<mbgl::Map> map;
diff --git a/platform/qt/config.cmake b/platform/qt/config.cmake
index d8ede6b450..6df311f885 100644
--- a/platform/qt/config.cmake
+++ b/platform/qt/config.cmake
@@ -43,8 +43,10 @@ endmacro()
macro(mbgl_platform_test)
target_sources(mbgl-test
PRIVATE test/src/main.cpp
+ PRIVATE platform/qt/test/headless_backend_qt.cpp
PRIVATE platform/qt/test/headless_view_qt.cpp
PRIVATE platform/qt/test/qmapboxgl.cpp
+ PRIVATE platform/default/headless_backend.cpp
PRIVATE platform/default/headless_display.cpp
PRIVATE platform/default/headless_view.cpp
)
diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp
index d0a05301f8..73a1771908 100644
--- a/platform/qt/src/qmapboxgl.cpp
+++ b/platform/qt/src/qmapboxgl.cpp
@@ -813,7 +813,7 @@ QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settin
settings.cacheDatabaseMaximumSize()))
, threadPool(4)
, mapObj(std::make_unique<mbgl::Map>(
- *this, *fileSourceObj, threadPool,
+ *this, *this, getPixelRatio(), *fileSourceObj, threadPool,
static_cast<mbgl::MapMode>(settings.mapMode()),
static_cast<mbgl::GLContextMode>(settings.contextMode()),
static_cast<mbgl::ConstrainMode>(settings.constrainMode()),
@@ -845,6 +845,11 @@ float QMapboxGLPrivate::getPixelRatio() const
return pixelRatio;
}
+void QMapboxGLPrivate::bind()
+{
+ MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
+}
+
std::array<uint16_t, 2> QMapboxGLPrivate::getSize() const
{
return {{ static_cast<uint16_t>(size.width()), static_cast<uint16_t>(size.height()) }};
diff --git a/platform/qt/src/qmapboxgl_p.hpp b/platform/qt/src/qmapboxgl_p.hpp
index c35ac4e7ba..5a228896dc 100644
--- a/platform/qt/src/qmapboxgl_p.hpp
+++ b/platform/qt/src/qmapboxgl_p.hpp
@@ -3,6 +3,7 @@
#include "qmapboxgl.hpp"
#include <mbgl/map/map.hpp>
+#include <mbgl/map/backend.hpp>
#include <mbgl/map/view.hpp>
#include <mbgl/platform/default/thread_pool.hpp>
#include <mbgl/storage/default_file_source.hpp>
@@ -11,7 +12,7 @@
#include <QObject>
#include <QSize>
-class QMapboxGLPrivate : public QObject, public mbgl::View
+class QMapboxGLPrivate : public QObject, public mbgl::View, public mbgl::Backend
{
Q_OBJECT
@@ -20,7 +21,8 @@ public:
virtual ~QMapboxGLPrivate();
// mbgl::View implementation.
- float getPixelRatio() const final;
+ float getPixelRatio() const;
+ void bind() final;
std::array<uint16_t, 2> getSize() const final;
std::array<uint16_t, 2> getFramebufferSize() const final;
diff --git a/platform/qt/test/headless_backend_qt.cpp b/platform/qt/test/headless_backend_qt.cpp
new file mode 100644
index 0000000000..3f287ae578
--- /dev/null
+++ b/platform/qt/test/headless_backend_qt.cpp
@@ -0,0 +1,46 @@
+#include <mbgl/platform/default/headless_backend.hpp>
+#include <mbgl/platform/default/headless_display.hpp>
+
+#include <QApplication>
+#include <QGLContext>
+#include <QGLWidget>
+
+#if QT_VERSION >= 0x050000
+#include <QOpenGLContext>
+#endif
+
+namespace mbgl {
+
+gl::glProc 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));
+#endif
+}
+
+void HeadlessBackend::createContext() {
+ static const char* argv[] = { "mbgl" };
+ static int argc = 1;
+ static auto* app = new QApplication(argc, const_cast<char**>(argv));
+
+ Q_UNUSED(app);
+
+ glContext = new QGLWidget;
+}
+
+void HeadlessBackend::destroyContext() {
+ delete glContext;
+}
+
+void HeadlessBackend::activateContext() {
+ glContext->makeCurrent();
+}
+
+void HeadlessBackend::deactivateContext() {
+ glContext->doneCurrent();
+}
+
+} // namespace mbgl
diff --git a/platform/qt/test/headless_view_qt.cpp b/platform/qt/test/headless_view_qt.cpp
index 03ecb741ab..133b4a2371 100644
--- a/platform/qt/test/headless_view_qt.cpp
+++ b/platform/qt/test/headless_view_qt.cpp
@@ -1,6 +1,7 @@
-#include <mbgl/platform/default/headless_display.hpp>
#include <mbgl/platform/default/headless_view.hpp>
+#include <mbgl/gl/gl.hpp>
+
#include <QApplication>
#include <QGLContext>
#include <QGLWidget>
@@ -9,30 +10,13 @@
#include <QOpenGLContext>
#endif
-namespace mbgl {
-
-gl::glProc HeadlessView::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));
-#endif
-}
-
-void HeadlessView::createContext() {
- static const char* argv[] = { "mbgl" };
- static int argc = 1;
- static auto* app = new QApplication(argc, const_cast<char**>(argv));
-
- Q_UNUSED(app);
+#include <cassert>
- glContext = new QGLWidget;
-}
+namespace mbgl {
-void HeadlessView::destroyContext() {
- delete glContext;
+void HeadlessView::bindFramebuffer() {
+ assert(fbo);
+ MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo));
}
void HeadlessView::resizeFramebuffer() {
@@ -95,12 +79,4 @@ void HeadlessView::clearBuffers() {
}
}
-void HeadlessView::activateContext() {
- glContext->makeCurrent();
-}
-
-void HeadlessView::deactivateContext() {
- glContext->doneCurrent();
-}
-
} // namespace mbgl