diff options
Diffstat (limited to 'platform/default')
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, ¶graphEndIndex, 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)); } |