summaryrefslogtreecommitdiff
path: root/platform/default
diff options
context:
space:
mode:
Diffstat (limited to 'platform/default')
-rw-r--r--platform/default/bidi.cpp128
-rw-r--r--platform/default/default_file_source.cpp2
-rw-r--r--platform/default/glfw_view.cpp628
-rw-r--r--platform/default/headless_backend_glx.cpp67
-rw-r--r--platform/default/headless_backend_osmesa.cpp65
-rw-r--r--platform/default/headless_display.cpp82
-rw-r--r--platform/default/http_file_source.cpp2
-rw-r--r--platform/default/image.cpp12
-rw-r--r--platform/default/jpeg_reader.cpp2
-rw-r--r--platform/default/logging_stderr.cpp (renamed from platform/default/log_stderr.cpp)2
-rw-r--r--platform/default/mbgl/gl/headless_backend.cpp (renamed from platform/default/headless_backend.cpp)28
-rw-r--r--platform/default/mbgl/gl/headless_backend.hpp57
-rw-r--r--platform/default/mbgl/gl/headless_display.cpp15
-rw-r--r--platform/default/mbgl/gl/headless_display.hpp20
-rw-r--r--platform/default/mbgl/gl/offscreen_view.cpp30
-rw-r--r--platform/default/mbgl/gl/offscreen_view.hpp33
-rw-r--r--platform/default/mbgl/storage/offline_database.cpp2
-rw-r--r--platform/default/mbgl/storage/offline_download.cpp2
-rw-r--r--platform/default/mbgl/util/default_styles.cpp16
-rw-r--r--platform/default/mbgl/util/default_styles.hpp31
-rw-r--r--platform/default/mbgl/util/default_thread_pool.cpp (renamed from platform/default/thread_pool.cpp)2
-rw-r--r--platform/default/mbgl/util/default_thread_pool.hpp27
-rw-r--r--platform/default/offscreen_view.cpp47
-rw-r--r--platform/default/online_file_source.cpp2
-rw-r--r--platform/default/png_reader.cpp4
-rw-r--r--platform/default/settings_json.cpp41
-rw-r--r--platform/default/sqlite3.cpp2
-rw-r--r--platform/default/string_stdlib.cpp4
-rw-r--r--platform/default/thread.cpp4
-rw-r--r--platform/default/webp_reader.cpp6
30 files changed, 439 insertions, 924 deletions
diff --git a/platform/default/bidi.cpp b/platform/default/bidi.cpp
new file mode 100644
index 0000000000..5b0c2f8da7
--- /dev/null
+++ b/platform/default/bidi.cpp
@@ -0,0 +1,128 @@
+#include <memory>
+
+#include <mbgl/text/bidi.hpp>
+#include <unicode/ubidi.h>
+#include <unicode/ushape.h>
+
+namespace mbgl {
+
+class BiDiImpl {
+public:
+ BiDiImpl() : bidiText(ubidi_open()), bidiLine(ubidi_open()) {}
+ ~BiDiImpl() { ubidi_close(bidiText); ubidi_close(bidiLine); }
+
+ UBiDi* bidiText = nullptr;
+ UBiDi* bidiLine = nullptr;
+};
+
+// Takes UTF16 input in logical order and applies Arabic shaping to the input while maintaining
+// logical order
+// Output won't be intelligible until the bidirectional algorithm is applied
+std::u16string applyArabicShaping(const std::u16string& input) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+
+ int32_t outputLength =
+ u_shapeArabic(input.c_str(), static_cast<int32_t>(input.size()), NULL, 0,
+ (U_SHAPE_LETTERS_SHAPE & U_SHAPE_LETTERS_MASK) |
+ (U_SHAPE_TEXT_DIRECTION_LOGICAL & U_SHAPE_TEXT_DIRECTION_MASK),
+ &errorCode);
+
+ // Pre-flighting will always set U_BUFFER_OVERFLOW_ERROR
+ errorCode = U_ZERO_ERROR;
+
+ std::unique_ptr<UChar[]> outputText = std::make_unique<UChar[]>(outputLength);
+ u_shapeArabic(input.c_str(), static_cast<int32_t>(input.size()), outputText.get(), outputLength,
+ (U_SHAPE_LETTERS_SHAPE & U_SHAPE_LETTERS_MASK) |
+ (U_SHAPE_TEXT_DIRECTION_LOGICAL & U_SHAPE_TEXT_DIRECTION_MASK),
+ &errorCode);
+
+ // If the algorithm fails for any reason, fall back to non-transformed text
+ if (U_FAILURE(errorCode))
+ return input;
+
+ return std::u16string(outputText.get(), outputLength);
+}
+
+ProcessedBiDiText::ProcessedBiDiText(BiDi& p_bidi) : bidi(p_bidi) {
+}
+
+void ProcessedBiDiText::mergeParagraphLineBreaks(std::set<int32_t>& lineBreakPoints) {
+ int32_t paragraphCount = ubidi_countParagraphs(bidi.impl->bidiText);
+ for (int32_t i = 0; i < paragraphCount; i++) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ int32_t paragraphEndIndex;
+ ubidi_getParagraphByIndex(bidi.impl->bidiText, i, NULL, &paragraphEndIndex, NULL, &errorCode);
+
+ if (U_FAILURE(errorCode))
+ throw std::runtime_error(std::string("ProcessedBiDiText::mergeParagraphLineBreaks: ") +
+ u_errorName(errorCode));
+
+ lineBreakPoints.insert(paragraphEndIndex);
+ }
+}
+
+std::vector<std::u16string>
+ProcessedBiDiText::applyLineBreaking(std::set<int32_t> lineBreakPoints) {
+ // BiDi::getLine will error if called across a paragraph boundary, so we need to ensure that all
+ // paragraph
+ // boundaries are included in the set of line break points. The calling code might not include
+ // the line break because it
+ // didn't need to wrap at that point, or because the text was separated with a more exotic code
+ // point such as (U+001C)
+ mergeParagraphLineBreaks(lineBreakPoints);
+
+ std::vector<std::u16string> transformedLines;
+ int32_t start = 0;
+ for (int32_t lineBreakPoint : lineBreakPoints) {
+ transformedLines.push_back(bidi.getLine(start, lineBreakPoint));
+ start = lineBreakPoint;
+ }
+
+ return transformedLines;
+}
+
+BiDi::BiDi() : impl(std::make_unique<BiDiImpl>())
+{
+}
+
+BiDi::~BiDi() {
+}
+
+ProcessedBiDiText BiDi::processText(const std::u16string& input) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+
+ ubidi_setPara(impl->bidiText, input.c_str(), static_cast<int32_t>(input.size()), UBIDI_DEFAULT_LTR,
+ NULL, &errorCode);
+
+ if (U_FAILURE(errorCode))
+ throw std::runtime_error(std::string("BiDi::processText: ") + u_errorName(errorCode));
+
+ return ProcessedBiDiText(*this);
+}
+
+std::u16string BiDi::getLine(int32_t start, int32_t end) {
+ UErrorCode errorCode = U_ZERO_ERROR;
+ ubidi_setLine(impl->bidiText, start, end, impl->bidiLine, &errorCode);
+
+ if (U_FAILURE(errorCode))
+ throw std::runtime_error(std::string("BiDi::getLine (setLine): ") + u_errorName(errorCode));
+
+ // Because we set UBIDI_REMOVE_BIDI_CONTROLS, the output may be smaller than what we reserve
+ // Setting UBIDI_INSERT_LRM_FOR_NUMERIC would require
+ // ubidi_getLength(pBiDi)+2*ubidi_countRuns(pBiDi)
+ int32_t outputLength = ubidi_getProcessedLength(impl->bidiLine);
+ std::unique_ptr<UChar[]> outputText = std::make_unique<UChar[]>(outputLength);
+
+ // UBIDI_DO_MIRRORING: Apply unicode mirroring of characters like parentheses
+ // UBIDI_REMOVE_BIDI_CONTROLS: Now that all the lines are set, remove control characters so that
+ // they don't show up on screen (some fonts have glyphs representing them)
+ ubidi_writeReordered(impl->bidiLine, outputText.get(), outputLength,
+ UBIDI_DO_MIRRORING | UBIDI_REMOVE_BIDI_CONTROLS, &errorCode);
+
+ if (U_FAILURE(errorCode))
+ throw std::runtime_error(std::string("BiDi::getLine (writeReordered): ") + u_errorName(errorCode));
+
+ return std::u16string(outputText.get(), outputLength);
+}
+
+} // end namespace mbgl
diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp
index 7b52637c15..c4222b5a12 100644
--- a/platform/default/default_file_source.cpp
+++ b/platform/default/default_file_source.cpp
@@ -5,7 +5,7 @@
#include <mbgl/storage/offline_database.hpp>
#include <mbgl/storage/offline_download.hpp>
-#include <mbgl/platform/platform.hpp>
+#include <mbgl/util/platform.hpp>
#include <mbgl/util/url.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/util/work_request.hpp>
diff --git a/platform/default/glfw_view.cpp b/platform/default/glfw_view.cpp
deleted file mode 100644
index 47551d786f..0000000000
--- a/platform/default/glfw_view.cpp
+++ /dev/null
@@ -1,628 +0,0 @@
-#include <mbgl/platform/default/glfw_view.hpp>
-#include <mbgl/annotation/annotation.hpp>
-#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/platform/log.hpp>
-#include <mbgl/platform/platform.hpp>
-#include <mbgl/util/string.hpp>
-#include <mbgl/util/chrono.hpp>
-#include <mbgl/map/camera.hpp>
-
-#include <mbgl/gl/state.hpp>
-#include <mbgl/gl/value.hpp>
-
-#include <cassert>
-#include <cstdlib>
-
-void glfwError(int error, const char *description) {
- mbgl::Log::Error(mbgl::Event::OpenGL, "GLFW error (%i): %s", error, description);
- assert(false);
-}
-
-GLFWView::GLFWView(bool fullscreen_, bool benchmark_)
- : fullscreen(fullscreen_), benchmark(benchmark_) {
- glfwSetErrorCallback(glfwError);
-
- std::srand(std::time(nullptr));
-
- if (!glfwInit()) {
- mbgl::Log::Error(mbgl::Event::OpenGL, "failed to initialize glfw");
- exit(1);
- }
-
- GLFWmonitor *monitor = nullptr;
- if (fullscreen) {
- monitor = glfwGetPrimaryMonitor();
- auto videoMode = glfwGetVideoMode(monitor);
- width = videoMode->width;
- height = videoMode->height;
- }
-
-#ifdef DEBUG
- glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
-#endif
-
-#ifdef GL_ES_VERSION_2_0
- glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
-#endif
-
- glfwWindowHint(GLFW_RED_BITS, 8);
- glfwWindowHint(GLFW_GREEN_BITS, 8);
- glfwWindowHint(GLFW_BLUE_BITS, 8);
- glfwWindowHint(GLFW_ALPHA_BITS, 8);
- glfwWindowHint(GLFW_STENCIL_BITS, 8);
- glfwWindowHint(GLFW_DEPTH_BITS, 16);
-
- window = glfwCreateWindow(width, height, "Mapbox GL", monitor, nullptr);
- if (!window) {
- glfwTerminate();
- mbgl::Log::Error(mbgl::Event::OpenGL, "failed to initialize window");
- exit(1);
- }
-
- glfwSetWindowUserPointer(window, this);
- glfwMakeContextCurrent(window);
- if (benchmark) {
- // Disables vsync on platforms that support it.
- glfwSwapInterval(0);
- } else {
- glfwSwapInterval(1);
- }
-
-
- glfwSetCursorPosCallback(window, onMouseMove);
- glfwSetMouseButtonCallback(window, onMouseClick);
- glfwSetWindowSizeCallback(window, onWindowResize);
- glfwSetFramebufferSizeCallback(window, onFramebufferResize);
- glfwSetScrollCallback(window, onScroll);
- glfwSetKeyCallback(window, onKey);
-
- mbgl::gl::InitializeExtensions(glfwGetProcAddress);
-
- glfwGetWindowSize(window, &width, &height);
- glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
- pixelRatio = static_cast<float>(fbWidth) / width;
-
- glfwMakeContextCurrent(nullptr);
-
- printf("\n");
- printf("================================================================================\n");
- printf("\n");
- printf("- Press `S` to cycle through bundled styles\n");
- printf("- Press `X` to reset the transform\n");
- printf("- Press `N` to reset north\n");
- printf("- Press `R` to toggle any available `night` style class\n");
- printf("- Press `Z` to cycle through north orientations\n");
- printf("- Prezz `X` to cycle through the viewport modes\n");
- printf("- Press `A` to cycle through Mapbox offices in the world + dateline monument\n");
- printf("- Press `B` to cycle through the color, stencil, and depth buffer\n");
- printf("\n");
- printf("- Press `1` through `6` to add increasing numbers of point annotations for testing\n");
- printf("- Press `7` through `0` to add increasing numbers of shape annotations for testing\n");
- printf("\n");
- printf("- Press `Q` to remove annotations\n");
- printf("- Press `P` to add a random custom runtime imagery annotation\n");
- printf("- Press `L` to add a random line annotation\n");
- printf("- Press `W` to pop the last-added annotation off\n");
- printf("\n");
- printf("- `Control` + mouse drag to rotate\n");
- printf("- `Shift` + mouse drag to tilt\n");
- printf("\n");
- printf("- Press `Tab` to cycle through the map debug options\n");
- printf("- Press `Esc` to quit\n");
- printf("\n");
- printf("================================================================================\n");
- printf("\n");
-}
-
-GLFWView::~GLFWView() {
- glfwDestroyWindow(window);
- glfwTerminate();
-}
-
-void GLFWView::setMap(mbgl::Map *map_) {
- map = map_;
- map->addAnnotationIcon("default_marker", makeSpriteImage(22, 22, 1));
-}
-
-void GLFWView::updateViewBinding() {
- getContext().bindFramebuffer.setCurrentValue(0);
- getContext().viewport.setCurrentValue(
- { 0, 0, static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) });
-}
-
-void GLFWView::bind() {
- getContext().bindFramebuffer = 0;
- getContext().viewport = { 0, 0, static_cast<uint16_t>(fbWidth),
- static_cast<uint16_t>(fbHeight) };
-}
-
-void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, int mods) {
- GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
-
- if (action == GLFW_RELEASE) {
- switch (key) {
- case GLFW_KEY_ESCAPE:
- glfwSetWindowShouldClose(window, true);
- break;
- case GLFW_KEY_TAB:
- view->map->cycleDebugOptions();
- break;
- case GLFW_KEY_X:
- if (!mods)
- view->map->resetPosition();
- break;
- case GLFW_KEY_S:
- if (view->changeStyleCallback)
- view->changeStyleCallback();
- break;
- case GLFW_KEY_R:
- if (!mods) {
- static const mbgl::style::TransitionOptions transition { { mbgl::Milliseconds(300) } };
- view->map->setTransitionOptions(transition);
- if (view->map->hasClass("night")) {
- view->map->removeClass("night");
- } else {
- view->map->addClass("night");
- }
- }
- break;
- case GLFW_KEY_B: {
- auto debug = view->map->getDebug();
- if (debug & mbgl::MapDebugOptions::StencilClip) {
- debug &= ~mbgl::MapDebugOptions::StencilClip;
- debug |= mbgl::MapDebugOptions::DepthBuffer;
- } else if (debug & mbgl::MapDebugOptions::DepthBuffer) {
- debug &= ~mbgl::MapDebugOptions::DepthBuffer;
- } else {
- debug |= mbgl::MapDebugOptions::StencilClip;
- }
- view->map->setDebug(debug);
- } break;
- case GLFW_KEY_N:
- if (!mods)
- view->map->resetNorth();
- break;
- case GLFW_KEY_Z:
- view->nextOrientation();
- break;
- case GLFW_KEY_Q: {
- auto result = view->map->queryPointAnnotations({ {}, { double(view->getSize()[0]), double(view->getSize()[1]) } });
- printf("visible point annotations: %lu\n", result.size());
- } break;
- case GLFW_KEY_C:
- view->clearAnnotations();
- break;
- case GLFW_KEY_P:
- view->addRandomCustomPointAnnotations(1);
- break;
- case GLFW_KEY_L:
- view->addRandomLineAnnotations(1);
- break;
- case GLFW_KEY_A: {
- // XXX Fix precision loss in flyTo:
- // https://github.com/mapbox/mapbox-gl-native/issues/4298
- static const std::vector<mbgl::LatLng> places = {
- mbgl::LatLng { -16.796665, -179.999983 }, // Dateline monument
- mbgl::LatLng { 12.9810542, 77.6345551 }, // Mapbox Bengaluru, India
- mbgl::LatLng { -13.15607,-74.21773 }, // Mapbox Peru
- mbgl::LatLng { 37.77572, -122.4158818 }, // Mapbox SF, USA
- mbgl::LatLng { 38.91318,-77.03255 }, // Mapbox DC, USA
- };
- static size_t nextPlace = 0;
- mbgl::CameraOptions cameraOptions;
- cameraOptions.center = places[nextPlace++];
- cameraOptions.zoom = 20;
- cameraOptions.pitch = 30;
-
- mbgl::AnimationOptions animationOptions(mbgl::Seconds(10));
- view->map->flyTo(cameraOptions, animationOptions);
- nextPlace = nextPlace % places.size();
- } break;
- }
- }
-
- if (action == GLFW_RELEASE || action == GLFW_REPEAT) {
- switch (key) {
- case GLFW_KEY_W: view->popAnnotation(); break;
- case GLFW_KEY_1: view->addRandomPointAnnotations(1); break;
- case GLFW_KEY_2: view->addRandomPointAnnotations(10); break;
- case GLFW_KEY_3: view->addRandomPointAnnotations(100); break;
- case GLFW_KEY_4: view->addRandomPointAnnotations(1000); break;
- case GLFW_KEY_5: view->addRandomPointAnnotations(10000); break;
- case GLFW_KEY_6: view->addRandomPointAnnotations(100000); break;
- case GLFW_KEY_7: view->addRandomShapeAnnotations(1); break;
- case GLFW_KEY_8: view->addRandomShapeAnnotations(10); break;
- case GLFW_KEY_9: view->addRandomShapeAnnotations(100); break;
- case GLFW_KEY_0: view->addRandomShapeAnnotations(1000); break;
- }
- }
-}
-
-mbgl::Color GLFWView::makeRandomColor() const {
- const float r = 1.0f * (float(std::rand()) / RAND_MAX);
- const float g = 1.0f * (float(std::rand()) / RAND_MAX);
- const float b = 1.0f * (float(std::rand()) / RAND_MAX);
- return { r, g, b, 1.0f };
-}
-
-mbgl::Point<double> GLFWView::makeRandomPoint() const {
- const double x = width * double(std::rand()) / RAND_MAX;
- const double y = height * double(std::rand()) / RAND_MAX;
- mbgl::LatLng latLng = map->latLngForPixel({ x, y });
- return { latLng.longitude, latLng.latitude };
-}
-
-std::shared_ptr<const mbgl::SpriteImage>
-GLFWView::makeSpriteImage(int width, int height, float pixelRatio) {
- const int r = 255 * (double(std::rand()) / RAND_MAX);
- const int g = 255 * (double(std::rand()) / RAND_MAX);
- const int b = 255 * (double(std::rand()) / RAND_MAX);
-
- const int w = std::ceil(pixelRatio * width);
- const int h = std::ceil(pixelRatio * height);
-
- mbgl::PremultipliedImage image(w, h);
- auto data = reinterpret_cast<uint32_t*>(image.data.get());
- const int dist = (w / 2) * (w / 2);
- for (int y = 0; y < h; y++) {
- for (int x = 0; x < w; x++) {
- const int dx = x - w / 2;
- const int dy = y - h / 2;
- const int diff = dist - (dx * dx + dy * dy);
- if (diff > 0) {
- const int a = std::min(0xFF, diff) * 0xFF / dist;
- // Premultiply the rgb values with alpha
- data[w * y + x] =
- (a << 24) | ((a * r / 0xFF) << 16) | ((a * g / 0xFF) << 8) | (a * b / 0xFF);
- }
- }
- }
-
- return std::make_shared<mbgl::SpriteImage>(std::move(image), pixelRatio);
-}
-
-void GLFWView::nextOrientation() {
- using NO = mbgl::NorthOrientation;
- switch (map->getNorthOrientation()) {
- case NO::Upwards: map->setNorthOrientation(NO::Rightwards); break;
- case NO::Rightwards: map->setNorthOrientation(NO::Downwards); break;
- case NO::Downwards: map->setNorthOrientation(NO::Leftwards); break;
- default: map->setNorthOrientation(NO::Upwards); break;
- }
-}
-
-void GLFWView::addRandomCustomPointAnnotations(int count) {
- for (int i = 0; i < count; i++) {
- static int spriteID = 1;
- const auto name = std::string{ "marker-" } + mbgl::util::toString(spriteID++);
- map->addAnnotationIcon(name, makeSpriteImage(22, 22, 1));
- spriteIDs.push_back(name);
- annotationIDs.push_back(map->addAnnotation(mbgl::SymbolAnnotation { makeRandomPoint(), name }));
- }
-}
-
-void GLFWView::addRandomPointAnnotations(int count) {
- for (int i = 0; i < count; ++i) {
- annotationIDs.push_back(map->addAnnotation(mbgl::SymbolAnnotation { makeRandomPoint(), "default_marker" }));
- }
-}
-
-void GLFWView::addRandomLineAnnotations(int count) {
- for (int i = 0; i < count; ++i) {
- mbgl::LineString<double> lineString;
- for (int j = 0; j < 3; ++j) {
- lineString.push_back(makeRandomPoint());
- }
- annotationIDs.push_back(map->addAnnotation(mbgl::LineAnnotation { lineString, 1.0f, 2.0f, { makeRandomColor() } }));
- }
-}
-
-void GLFWView::addRandomShapeAnnotations(int count) {
- for (int i = 0; i < count; ++i) {
- mbgl::Polygon<double> triangle;
- triangle.push_back({ makeRandomPoint(), makeRandomPoint(), makeRandomPoint() });
- annotationIDs.push_back(map->addAnnotation(mbgl::FillAnnotation { triangle, 0.5f, { makeRandomColor() }, { makeRandomColor() } }));
- }
-}
-
-void GLFWView::clearAnnotations() {
- for (const auto& id : annotationIDs) {
- map->removeAnnotation(id);
- }
-
- annotationIDs.clear();
-}
-
-void GLFWView::popAnnotation() {
- if (annotationIDs.empty()) {
- return;
- }
-
- map->removeAnnotation(annotationIDs.back());
- annotationIDs.pop_back();
-}
-
-void GLFWView::onScroll(GLFWwindow *window, double /*xOffset*/, double yOffset) {
- GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
- double delta = yOffset * 40;
-
- bool isWheel = delta != 0 && std::fmod(delta, 4.000244140625) == 0;
-
- double absDelta = delta < 0 ? -delta : delta;
- double scale = 2.0 / (1.0 + std::exp(-absDelta / 100.0));
-
- // Make the scroll wheel a bit slower.
- if (!isWheel) {
- scale = (scale - 1.0) / 2.0 + 1.0;
- }
-
- // Zooming out.
- if (delta < 0 && scale != 0) {
- scale = 1.0 / scale;
- }
-
- view->map->scaleBy(scale, mbgl::ScreenCoordinate { view->lastX, view->lastY });
-}
-
-void GLFWView::onWindowResize(GLFWwindow *window, int width, int height) {
- GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
- view->width = width;
- view->height = height;
- view->map->setSize({{ static_cast<uint16_t>(view->width),
- static_cast<uint16_t>(view->height) }});
-}
-
-void GLFWView::onFramebufferResize(GLFWwindow *window, int width, int height) {
- GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
- view->fbWidth = width;
- view->fbHeight = height;
-
- // This is only triggered when the framebuffer is resized, but not the window. It can
- // happen when you move the window between screens with a different pixel ratio.
- // We are forcing a repaint my invalidating the view, which triggers a rerender with the
- // new framebuffer dimensions.
- view->invalidate();
-}
-
-void GLFWView::onMouseClick(GLFWwindow *window, int button, int action, int modifiers) {
- GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
-
- if (button == GLFW_MOUSE_BUTTON_RIGHT ||
- (button == GLFW_MOUSE_BUTTON_LEFT && modifiers & GLFW_MOD_CONTROL)) {
- view->rotating = action == GLFW_PRESS;
- view->map->setGestureInProgress(view->rotating);
- } else if (button == GLFW_MOUSE_BUTTON_LEFT && (modifiers & GLFW_MOD_SHIFT)) {
- view->pitching = action == GLFW_PRESS;
- view->map->setGestureInProgress(view->pitching);
- } else if (button == GLFW_MOUSE_BUTTON_LEFT) {
- view->tracking = action == GLFW_PRESS;
- view->map->setGestureInProgress(view->tracking);
-
- if (action == GLFW_RELEASE) {
- double now = glfwGetTime();
- if (now - view->lastClick < 0.4 /* ms */) {
- if (modifiers & GLFW_MOD_SHIFT) {
- view->map->scaleBy(0.5, mbgl::ScreenCoordinate { view->lastX, view->lastY }, mbgl::Milliseconds(500));
- } else {
- view->map->scaleBy(2.0, mbgl::ScreenCoordinate { view->lastX, view->lastY }, mbgl::Milliseconds(500));
- }
- }
- view->lastClick = now;
- }
- }
-}
-
-void GLFWView::onMouseMove(GLFWwindow *window, double x, double y) {
- GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
- if (view->tracking) {
- double dx = x - view->lastX;
- double dy = y - view->lastY;
- if (dx || dy) {
- view->map->setLatLng(
- view->map->latLngForPixel(mbgl::ScreenCoordinate(x - dx, y - dy)),
- mbgl::ScreenCoordinate(x, y));
- }
- } else if (view->rotating) {
- view->map->rotateBy({ view->lastX, view->lastY }, { x, y });
- } else if (view->pitching) {
- const double dy = y - view->lastY;
- if (dy) {
- view->map->setPitch(view->map->getPitch() - dy / 2);
- }
- }
- view->lastX = x;
- view->lastY = y;
-}
-
-void GLFWView::run() {
- auto callback = [&] {
- if (glfwWindowShouldClose(window)) {
- runLoop.stop();
- return;
- }
-
- glfwPollEvents();
-
- if (dirty) {
- const double started = glfwGetTime();
-
- glfwMakeContextCurrent(window);
-
- updateViewBinding();
- map->render(*this);
-
- glfwSwapBuffers(window);
-
- report(1000 * (glfwGetTime() - started));
- if (benchmark) {
- invalidate();
- }
-
- dirty = false;
- }
- };
-
- frameTick.start(mbgl::Duration::zero(), mbgl::Milliseconds(1000 / 60), callback);
-#if defined(__APPLE__)
- while (!glfwWindowShouldClose(window)) runLoop.run();
-#else
- runLoop.run();
-#endif
-}
-
-float GLFWView::getPixelRatio() const {
- return pixelRatio;
-}
-
-std::array<uint16_t, 2> GLFWView::getSize() const {
- return {{ static_cast<uint16_t>(width), static_cast<uint16_t>(height) }};
-}
-
-std::array<uint16_t, 2> GLFWView::getFramebufferSize() const {
- return {{ static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) }};
-}
-
-void GLFWView::activate() {
- glfwMakeContextCurrent(window);
-}
-
-void GLFWView::deactivate() {
- glfwMakeContextCurrent(nullptr);
-}
-
-void GLFWView::invalidate() {
- dirty = true;
- glfwPostEmptyEvent();
-}
-
-void GLFWView::report(float duration) {
- frames++;
- frameTime += duration;
-
- const double currentTime = glfwGetTime();
- if (currentTime - lastReported >= 1) {
- frameTime /= frames;
- mbgl::Log::Info(mbgl::Event::OpenGL, "Frame time: %6.2fms (%6.2f fps)", frameTime,
- 1000 / frameTime);
- frames = 0;
- frameTime = 0;
- lastReported = currentTime;
- }
-}
-
-void GLFWView::setChangeStyleCallback(std::function<void()> callback) {
- changeStyleCallback = callback;
-}
-
-void GLFWView::setShouldClose() {
- glfwSetWindowShouldClose(window, true);
- glfwPostEmptyEvent();
-}
-
-void GLFWView::setWindowTitle(const std::string& title) {
- glfwSetWindowTitle(window, (std::string { "Mapbox GL: " } + title).c_str());
-}
-
-void GLFWView::setMapChangeCallback(std::function<void(mbgl::MapChange)> callback) {
- this->mapChangeCallback = callback;
-}
-
-void GLFWView::notifyMapChange(mbgl::MapChange change) {
- if (mapChangeCallback) {
- mapChangeCallback(change);
- }
-}
-
-namespace mbgl {
-namespace platform {
-
-#ifndef GL_ES_VERSION_2_0
-void showDebugImage(std::string name, const char *data, size_t width, size_t height) {
- glfwInit();
-
- static GLFWwindow *debugWindow = nullptr;
- if (!debugWindow) {
- debugWindow = glfwCreateWindow(width, height, name.c_str(), nullptr, nullptr);
- if (!debugWindow) {
- glfwTerminate();
- fprintf(stderr, "Failed to initialize window\n");
- exit(1);
- }
- }
-
- GLFWwindow *currentWindow = glfwGetCurrentContext();
-
- glfwSetWindowSize(debugWindow, width, height);
- glfwMakeContextCurrent(debugWindow);
-
- int fbWidth, fbHeight;
- glfwGetFramebufferSize(debugWindow, &fbWidth, &fbHeight);
- float scale = static_cast<float>(fbWidth) / static_cast<float>(width);
-
- {
- gl::PreserveState<gl::value::PixelZoom> pixelZoom;
- gl::PreserveState<gl::value::RasterPos> rasterPos;
-
- MBGL_CHECK_ERROR(glPixelZoom(scale, -scale));
- MBGL_CHECK_ERROR(glRasterPos2f(-1.0f, 1.0f));
- MBGL_CHECK_ERROR(glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, data));
- }
-
- glfwSwapBuffers(debugWindow);
-
- glfwMakeContextCurrent(currentWindow);
-}
-
-void showColorDebugImage(std::string name, const char *data, size_t logicalWidth, size_t logicalHeight, size_t width, size_t height) {
- glfwInit();
-
- static GLFWwindow *debugWindow = nullptr;
- if (!debugWindow) {
- debugWindow = glfwCreateWindow(logicalWidth, logicalHeight, name.c_str(), nullptr, nullptr);
- if (!debugWindow) {
- glfwTerminate();
- fprintf(stderr, "Failed to initialize window\n");
- exit(1);
- }
- }
-
- GLFWwindow *currentWindow = glfwGetCurrentContext();
-
- glfwSetWindowSize(debugWindow, logicalWidth, logicalHeight);
- glfwMakeContextCurrent(debugWindow);
-
- int fbWidth, fbHeight;
- glfwGetFramebufferSize(debugWindow, &fbWidth, &fbHeight);
- float xScale = static_cast<float>(fbWidth) / static_cast<float>(width);
- float yScale = static_cast<float>(fbHeight) / static_cast<float>(height);
-
- {
- gl::PreserveState<gl::value::ClearColor> clearColor;
- gl::PreserveState<gl::value::Blend> blend;
- gl::PreserveState<gl::value::BlendFunc> blendFunc;
- gl::PreserveState<gl::value::PixelZoom> pixelZoom;
- gl::PreserveState<gl::value::RasterPos> rasterPos;
-
- MBGL_CHECK_ERROR(glClearColor(0.8, 0.8, 0.8, 1));
- MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
- MBGL_CHECK_ERROR(glEnable(GL_BLEND));
- MBGL_CHECK_ERROR(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
- MBGL_CHECK_ERROR(glPixelZoom(xScale, -yScale));
- MBGL_CHECK_ERROR(glRasterPos2f(-1.0f, 1.0f));
- MBGL_CHECK_ERROR(glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, data));
- }
-
- glfwSwapBuffers(debugWindow);
-
- glfwMakeContextCurrent(currentWindow);
-}
-#endif
-
-} // namespace platform
-} // namespace mbgl
diff --git a/platform/default/headless_backend_glx.cpp b/platform/default/headless_backend_glx.cpp
deleted file mode 100644
index bbfd19345b..0000000000
--- a/platform/default/headless_backend_glx.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#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_backend_osmesa.cpp b/platform/default/headless_backend_osmesa.cpp
index e0e385fcc6..081bddf170 100644
--- a/platform/default/headless_backend_osmesa.cpp
+++ b/platform/default/headless_backend_osmesa.cpp
@@ -1,47 +1,54 @@
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/util/logging.hpp>
-namespace mbgl {
+#include <GL/osmesa.h>
-gl::glProc HeadlessBackend::initializeExtension(const char* name) {
- return OSMesaGetProcAddress(name);
-}
+#include <cassert>
-void HeadlessBackend::createContext() {
- if (glContext == nullptr) {
-#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
- glContext = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, nullptr);
-#else
- glContext = OSMesaCreateContext(OSMESA_RGBA, nullptr);
-#endif
- if (glContext == nullptr) {
- Log::Error(Event::OpenGL, "failed to create OSMesa context");
- }
- }
+namespace mbgl {
- if (glContext == nullptr) {
- throw std::runtime_error("Error creating GL context object.");
+struct OSMesaImpl : public HeadlessBackend::Impl {
+ OSMesaImpl(OSMesaContext glContext_) : glContext(glContext_) {
}
-}
-void HeadlessBackend::destroyContext() {
- if (glContext) {
+ ~OSMesaImpl() {
if (glContext != OSMesaGetCurrentContext()) {
activateContext();
}
OSMesaDestroyContext(glContext);
- glContext = nullptr;
}
-}
-void HeadlessBackend::activateContext() {
- if (!OSMesaMakeCurrent(glContext, &fakeBuffer, GL_UNSIGNED_BYTE, 1, 1)) {
- throw std::runtime_error("Switching OpenGL context failed.\n");
+ void activateContext() final {
+ if (!OSMesaMakeCurrent(glContext, &fakeBuffer, GL_UNSIGNED_BYTE, 1, 1)) {
+ throw std::runtime_error("Switching OpenGL context failed.\n");
+ }
}
+
+ OSMesaContext glContext = nullptr;
+ GLubyte fakeBuffer = 0;
+};
+
+gl::glProc HeadlessBackend::initializeExtension(const char* name) {
+ return OSMesaGetProcAddress(name);
}
-void HeadlessBackend::deactivateContext() {
- // no-op.
+bool HeadlessBackend::hasDisplay() {
+ return true;
+};
+
+void HeadlessBackend::createContext() {
+ assert(!hasContext());
+
+#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
+ OSMesaContext glContext = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, nullptr);
+#else
+ OSMesaContext glContext = OSMesaCreateContext(OSMESA_RGBA, nullptr);
+#endif
+ if (glContext == nullptr) {
+ throw std::runtime_error("Error creating GL context object.");
+ }
+
+ impl.reset(new OSMesaImpl(glContext));
}
} // namespace mbgl
diff --git a/platform/default/headless_display.cpp b/platform/default/headless_display.cpp
deleted file mode 100644
index b98aef7903..0000000000
--- a/platform/default/headless_display.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-#include <mbgl/platform/default/headless_display.hpp>
-
-#if MBGL_USE_GLX
-#include <GL/glx.h>
-#endif
-
-#include <cstring>
-#include <stdexcept>
-#include <string>
-
-namespace mbgl {
-
-HeadlessDisplay::HeadlessDisplay() {
-#if MBGL_USE_CGL
- // TODO: test if OpenGL 4.1 with GL_ARB_ES2_compatibility is supported
- // If it is, use kCGLOGLPVersion_3_2_Core and enable that extension.
- CGLPixelFormatAttribute attributes[] = {
- kCGLPFAOpenGLProfile,
- static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_Legacy),
- static_cast<CGLPixelFormatAttribute>(0)
- };
-
- GLint num;
- CGLError error = CGLChoosePixelFormat(attributes, &pixelFormat, &num);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Error choosing pixel format:") + CGLErrorString(error) + "\n");
- }
- if (num <= 0) {
- throw std::runtime_error("No pixel formats found.");
- }
-#endif
-
-#if MBGL_USE_GLX
- if (!XInitThreads()) {
- throw std::runtime_error("Failed to XInitThreads.");
- }
-
- xDisplay = XOpenDisplay(nullptr);
- if (xDisplay == nullptr) {
- throw std::runtime_error("Failed to open X display.");
- }
-
- const char *extensions = reinterpret_cast<const char *>(glXQueryServerString(xDisplay, DefaultScreen(xDisplay), GLX_EXTENSIONS));
- if (!extensions) {
- throw std::runtime_error("Cannot read GLX extensions.");
- }
- if (!strstr(extensions,"GLX_SGIX_fbconfig")) {
- throw std::runtime_error("Extension GLX_SGIX_fbconfig was not found.");
- }
- if (!strstr(extensions, "GLX_SGIX_pbuffer")) {
- throw std::runtime_error("Cannot find glXCreateContextAttribsARB.");
- }
-
- // We're creating a dummy pbuffer anyway that we're not using.
- static int pixelFormat[] = {
- GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
- None
- };
-
- int configs = 0;
- fbConfigs = glXChooseFBConfig(xDisplay, DefaultScreen(xDisplay), pixelFormat, &configs);
- if (fbConfigs == nullptr) {
- throw std::runtime_error("Failed to glXChooseFBConfig.");
- }
- if (configs <= 0) {
- throw std::runtime_error("No Framebuffer configurations.");
- }
-#endif
-}
-
-HeadlessDisplay::~HeadlessDisplay() {
-#if MBGL_USE_CGL
- CGLDestroyPixelFormat(pixelFormat);
-#endif
-
-#if MBGL_USE_GLX
- XFree(fbConfigs);
- XCloseDisplay(xDisplay);
-#endif
-}
-
-} // namespace mbgl
diff --git a/platform/default/http_file_source.cpp b/platform/default/http_file_source.cpp
index ce6987fbdd..867d85fa4d 100644
--- a/platform/default/http_file_source.cpp
+++ b/platform/default/http_file_source.cpp
@@ -1,7 +1,7 @@
#include <mbgl/storage/http_file_source.hpp>
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/util.hpp>
#include <mbgl/util/optional.hpp>
diff --git a/platform/default/image.cpp b/platform/default/image.cpp
index 890d442683..84db1e9c71 100644
--- a/platform/default/image.cpp
+++ b/platform/default/image.cpp
@@ -25,8 +25,8 @@ const static bool png_version_check __attribute__((unused)) = []() {
namespace mbgl {
std::string encodePNG(const PremultipliedImage& pre) {
- PremultipliedImage copy { pre.width, pre.height };
- std::copy(pre.data.get(), pre.data.get() + pre.size(), copy.data.get());
+ PremultipliedImage copy(pre.size);
+ std::copy(pre.data.get(), pre.data.get() + pre.bytes(), copy.data.get());
UnassociatedImage src = util::unpremultiply(std::move(copy));
@@ -42,8 +42,8 @@ std::string encodePNG(const PremultipliedImage& pre) {
throw std::runtime_error("couldn't create info_ptr");
}
- png_set_IHDR(png_ptr, info_ptr, src.width, src.height, 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
+ png_set_IHDR(png_ptr, info_ptr, src.size.width, src.size.height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
jmp_buf *jmp_context = (jmp_buf *)png_get_error_ptr(png_ptr);
if (jmp_context) {
@@ -61,9 +61,9 @@ std::string encodePNG(const PremultipliedImage& pre) {
ptrs(size_t count) : rows(new png_bytep[count]) {}
~ptrs() { delete[] rows; }
png_bytep *rows = nullptr;
- } pointers(src.height);
+ } pointers(src.size.height);
- for (size_t i = 0; i < src.height; i++) {
+ for (size_t i = 0; i < src.size.height; i++) {
pointers.rows[i] = src.data.get() + src.stride() * i;
}
diff --git a/platform/default/jpeg_reader.cpp b/platform/default/jpeg_reader.cpp
index 5151060a12..78c74f2fd7 100644
--- a/platform/default/jpeg_reader.cpp
+++ b/platform/default/jpeg_reader.cpp
@@ -119,7 +119,7 @@ PremultipliedImage decodeJPEG(const uint8_t* data, size_t size) {
size_t components = cinfo.output_components;
size_t rowStride = components * width;
- PremultipliedImage image { static_cast<uint16_t>(width), static_cast<uint16_t>(height) };
+ PremultipliedImage image({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
uint8_t* dst = image.data.get();
JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, rowStride, 1);
diff --git a/platform/default/log_stderr.cpp b/platform/default/logging_stderr.cpp
index 145cdeda03..41585fb7bb 100644
--- a/platform/default/log_stderr.cpp
+++ b/platform/default/logging_stderr.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/enum.hpp>
#include <iostream>
diff --git a/platform/default/headless_backend.cpp b/platform/default/mbgl/gl/headless_backend.cpp
index 279a7973c9..0bfdf11c98 100644
--- a/platform/default/headless_backend.cpp
+++ b/platform/default/mbgl/gl/headless_backend.cpp
@@ -1,17 +1,18 @@
-#include <mbgl/platform/default/headless_backend.hpp>
-#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/gl/headless_backend.hpp>
+#include <mbgl/gl/headless_display.hpp>
#include <cassert>
#include <stdexcept>
+#include <type_traits>
namespace mbgl {
-HeadlessBackend::HeadlessBackend() : display(std::make_shared<HeadlessDisplay>()) {
+HeadlessBackend::HeadlessBackend() {
activate();
}
HeadlessBackend::HeadlessBackend(std::shared_ptr<HeadlessDisplay> display_)
- : display(std::move(display_)) {
+ : display(std::move(display_)) {
activate();
}
@@ -23,8 +24,8 @@ HeadlessBackend::~HeadlessBackend() {
void HeadlessBackend::activate() {
active = true;
- if (!glContext) {
- if (!display) {
+ if (!hasContext()) {
+ if (!hasDisplay()) {
throw std::runtime_error("Display is not set");
}
createContext();
@@ -47,6 +48,21 @@ void HeadlessBackend::invalidate() {
assert(false);
}
+void HeadlessBackend::destroyContext() {
+ assert(hasContext());
+ impl.reset();
+}
+
+void HeadlessBackend::activateContext() {
+ assert(hasContext());
+ impl->activateContext();
+}
+
+void HeadlessBackend::deactivateContext() {
+ assert(hasContext());
+ impl->deactivateContext();
+}
+
void HeadlessBackend::notifyMapChange(MapChange change) {
if (mapChangeCallback) {
mapChangeCallback(change);
diff --git a/platform/default/mbgl/gl/headless_backend.hpp b/platform/default/mbgl/gl/headless_backend.hpp
new file mode 100644
index 0000000000..da8c55e044
--- /dev/null
+++ b/platform/default/mbgl/gl/headless_backend.hpp
@@ -0,0 +1,57 @@
+#pragma once
+
+#include <mbgl/gl/extension.hpp>
+
+#include <mbgl/map/backend.hpp>
+
+#include <memory>
+#include <functional>
+
+namespace mbgl {
+
+class HeadlessDisplay;
+
+class HeadlessBackend : public Backend {
+public:
+ HeadlessBackend();
+ HeadlessBackend(std::shared_ptr<HeadlessDisplay>);
+ ~HeadlessBackend() override;
+
+ void invalidate() override;
+ void activate() override;
+ void deactivate() override;
+ void notifyMapChange(MapChange) override;
+
+ void setMapChangeCallback(std::function<void(MapChange)>&& cb) { mapChangeCallback = std::move(cb); }
+
+ struct Impl {
+ virtual ~Impl() {}
+ virtual void activateContext() = 0;
+ virtual void deactivateContext() {}
+ };
+
+private:
+ // Implementation specific functions
+ static gl::glProc initializeExtension(const char*);
+
+ bool hasContext() const { return bool(impl); }
+ bool hasDisplay();
+
+ void createContext();
+
+private:
+ void destroyContext();
+
+ void activateContext();
+ void deactivateContext();
+
+ std::unique_ptr<Impl> impl;
+ std::shared_ptr<HeadlessDisplay> display;
+
+ bool extensionsLoaded = false;
+ bool active = false;
+
+ std::function<void(MapChange)> mapChangeCallback;
+};
+
+} // namespace mbgl
diff --git a/platform/default/mbgl/gl/headless_display.cpp b/platform/default/mbgl/gl/headless_display.cpp
new file mode 100644
index 0000000000..6247046c29
--- /dev/null
+++ b/platform/default/mbgl/gl/headless_display.cpp
@@ -0,0 +1,15 @@
+#include <mbgl/gl/headless_display.hpp>
+
+namespace mbgl {
+
+class HeadlessDisplay::Impl {};
+
+HeadlessDisplay::HeadlessDisplay() {
+ // no-op
+}
+
+HeadlessDisplay::~HeadlessDisplay() {
+ // no-op
+}
+
+} // namespace mbgl
diff --git a/platform/default/mbgl/gl/headless_display.hpp b/platform/default/mbgl/gl/headless_display.hpp
new file mode 100644
index 0000000000..a5c95085b8
--- /dev/null
+++ b/platform/default/mbgl/gl/headless_display.hpp
@@ -0,0 +1,20 @@
+#pragma once
+
+#include <memory>
+
+namespace mbgl {
+
+class HeadlessDisplay {
+public:
+ HeadlessDisplay();
+ ~HeadlessDisplay();
+
+ template <typename DisplayAttribute>
+ DisplayAttribute attribute() const;
+
+private:
+ class Impl;
+ std::unique_ptr<Impl> impl;
+};
+
+} // namespace mbgl
diff --git a/platform/default/mbgl/gl/offscreen_view.cpp b/platform/default/mbgl/gl/offscreen_view.cpp
new file mode 100644
index 0000000000..16faf6a4a9
--- /dev/null
+++ b/platform/default/mbgl/gl/offscreen_view.cpp
@@ -0,0 +1,30 @@
+#include <mbgl/gl/offscreen_view.hpp>
+#include <mbgl/gl/context.hpp>
+
+#include <cstring>
+#include <cassert>
+
+namespace mbgl {
+
+OffscreenView::OffscreenView(gl::Context& context_, const Size size_)
+ : size(std::move(size_)), context(context_) {
+ assert(size);
+}
+
+void OffscreenView::bind() {
+ if (!framebuffer) {
+ color = context.createRenderbuffer<gl::RenderbufferType::RGBA>(size);
+ depthStencil = context.createRenderbuffer<gl::RenderbufferType::DepthStencil>(size);
+ framebuffer = context.createFramebuffer(*color, *depthStencil);
+ } else {
+ context.bindFramebuffer = framebuffer->framebuffer;
+ }
+
+ context.viewport = { 0, 0, size };
+}
+
+PremultipliedImage OffscreenView::readStillImage() {
+ return context.readFramebuffer<PremultipliedImage>(size);
+}
+
+} // namespace mbgl
diff --git a/platform/default/mbgl/gl/offscreen_view.hpp b/platform/default/mbgl/gl/offscreen_view.hpp
new file mode 100644
index 0000000000..0e839e14cc
--- /dev/null
+++ b/platform/default/mbgl/gl/offscreen_view.hpp
@@ -0,0 +1,33 @@
+#pragma once
+
+#include <mbgl/map/view.hpp>
+#include <mbgl/gl/framebuffer.hpp>
+#include <mbgl/gl/renderbuffer.hpp>
+#include <mbgl/util/optional.hpp>
+#include <mbgl/util/image.hpp>
+
+namespace mbgl {
+
+namespace gl {
+class Context;
+} // namespace gl
+
+class OffscreenView : public View {
+public:
+ OffscreenView(gl::Context&, Size size = { 256, 256 });
+
+ void bind() override;
+
+ PremultipliedImage readStillImage();
+
+public:
+ const Size size;
+
+private:
+ gl::Context& context;
+ optional<gl::Framebuffer> framebuffer;
+ optional<gl::Renderbuffer<gl::RenderbufferType::RGBA>> color;
+ optional<gl::Renderbuffer<gl::RenderbufferType::DepthStencil>> depthStencil;
+};
+
+} // namespace mbgl
diff --git a/platform/default/mbgl/storage/offline_database.cpp b/platform/default/mbgl/storage/offline_database.cpp
index 4bcc9ad711..73364b042f 100644
--- a/platform/default/mbgl/storage/offline_database.cpp
+++ b/platform/default/mbgl/storage/offline_database.cpp
@@ -4,7 +4,7 @@
#include <mbgl/util/io.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/chrono.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include "sqlite3.hpp"
#include <sqlite3.h>
diff --git a/platform/default/mbgl/storage/offline_download.cpp b/platform/default/mbgl/storage/offline_download.cpp
index 9e2e11c86f..3edc75845c 100644
--- a/platform/default/mbgl/storage/offline_download.cpp
+++ b/platform/default/mbgl/storage/offline_download.cpp
@@ -184,7 +184,7 @@ void OfflineDownload::activateDownload() {
if (!parser.glyphURL.empty()) {
for (const auto& fontStack : parser.fontStacks()) {
- for (uint32_t i = 0; i < GLYPH_RANGES_PER_FONT_STACK; i++) {
+ for (char16_t i = 0; i < GLYPH_RANGES_PER_FONT_STACK; i++) {
queueResource(Resource::glyphs(parser.glyphURL, fontStack, getGlyphRange(i * GLYPHS_PER_GLYPH_RANGE)));
}
}
diff --git a/platform/default/mbgl/util/default_styles.cpp b/platform/default/mbgl/util/default_styles.cpp
new file mode 100644
index 0000000000..17cc2f5740
--- /dev/null
+++ b/platform/default/mbgl/util/default_styles.cpp
@@ -0,0 +1,16 @@
+#include <mbgl/util/default_styles.hpp>
+
+namespace mbgl {
+namespace util {
+namespace default_styles {
+
+const DefaultStyle streets = { "mapbox://styles/mapbox/streets-v9", "Streets" };
+const DefaultStyle outdoors = { "mapbox://styles/mapbox/outdoors-v9", "Outdoors" };
+const DefaultStyle light = { "mapbox://styles/mapbox/light-v9", "Light" };
+const DefaultStyle dark = { "mapbox://styles/mapbox/dark-v9", "Dark" };
+const DefaultStyle satellite = { "mapbox://styles/mapbox/satellite-v9", "Satellite" };
+const DefaultStyle satelliteStreets = { "mapbox://styles/mapbox/satellite-streets-v9", "Satellite Streets" };
+
+} // namespace default_styles
+} // end namespace util
+} // end namespace mbgl
diff --git a/platform/default/mbgl/util/default_styles.hpp b/platform/default/mbgl/util/default_styles.hpp
new file mode 100644
index 0000000000..eb7e034722
--- /dev/null
+++ b/platform/default/mbgl/util/default_styles.hpp
@@ -0,0 +1,31 @@
+#pragma once
+
+#include <vector>
+#include <string>
+
+namespace mbgl {
+namespace util {
+namespace default_styles {
+
+struct DefaultStyle {
+ const char* url;
+ const char* name;
+};
+
+extern const DefaultStyle streets;
+extern const DefaultStyle outdoors;
+extern const DefaultStyle light;
+extern const DefaultStyle dark;
+extern const DefaultStyle satellite;
+extern const DefaultStyle satelliteStreets;
+
+const DefaultStyle orderedStyles[] = {
+ streets, outdoors, light, dark, satellite, satelliteStreets,
+};
+const size_t numOrderedStyles = sizeof(orderedStyles) / sizeof(DefaultStyle);
+
+static const unsigned currentVersion = 9;
+
+} // end namespace default_styles
+} // end namespace util
+} // end namespace mbgl
diff --git a/platform/default/thread_pool.cpp b/platform/default/mbgl/util/default_thread_pool.cpp
index b7e02db157..92c0f06745 100644
--- a/platform/default/thread_pool.cpp
+++ b/platform/default/mbgl/util/default_thread_pool.cpp
@@ -1,4 +1,4 @@
-#include <mbgl/platform/default/thread_pool.hpp>
+#include <mbgl/util/default_thread_pool.hpp>
#include <mbgl/actor/mailbox.hpp>
namespace mbgl {
diff --git a/platform/default/mbgl/util/default_thread_pool.hpp b/platform/default/mbgl/util/default_thread_pool.hpp
new file mode 100644
index 0000000000..a14d16d771
--- /dev/null
+++ b/platform/default/mbgl/util/default_thread_pool.hpp
@@ -0,0 +1,27 @@
+#pragma once
+
+#include <mbgl/actor/scheduler.hpp>
+
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <thread>
+
+namespace mbgl {
+
+class ThreadPool : public Scheduler {
+public:
+ ThreadPool(std::size_t count);
+ ~ThreadPool() override;
+
+ void schedule(std::weak_ptr<Mailbox>) override;
+
+private:
+ std::vector<std::thread> threads;
+ std::queue<std::weak_ptr<Mailbox>> queue;
+ std::mutex mutex;
+ std::condition_variable cv;
+ bool terminate { false };
+};
+
+} // namespace mbgl
diff --git a/platform/default/offscreen_view.cpp b/platform/default/offscreen_view.cpp
deleted file mode 100644
index eaf87d0f87..0000000000
--- a/platform/default/offscreen_view.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-#include <mbgl/platform/default/offscreen_view.hpp>
-#include <mbgl/gl/context.hpp>
-#include <mbgl/gl/gl.hpp>
-
-#include <cstring>
-#include <cassert>
-
-namespace mbgl {
-
-OffscreenView::OffscreenView(gl::Context& context_, std::array<uint16_t, 2> size_)
- : context(context_), size(std::move(size_)) {
- assert(size[0] > 0 && size[1] > 0);
-}
-
-void OffscreenView::bind() {
- if (!framebuffer) {
- color = context.createRenderbuffer<gl::RenderbufferType::RGBA>(size);
- depthStencil = context.createRenderbuffer<gl::RenderbufferType::DepthStencil>(size);
- framebuffer = context.createFramebuffer(*color, *depthStencil);
- } else {
- context.bindFramebuffer = framebuffer->framebuffer;
- }
-
- context.viewport = { 0, 0, size[0], size[1] };
-}
-
-PremultipliedImage OffscreenView::readStillImage() {
- PremultipliedImage image { size[0], size[1] };
- MBGL_CHECK_ERROR(glReadPixels(0, 0, size[0], size[1], GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
-
- const auto stride = image.stride();
- auto tmp = std::make_unique<uint8_t[]>(stride);
- uint8_t* rgba = image.data.get();
- for (int i = 0, j = size[1] - 1; i < j; i++, j--) {
- std::memcpy(tmp.get(), rgba + i * stride, stride);
- std::memcpy(rgba + i * stride, rgba + j * stride, stride);
- std::memcpy(rgba + j * stride, tmp.get(), stride);
- }
-
- return image;
-}
-
-std::array<uint16_t, 2> OffscreenView::getSize() const {
- return size;
-}
-
-} // namespace mbgl
diff --git a/platform/default/online_file_source.cpp b/platform/default/online_file_source.cpp
index 4f191f6cf7..0f2bc5ff56 100644
--- a/platform/default/online_file_source.cpp
+++ b/platform/default/online_file_source.cpp
@@ -3,7 +3,7 @@
#include <mbgl/storage/network_status.hpp>
#include <mbgl/storage/response.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/thread.hpp>
diff --git a/platform/default/png_reader.cpp b/platform/default/png_reader.cpp
index 5111edaa59..5ae74d74db 100644
--- a/platform/default/png_reader.cpp
+++ b/platform/default/png_reader.cpp
@@ -1,7 +1,7 @@
#include <mbgl/util/image.hpp>
#include <mbgl/util/premultiply.hpp>
#include <mbgl/util/char_array_buffer.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
#include <istream>
#include <sstream>
@@ -80,7 +80,7 @@ PremultipliedImage decodePNG(const uint8_t* data, size_t size) {
int color_type = 0;
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, nullptr, nullptr, nullptr);
- UnassociatedImage image { static_cast<uint16_t>(width), static_cast<uint16_t>(height) };
+ UnassociatedImage image({ width, height });
if (color_type == PNG_COLOR_TYPE_PALETTE)
png_set_expand(png_ptr);
diff --git a/platform/default/settings_json.cpp b/platform/default/settings_json.cpp
deleted file mode 100644
index ef53aa83e7..0000000000
--- a/platform/default/settings_json.cpp
+++ /dev/null
@@ -1,41 +0,0 @@
-#include <mbgl/platform/default/settings_json.hpp>
-#include <fstream>
-
-namespace mbgl {
-
-Settings_JSON::Settings_JSON() { load(); }
-
-void Settings_JSON::load() {
- std::ifstream file("/tmp/mbgl-native.cfg");
- if (file) {
- file >> longitude;
- file >> latitude;
- file >> zoom;
- file >> bearing;
- file >> pitch;
- file >> debug;
- }
-}
-
-void Settings_JSON::save() {
- std::ofstream file("/tmp/mbgl-native.cfg");
- if (file) {
- file << longitude << std::endl;
- file << latitude << std::endl;
- file << zoom << std::endl;
- file << bearing << std::endl;
- file << pitch << std::endl;
- file << debug << std::endl;
- }
-}
-
-void Settings_JSON::clear() {
- longitude = 0;
- latitude = 0;
- zoom = 0;
- bearing = 0;
- pitch = 0;
- debug = 0;
-}
-
-} // namespace mbgl
diff --git a/platform/default/sqlite3.cpp b/platform/default/sqlite3.cpp
index 578e407739..670b7b84cc 100644
--- a/platform/default/sqlite3.cpp
+++ b/platform/default/sqlite3.cpp
@@ -7,7 +7,7 @@
#include <chrono>
#include <experimental/optional>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
namespace mapbox {
namespace sqlite {
diff --git a/platform/default/string_stdlib.cpp b/platform/default/string_stdlib.cpp
index 90a75c1738..2642e88aff 100644
--- a/platform/default/string_stdlib.cpp
+++ b/platform/default/string_stdlib.cpp
@@ -1,10 +1,10 @@
-#include <mbgl/platform/platform.hpp>
-#include <mbgl/util/utf.hpp>
+#include <mbgl/util/platform.hpp>
#define NU_WITH_TOUPPER
#define NU_WITH_TOLOWER
#define NU_WITH_UTF8_WRITER
#include <libnu/libnu.h>
#include <cstring>
+#include <sstream>
namespace mbgl { namespace platform {
diff --git a/platform/default/thread.cpp b/platform/default/thread.cpp
index f4d0b9a855..c7c79b4fb0 100644
--- a/platform/default/thread.cpp
+++ b/platform/default/thread.cpp
@@ -1,5 +1,5 @@
-#include <mbgl/platform/platform.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/platform.hpp>
+#include <mbgl/util/logging.hpp>
#include <string>
diff --git a/platform/default/webp_reader.cpp b/platform/default/webp_reader.cpp
index 6f90fe02f5..2c01fb4479 100644
--- a/platform/default/webp_reader.cpp
+++ b/platform/default/webp_reader.cpp
@@ -1,6 +1,6 @@
#include <mbgl/util/image.hpp>
#include <mbgl/util/premultiply.hpp>
-#include <mbgl/platform/log.hpp>
+#include <mbgl/util/logging.hpp>
extern "C"
{
@@ -23,8 +23,8 @@ PremultipliedImage decodeWebP(const uint8_t* data, size_t size) {
throw std::runtime_error("failed to decode WebP data");
}
- UnassociatedImage image{ static_cast<uint16_t>(width), static_cast<uint16_t>(height),
- std::move(webp) };
+ UnassociatedImage image({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) },
+ std::move(webp));
return util::premultiply(std::move(image));
}