From 84e39611a096058826dbdb89dccbd1affad05f76 Mon Sep 17 00:00:00 2001 From: Asheem Mamoowala Date: Fri, 12 May 2017 17:07:48 -0700 Subject: [core] Move renderer/* files into sub-folders (#8983) Move renderer/* files into sub-folders --- cmake/core-files.cmake | 84 ++-- src/mbgl/geometry/feature_index.cpp | 2 +- src/mbgl/layout/symbol_layout.cpp | 4 +- src/mbgl/programs/symbol_program.hpp | 2 +- src/mbgl/renderer/buckets/circle_bucket.cpp | 123 +++++ src/mbgl/renderer/buckets/circle_bucket.hpp | 42 ++ src/mbgl/renderer/buckets/debug_bucket.cpp | 83 ++++ src/mbgl/renderer/buckets/debug_bucket.hpp | 41 ++ src/mbgl/renderer/buckets/fill_bucket.cpp | 145 ++++++ src/mbgl/renderer/buckets/fill_bucket.hpp | 43 ++ .../renderer/buckets/fill_extrusion_bucket.cpp | 177 +++++++ .../renderer/buckets/fill_extrusion_bucket.hpp | 38 ++ src/mbgl/renderer/buckets/line_bucket.cpp | 506 +++++++++++++++++++++ src/mbgl/renderer/buckets/line_bucket.hpp | 67 +++ src/mbgl/renderer/buckets/raster_bucket.cpp | 30 ++ src/mbgl/renderer/buckets/raster_bucket.hpp | 22 + src/mbgl/renderer/buckets/symbol_bucket.cpp | 86 ++++ src/mbgl/renderer/buckets/symbol_bucket.hpp | 77 ++++ src/mbgl/renderer/circle_bucket.cpp | 123 ----- src/mbgl/renderer/circle_bucket.hpp | 42 -- src/mbgl/renderer/debug_bucket.cpp | 83 ---- src/mbgl/renderer/debug_bucket.hpp | 41 -- src/mbgl/renderer/fill_bucket.cpp | 145 ------ src/mbgl/renderer/fill_bucket.hpp | 43 -- src/mbgl/renderer/fill_extrusion_bucket.cpp | 177 ------- src/mbgl/renderer/fill_extrusion_bucket.hpp | 38 -- .../renderer/layers/render_background_layer.cpp | 36 ++ .../renderer/layers/render_background_layer.hpp | 32 ++ src/mbgl/renderer/layers/render_circle_layer.cpp | 66 +++ src/mbgl/renderer/layers/render_circle_layer.hpp | 39 ++ src/mbgl/renderer/layers/render_custom_layer.cpp | 28 ++ src/mbgl/renderer/layers/render_custom_layer.hpp | 27 ++ .../layers/render_fill_extrusion_layer.cpp | 54 +++ .../layers/render_fill_extrusion_layer.hpp | 39 ++ src/mbgl/renderer/layers/render_fill_layer.cpp | 70 +++ src/mbgl/renderer/layers/render_fill_layer.hpp | 39 ++ src/mbgl/renderer/layers/render_line_layer.cpp | 116 +++++ src/mbgl/renderer/layers/render_line_layer.hpp | 45 ++ src/mbgl/renderer/layers/render_raster_layer.cpp | 34 ++ src/mbgl/renderer/layers/render_raster_layer.hpp | 32 ++ src/mbgl/renderer/layers/render_symbol_layer.cpp | 112 +++++ src/mbgl/renderer/layers/render_symbol_layer.hpp | 96 ++++ src/mbgl/renderer/line_bucket.cpp | 506 --------------------- src/mbgl/renderer/line_bucket.hpp | 67 --- src/mbgl/renderer/painter.cpp | 6 +- src/mbgl/renderer/painter_background.cpp | 82 ---- src/mbgl/renderer/painter_circle.cpp | 57 --- src/mbgl/renderer/painter_clipping.cpp | 37 -- src/mbgl/renderer/painter_debug.cpp | 134 ------ src/mbgl/renderer/painter_fill.cpp | 140 ------ src/mbgl/renderer/painter_fill_extrusion.cpp | 87 ---- src/mbgl/renderer/painter_line.cpp | 91 ---- src/mbgl/renderer/painter_raster.cpp | 88 ---- src/mbgl/renderer/painter_symbol.cpp | 165 ------- src/mbgl/renderer/painters/painter_background.cpp | 82 ++++ src/mbgl/renderer/painters/painter_circle.cpp | 57 +++ src/mbgl/renderer/painters/painter_clipping.cpp | 37 ++ src/mbgl/renderer/painters/painter_debug.cpp | 134 ++++++ src/mbgl/renderer/painters/painter_fill.cpp | 140 ++++++ .../renderer/painters/painter_fill_extrusion.cpp | 87 ++++ src/mbgl/renderer/painters/painter_line.cpp | 91 ++++ src/mbgl/renderer/painters/painter_raster.cpp | 88 ++++ src/mbgl/renderer/painters/painter_symbol.cpp | 165 +++++++ src/mbgl/renderer/raster_bucket.cpp | 30 -- src/mbgl/renderer/raster_bucket.hpp | 22 - src/mbgl/renderer/render_background_layer.cpp | 36 -- src/mbgl/renderer/render_background_layer.hpp | 32 -- src/mbgl/renderer/render_circle_layer.cpp | 66 --- src/mbgl/renderer/render_circle_layer.hpp | 39 -- src/mbgl/renderer/render_custom_layer.cpp | 28 -- src/mbgl/renderer/render_custom_layer.hpp | 27 -- src/mbgl/renderer/render_fill_extrusion_layer.cpp | 54 --- src/mbgl/renderer/render_fill_extrusion_layer.hpp | 39 -- src/mbgl/renderer/render_fill_layer.cpp | 70 --- src/mbgl/renderer/render_fill_layer.hpp | 39 -- src/mbgl/renderer/render_layer.cpp | 18 +- src/mbgl/renderer/render_line_layer.cpp | 116 ----- src/mbgl/renderer/render_line_layer.hpp | 45 -- src/mbgl/renderer/render_raster_layer.cpp | 34 -- src/mbgl/renderer/render_raster_layer.hpp | 32 -- src/mbgl/renderer/render_symbol_layer.cpp | 112 ----- src/mbgl/renderer/render_symbol_layer.hpp | 96 ---- src/mbgl/renderer/symbol_bucket.cpp | 86 ---- src/mbgl/renderer/symbol_bucket.hpp | 77 ---- src/mbgl/style/style.cpp | 16 +- src/mbgl/tile/geometry_tile.cpp | 8 +- src/mbgl/tile/geometry_tile_worker.cpp | 4 +- src/mbgl/tile/raster_tile.cpp | 2 +- src/mbgl/tile/raster_tile_worker.cpp | 2 +- src/mbgl/tile/tile.cpp | 2 +- test/gl/bucket.test.cpp | 8 +- test/tile/raster_tile.test.cpp | 2 +- test/tile/vector_tile.test.cpp | 2 +- 93 files changed, 3310 insertions(+), 3304 deletions(-) create mode 100644 src/mbgl/renderer/buckets/circle_bucket.cpp create mode 100644 src/mbgl/renderer/buckets/circle_bucket.hpp create mode 100644 src/mbgl/renderer/buckets/debug_bucket.cpp create mode 100644 src/mbgl/renderer/buckets/debug_bucket.hpp create mode 100644 src/mbgl/renderer/buckets/fill_bucket.cpp create mode 100644 src/mbgl/renderer/buckets/fill_bucket.hpp create mode 100644 src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp create mode 100644 src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp create mode 100644 src/mbgl/renderer/buckets/line_bucket.cpp create mode 100644 src/mbgl/renderer/buckets/line_bucket.hpp create mode 100644 src/mbgl/renderer/buckets/raster_bucket.cpp create mode 100644 src/mbgl/renderer/buckets/raster_bucket.hpp create mode 100644 src/mbgl/renderer/buckets/symbol_bucket.cpp create mode 100644 src/mbgl/renderer/buckets/symbol_bucket.hpp delete mode 100644 src/mbgl/renderer/circle_bucket.cpp delete mode 100644 src/mbgl/renderer/circle_bucket.hpp delete mode 100644 src/mbgl/renderer/debug_bucket.cpp delete mode 100644 src/mbgl/renderer/debug_bucket.hpp delete mode 100644 src/mbgl/renderer/fill_bucket.cpp delete mode 100644 src/mbgl/renderer/fill_bucket.hpp delete mode 100644 src/mbgl/renderer/fill_extrusion_bucket.cpp delete mode 100644 src/mbgl/renderer/fill_extrusion_bucket.hpp create mode 100644 src/mbgl/renderer/layers/render_background_layer.cpp create mode 100644 src/mbgl/renderer/layers/render_background_layer.hpp create mode 100644 src/mbgl/renderer/layers/render_circle_layer.cpp create mode 100644 src/mbgl/renderer/layers/render_circle_layer.hpp create mode 100644 src/mbgl/renderer/layers/render_custom_layer.cpp create mode 100644 src/mbgl/renderer/layers/render_custom_layer.hpp create mode 100644 src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp create mode 100644 src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp create mode 100644 src/mbgl/renderer/layers/render_fill_layer.cpp create mode 100644 src/mbgl/renderer/layers/render_fill_layer.hpp create mode 100644 src/mbgl/renderer/layers/render_line_layer.cpp create mode 100644 src/mbgl/renderer/layers/render_line_layer.hpp create mode 100644 src/mbgl/renderer/layers/render_raster_layer.cpp create mode 100644 src/mbgl/renderer/layers/render_raster_layer.hpp create mode 100644 src/mbgl/renderer/layers/render_symbol_layer.cpp create mode 100644 src/mbgl/renderer/layers/render_symbol_layer.hpp delete mode 100644 src/mbgl/renderer/line_bucket.cpp delete mode 100644 src/mbgl/renderer/line_bucket.hpp delete mode 100644 src/mbgl/renderer/painter_background.cpp delete mode 100644 src/mbgl/renderer/painter_circle.cpp delete mode 100644 src/mbgl/renderer/painter_clipping.cpp delete mode 100644 src/mbgl/renderer/painter_debug.cpp delete mode 100644 src/mbgl/renderer/painter_fill.cpp delete mode 100644 src/mbgl/renderer/painter_fill_extrusion.cpp delete mode 100644 src/mbgl/renderer/painter_line.cpp delete mode 100644 src/mbgl/renderer/painter_raster.cpp delete mode 100644 src/mbgl/renderer/painter_symbol.cpp create mode 100644 src/mbgl/renderer/painters/painter_background.cpp create mode 100644 src/mbgl/renderer/painters/painter_circle.cpp create mode 100644 src/mbgl/renderer/painters/painter_clipping.cpp create mode 100644 src/mbgl/renderer/painters/painter_debug.cpp create mode 100644 src/mbgl/renderer/painters/painter_fill.cpp create mode 100644 src/mbgl/renderer/painters/painter_fill_extrusion.cpp create mode 100644 src/mbgl/renderer/painters/painter_line.cpp create mode 100644 src/mbgl/renderer/painters/painter_raster.cpp create mode 100644 src/mbgl/renderer/painters/painter_symbol.cpp delete mode 100644 src/mbgl/renderer/raster_bucket.cpp delete mode 100644 src/mbgl/renderer/raster_bucket.hpp delete mode 100644 src/mbgl/renderer/render_background_layer.cpp delete mode 100644 src/mbgl/renderer/render_background_layer.hpp delete mode 100644 src/mbgl/renderer/render_circle_layer.cpp delete mode 100644 src/mbgl/renderer/render_circle_layer.hpp delete mode 100644 src/mbgl/renderer/render_custom_layer.cpp delete mode 100644 src/mbgl/renderer/render_custom_layer.hpp delete mode 100644 src/mbgl/renderer/render_fill_extrusion_layer.cpp delete mode 100644 src/mbgl/renderer/render_fill_extrusion_layer.hpp delete mode 100644 src/mbgl/renderer/render_fill_layer.cpp delete mode 100644 src/mbgl/renderer/render_fill_layer.hpp delete mode 100644 src/mbgl/renderer/render_line_layer.cpp delete mode 100644 src/mbgl/renderer/render_line_layer.hpp delete mode 100644 src/mbgl/renderer/render_raster_layer.cpp delete mode 100644 src/mbgl/renderer/render_raster_layer.hpp delete mode 100644 src/mbgl/renderer/render_symbol_layer.cpp delete mode 100644 src/mbgl/renderer/render_symbol_layer.hpp delete mode 100644 src/mbgl/renderer/symbol_bucket.cpp delete mode 100644 src/mbgl/renderer/symbol_bucket.hpp diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake index fbe43bef3b..a191061354 100644 --- a/cmake/core-files.cmake +++ b/cmake/core-files.cmake @@ -161,79 +161,85 @@ set(MBGL_CORE_FILES src/mbgl/renderer/bucket_parameters.cpp src/mbgl/renderer/bucket_parameters.hpp src/mbgl/renderer/cascade_parameters.hpp - src/mbgl/renderer/circle_bucket.cpp - src/mbgl/renderer/circle_bucket.hpp src/mbgl/renderer/cross_faded_property_evaluator.cpp src/mbgl/renderer/cross_faded_property_evaluator.hpp src/mbgl/renderer/data_driven_property_evaluator.hpp - src/mbgl/renderer/debug_bucket.cpp - src/mbgl/renderer/debug_bucket.hpp - src/mbgl/renderer/fill_bucket.cpp - src/mbgl/renderer/fill_bucket.hpp - src/mbgl/renderer/fill_extrusion_bucket.cpp - src/mbgl/renderer/fill_extrusion_bucket.hpp src/mbgl/renderer/frame_history.cpp src/mbgl/renderer/frame_history.hpp src/mbgl/renderer/group_by_layout.cpp src/mbgl/renderer/group_by_layout.hpp - src/mbgl/renderer/line_bucket.cpp - src/mbgl/renderer/line_bucket.hpp src/mbgl/renderer/paint_parameters.hpp src/mbgl/renderer/paint_property_binder.hpp src/mbgl/renderer/paint_property_statistics.hpp src/mbgl/renderer/painter.cpp src/mbgl/renderer/painter.hpp - src/mbgl/renderer/painter_background.cpp - src/mbgl/renderer/painter_circle.cpp - src/mbgl/renderer/painter_clipping.cpp - src/mbgl/renderer/painter_debug.cpp - src/mbgl/renderer/painter_fill.cpp - src/mbgl/renderer/painter_fill_extrusion.cpp - src/mbgl/renderer/painter_line.cpp - src/mbgl/renderer/painter_raster.cpp - src/mbgl/renderer/painter_symbol.cpp src/mbgl/renderer/possibly_evaluated_property_value.hpp src/mbgl/renderer/property_evaluation_parameters.hpp src/mbgl/renderer/property_evaluator.hpp - src/mbgl/renderer/raster_bucket.cpp - src/mbgl/renderer/raster_bucket.hpp - src/mbgl/renderer/render_background_layer.cpp - src/mbgl/renderer/render_background_layer.hpp - src/mbgl/renderer/render_circle_layer.cpp - src/mbgl/renderer/render_circle_layer.hpp - src/mbgl/renderer/render_custom_layer.cpp - src/mbgl/renderer/render_custom_layer.hpp - src/mbgl/renderer/render_fill_extrusion_layer.cpp - src/mbgl/renderer/render_fill_extrusion_layer.hpp - src/mbgl/renderer/render_fill_layer.cpp - src/mbgl/renderer/render_fill_layer.hpp src/mbgl/renderer/render_item.hpp src/mbgl/renderer/render_layer.cpp src/mbgl/renderer/render_layer.hpp src/mbgl/renderer/render_light.cpp src/mbgl/renderer/render_light.hpp - src/mbgl/renderer/render_line_layer.cpp - src/mbgl/renderer/render_line_layer.hpp src/mbgl/renderer/render_pass.hpp - src/mbgl/renderer/render_raster_layer.cpp - src/mbgl/renderer/render_raster_layer.hpp src/mbgl/renderer/render_source.cpp src/mbgl/renderer/render_source.hpp src/mbgl/renderer/render_source_observer.hpp - src/mbgl/renderer/render_symbol_layer.cpp - src/mbgl/renderer/render_symbol_layer.hpp src/mbgl/renderer/render_tile.cpp src/mbgl/renderer/render_tile.hpp src/mbgl/renderer/style_diff.cpp src/mbgl/renderer/style_diff.hpp - src/mbgl/renderer/symbol_bucket.cpp - src/mbgl/renderer/symbol_bucket.hpp src/mbgl/renderer/tile_parameters.hpp src/mbgl/renderer/tile_pyramid.cpp src/mbgl/renderer/tile_pyramid.hpp src/mbgl/renderer/transitioning_property.hpp src/mbgl/renderer/update_parameters.hpp + # renderer/buckets + src/mbgl/renderer/buckets/circle_bucket.cpp + src/mbgl/renderer/buckets/circle_bucket.hpp + src/mbgl/renderer/buckets/debug_bucket.cpp + src/mbgl/renderer/buckets/debug_bucket.hpp + src/mbgl/renderer/buckets/fill_bucket.cpp + src/mbgl/renderer/buckets/fill_bucket.hpp + src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp + src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp + src/mbgl/renderer/buckets/line_bucket.cpp + src/mbgl/renderer/buckets/line_bucket.hpp + src/mbgl/renderer/buckets/raster_bucket.cpp + src/mbgl/renderer/buckets/raster_bucket.hpp + src/mbgl/renderer/buckets/symbol_bucket.cpp + src/mbgl/renderer/buckets/symbol_bucket.hpp + + # renderer/layers + src/mbgl/renderer/layers/render_background_layer.cpp + src/mbgl/renderer/layers/render_background_layer.hpp + src/mbgl/renderer/layers/render_circle_layer.cpp + src/mbgl/renderer/layers/render_circle_layer.hpp + src/mbgl/renderer/layers/render_custom_layer.cpp + src/mbgl/renderer/layers/render_custom_layer.hpp + src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp + src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp + src/mbgl/renderer/layers/render_fill_layer.cpp + src/mbgl/renderer/layers/render_fill_layer.hpp + src/mbgl/renderer/layers/render_line_layer.cpp + src/mbgl/renderer/layers/render_line_layer.hpp + src/mbgl/renderer/layers/render_raster_layer.cpp + src/mbgl/renderer/layers/render_raster_layer.hpp + src/mbgl/renderer/layers/render_symbol_layer.cpp + src/mbgl/renderer/layers/render_symbol_layer.hpp + + # renderer/painters + src/mbgl/renderer/painters/painter_background.cpp + src/mbgl/renderer/painters/painter_circle.cpp + src/mbgl/renderer/painters/painter_clipping.cpp + src/mbgl/renderer/painters/painter_debug.cpp + src/mbgl/renderer/painters/painter_fill.cpp + src/mbgl/renderer/painters/painter_fill_extrusion.cpp + src/mbgl/renderer/painters/painter_line.cpp + src/mbgl/renderer/painters/painter_raster.cpp + src/mbgl/renderer/painters/painter_symbol.cpp + # renderer/sources src/mbgl/renderer/sources/render_geojson_source.cpp src/mbgl/renderer/sources/render_geojson_source.hpp diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp index 451943ff26..115b9f354d 100644 --- a/src/mbgl/geometry/feature_index.cpp +++ b/src/mbgl/geometry/feature_index.cpp @@ -1,7 +1,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp index fe857fec7e..5142584c91 100644 --- a/src/mbgl/layout/symbol_layout.cpp +++ b/src/mbgl/layout/symbol_layout.cpp @@ -1,10 +1,10 @@ #include #include #include -#include +#include #include #include -#include +#include #include #include #include diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp index 1cac99bfc2..ec68dc2098 100644 --- a/src/mbgl/programs/symbol_program.hpp +++ b/src/mbgl/programs/symbol_program.hpp @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include diff --git a/src/mbgl/renderer/buckets/circle_bucket.cpp b/src/mbgl/renderer/buckets/circle_bucket.cpp new file mode 100644 index 0000000000..8b5743d500 --- /dev/null +++ b/src/mbgl/renderer/buckets/circle_bucket.cpp @@ -0,0 +1,123 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +CircleBucket::CircleBucket(const BucketParameters& parameters, const std::vector& layers) + : mode(parameters.mode) { + for (const auto& layer : layers) { + paintPropertyBinders.emplace( + std::piecewise_construct, + std::forward_as_tuple(layer->getID()), + std::forward_as_tuple( + layer->as()->evaluated, + parameters.tileID.overscaledZ)); + } +} + +void CircleBucket::upload(gl::Context& context) { + vertexBuffer = context.createVertexBuffer(std::move(vertices)); + indexBuffer = context.createIndexBuffer(std::move(triangles)); + + for (auto& pair : paintPropertyBinders) { + pair.second.upload(context); + } + + uploaded = true; +} + +void CircleBucket::render(Painter& painter, + PaintParameters& parameters, + const RenderLayer& layer, + const RenderTile& tile) { + painter.renderCircle(parameters, *this, *layer.as(), tile); +} + +bool CircleBucket::hasData() const { + return !segments.empty(); +} + +void CircleBucket::addFeature(const GeometryTileFeature& feature, + const GeometryCollection& geometry) { + constexpr const uint16_t vertexLength = 4; + + for (auto& circle : geometry) { + for(auto& point : circle) { + auto x = point.x; + auto y = point.y; + + // Do not include points that are outside the tile boundaries. + // Include all points in Still mode. You need to include points from + // neighbouring tiles so that they are not clipped at tile boundaries. + if ((mode != MapMode::Still) && + (x < 0 || x >= util::EXTENT || y < 0 || y >= util::EXTENT)) continue; + + if (segments.empty() || segments.back().vertexLength + vertexLength > std::numeric_limits::max()) { + // Move to a new segments because the old one can't hold the geometry. + segments.emplace_back(vertices.vertexSize(), triangles.indexSize()); + } + + // this geometry will be of the Point type, and we'll derive + // two triangles from it. + // + // ┌─────────┐ + // │ 4 3 │ + // │ │ + // │ 1 2 │ + // └─────────┘ + // + vertices.emplace_back(CircleProgram::vertex(point, -1, -1)); // 1 + vertices.emplace_back(CircleProgram::vertex(point, 1, -1)); // 2 + vertices.emplace_back(CircleProgram::vertex(point, 1, 1)); // 3 + vertices.emplace_back(CircleProgram::vertex(point, -1, 1)); // 4 + + auto& segment = segments.back(); + assert(segment.vertexLength <= std::numeric_limits::max()); + uint16_t index = segment.vertexLength; + + // 1, 2, 3 + // 1, 4, 3 + triangles.emplace_back(index, index + 1, index + 2); + triangles.emplace_back(index, index + 3, index + 2); + + segment.vertexLength += vertexLength; + segment.indexLength += 6; + } + } + + for (auto& pair : paintPropertyBinders) { + pair.second.populateVertexVectors(feature, vertices.vertexSize()); + } +} + +template +static float get(const RenderCircleLayer& layer, const std::map& paintPropertyBinders) { + auto it = paintPropertyBinders.find(layer.getID()); + if (it == paintPropertyBinders.end() || !it->second.statistics().max()) { + return layer.evaluated.get().constantOr(Property::defaultValue()); + } else { + return *it->second.statistics().max(); + } +} + +float CircleBucket::getQueryRadius(const RenderLayer& layer) const { + if (!layer.is()) { + return 0; + } + + auto circleLayer = layer.as(); + + float radius = get(*circleLayer, paintPropertyBinders); + auto translate = circleLayer->evaluated.get(); + return radius + util::length(translate[0], translate[1]); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/circle_bucket.hpp b/src/mbgl/renderer/buckets/circle_bucket.hpp new file mode 100644 index 0000000000..b048fd7675 --- /dev/null +++ b/src/mbgl/renderer/buckets/circle_bucket.hpp @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +class BucketParameters; + +class CircleBucket : public Bucket { +public: + CircleBucket(const BucketParameters&, const std::vector&); + + void addFeature(const GeometryTileFeature&, + const GeometryCollection&) override; + bool hasData() const override; + + void upload(gl::Context&) override; + + void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; + + float getQueryRadius(const RenderLayer&) const override; + + gl::VertexVector vertices; + gl::IndexVector triangles; + gl::SegmentVector segments; + + optional> vertexBuffer; + optional> indexBuffer; + + std::map paintPropertyBinders; + + const MapMode mode; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/debug_bucket.cpp b/src/mbgl/renderer/buckets/debug_bucket.cpp new file mode 100644 index 0000000000..acfe15d2fb --- /dev/null +++ b/src/mbgl/renderer/buckets/debug_bucket.cpp @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +namespace mbgl { + +DebugBucket::DebugBucket(const OverscaledTileID& id, + const bool renderable_, + const bool complete_, + optional modified_, + optional expires_, + MapDebugOptions debugMode_, + gl::Context& context) + : renderable(renderable_), + complete(complete_), + modified(std::move(modified_)), + expires(std::move(expires_)), + debugMode(debugMode_) { + + gl::VertexVector vertices; + gl::IndexVector indices; + + auto addText = [&] (const std::string& text, double left, double baseline, double scale) { + for (uint8_t c : text) { + if (c < 32 || c >= 127) + continue; + + optional> prev; + + const glyph& glyph = simplex[c - 32]; + for (int32_t j = 0; j < glyph.length; j += 2) { + if (glyph.data[j] == -1 && glyph.data[j + 1] == -1) { + prev = {}; + } else { + Point p { + int16_t(::round(left + glyph.data[j] * scale)), + int16_t(::round(baseline - glyph.data[j + 1] * scale)) + }; + + vertices.emplace_back(FillProgram::layoutVertex(p)); + + if (prev) { + indices.emplace_back(vertices.vertexSize() - 2, + vertices.vertexSize() - 1); + } + + prev = p; + } + } + + left += glyph.width * scale; + } + }; + + double baseline = 200; + if (debugMode & MapDebugOptions::ParseStatus) { + const std::string text = util::toString(id) + " - " + + (complete ? "complete" : renderable ? "renderable" : "pending"); + addText(text, 50, baseline, 5); + baseline += 200; + } + + if (debugMode & MapDebugOptions::Timestamps && modified && expires) { + const std::string modifiedText = "modified: " + util::iso8601(*modified); + addText(modifiedText, 50, baseline, 5); + + const std::string expiresText = "expires: " + util::iso8601(*expires); + addText(expiresText, 50, baseline + 200, 5); + } + + segments.emplace_back(0, 0, vertices.vertexSize(), indices.indexSize()); + + vertexBuffer = context.createVertexBuffer(std::move(vertices)); + indexBuffer = context.createIndexBuffer(std::move(indices)); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/debug_bucket.hpp b/src/mbgl/renderer/buckets/debug_bucket.hpp new file mode 100644 index 0000000000..756e58a6de --- /dev/null +++ b/src/mbgl/renderer/buckets/debug_bucket.hpp @@ -0,0 +1,41 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +class OverscaledTileID; + +namespace gl { +class Context; +} // namespace gl + +class DebugBucket : private util::noncopyable { +public: + DebugBucket(const OverscaledTileID& id, + bool renderable, + bool complete, + optional modified, + optional expires, + MapDebugOptions, + gl::Context&); + + const bool renderable; + const bool complete; + const optional modified; + const optional expires; + const MapDebugOptions debugMode; + + gl::SegmentVector segments; + optional> vertexBuffer; + optional> indexBuffer; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/fill_bucket.cpp b/src/mbgl/renderer/buckets/fill_bucket.cpp new file mode 100644 index 0000000000..042d7b7506 --- /dev/null +++ b/src/mbgl/renderer/buckets/fill_bucket.cpp @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace mapbox { +namespace util { +template <> struct nth<0, mbgl::GeometryCoordinate> { + static int64_t get(const mbgl::GeometryCoordinate& t) { return t.x; }; +}; + +template <> struct nth<1, mbgl::GeometryCoordinate> { + static int64_t get(const mbgl::GeometryCoordinate& t) { return t.y; }; +}; +} // namespace util +} // namespace mapbox + +namespace mbgl { + +using namespace style; + +struct GeometryTooLongException : std::exception {}; + +FillBucket::FillBucket(const BucketParameters& parameters, const std::vector& layers) { + for (const auto& layer : layers) { + paintPropertyBinders.emplace( + std::piecewise_construct, + std::forward_as_tuple(layer->getID()), + std::forward_as_tuple( + layer->as()->evaluated, + parameters.tileID.overscaledZ)); + } +} + +void FillBucket::addFeature(const GeometryTileFeature& feature, + const GeometryCollection& geometry) { + for (auto& polygon : classifyRings(geometry)) { + // Optimize polygons with many interior rings for earcut tesselation. + limitHoles(polygon, 500); + + std::size_t totalVertices = 0; + + for (const auto& ring : polygon) { + totalVertices += ring.size(); + if (totalVertices > std::numeric_limits::max()) + throw GeometryTooLongException(); + } + + std::size_t startVertices = vertices.vertexSize(); + + for (const auto& ring : polygon) { + std::size_t nVertices = ring.size(); + + if (nVertices == 0) + continue; + + if (lineSegments.empty() || lineSegments.back().vertexLength + nVertices > std::numeric_limits::max()) { + lineSegments.emplace_back(vertices.vertexSize(), lines.indexSize()); + } + + auto& lineSegment = lineSegments.back(); + assert(lineSegment.vertexLength <= std::numeric_limits::max()); + uint16_t lineIndex = lineSegment.vertexLength; + + vertices.emplace_back(FillProgram::layoutVertex(ring[0])); + lines.emplace_back(lineIndex + nVertices - 1, lineIndex); + + for (uint32_t i = 1; i < nVertices; i++) { + vertices.emplace_back(FillProgram::layoutVertex(ring[i])); + lines.emplace_back(lineIndex + i - 1, lineIndex + i); + } + + lineSegment.vertexLength += nVertices; + lineSegment.indexLength += nVertices * 2; + } + + std::vector indices = mapbox::earcut(polygon); + + std::size_t nIndicies = indices.size(); + assert(nIndicies % 3 == 0); + + if (triangleSegments.empty() || triangleSegments.back().vertexLength + totalVertices > std::numeric_limits::max()) { + triangleSegments.emplace_back(startVertices, triangles.indexSize()); + } + + auto& triangleSegment = triangleSegments.back(); + assert(triangleSegment.vertexLength <= std::numeric_limits::max()); + uint16_t triangleIndex = triangleSegment.vertexLength; + + for (uint32_t i = 0; i < nIndicies; i += 3) { + triangles.emplace_back(triangleIndex + indices[i], + triangleIndex + indices[i + 1], + triangleIndex + indices[i + 2]); + } + + triangleSegment.vertexLength += totalVertices; + triangleSegment.indexLength += nIndicies; + } + + for (auto& pair : paintPropertyBinders) { + pair.second.populateVertexVectors(feature, vertices.vertexSize()); + } +} + +void FillBucket::upload(gl::Context& context) { + vertexBuffer = context.createVertexBuffer(std::move(vertices)); + lineIndexBuffer = context.createIndexBuffer(std::move(lines)); + triangleIndexBuffer = context.createIndexBuffer(std::move(triangles)); + + for (auto& pair : paintPropertyBinders) { + pair.second.upload(context); + } + + uploaded = true; +} + +void FillBucket::render(Painter& painter, + PaintParameters& parameters, + const RenderLayer& layer, + const RenderTile& tile) { + painter.renderFill(parameters, *this, *layer.as(), tile); +} + +bool FillBucket::hasData() const { + return !triangleSegments.empty() || !lineSegments.empty(); +} + +float FillBucket::getQueryRadius(const RenderLayer& layer) const { + if (!layer.is()) { + return 0; + } + + const std::array& translate = layer.as()->evaluated.get(); + return util::length(translate[0], translate[1]); + +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/fill_bucket.hpp b/src/mbgl/renderer/buckets/fill_bucket.hpp new file mode 100644 index 0000000000..421d8b332b --- /dev/null +++ b/src/mbgl/renderer/buckets/fill_bucket.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace mbgl { + +class BucketParameters; + +class FillBucket : public Bucket { +public: + FillBucket(const BucketParameters&, const std::vector&); + + void addFeature(const GeometryTileFeature&, + const GeometryCollection&) override; + bool hasData() const override; + + void upload(gl::Context&) override; + void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; + + float getQueryRadius(const RenderLayer&) const override; + + gl::VertexVector vertices; + gl::IndexVector lines; + gl::IndexVector triangles; + gl::SegmentVector lineSegments; + gl::SegmentVector triangleSegments; + + optional> vertexBuffer; + optional> lineIndexBuffer; + optional> triangleIndexBuffer; + + std::map paintPropertyBinders; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp new file mode 100644 index 0000000000..f61f1d1549 --- /dev/null +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.cpp @@ -0,0 +1,177 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +namespace mapbox { +namespace util { +template <> +struct nth<0, mbgl::GeometryCoordinate> { + static int64_t get(const mbgl::GeometryCoordinate& t) { + return t.x; + }; +}; + +template <> +struct nth<1, mbgl::GeometryCoordinate> { + static int64_t get(const mbgl::GeometryCoordinate& t) { + return t.y; + }; +}; +} // namespace util +} // namespace mapbox + +namespace mbgl { + +using namespace style; + +struct GeometryTooLongException : std::exception {}; + +FillExtrusionBucket::FillExtrusionBucket(const BucketParameters& parameters, const std::vector& layers) { + for (const auto& layer : layers) { + paintPropertyBinders.emplace(std::piecewise_construct, + std::forward_as_tuple(layer->getID()), + std::forward_as_tuple( + layer->as()->evaluated, + parameters.tileID.overscaledZ)); + } +} + +void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, + const GeometryCollection& geometry) { + for (auto& polygon : classifyRings(geometry)) { + // Optimize polygons with many interior rings for earcut tesselation. + limitHoles(polygon, 500); + + std::size_t totalVertices = 0; + + for (const auto& ring : polygon) { + totalVertices += ring.size(); + if (totalVertices > std::numeric_limits::max()) + throw GeometryTooLongException(); + } + + if (totalVertices == 0) continue; + + std::vector flatIndices; + flatIndices.reserve(totalVertices); + + std::size_t startVertices = vertices.vertexSize(); + + if (triangleSegments.empty() || + triangleSegments.back().vertexLength + (5 * (totalVertices - 1) + 1) > + std::numeric_limits::max()) { + triangleSegments.emplace_back(startVertices, triangles.indexSize()); + } + + auto& triangleSegment = triangleSegments.back(); + assert(triangleSegment.vertexLength <= std::numeric_limits::max()); + uint16_t triangleIndex = triangleSegment.vertexLength; + + assert(triangleIndex + (5 * (totalVertices - 1) + 1) <= + std::numeric_limits::max()); + + for (const auto& ring : polygon) { + std::size_t nVertices = ring.size(); + + if (nVertices == 0) + continue; + + auto edgeDistance = 0; + + for (uint32_t i = 0; i < nVertices; i++) { + const auto& p1 = ring[i]; + + vertices.emplace_back( + FillExtrusionProgram::layoutVertex(p1, 0, 0, 1, 1, edgeDistance)); + flatIndices.emplace_back(triangleIndex); + triangleIndex++; + + if (i != 0) { + const auto& p2 = ring[i - 1]; + + const auto d1 = convertPoint(p1); + const auto d2 = convertPoint(p2); + + const Point perp = util::unit(util::perp(d1 - d2)); + + vertices.emplace_back( + FillExtrusionProgram::layoutVertex(p1, perp.x, perp.y, 0, 0, edgeDistance)); + vertices.emplace_back( + FillExtrusionProgram::layoutVertex(p1, perp.x, perp.y, 0, 1, edgeDistance)); + + edgeDistance += util::dist(d1, d2); + + vertices.emplace_back( + FillExtrusionProgram::layoutVertex(p2, perp.x, perp.y, 0, 0, edgeDistance)); + vertices.emplace_back( + FillExtrusionProgram::layoutVertex(p2, perp.x, perp.y, 0, 1, edgeDistance)); + + triangles.emplace_back(triangleIndex, triangleIndex + 1, triangleIndex + 2); + triangles.emplace_back(triangleIndex + 1, triangleIndex + 2, triangleIndex + 3); + triangleIndex += 4; + triangleSegment.vertexLength += 4; + triangleSegment.indexLength += 6; + } + } + } + + std::vector indices = mapbox::earcut(polygon); + + std::size_t nIndices = indices.size(); + assert(nIndices % 3 == 0); + + for (uint32_t i = 0; i < nIndices; i += 3) { + triangles.emplace_back(flatIndices[indices[i]], flatIndices[indices[i + 1]], + flatIndices[indices[i + 2]]); + } + + triangleSegment.vertexLength += totalVertices; + triangleSegment.indexLength += nIndices; + } + + for (auto& pair : paintPropertyBinders) { + pair.second.populateVertexVectors(feature, vertices.vertexSize()); + } +} + +void FillExtrusionBucket::upload(gl::Context& context) { + vertexBuffer = context.createVertexBuffer(std::move(vertices)); + indexBuffer = context.createIndexBuffer(std::move(triangles)); + + for (auto& pair : paintPropertyBinders) { + pair.second.upload(context); + } + + uploaded = true; +} + +void FillExtrusionBucket::render(Painter& painter, + PaintParameters& parameters, + const RenderLayer& layer, + const RenderTile& tile) { + painter.renderFillExtrusion(parameters, *this, *layer.as(), tile); +} + +bool FillExtrusionBucket::hasData() const { + return !triangleSegments.empty(); +} + +float FillExtrusionBucket::getQueryRadius(const RenderLayer& layer) const { + if (!layer.is()) { + return 0; + } + + const std::array& translate = layer.as()->evaluated.get(); + return util::length(translate[0], translate[1]); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp new file mode 100644 index 0000000000..c54805d743 --- /dev/null +++ b/src/mbgl/renderer/buckets/fill_extrusion_bucket.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +class BucketParameters; + +class FillExtrusionBucket : public Bucket { +public: + FillExtrusionBucket(const BucketParameters&, const std::vector&); + + void addFeature(const GeometryTileFeature&, + const GeometryCollection&) override; + bool hasData() const override; + + void upload(gl::Context&) override; + void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; + + float getQueryRadius(const RenderLayer&) const override; + + gl::VertexVector vertices; + gl::IndexVector triangles; + gl::SegmentVector triangleSegments; + + optional> vertexBuffer; + optional> indexBuffer; + + std::unordered_map paintPropertyBinders; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp new file mode 100644 index 0000000000..3c5fa6bc67 --- /dev/null +++ b/src/mbgl/renderer/buckets/line_bucket.cpp @@ -0,0 +1,506 @@ +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace mbgl { + +using namespace style; + +LineBucket::LineBucket(const BucketParameters& parameters, + const std::vector& layers, + const style::LineLayoutProperties& layout_) + : layout(layout_.evaluate(PropertyEvaluationParameters(parameters.tileID.overscaledZ))), + overscaling(parameters.tileID.overscaleFactor()) { + for (const auto& layer : layers) { + paintPropertyBinders.emplace( + std::piecewise_construct, + std::forward_as_tuple(layer->getID()), + std::forward_as_tuple( + layer->as()->evaluated, + parameters.tileID.overscaledZ)); + } +} + +void LineBucket::addFeature(const GeometryTileFeature& feature, + const GeometryCollection& geometryCollection) { + for (auto& line : geometryCollection) { + addGeometry(line, feature.getType()); + } + + for (auto& pair : paintPropertyBinders) { + pair.second.populateVertexVectors(feature, vertices.vertexSize()); + } +} + +/* + * Sharp corners cause dashed lines to tilt because the distance along the line + * is the same at both the inner and outer corners. To improve the appearance of + * dashed lines we add extra points near sharp corners so that a smaller part + * of the line is tilted. + * + * COS_HALF_SHARP_CORNER controls how sharp a corner has to be for us to add an + * extra vertex. The default is 75 degrees. + * + * The newly created vertices are placed SHARP_CORNER_OFFSET pixels from the corner. + */ +const float COS_HALF_SHARP_CORNER = std::cos(75.0 / 2.0 * (M_PI / 180.0)); +const float SHARP_CORNER_OFFSET = 15.0f; + +// The number of bits that is used to store the line distance in the buffer. +const int LINE_DISTANCE_BUFFER_BITS = 14; + +// We don't have enough bits for the line distance as we'd like to have, so +// use this value to scale the line distance (in tile units) down to a smaller +// value. This lets us store longer distances while sacrificing precision. +const float LINE_DISTANCE_SCALE = 1.0 / 2.0; + +// The maximum line distance, in tile units, that fits in the buffer. +const float MAX_LINE_DISTANCE = std::pow(2, LINE_DISTANCE_BUFFER_BITS) / LINE_DISTANCE_SCALE; + +void LineBucket::addGeometry(const GeometryCoordinates& coordinates, FeatureType type) { + const std::size_t len = [&coordinates] { + std::size_t l = coordinates.size(); + // If the line has duplicate vertices at the end, adjust length to remove them. + while (l >= 2 && coordinates[l - 1] == coordinates[l - 2]) { + l--; + } + return l; + }(); + + const std::size_t first = [&coordinates, &len] { + std::size_t i = 0; + // If the line has duplicate vertices at the start, adjust index to remove them. + while (i < len - 1 && coordinates[i] == coordinates[i + 1]) { + i++; + } + return i; + }(); + + // Ignore invalid geometry. + if (len < (type == FeatureType::Polygon ? 3 : 2)) { + return; + } + + const float miterLimit = layout.get() == LineJoinType::Bevel ? 1.05f : float(layout.get()); + + const double sharpCornerOffset = SHARP_CORNER_OFFSET * (float(util::EXTENT) / (util::tileSize * overscaling)); + + const GeometryCoordinate firstCoordinate = coordinates[first]; + const LineCapType beginCap = layout.get(); + const LineCapType endCap = type == FeatureType::Polygon ? LineCapType::Butt : LineCapType(layout.get()); + + double distance = 0; + bool startOfLine = true; + optional currentCoordinate; + optional prevCoordinate; + optional nextCoordinate; + optional> prevNormal; + optional> nextNormal; + + // the last three vertices added + e1 = e2 = e3 = -1; + + if (type == FeatureType::Polygon) { + currentCoordinate = coordinates[len - 2]; + nextNormal = util::perp(util::unit(convertPoint(firstCoordinate - *currentCoordinate))); + } + + const std::size_t startVertex = vertices.vertexSize(); + std::vector triangleStore; + + for (std::size_t i = first; i < len; ++i) { + if (type == FeatureType::Polygon && i == len - 1) { + // if the line is closed, we treat the last vertex like the first + nextCoordinate = coordinates[first + 1]; + } else if (i + 1 < len) { + // just the next vertex + nextCoordinate = coordinates[i + 1]; + } else { + // there is no next vertex + nextCoordinate = {}; + } + + // if two consecutive vertices exist, skip the current one + if (nextCoordinate && coordinates[i] == *nextCoordinate) { + continue; + } + + if (nextNormal) { + prevNormal = *nextNormal; + } + if (currentCoordinate) { + prevCoordinate = *currentCoordinate; + } + + currentCoordinate = coordinates[i]; + + // Calculate the normal towards the next vertex in this line. In case + // there is no next vertex, pretend that the line is continuing straight, + // meaning that we are just using the previous normal. + nextNormal = nextCoordinate ? util::perp(util::unit(convertPoint(*nextCoordinate - *currentCoordinate))) + : prevNormal; + + // If we still don't have a previous normal, this is the beginning of a + // non-closed line, so we're doing a straight "join". + if (!prevNormal) { + prevNormal = *nextNormal; + } + + // Determine the normal of the join extrusion. It is the angle bisector + // of the segments between the previous line and the next line. + // In the case of 180° angles, the prev and next normals cancel each other out: + // prevNormal + nextNormal = (0, 0), its magnitude is 0, so the unit vector would be + // undefined. In that case, we're keeping the joinNormal at (0, 0), so that the cosHalfAngle + // below will also become 0 and miterLength will become Infinity. + Point joinNormal = *prevNormal + *nextNormal; + if (joinNormal.x != 0 || joinNormal.y != 0) { + joinNormal = util::unit(joinNormal); + } + + /* joinNormal prevNormal + * ↖ ↑ + * .________. prevVertex + * | + * nextNormal ← | currentVertex + * | + * nextVertex ! + * + */ + + // Calculate the length of the miter (the ratio of the miter to the width). + // Find the cosine of the angle between the next and join normals + // using dot product. The inverse of that is the miter length. + const double cosHalfAngle = joinNormal.x * nextNormal->x + joinNormal.y * nextNormal->y; + const double miterLength = + cosHalfAngle != 0 ? 1 / cosHalfAngle : std::numeric_limits::infinity(); + + const bool isSharpCorner = cosHalfAngle < COS_HALF_SHARP_CORNER && prevCoordinate && nextCoordinate; + + if (isSharpCorner && i > first) { + const auto prevSegmentLength = util::dist(*currentCoordinate, *prevCoordinate); + if (prevSegmentLength > 2.0 * sharpCornerOffset) { + GeometryCoordinate newPrevVertex = *currentCoordinate - convertPoint(util::round(convertPoint(*currentCoordinate - *prevCoordinate) * (sharpCornerOffset / prevSegmentLength))); + distance += util::dist(newPrevVertex, *prevCoordinate); + addCurrentVertex(newPrevVertex, distance, *prevNormal, 0, 0, false, startVertex, triangleStore); + prevCoordinate = newPrevVertex; + } + } + + // The join if a middle vertex, otherwise the cap + const bool middleVertex = prevCoordinate && nextCoordinate; + LineJoinType currentJoin = layout.get(); + const LineCapType currentCap = nextCoordinate ? beginCap : endCap; + + if (middleVertex) { + if (currentJoin == LineJoinType::Round) { + if (miterLength < layout.get()) { + currentJoin = LineJoinType::Miter; + } else if (miterLength <= 2) { + currentJoin = LineJoinType::FakeRound; + } + } + + if (currentJoin == LineJoinType::Miter && miterLength > miterLimit) { + currentJoin = LineJoinType::Bevel; + } + + if (currentJoin == LineJoinType::Bevel) { + // The maximum extrude length is 128 / 63 = 2 times the width of the line + // so if miterLength >= 2 we need to draw a different type of bevel here. + if (miterLength > 2) { + currentJoin = LineJoinType::FlipBevel; + } + + // If the miterLength is really small and the line bevel wouldn't be visible, + // just draw a miter join to save a triangle. + if (miterLength < miterLimit) { + currentJoin = LineJoinType::Miter; + } + } + } + + // Calculate how far along the line the currentVertex is + if (prevCoordinate) + distance += util::dist(*currentCoordinate, *prevCoordinate); + + if (middleVertex && currentJoin == LineJoinType::Miter) { + joinNormal = joinNormal * miterLength; + addCurrentVertex(*currentCoordinate, distance, joinNormal, 0, 0, false, startVertex, + triangleStore); + + } else if (middleVertex && currentJoin == LineJoinType::FlipBevel) { + // miter is too big, flip the direction to make a beveled join + + if (miterLength > 100) { + // Almost parallel lines + joinNormal = *nextNormal * -1.0; + } else { + const double direction = prevNormal->x * nextNormal->y - prevNormal->y * nextNormal->x > 0 ? -1 : 1; + const double bevelLength = miterLength * util::mag(*prevNormal + *nextNormal) / + util::mag(*prevNormal - *nextNormal); + joinNormal = util::perp(joinNormal) * bevelLength * direction; + } + + addCurrentVertex(*currentCoordinate, distance, joinNormal, 0, 0, false, startVertex, + triangleStore); + + addCurrentVertex(*currentCoordinate, distance, joinNormal * -1.0, 0, 0, false, startVertex, + triangleStore); + } else if (middleVertex && (currentJoin == LineJoinType::Bevel || currentJoin == LineJoinType::FakeRound)) { + const bool lineTurnsLeft = (prevNormal->x * nextNormal->y - prevNormal->y * nextNormal->x) > 0; + const float offset = -std::sqrt(miterLength * miterLength - 1); + float offsetA; + float offsetB; + + if (lineTurnsLeft) { + offsetB = 0; + offsetA = offset; + } else { + offsetA = 0; + offsetB = offset; + } + + // Close previous segement with bevel + if (!startOfLine) { + addCurrentVertex(*currentCoordinate, distance, *prevNormal, offsetA, offsetB, false, + startVertex, triangleStore); + } + + if (currentJoin == LineJoinType::FakeRound) { + // The join angle is sharp enough that a round join would be visible. + // Bevel joins fill the gap between segments with a single pie slice triangle. + // Create a round join by adding multiple pie slices. The join isn't actually round, but + // it looks like it is at the sizes we render lines at. + + // Add more triangles for sharper angles. + // This math is just a good enough approximation. It isn't "correct". + const int n = std::floor((0.5 - (cosHalfAngle - 0.5)) * 8); + + for (int m = 0; m < n; m++) { + auto approxFractionalJoinNormal = util::unit(*nextNormal * ((m + 1.0) / (n + 1.0)) + *prevNormal); + addPieSliceVertex(*currentCoordinate, distance, approxFractionalJoinNormal, lineTurnsLeft, startVertex, triangleStore); + } + + addPieSliceVertex(*currentCoordinate, distance, joinNormal, lineTurnsLeft, startVertex, triangleStore); + + for (int k = n - 1; k >= 0; k--) { + auto approxFractionalJoinNormal = util::unit(*prevNormal * ((k + 1.0) / (n + 1.0)) + *nextNormal); + addPieSliceVertex(*currentCoordinate, distance, approxFractionalJoinNormal, lineTurnsLeft, startVertex, triangleStore); + } + } + + // Start next segment + if (nextCoordinate) { + addCurrentVertex(*currentCoordinate, distance, *nextNormal, -offsetA, -offsetB, + false, startVertex, triangleStore); + } + + } else if (!middleVertex && currentCap == LineCapType::Butt) { + if (!startOfLine) { + // Close previous segment with a butt + addCurrentVertex(*currentCoordinate, distance, *prevNormal, 0, 0, false, + startVertex, triangleStore); + } + + // Start next segment with a butt + if (nextCoordinate) { + addCurrentVertex(*currentCoordinate, distance, *nextNormal, 0, 0, false, + startVertex, triangleStore); + } + + } else if (!middleVertex && currentCap == LineCapType::Square) { + if (!startOfLine) { + // Close previous segment with a square cap + addCurrentVertex(*currentCoordinate, distance, *prevNormal, 1, 1, false, + startVertex, triangleStore); + + // The segment is done. Unset vertices to disconnect segments. + e1 = e2 = -1; + } + + // Start next segment + if (nextCoordinate) { + addCurrentVertex(*currentCoordinate, distance, *nextNormal, -1, -1, false, + startVertex, triangleStore); + } + + } else if (middleVertex ? currentJoin == LineJoinType::Round : currentCap == LineCapType::Round) { + if (!startOfLine) { + // Close previous segment with a butt + addCurrentVertex(*currentCoordinate, distance, *prevNormal, 0, 0, false, + startVertex, triangleStore); + + // Add round cap or linejoin at end of segment + addCurrentVertex(*currentCoordinate, distance, *prevNormal, 1, 1, true, startVertex, + triangleStore); + + // The segment is done. Unset vertices to disconnect segments. + e1 = e2 = -1; + } + + // Start next segment with a butt + if (nextCoordinate) { + // Add round cap before first segment + addCurrentVertex(*currentCoordinate, distance, *nextNormal, -1, -1, true, + startVertex, triangleStore); + + addCurrentVertex(*currentCoordinate, distance, *nextNormal, 0, 0, false, + startVertex, triangleStore); + } + } + + if (isSharpCorner && i < len - 1) { + const auto nextSegmentLength = util::dist(*currentCoordinate, *nextCoordinate); + if (nextSegmentLength > 2 * sharpCornerOffset) { + GeometryCoordinate newCurrentVertex = *currentCoordinate + convertPoint(util::round(convertPoint(*nextCoordinate - *currentCoordinate) * (sharpCornerOffset / nextSegmentLength))); + distance += util::dist(newCurrentVertex, *currentCoordinate); + addCurrentVertex(newCurrentVertex, distance, *nextNormal, 0, 0, false, startVertex, triangleStore); + currentCoordinate = newCurrentVertex; + } + } + + startOfLine = false; + } + + const std::size_t endVertex = vertices.vertexSize(); + const std::size_t vertexCount = endVertex - startVertex; + + if (segments.empty() || segments.back().vertexLength + vertexCount > std::numeric_limits::max()) { + segments.emplace_back(startVertex, triangles.indexSize()); + } + + auto& segment = segments.back(); + assert(segment.vertexLength <= std::numeric_limits::max()); + uint16_t index = segment.vertexLength; + + for (const auto& triangle : triangleStore) { + triangles.emplace_back(index + triangle.a, index + triangle.b, index + triangle.c); + } + + segment.vertexLength += vertexCount; + segment.indexLength += triangleStore.size() * 3; +} + +void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate, + double &distance, + const Point& normal, + double endLeft, + double endRight, + bool round, + std::size_t startVertex, + std::vector& triangleStore) { + Point extrude = normal; + if (endLeft) + extrude = extrude - (util::perp(normal) * endLeft); + vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, { round, false }, endLeft, distance * LINE_DISTANCE_SCALE)); + e3 = vertices.vertexSize() - 1 - startVertex; + if (e1 >= 0 && e2 >= 0) { + triangleStore.emplace_back(e1, e2, e3); + } + e1 = e2; + e2 = e3; + + extrude = normal * -1.0; + if (endRight) + extrude = extrude - (util::perp(normal) * endRight); + vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, { round, true }, -endRight, distance * LINE_DISTANCE_SCALE)); + e3 = vertices.vertexSize() - 1 - startVertex; + if (e1 >= 0 && e2 >= 0) { + triangleStore.emplace_back(e1, e2, e3); + } + e1 = e2; + e2 = e3; + + // There is a maximum "distance along the line" that we can store in the buffers. + // When we get close to the distance, reset it to zero and add the vertex again with + // a distance of zero. The max distance is determined by the number of bits we allocate + // to `linesofar`. + if (distance > MAX_LINE_DISTANCE / 2.0f) { + distance = 0; + addCurrentVertex(currentCoordinate, distance, normal, endLeft, endRight, round, startVertex, triangleStore); + } +} + +void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex, + double distance, + const Point& extrude, + bool lineTurnsLeft, + std::size_t startVertex, + std::vector& triangleStore) { + Point flippedExtrude = extrude * (lineTurnsLeft ? -1.0 : 1.0); + vertices.emplace_back(LineProgram::layoutVertex(currentVertex, flippedExtrude, { false, lineTurnsLeft }, 0, distance * LINE_DISTANCE_SCALE)); + e3 = vertices.vertexSize() - 1 - startVertex; + if (e1 >= 0 && e2 >= 0) { + triangleStore.emplace_back(e1, e2, e3); + } + + if (lineTurnsLeft) { + e2 = e3; + } else { + e1 = e3; + } +} + +void LineBucket::upload(gl::Context& context) { + vertexBuffer = context.createVertexBuffer(std::move(vertices)); + indexBuffer = context.createIndexBuffer(std::move(triangles)); + + for (auto& pair : paintPropertyBinders) { + pair.second.upload(context); + } + + uploaded = true; +} + +void LineBucket::render(Painter& painter, + PaintParameters& parameters, + const RenderLayer& layer, + const RenderTile& tile) { + painter.renderLine(parameters, *this, *layer.as(), tile); +} + +bool LineBucket::hasData() const { + return !segments.empty(); +} + +template +static float get(const RenderLineLayer& layer, const std::map& paintPropertyBinders) { + auto it = paintPropertyBinders.find(layer.getID()); + if (it == paintPropertyBinders.end() || !it->second.statistics().max()) { + return layer.evaluated.get().constantOr(Property::defaultValue()); + } else { + return *it->second.statistics().max(); + } +} + +float LineBucket::getLineWidth(const RenderLineLayer& layer) const { + float lineWidth = layer.evaluated.get(); + float gapWidth = get(layer, paintPropertyBinders); + + if (gapWidth) { + return gapWidth + 2 * lineWidth; + } else { + return lineWidth; + } +} + +float LineBucket::getQueryRadius(const RenderLayer& layer) const { + if (!layer.is()) { + return 0; + } + + auto lineLayer = layer.as(); + + const std::array& translate = lineLayer->evaluated.get(); + float offset = get(*lineLayer, paintPropertyBinders); + return getLineWidth(*lineLayer) / 2.0 + std::abs(offset) + util::length(translate[0], translate[1]); +} + + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/line_bucket.hpp b/src/mbgl/renderer/buckets/line_bucket.hpp new file mode 100644 index 0000000000..c319548714 --- /dev/null +++ b/src/mbgl/renderer/buckets/line_bucket.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace mbgl { + +class BucketParameters; +class RenderLineLayer; + +class LineBucket : public Bucket { +public: + LineBucket(const BucketParameters&, + const std::vector&, + const style::LineLayoutProperties&); + + void addFeature(const GeometryTileFeature&, + const GeometryCollection&) override; + bool hasData() const override; + + void upload(gl::Context&) override; + void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; + + float getQueryRadius(const RenderLayer&) const override; + + style::LineLayoutProperties::PossiblyEvaluated layout; + + gl::VertexVector vertices; + gl::IndexVector triangles; + gl::SegmentVector segments; + + optional> vertexBuffer; + optional> indexBuffer; + + std::map paintPropertyBinders; + +private: + void addGeometry(const GeometryCoordinates&, FeatureType); + + struct TriangleElement { + TriangleElement(uint16_t a_, uint16_t b_, uint16_t c_) : a(a_), b(b_), c(c_) {} + uint16_t a, b, c; + }; + void addCurrentVertex(const GeometryCoordinate& currentVertex, double& distance, + const Point& normal, double endLeft, double endRight, bool round, + std::size_t startVertex, std::vector& triangleStore); + void addPieSliceVertex(const GeometryCoordinate& currentVertex, double distance, + const Point& extrude, bool lineTurnsLeft, std::size_t startVertex, + std::vector& triangleStore); + + std::ptrdiff_t e1; + std::ptrdiff_t e2; + std::ptrdiff_t e3; + + const uint32_t overscaling; + + float getLineWidth(const RenderLineLayer& layer) const; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/raster_bucket.cpp b/src/mbgl/renderer/buckets/raster_bucket.cpp new file mode 100644 index 0000000000..4a25959868 --- /dev/null +++ b/src/mbgl/renderer/buckets/raster_bucket.cpp @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +RasterBucket::RasterBucket(UnassociatedImage&& image_) : image(std::move(image_)) { +} + +void RasterBucket::upload(gl::Context& context) { + texture = context.createTexture(std::move(image)); + uploaded = true; +} + +void RasterBucket::render(Painter& painter, + PaintParameters& parameters, + const RenderLayer& layer, + const RenderTile& tile) { + painter.renderRaster(parameters, *this, *layer.as(), tile); +} + +bool RasterBucket::hasData() const { + return true; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/raster_bucket.hpp b/src/mbgl/renderer/buckets/raster_bucket.hpp new file mode 100644 index 0000000000..334954e3f4 --- /dev/null +++ b/src/mbgl/renderer/buckets/raster_bucket.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include +#include + +namespace mbgl { + +class RasterBucket : public Bucket { +public: + RasterBucket(UnassociatedImage&&); + + void upload(gl::Context&) override; + void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; + bool hasData() const override; + + UnassociatedImage image; + optional texture; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/symbol_bucket.cpp b/src/mbgl/renderer/buckets/symbol_bucket.cpp new file mode 100644 index 0000000000..423161f24c --- /dev/null +++ b/src/mbgl/renderer/buckets/symbol_bucket.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated layout_, + const std::map>& layerPaintProperties, + const style::DataDrivenPropertyValue& textSize, + const style::DataDrivenPropertyValue& iconSize, + float zoom, + bool sdfIcons_, + bool iconsNeedLinear_) + : layout(std::move(layout_)), + sdfIcons(sdfIcons_), + iconsNeedLinear(iconsNeedLinear_ || iconSize.isDataDriven() || !iconSize.isZoomConstant()), + textSizeBinder(SymbolSizeBinder::create(zoom, textSize, TextSize::defaultValue())), + iconSizeBinder(SymbolSizeBinder::create(zoom, iconSize, IconSize::defaultValue())) { + + for (const auto& pair : layerPaintProperties) { + paintPropertyBinders.emplace( + std::piecewise_construct, + std::forward_as_tuple(pair.first), + std::forward_as_tuple( + std::piecewise_construct, + std::forward_as_tuple(pair.second.first, zoom), + std::forward_as_tuple(pair.second.second, zoom))); + } +} + +void SymbolBucket::upload(gl::Context& context) { + if (hasTextData()) { + text.vertexBuffer = context.createVertexBuffer(std::move(text.vertices)); + text.indexBuffer = context.createIndexBuffer(std::move(text.triangles)); + textSizeBinder->upload(context); + } + + if (hasIconData()) { + icon.vertexBuffer = context.createVertexBuffer(std::move(icon.vertices)); + icon.indexBuffer = context.createIndexBuffer(std::move(icon.triangles)); + iconSizeBinder->upload(context); + } + + if (!collisionBox.vertices.empty()) { + collisionBox.vertexBuffer = context.createVertexBuffer(std::move(collisionBox.vertices)); + collisionBox.indexBuffer = context.createIndexBuffer(std::move(collisionBox.lines)); + } + + for (auto& pair : paintPropertyBinders) { + pair.second.first.upload(context); + pair.second.second.upload(context); + } + + uploaded = true; +} + +void SymbolBucket::render(Painter& painter, + PaintParameters& parameters, + const RenderLayer& layer, + const RenderTile& tile) { + painter.renderSymbol(parameters, *this, *layer.as(), tile); +} + +bool SymbolBucket::hasData() const { + assert(false); // Should be calling SymbolLayout::has{Text,Icon,CollisonBox}Data() instead. + return false; +} + +bool SymbolBucket::hasTextData() const { + return !text.segments.empty(); +} + +bool SymbolBucket::hasIconData() const { + return !icon.segments.empty(); +} + +bool SymbolBucket::hasCollisionBoxData() const { + return !collisionBox.segments.empty(); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/buckets/symbol_bucket.hpp b/src/mbgl/renderer/buckets/symbol_bucket.hpp new file mode 100644 index 0000000000..f7e4bcfa20 --- /dev/null +++ b/src/mbgl/renderer/buckets/symbol_bucket.hpp @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace mbgl { + +class SymbolBucket : public Bucket { +public: + SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated, + const std::map>&, + const style::DataDrivenPropertyValue& textSize, + const style::DataDrivenPropertyValue& iconSize, + float zoom, + bool sdfIcons, + bool iconsNeedLinear); + + void upload(gl::Context&) override; + void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; + bool hasData() const override; + bool hasTextData() const; + bool hasIconData() const; + bool hasCollisionBoxData() const; + + const style::SymbolLayoutProperties::PossiblyEvaluated layout; + const bool sdfIcons; + const bool iconsNeedLinear; + + std::map> paintPropertyBinders; + + std::unique_ptr textSizeBinder; + + struct TextBuffer { + gl::VertexVector vertices; + gl::IndexVector triangles; + gl::SegmentVector segments; + + optional> vertexBuffer; + optional> indexBuffer; + } text; + + std::unique_ptr iconSizeBinder; + + struct IconBuffer { + gl::VertexVector vertices; + gl::IndexVector triangles; + gl::SegmentVector segments; + + optional> vertexBuffer; + optional> indexBuffer; + } icon; + + struct CollisionBoxBuffer { + gl::VertexVector vertices; + gl::IndexVector lines; + gl::SegmentVector segments; + + optional> vertexBuffer; + optional> indexBuffer; + } collisionBox; + + SpriteAtlas* spriteAtlas = nullptr; +}; + +} // namespace mbgl diff --git a/src/mbgl/renderer/circle_bucket.cpp b/src/mbgl/renderer/circle_bucket.cpp deleted file mode 100644 index 1e08eca478..0000000000 --- a/src/mbgl/renderer/circle_bucket.cpp +++ /dev/null @@ -1,123 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -using namespace style; - -CircleBucket::CircleBucket(const BucketParameters& parameters, const std::vector& layers) - : mode(parameters.mode) { - for (const auto& layer : layers) { - paintPropertyBinders.emplace( - std::piecewise_construct, - std::forward_as_tuple(layer->getID()), - std::forward_as_tuple( - layer->as()->evaluated, - parameters.tileID.overscaledZ)); - } -} - -void CircleBucket::upload(gl::Context& context) { - vertexBuffer = context.createVertexBuffer(std::move(vertices)); - indexBuffer = context.createIndexBuffer(std::move(triangles)); - - for (auto& pair : paintPropertyBinders) { - pair.second.upload(context); - } - - uploaded = true; -} - -void CircleBucket::render(Painter& painter, - PaintParameters& parameters, - const RenderLayer& layer, - const RenderTile& tile) { - painter.renderCircle(parameters, *this, *layer.as(), tile); -} - -bool CircleBucket::hasData() const { - return !segments.empty(); -} - -void CircleBucket::addFeature(const GeometryTileFeature& feature, - const GeometryCollection& geometry) { - constexpr const uint16_t vertexLength = 4; - - for (auto& circle : geometry) { - for(auto& point : circle) { - auto x = point.x; - auto y = point.y; - - // Do not include points that are outside the tile boundaries. - // Include all points in Still mode. You need to include points from - // neighbouring tiles so that they are not clipped at tile boundaries. - if ((mode != MapMode::Still) && - (x < 0 || x >= util::EXTENT || y < 0 || y >= util::EXTENT)) continue; - - if (segments.empty() || segments.back().vertexLength + vertexLength > std::numeric_limits::max()) { - // Move to a new segments because the old one can't hold the geometry. - segments.emplace_back(vertices.vertexSize(), triangles.indexSize()); - } - - // this geometry will be of the Point type, and we'll derive - // two triangles from it. - // - // ┌─────────┐ - // │ 4 3 │ - // │ │ - // │ 1 2 │ - // └─────────┘ - // - vertices.emplace_back(CircleProgram::vertex(point, -1, -1)); // 1 - vertices.emplace_back(CircleProgram::vertex(point, 1, -1)); // 2 - vertices.emplace_back(CircleProgram::vertex(point, 1, 1)); // 3 - vertices.emplace_back(CircleProgram::vertex(point, -1, 1)); // 4 - - auto& segment = segments.back(); - assert(segment.vertexLength <= std::numeric_limits::max()); - uint16_t index = segment.vertexLength; - - // 1, 2, 3 - // 1, 4, 3 - triangles.emplace_back(index, index + 1, index + 2); - triangles.emplace_back(index, index + 3, index + 2); - - segment.vertexLength += vertexLength; - segment.indexLength += 6; - } - } - - for (auto& pair : paintPropertyBinders) { - pair.second.populateVertexVectors(feature, vertices.vertexSize()); - } -} - -template -static float get(const RenderCircleLayer& layer, const std::map& paintPropertyBinders) { - auto it = paintPropertyBinders.find(layer.getID()); - if (it == paintPropertyBinders.end() || !it->second.statistics().max()) { - return layer.evaluated.get().constantOr(Property::defaultValue()); - } else { - return *it->second.statistics().max(); - } -} - -float CircleBucket::getQueryRadius(const RenderLayer& layer) const { - if (!layer.is()) { - return 0; - } - - auto circleLayer = layer.as(); - - float radius = get(*circleLayer, paintPropertyBinders); - auto translate = circleLayer->evaluated.get(); - return radius + util::length(translate[0], translate[1]); -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/circle_bucket.hpp b/src/mbgl/renderer/circle_bucket.hpp deleted file mode 100644 index b048fd7675..0000000000 --- a/src/mbgl/renderer/circle_bucket.hpp +++ /dev/null @@ -1,42 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -class BucketParameters; - -class CircleBucket : public Bucket { -public: - CircleBucket(const BucketParameters&, const std::vector&); - - void addFeature(const GeometryTileFeature&, - const GeometryCollection&) override; - bool hasData() const override; - - void upload(gl::Context&) override; - - void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; - - float getQueryRadius(const RenderLayer&) const override; - - gl::VertexVector vertices; - gl::IndexVector triangles; - gl::SegmentVector segments; - - optional> vertexBuffer; - optional> indexBuffer; - - std::map paintPropertyBinders; - - const MapMode mode; -}; - -} // namespace mbgl diff --git a/src/mbgl/renderer/debug_bucket.cpp b/src/mbgl/renderer/debug_bucket.cpp deleted file mode 100644 index 2a514989cf..0000000000 --- a/src/mbgl/renderer/debug_bucket.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include -#include -#include -#include - -#include -#include -#include - -namespace mbgl { - -DebugBucket::DebugBucket(const OverscaledTileID& id, - const bool renderable_, - const bool complete_, - optional modified_, - optional expires_, - MapDebugOptions debugMode_, - gl::Context& context) - : renderable(renderable_), - complete(complete_), - modified(std::move(modified_)), - expires(std::move(expires_)), - debugMode(debugMode_) { - - gl::VertexVector vertices; - gl::IndexVector indices; - - auto addText = [&] (const std::string& text, double left, double baseline, double scale) { - for (uint8_t c : text) { - if (c < 32 || c >= 127) - continue; - - optional> prev; - - const glyph& glyph = simplex[c - 32]; - for (int32_t j = 0; j < glyph.length; j += 2) { - if (glyph.data[j] == -1 && glyph.data[j + 1] == -1) { - prev = {}; - } else { - Point p { - int16_t(::round(left + glyph.data[j] * scale)), - int16_t(::round(baseline - glyph.data[j + 1] * scale)) - }; - - vertices.emplace_back(FillProgram::layoutVertex(p)); - - if (prev) { - indices.emplace_back(vertices.vertexSize() - 2, - vertices.vertexSize() - 1); - } - - prev = p; - } - } - - left += glyph.width * scale; - } - }; - - double baseline = 200; - if (debugMode & MapDebugOptions::ParseStatus) { - const std::string text = util::toString(id) + " - " + - (complete ? "complete" : renderable ? "renderable" : "pending"); - addText(text, 50, baseline, 5); - baseline += 200; - } - - if (debugMode & MapDebugOptions::Timestamps && modified && expires) { - const std::string modifiedText = "modified: " + util::iso8601(*modified); - addText(modifiedText, 50, baseline, 5); - - const std::string expiresText = "expires: " + util::iso8601(*expires); - addText(expiresText, 50, baseline + 200, 5); - } - - segments.emplace_back(0, 0, vertices.vertexSize(), indices.indexSize()); - - vertexBuffer = context.createVertexBuffer(std::move(vertices)); - indexBuffer = context.createIndexBuffer(std::move(indices)); -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/debug_bucket.hpp b/src/mbgl/renderer/debug_bucket.hpp deleted file mode 100644 index 756e58a6de..0000000000 --- a/src/mbgl/renderer/debug_bucket.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -class OverscaledTileID; - -namespace gl { -class Context; -} // namespace gl - -class DebugBucket : private util::noncopyable { -public: - DebugBucket(const OverscaledTileID& id, - bool renderable, - bool complete, - optional modified, - optional expires, - MapDebugOptions, - gl::Context&); - - const bool renderable; - const bool complete; - const optional modified; - const optional expires; - const MapDebugOptions debugMode; - - gl::SegmentVector segments; - optional> vertexBuffer; - optional> indexBuffer; -}; - -} // namespace mbgl diff --git a/src/mbgl/renderer/fill_bucket.cpp b/src/mbgl/renderer/fill_bucket.cpp deleted file mode 100644 index 2409fd365b..0000000000 --- a/src/mbgl/renderer/fill_bucket.cpp +++ /dev/null @@ -1,145 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace mapbox { -namespace util { -template <> struct nth<0, mbgl::GeometryCoordinate> { - static int64_t get(const mbgl::GeometryCoordinate& t) { return t.x; }; -}; - -template <> struct nth<1, mbgl::GeometryCoordinate> { - static int64_t get(const mbgl::GeometryCoordinate& t) { return t.y; }; -}; -} // namespace util -} // namespace mapbox - -namespace mbgl { - -using namespace style; - -struct GeometryTooLongException : std::exception {}; - -FillBucket::FillBucket(const BucketParameters& parameters, const std::vector& layers) { - for (const auto& layer : layers) { - paintPropertyBinders.emplace( - std::piecewise_construct, - std::forward_as_tuple(layer->getID()), - std::forward_as_tuple( - layer->as()->evaluated, - parameters.tileID.overscaledZ)); - } -} - -void FillBucket::addFeature(const GeometryTileFeature& feature, - const GeometryCollection& geometry) { - for (auto& polygon : classifyRings(geometry)) { - // Optimize polygons with many interior rings for earcut tesselation. - limitHoles(polygon, 500); - - std::size_t totalVertices = 0; - - for (const auto& ring : polygon) { - totalVertices += ring.size(); - if (totalVertices > std::numeric_limits::max()) - throw GeometryTooLongException(); - } - - std::size_t startVertices = vertices.vertexSize(); - - for (const auto& ring : polygon) { - std::size_t nVertices = ring.size(); - - if (nVertices == 0) - continue; - - if (lineSegments.empty() || lineSegments.back().vertexLength + nVertices > std::numeric_limits::max()) { - lineSegments.emplace_back(vertices.vertexSize(), lines.indexSize()); - } - - auto& lineSegment = lineSegments.back(); - assert(lineSegment.vertexLength <= std::numeric_limits::max()); - uint16_t lineIndex = lineSegment.vertexLength; - - vertices.emplace_back(FillProgram::layoutVertex(ring[0])); - lines.emplace_back(lineIndex + nVertices - 1, lineIndex); - - for (uint32_t i = 1; i < nVertices; i++) { - vertices.emplace_back(FillProgram::layoutVertex(ring[i])); - lines.emplace_back(lineIndex + i - 1, lineIndex + i); - } - - lineSegment.vertexLength += nVertices; - lineSegment.indexLength += nVertices * 2; - } - - std::vector indices = mapbox::earcut(polygon); - - std::size_t nIndicies = indices.size(); - assert(nIndicies % 3 == 0); - - if (triangleSegments.empty() || triangleSegments.back().vertexLength + totalVertices > std::numeric_limits::max()) { - triangleSegments.emplace_back(startVertices, triangles.indexSize()); - } - - auto& triangleSegment = triangleSegments.back(); - assert(triangleSegment.vertexLength <= std::numeric_limits::max()); - uint16_t triangleIndex = triangleSegment.vertexLength; - - for (uint32_t i = 0; i < nIndicies; i += 3) { - triangles.emplace_back(triangleIndex + indices[i], - triangleIndex + indices[i + 1], - triangleIndex + indices[i + 2]); - } - - triangleSegment.vertexLength += totalVertices; - triangleSegment.indexLength += nIndicies; - } - - for (auto& pair : paintPropertyBinders) { - pair.second.populateVertexVectors(feature, vertices.vertexSize()); - } -} - -void FillBucket::upload(gl::Context& context) { - vertexBuffer = context.createVertexBuffer(std::move(vertices)); - lineIndexBuffer = context.createIndexBuffer(std::move(lines)); - triangleIndexBuffer = context.createIndexBuffer(std::move(triangles)); - - for (auto& pair : paintPropertyBinders) { - pair.second.upload(context); - } - - uploaded = true; -} - -void FillBucket::render(Painter& painter, - PaintParameters& parameters, - const RenderLayer& layer, - const RenderTile& tile) { - painter.renderFill(parameters, *this, *layer.as(), tile); -} - -bool FillBucket::hasData() const { - return !triangleSegments.empty() || !lineSegments.empty(); -} - -float FillBucket::getQueryRadius(const RenderLayer& layer) const { - if (!layer.is()) { - return 0; - } - - const std::array& translate = layer.as()->evaluated.get(); - return util::length(translate[0], translate[1]); - -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/fill_bucket.hpp b/src/mbgl/renderer/fill_bucket.hpp deleted file mode 100644 index 421d8b332b..0000000000 --- a/src/mbgl/renderer/fill_bucket.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace mbgl { - -class BucketParameters; - -class FillBucket : public Bucket { -public: - FillBucket(const BucketParameters&, const std::vector&); - - void addFeature(const GeometryTileFeature&, - const GeometryCollection&) override; - bool hasData() const override; - - void upload(gl::Context&) override; - void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; - - float getQueryRadius(const RenderLayer&) const override; - - gl::VertexVector vertices; - gl::IndexVector lines; - gl::IndexVector triangles; - gl::SegmentVector lineSegments; - gl::SegmentVector triangleSegments; - - optional> vertexBuffer; - optional> lineIndexBuffer; - optional> triangleIndexBuffer; - - std::map paintPropertyBinders; -}; - -} // namespace mbgl diff --git a/src/mbgl/renderer/fill_extrusion_bucket.cpp b/src/mbgl/renderer/fill_extrusion_bucket.cpp deleted file mode 100644 index 2b352ab66a..0000000000 --- a/src/mbgl/renderer/fill_extrusion_bucket.cpp +++ /dev/null @@ -1,177 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -namespace mapbox { -namespace util { -template <> -struct nth<0, mbgl::GeometryCoordinate> { - static int64_t get(const mbgl::GeometryCoordinate& t) { - return t.x; - }; -}; - -template <> -struct nth<1, mbgl::GeometryCoordinate> { - static int64_t get(const mbgl::GeometryCoordinate& t) { - return t.y; - }; -}; -} // namespace util -} // namespace mapbox - -namespace mbgl { - -using namespace style; - -struct GeometryTooLongException : std::exception {}; - -FillExtrusionBucket::FillExtrusionBucket(const BucketParameters& parameters, const std::vector& layers) { - for (const auto& layer : layers) { - paintPropertyBinders.emplace(std::piecewise_construct, - std::forward_as_tuple(layer->getID()), - std::forward_as_tuple( - layer->as()->evaluated, - parameters.tileID.overscaledZ)); - } -} - -void FillExtrusionBucket::addFeature(const GeometryTileFeature& feature, - const GeometryCollection& geometry) { - for (auto& polygon : classifyRings(geometry)) { - // Optimize polygons with many interior rings for earcut tesselation. - limitHoles(polygon, 500); - - std::size_t totalVertices = 0; - - for (const auto& ring : polygon) { - totalVertices += ring.size(); - if (totalVertices > std::numeric_limits::max()) - throw GeometryTooLongException(); - } - - if (totalVertices == 0) continue; - - std::vector flatIndices; - flatIndices.reserve(totalVertices); - - std::size_t startVertices = vertices.vertexSize(); - - if (triangleSegments.empty() || - triangleSegments.back().vertexLength + (5 * (totalVertices - 1) + 1) > - std::numeric_limits::max()) { - triangleSegments.emplace_back(startVertices, triangles.indexSize()); - } - - auto& triangleSegment = triangleSegments.back(); - assert(triangleSegment.vertexLength <= std::numeric_limits::max()); - uint16_t triangleIndex = triangleSegment.vertexLength; - - assert(triangleIndex + (5 * (totalVertices - 1) + 1) <= - std::numeric_limits::max()); - - for (const auto& ring : polygon) { - std::size_t nVertices = ring.size(); - - if (nVertices == 0) - continue; - - auto edgeDistance = 0; - - for (uint32_t i = 0; i < nVertices; i++) { - const auto& p1 = ring[i]; - - vertices.emplace_back( - FillExtrusionProgram::layoutVertex(p1, 0, 0, 1, 1, edgeDistance)); - flatIndices.emplace_back(triangleIndex); - triangleIndex++; - - if (i != 0) { - const auto& p2 = ring[i - 1]; - - const auto d1 = convertPoint(p1); - const auto d2 = convertPoint(p2); - - const Point perp = util::unit(util::perp(d1 - d2)); - - vertices.emplace_back( - FillExtrusionProgram::layoutVertex(p1, perp.x, perp.y, 0, 0, edgeDistance)); - vertices.emplace_back( - FillExtrusionProgram::layoutVertex(p1, perp.x, perp.y, 0, 1, edgeDistance)); - - edgeDistance += util::dist(d1, d2); - - vertices.emplace_back( - FillExtrusionProgram::layoutVertex(p2, perp.x, perp.y, 0, 0, edgeDistance)); - vertices.emplace_back( - FillExtrusionProgram::layoutVertex(p2, perp.x, perp.y, 0, 1, edgeDistance)); - - triangles.emplace_back(triangleIndex, triangleIndex + 1, triangleIndex + 2); - triangles.emplace_back(triangleIndex + 1, triangleIndex + 2, triangleIndex + 3); - triangleIndex += 4; - triangleSegment.vertexLength += 4; - triangleSegment.indexLength += 6; - } - } - } - - std::vector indices = mapbox::earcut(polygon); - - std::size_t nIndices = indices.size(); - assert(nIndices % 3 == 0); - - for (uint32_t i = 0; i < nIndices; i += 3) { - triangles.emplace_back(flatIndices[indices[i]], flatIndices[indices[i + 1]], - flatIndices[indices[i + 2]]); - } - - triangleSegment.vertexLength += totalVertices; - triangleSegment.indexLength += nIndices; - } - - for (auto& pair : paintPropertyBinders) { - pair.second.populateVertexVectors(feature, vertices.vertexSize()); - } -} - -void FillExtrusionBucket::upload(gl::Context& context) { - vertexBuffer = context.createVertexBuffer(std::move(vertices)); - indexBuffer = context.createIndexBuffer(std::move(triangles)); - - for (auto& pair : paintPropertyBinders) { - pair.second.upload(context); - } - - uploaded = true; -} - -void FillExtrusionBucket::render(Painter& painter, - PaintParameters& parameters, - const RenderLayer& layer, - const RenderTile& tile) { - painter.renderFillExtrusion(parameters, *this, *layer.as(), tile); -} - -bool FillExtrusionBucket::hasData() const { - return !triangleSegments.empty(); -} - -float FillExtrusionBucket::getQueryRadius(const RenderLayer& layer) const { - if (!layer.is()) { - return 0; - } - - const std::array& translate = layer.as()->evaluated.get(); - return util::length(translate[0], translate[1]); -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/fill_extrusion_bucket.hpp b/src/mbgl/renderer/fill_extrusion_bucket.hpp deleted file mode 100644 index c54805d743..0000000000 --- a/src/mbgl/renderer/fill_extrusion_bucket.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -class BucketParameters; - -class FillExtrusionBucket : public Bucket { -public: - FillExtrusionBucket(const BucketParameters&, const std::vector&); - - void addFeature(const GeometryTileFeature&, - const GeometryCollection&) override; - bool hasData() const override; - - void upload(gl::Context&) override; - void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; - - float getQueryRadius(const RenderLayer&) const override; - - gl::VertexVector vertices; - gl::IndexVector triangles; - gl::SegmentVector triangleSegments; - - optional> vertexBuffer; - optional> indexBuffer; - - std::unordered_map paintPropertyBinders; -}; - -} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_background_layer.cpp b/src/mbgl/renderer/layers/render_background_layer.cpp new file mode 100644 index 0000000000..2937b115fc --- /dev/null +++ b/src/mbgl/renderer/layers/render_background_layer.cpp @@ -0,0 +1,36 @@ +#include +#include +#include + +namespace mbgl { + +RenderBackgroundLayer::RenderBackgroundLayer(Immutable _impl) + : RenderLayer(style::LayerType::Background, _impl) { +} + +const style::BackgroundLayer::Impl& RenderBackgroundLayer::impl() const { + return static_cast(*baseImpl); +} + +std::unique_ptr RenderBackgroundLayer::createBucket(const BucketParameters &, + const std::vector &) const { + assert(false); + return nullptr; +} + +void RenderBackgroundLayer::cascade(const CascadeParameters ¶meters) { + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); +} + +void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters ¶meters) { + evaluated = unevaluated.evaluate(parameters); + + passes = evaluated.get() > 0 ? RenderPass::Translucent + : RenderPass::None; +} + +bool RenderBackgroundLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_background_layer.hpp b/src/mbgl/renderer/layers/render_background_layer.hpp new file mode 100644 index 0000000000..7eabf47345 --- /dev/null +++ b/src/mbgl/renderer/layers/render_background_layer.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { + +class RenderBackgroundLayer: public RenderLayer { +public: + RenderBackgroundLayer(Immutable); + ~RenderBackgroundLayer() final = default; + + void cascade(const CascadeParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; + + // Paint properties + style::BackgroundPaintProperties::Unevaluated unevaluated; + style::BackgroundPaintProperties::Evaluated evaluated; + + const style::BackgroundLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is() const { + return type == style::LayerType::Background; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_circle_layer.cpp b/src/mbgl/renderer/layers/render_circle_layer.cpp new file mode 100644 index 0000000000..a9c451d28c --- /dev/null +++ b/src/mbgl/renderer/layers/render_circle_layer.cpp @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +RenderCircleLayer::RenderCircleLayer(Immutable _impl) + : RenderLayer(style::LayerType::Circle, _impl) { +} + +const style::CircleLayer::Impl& RenderCircleLayer::impl() const { + return static_cast(*baseImpl); +} + +std::unique_ptr RenderCircleLayer::createBucket(const BucketParameters& parameters, const std::vector& layers) const { + return std::make_unique(parameters, layers); +} + +void RenderCircleLayer::cascade(const CascadeParameters& parameters) { + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); +} + +void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters) { + evaluated = unevaluated.evaluate(parameters); + + passes = ((evaluated.get().constantOr(1) > 0 || + evaluated.get().constantOr(1) > 0) + && (evaluated.get().constantOr(Color::black()).a > 0 || + evaluated.get().constantOr(Color::black()).a > 0) + && (evaluated.get().constantOr(1) > 0 || + evaluated.get().constantOr(1) > 0)) + ? RenderPass::Translucent : RenderPass::None; +} + +bool RenderCircleLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +bool RenderCircleLayer::queryIntersectsFeature( + const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, + const float zoom, + const float bearing, + const float pixelsToTileUnits) const { + + // Translate query geometry + auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + queryGeometry, + evaluated.get(), + evaluated.get(), + bearing, + pixelsToTileUnits); + + // Evaluate function + auto circleRadius = evaluated.get() + .evaluate(feature, zoom, style::CircleRadius::defaultValue()) + * pixelsToTileUnits; + + // Test intersection + return util::polygonIntersectsBufferedMultiPoint(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries(), circleRadius); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_circle_layer.hpp b/src/mbgl/renderer/layers/render_circle_layer.hpp new file mode 100644 index 0000000000..2b517912c9 --- /dev/null +++ b/src/mbgl/renderer/layers/render_circle_layer.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { + +class RenderCircleLayer: public RenderLayer { +public: + RenderCircleLayer(Immutable); + ~RenderCircleLayer() final = default; + + void cascade(const CascadeParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + bool queryIntersectsFeature( + const GeometryCoordinates&, + const GeometryTileFeature&, + const float, + const float, + const float) const override; + + std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; + + // Paint properties + style::CirclePaintProperties::Unevaluated unevaluated; + style::CirclePaintProperties::Evaluated evaluated; + + const style::CircleLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is() const { + return type == style::LayerType::Circle; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_custom_layer.cpp b/src/mbgl/renderer/layers/render_custom_layer.cpp new file mode 100644 index 0000000000..add3d0d5ad --- /dev/null +++ b/src/mbgl/renderer/layers/render_custom_layer.cpp @@ -0,0 +1,28 @@ +#include +#include +#include + +namespace mbgl { + +RenderCustomLayer::RenderCustomLayer(Immutable _impl) + : RenderLayer(style::LayerType::Custom, _impl) { +} + +const style::CustomLayer::Impl& RenderCustomLayer::impl() const { + return static_cast(*baseImpl); +} + +void RenderCustomLayer::evaluate(const PropertyEvaluationParameters&) { + passes = RenderPass::Translucent; +} + +bool RenderCustomLayer::hasTransition() const { + return false; +} + +std::unique_ptr RenderCustomLayer::createBucket(const BucketParameters&, const std::vector&) const { + assert(false); + return nullptr; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_custom_layer.hpp b/src/mbgl/renderer/layers/render_custom_layer.hpp new file mode 100644 index 0000000000..d448433092 --- /dev/null +++ b/src/mbgl/renderer/layers/render_custom_layer.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +namespace mbgl { + +class RenderCustomLayer: public RenderLayer { +public: + RenderCustomLayer(Immutable); + ~RenderCustomLayer() final = default; + + void cascade(const CascadeParameters&) final {} + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const final; + + const style::CustomLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is() const { + return type == style::LayerType::Custom; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp new file mode 100644 index 0000000000..2acdaecbc3 --- /dev/null +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp @@ -0,0 +1,54 @@ +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +RenderFillExtrusionLayer::RenderFillExtrusionLayer(Immutable _impl) + : RenderLayer(style::LayerType::FillExtrusion, _impl) { +} + +const style::FillExtrusionLayer::Impl& RenderFillExtrusionLayer::impl() const { + return static_cast(*baseImpl); +} + +std::unique_ptr RenderFillExtrusionLayer::createBucket(const BucketParameters& parameters, const std::vector& layers) const { + return std::make_unique(parameters, layers); +} + +void RenderFillExtrusionLayer::cascade(const CascadeParameters& parameters) { + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); +} + +void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) { + evaluated = unevaluated.evaluate(parameters); + + passes = (evaluated.get() > 0) ? RenderPass::Translucent + : RenderPass::None; +} + +bool RenderFillExtrusionLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +bool RenderFillExtrusionLayer::queryIntersectsFeature( + const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, + const float, + const float bearing, + const float pixelsToTileUnits) const { + + auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + queryGeometry, + evaluated.get(), + evaluated.get(), + bearing, + pixelsToTileUnits); + + return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries()); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp new file mode 100644 index 0000000000..f6166495c6 --- /dev/null +++ b/src/mbgl/renderer/layers/render_fill_extrusion_layer.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { + +class RenderFillExtrusionLayer: public RenderLayer { +public: + RenderFillExtrusionLayer(Immutable); + ~RenderFillExtrusionLayer() final = default; + + void cascade(const CascadeParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + bool queryIntersectsFeature( + const GeometryCoordinates&, + const GeometryTileFeature&, + const float, + const float, + const float) const override; + + std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; + + // Paint properties + style::FillExtrusionPaintProperties::Unevaluated unevaluated; + style::FillExtrusionPaintProperties::Evaluated evaluated; + + const style::FillExtrusionLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is() const { + return type == style::LayerType::FillExtrusion; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_layer.cpp b/src/mbgl/renderer/layers/render_fill_layer.cpp new file mode 100644 index 0000000000..89fb9a364f --- /dev/null +++ b/src/mbgl/renderer/layers/render_fill_layer.cpp @@ -0,0 +1,70 @@ +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +RenderFillLayer::RenderFillLayer(Immutable _impl) + : RenderLayer(style::LayerType::Fill, _impl) { +} + +const style::FillLayer::Impl& RenderFillLayer::impl() const { + return static_cast(*baseImpl); +} + +std::unique_ptr RenderFillLayer::createBucket(const BucketParameters& parameters, const std::vector& layers) const { + return std::make_unique(parameters, layers); +} + +void RenderFillLayer::cascade(const CascadeParameters& parameters) { + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); +} + +void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { + evaluated = unevaluated.evaluate(parameters); + + if (unevaluated.get().isUndefined()) { + evaluated.get() = evaluated.get(); + } + + passes = RenderPass::None; + + if (evaluated.get()) { + passes |= RenderPass::Translucent; + } + + if (!unevaluated.get().isUndefined() + || evaluated.get().constantOr(Color()).a < 1.0f + || evaluated.get().constantOr(0) < 1.0f) { + passes |= RenderPass::Translucent; + } else { + passes |= RenderPass::Opaque; + } +} + +bool RenderFillLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +bool RenderFillLayer::queryIntersectsFeature( + const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, + const float, + const float bearing, + const float pixelsToTileUnits) const { + + auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + queryGeometry, + evaluated.get(), + evaluated.get(), + bearing, + pixelsToTileUnits); + + return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries()); +} + + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_fill_layer.hpp b/src/mbgl/renderer/layers/render_fill_layer.hpp new file mode 100644 index 0000000000..d26ca10b44 --- /dev/null +++ b/src/mbgl/renderer/layers/render_fill_layer.hpp @@ -0,0 +1,39 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { + +class RenderFillLayer: public RenderLayer { +public: + RenderFillLayer(Immutable); + ~RenderFillLayer() final = default; + + void cascade(const CascadeParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + bool queryIntersectsFeature( + const GeometryCoordinates&, + const GeometryTileFeature&, + const float, + const float, + const float) const override; + + std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; + + // Paint properties + style::FillPaintProperties::Unevaluated unevaluated; + style::FillPaintProperties::Evaluated evaluated; + + const style::FillLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is() const { + return type == style::LayerType::Fill; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_line_layer.cpp b/src/mbgl/renderer/layers/render_line_layer.cpp new file mode 100644 index 0000000000..f54f4d9174 --- /dev/null +++ b/src/mbgl/renderer/layers/render_line_layer.cpp @@ -0,0 +1,116 @@ +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +RenderLineLayer::RenderLineLayer(Immutable _impl) + : RenderLayer(style::LayerType::Line, _impl) { +} + +const style::LineLayer::Impl& RenderLineLayer::impl() const { + return static_cast(*baseImpl); +} + +std::unique_ptr RenderLineLayer::createBucket(const BucketParameters& parameters, const std::vector& layers) const { + return std::make_unique(parameters, layers, impl().layout); +} + +void RenderLineLayer::cascade(const CascadeParameters& parameters) { + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); +} + +void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) { + // for scaling dasharrays + auto dashArrayParams = parameters; + dashArrayParams.z = std::floor(dashArrayParams.z); + dashLineWidth = unevaluated.evaluate(dashArrayParams); + + evaluated = unevaluated.evaluate(parameters); + + passes = (evaluated.get().constantOr(1.0) > 0 + && evaluated.get().constantOr(Color::black()).a > 0 + && evaluated.get() > 0) + ? RenderPass::Translucent : RenderPass::None; +} + +bool RenderLineLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +optional offsetLine(const GeometryCollection& rings, const double offset) { + if (offset == 0) return {}; + + GeometryCollection newRings; + Point zero(0, 0); + for (const auto& ring : rings) { + newRings.emplace_back(); + auto& newRing = newRings.back(); + + for (auto i = ring.begin(); i != ring.end(); i++) { + auto& p = *i; + + Point aToB = i == ring.begin() ? + zero : + util::perp(util::unit(convertPoint(p - *(i - 1)))); + Point bToC = i + 1 == ring.end() ? + zero : + util::perp(util::unit(convertPoint(*(i + 1) - p))); + Point extrude = util::unit(aToB + bToC); + + const double cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y; + extrude *= (1.0 / cosHalfAngle); + + newRing.push_back(convertPoint(extrude * offset) + p); + } + } + + return newRings; +} + +bool RenderLineLayer::queryIntersectsFeature( + const GeometryCoordinates& queryGeometry, + const GeometryTileFeature& feature, + const float zoom, + const float bearing, + const float pixelsToTileUnits) const { + + // Translate query geometry + auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( + queryGeometry, + evaluated.get(), + evaluated.get(), + bearing, + pixelsToTileUnits); + + // Evaluate function + auto offset = evaluated.get() + .evaluate(feature, zoom, style::LineOffset::defaultValue()) * pixelsToTileUnits; + + // Apply offset to geometry + auto offsetGeometry = offsetLine(feature.getGeometries(), offset); + + // Test intersection + const float halfWidth = getLineWidth(feature, zoom) / 2.0 * pixelsToTileUnits; + return util::polygonIntersectsBufferedMultiLine( + translatedQueryGeometry.value_or(queryGeometry), + offsetGeometry.value_or(feature.getGeometries()), + halfWidth); +} + +float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, const float zoom) const { + float lineWidth = evaluated.get(); + float gapWidth = evaluated.get() + .evaluate(feature, zoom, style::LineGapWidth::defaultValue()); + if (gapWidth) { + return gapWidth + 2 * lineWidth; + } else { + return lineWidth; + } +} + + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_line_layer.hpp b/src/mbgl/renderer/layers/render_line_layer.hpp new file mode 100644 index 0000000000..0276e6a6d9 --- /dev/null +++ b/src/mbgl/renderer/layers/render_line_layer.hpp @@ -0,0 +1,45 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { + +class RenderLineLayer: public RenderLayer { +public: + RenderLineLayer(Immutable); + ~RenderLineLayer() final = default; + + void cascade(const CascadeParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + bool queryIntersectsFeature( + const GeometryCoordinates&, + const GeometryTileFeature&, + const float, + const float, + const float) const override; + + std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; + + // Paint properties + style::LinePaintProperties::Unevaluated unevaluated; + style::LinePaintProperties::Evaluated evaluated; + + const style::LineLayer::Impl& impl() const; + + // Special case + float dashLineWidth = 1; + +private: + float getLineWidth(const GeometryTileFeature&, const float) const; +}; + +template <> +inline bool RenderLayer::is() const { + return type == style::LayerType::Line; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp new file mode 100644 index 0000000000..739f1d83ff --- /dev/null +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -0,0 +1,34 @@ +#include +#include +#include + +namespace mbgl { + +RenderRasterLayer::RenderRasterLayer(Immutable _impl) + : RenderLayer(style::LayerType::Raster, _impl) { +} + +const style::RasterLayer::Impl& RenderRasterLayer::impl() const { + return static_cast(*baseImpl); +} + +std::unique_ptr RenderRasterLayer::createBucket(const BucketParameters&, const std::vector&) const { + assert(false); + return nullptr; +} + +void RenderRasterLayer::cascade(const CascadeParameters& parameters) { + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); +} + +void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) { + evaluated = unevaluated.evaluate(parameters); + + passes = evaluated.get() > 0 ? RenderPass::Translucent : RenderPass::None; +} + +bool RenderRasterLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_raster_layer.hpp b/src/mbgl/renderer/layers/render_raster_layer.hpp new file mode 100644 index 0000000000..50c213aa26 --- /dev/null +++ b/src/mbgl/renderer/layers/render_raster_layer.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include +#include + +namespace mbgl { + +class RenderRasterLayer: public RenderLayer { +public: + RenderRasterLayer(Immutable); + ~RenderRasterLayer() final = default; + + void cascade(const CascadeParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; + + // Paint properties + style::RasterPaintProperties::Unevaluated unevaluated; + style::RasterPaintProperties::Evaluated evaluated; + + const style::RasterLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is() const { + return type == style::LayerType::Raster; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_symbol_layer.cpp b/src/mbgl/renderer/layers/render_symbol_layer.cpp new file mode 100644 index 0000000000..2d34054675 --- /dev/null +++ b/src/mbgl/renderer/layers/render_symbol_layer.cpp @@ -0,0 +1,112 @@ +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +RenderSymbolLayer::RenderSymbolLayer(Immutable _impl) + : RenderLayer(style::LayerType::Symbol, _impl) { +} + +const style::SymbolLayer::Impl& RenderSymbolLayer::impl() const { + return static_cast(*baseImpl); +} + +std::unique_ptr RenderSymbolLayer::createBucket(const BucketParameters&, const std::vector&) const { + assert(false); // Should be calling createLayout() instead. + return nullptr; +} + +std::unique_ptr RenderSymbolLayer::createLayout(const BucketParameters& parameters, + const std::vector& group, + const GeometryTileLayer& layer, + GlyphDependencies& glyphDependencies, + IconDependencies& iconDependencies) const { + return std::make_unique(parameters, + group, + layer, + iconDependencies, + glyphDependencies); +} + +void RenderSymbolLayer::cascade(const CascadeParameters& parameters) { + unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); +} + +void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) { + evaluated = unevaluated.evaluate(parameters); + + auto hasIconOpacity = evaluated.get().constantOr(Color::black()).a > 0 || + evaluated.get().constantOr(Color::black()).a > 0; + auto hasTextOpacity = evaluated.get().constantOr(Color::black()).a > 0 || + evaluated.get().constantOr(Color::black()).a > 0; + + passes = ((evaluated.get().constantOr(1) > 0 && hasIconOpacity && iconSize > 0) + || (evaluated.get().constantOr(1) > 0 && hasTextOpacity && textSize > 0)) + ? RenderPass::Translucent : RenderPass::None; +} + +bool RenderSymbolLayer::hasTransition() const { + return unevaluated.hasTransition(); +} + +style::IconPaintProperties::Evaluated RenderSymbolLayer::iconPaintProperties() const { + return style::IconPaintProperties::Evaluated { + evaluated.get(), + evaluated.get(), + evaluated.get(), + evaluated.get(), + evaluated.get(), + evaluated.get(), + evaluated.get() + }; +} + +style::TextPaintProperties::Evaluated RenderSymbolLayer::textPaintProperties() const { + return style::TextPaintProperties::Evaluated { + evaluated.get(), + evaluated.get(), + evaluated.get(), + evaluated.get(), + evaluated.get(), + evaluated.get(), + evaluated.get() + }; +} + + +style::SymbolPropertyValues RenderSymbolLayer::iconPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated& layout_) const { + return style::SymbolPropertyValues { + layout_.get(), // icon-pitch-alignment is not yet implemented; inherit the rotation alignment + layout_.get(), + layout_.get(), + evaluated.get(), + evaluated.get(), + iconSize, + 1.0f, + evaluated.get().constantOr(Color::black()).a > 0 && + evaluated.get().constantOr(1), + evaluated.get().constantOr(Color::black()).a > 0 + }; +} + +style::SymbolPropertyValues RenderSymbolLayer::textPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated& layout_) const { + return style::SymbolPropertyValues { + layout_.get(), + layout_.get(), + layout_.get(), + evaluated.get(), + evaluated.get(), + textSize, + 24.0f, + evaluated.get().constantOr(Color::black()).a > 0 && + evaluated.get().constantOr(1), + evaluated.get().constantOr(Color::black()).a > 0 + }; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_symbol_layer.hpp b/src/mbgl/renderer/layers/render_symbol_layer.hpp new file mode 100644 index 0000000000..ba1b047663 --- /dev/null +++ b/src/mbgl/renderer/layers/render_symbol_layer.hpp @@ -0,0 +1,96 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace mbgl { + +namespace style { + +// {icon,text}-specific paint-property packs for use in the symbol Programs. +// Since each program deals either with icons or text, using a smaller property set +// lets us avoid unnecessarily binding attributes for properties the program wouldn't use. +class IconPaintProperties : public PaintProperties< + IconOpacity, + IconColor, + IconHaloColor, + IconHaloWidth, + IconHaloBlur, + IconTranslate, + IconTranslateAnchor +> {}; + +class TextPaintProperties : public PaintProperties< + TextOpacity, + TextColor, + TextHaloColor, + TextHaloWidth, + TextHaloBlur, + TextTranslate, + TextTranslateAnchor +> {}; + +// Repackaging evaluated values from SymbolLayoutProperties + SymbolPaintProperties +// for genericity over icons vs. text. +class SymbolPropertyValues { +public: + // Layout + AlignmentType pitchAlignment; + AlignmentType rotationAlignment; + PossiblyEvaluatedPropertyValue layoutSize; + + // Paint + std::array translate; + TranslateAnchorType translateAnchor; + float paintSize; + + float sdfScale; // Constant (1.0 or 24.0) + + bool hasHalo; + bool hasFill; +}; + +} // namespace style + +class BucketParameters; +class SymbolLayout; +class GeometryTileLayer; + +class RenderSymbolLayer: public RenderLayer { +public: + RenderSymbolLayer(Immutable); + ~RenderSymbolLayer() final = default; + + void cascade(const CascadeParameters&) override; + void evaluate(const PropertyEvaluationParameters&) override; + bool hasTransition() const override; + + style::IconPaintProperties::Evaluated iconPaintProperties() const; + style::TextPaintProperties::Evaluated textPaintProperties() const; + + style::SymbolPropertyValues iconPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated&) const; + style::SymbolPropertyValues textPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated&) const; + + std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; + std::unique_ptr createLayout(const BucketParameters&, const std::vector&, + const GeometryTileLayer&, GlyphDependencies&, IconDependencies&) const; + + // Paint properties + style::SymbolPaintProperties::Unevaluated unevaluated; + style::SymbolPaintProperties::Evaluated evaluated; + + float iconSize = 1.0f; + float textSize = 16.0f; + + const style::SymbolLayer::Impl& impl() const; +}; + +template <> +inline bool RenderLayer::is() const { + return type == style::LayerType::Symbol; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/line_bucket.cpp b/src/mbgl/renderer/line_bucket.cpp deleted file mode 100644 index f322ba4614..0000000000 --- a/src/mbgl/renderer/line_bucket.cpp +++ /dev/null @@ -1,506 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace mbgl { - -using namespace style; - -LineBucket::LineBucket(const BucketParameters& parameters, - const std::vector& layers, - const style::LineLayoutProperties& layout_) - : layout(layout_.evaluate(PropertyEvaluationParameters(parameters.tileID.overscaledZ))), - overscaling(parameters.tileID.overscaleFactor()) { - for (const auto& layer : layers) { - paintPropertyBinders.emplace( - std::piecewise_construct, - std::forward_as_tuple(layer->getID()), - std::forward_as_tuple( - layer->as()->evaluated, - parameters.tileID.overscaledZ)); - } -} - -void LineBucket::addFeature(const GeometryTileFeature& feature, - const GeometryCollection& geometryCollection) { - for (auto& line : geometryCollection) { - addGeometry(line, feature.getType()); - } - - for (auto& pair : paintPropertyBinders) { - pair.second.populateVertexVectors(feature, vertices.vertexSize()); - } -} - -/* - * Sharp corners cause dashed lines to tilt because the distance along the line - * is the same at both the inner and outer corners. To improve the appearance of - * dashed lines we add extra points near sharp corners so that a smaller part - * of the line is tilted. - * - * COS_HALF_SHARP_CORNER controls how sharp a corner has to be for us to add an - * extra vertex. The default is 75 degrees. - * - * The newly created vertices are placed SHARP_CORNER_OFFSET pixels from the corner. - */ -const float COS_HALF_SHARP_CORNER = std::cos(75.0 / 2.0 * (M_PI / 180.0)); -const float SHARP_CORNER_OFFSET = 15.0f; - -// The number of bits that is used to store the line distance in the buffer. -const int LINE_DISTANCE_BUFFER_BITS = 14; - -// We don't have enough bits for the line distance as we'd like to have, so -// use this value to scale the line distance (in tile units) down to a smaller -// value. This lets us store longer distances while sacrificing precision. -const float LINE_DISTANCE_SCALE = 1.0 / 2.0; - -// The maximum line distance, in tile units, that fits in the buffer. -const float MAX_LINE_DISTANCE = std::pow(2, LINE_DISTANCE_BUFFER_BITS) / LINE_DISTANCE_SCALE; - -void LineBucket::addGeometry(const GeometryCoordinates& coordinates, FeatureType type) { - const std::size_t len = [&coordinates] { - std::size_t l = coordinates.size(); - // If the line has duplicate vertices at the end, adjust length to remove them. - while (l >= 2 && coordinates[l - 1] == coordinates[l - 2]) { - l--; - } - return l; - }(); - - const std::size_t first = [&coordinates, &len] { - std::size_t i = 0; - // If the line has duplicate vertices at the start, adjust index to remove them. - while (i < len - 1 && coordinates[i] == coordinates[i + 1]) { - i++; - } - return i; - }(); - - // Ignore invalid geometry. - if (len < (type == FeatureType::Polygon ? 3 : 2)) { - return; - } - - const float miterLimit = layout.get() == LineJoinType::Bevel ? 1.05f : float(layout.get()); - - const double sharpCornerOffset = SHARP_CORNER_OFFSET * (float(util::EXTENT) / (util::tileSize * overscaling)); - - const GeometryCoordinate firstCoordinate = coordinates[first]; - const LineCapType beginCap = layout.get(); - const LineCapType endCap = type == FeatureType::Polygon ? LineCapType::Butt : LineCapType(layout.get()); - - double distance = 0; - bool startOfLine = true; - optional currentCoordinate; - optional prevCoordinate; - optional nextCoordinate; - optional> prevNormal; - optional> nextNormal; - - // the last three vertices added - e1 = e2 = e3 = -1; - - if (type == FeatureType::Polygon) { - currentCoordinate = coordinates[len - 2]; - nextNormal = util::perp(util::unit(convertPoint(firstCoordinate - *currentCoordinate))); - } - - const std::size_t startVertex = vertices.vertexSize(); - std::vector triangleStore; - - for (std::size_t i = first; i < len; ++i) { - if (type == FeatureType::Polygon && i == len - 1) { - // if the line is closed, we treat the last vertex like the first - nextCoordinate = coordinates[first + 1]; - } else if (i + 1 < len) { - // just the next vertex - nextCoordinate = coordinates[i + 1]; - } else { - // there is no next vertex - nextCoordinate = {}; - } - - // if two consecutive vertices exist, skip the current one - if (nextCoordinate && coordinates[i] == *nextCoordinate) { - continue; - } - - if (nextNormal) { - prevNormal = *nextNormal; - } - if (currentCoordinate) { - prevCoordinate = *currentCoordinate; - } - - currentCoordinate = coordinates[i]; - - // Calculate the normal towards the next vertex in this line. In case - // there is no next vertex, pretend that the line is continuing straight, - // meaning that we are just using the previous normal. - nextNormal = nextCoordinate ? util::perp(util::unit(convertPoint(*nextCoordinate - *currentCoordinate))) - : prevNormal; - - // If we still don't have a previous normal, this is the beginning of a - // non-closed line, so we're doing a straight "join". - if (!prevNormal) { - prevNormal = *nextNormal; - } - - // Determine the normal of the join extrusion. It is the angle bisector - // of the segments between the previous line and the next line. - // In the case of 180° angles, the prev and next normals cancel each other out: - // prevNormal + nextNormal = (0, 0), its magnitude is 0, so the unit vector would be - // undefined. In that case, we're keeping the joinNormal at (0, 0), so that the cosHalfAngle - // below will also become 0 and miterLength will become Infinity. - Point joinNormal = *prevNormal + *nextNormal; - if (joinNormal.x != 0 || joinNormal.y != 0) { - joinNormal = util::unit(joinNormal); - } - - /* joinNormal prevNormal - * ↖ ↑ - * .________. prevVertex - * | - * nextNormal ← | currentVertex - * | - * nextVertex ! - * - */ - - // Calculate the length of the miter (the ratio of the miter to the width). - // Find the cosine of the angle between the next and join normals - // using dot product. The inverse of that is the miter length. - const double cosHalfAngle = joinNormal.x * nextNormal->x + joinNormal.y * nextNormal->y; - const double miterLength = - cosHalfAngle != 0 ? 1 / cosHalfAngle : std::numeric_limits::infinity(); - - const bool isSharpCorner = cosHalfAngle < COS_HALF_SHARP_CORNER && prevCoordinate && nextCoordinate; - - if (isSharpCorner && i > first) { - const auto prevSegmentLength = util::dist(*currentCoordinate, *prevCoordinate); - if (prevSegmentLength > 2.0 * sharpCornerOffset) { - GeometryCoordinate newPrevVertex = *currentCoordinate - convertPoint(util::round(convertPoint(*currentCoordinate - *prevCoordinate) * (sharpCornerOffset / prevSegmentLength))); - distance += util::dist(newPrevVertex, *prevCoordinate); - addCurrentVertex(newPrevVertex, distance, *prevNormal, 0, 0, false, startVertex, triangleStore); - prevCoordinate = newPrevVertex; - } - } - - // The join if a middle vertex, otherwise the cap - const bool middleVertex = prevCoordinate && nextCoordinate; - LineJoinType currentJoin = layout.get(); - const LineCapType currentCap = nextCoordinate ? beginCap : endCap; - - if (middleVertex) { - if (currentJoin == LineJoinType::Round) { - if (miterLength < layout.get()) { - currentJoin = LineJoinType::Miter; - } else if (miterLength <= 2) { - currentJoin = LineJoinType::FakeRound; - } - } - - if (currentJoin == LineJoinType::Miter && miterLength > miterLimit) { - currentJoin = LineJoinType::Bevel; - } - - if (currentJoin == LineJoinType::Bevel) { - // The maximum extrude length is 128 / 63 = 2 times the width of the line - // so if miterLength >= 2 we need to draw a different type of bevel here. - if (miterLength > 2) { - currentJoin = LineJoinType::FlipBevel; - } - - // If the miterLength is really small and the line bevel wouldn't be visible, - // just draw a miter join to save a triangle. - if (miterLength < miterLimit) { - currentJoin = LineJoinType::Miter; - } - } - } - - // Calculate how far along the line the currentVertex is - if (prevCoordinate) - distance += util::dist(*currentCoordinate, *prevCoordinate); - - if (middleVertex && currentJoin == LineJoinType::Miter) { - joinNormal = joinNormal * miterLength; - addCurrentVertex(*currentCoordinate, distance, joinNormal, 0, 0, false, startVertex, - triangleStore); - - } else if (middleVertex && currentJoin == LineJoinType::FlipBevel) { - // miter is too big, flip the direction to make a beveled join - - if (miterLength > 100) { - // Almost parallel lines - joinNormal = *nextNormal * -1.0; - } else { - const double direction = prevNormal->x * nextNormal->y - prevNormal->y * nextNormal->x > 0 ? -1 : 1; - const double bevelLength = miterLength * util::mag(*prevNormal + *nextNormal) / - util::mag(*prevNormal - *nextNormal); - joinNormal = util::perp(joinNormal) * bevelLength * direction; - } - - addCurrentVertex(*currentCoordinate, distance, joinNormal, 0, 0, false, startVertex, - triangleStore); - - addCurrentVertex(*currentCoordinate, distance, joinNormal * -1.0, 0, 0, false, startVertex, - triangleStore); - } else if (middleVertex && (currentJoin == LineJoinType::Bevel || currentJoin == LineJoinType::FakeRound)) { - const bool lineTurnsLeft = (prevNormal->x * nextNormal->y - prevNormal->y * nextNormal->x) > 0; - const float offset = -std::sqrt(miterLength * miterLength - 1); - float offsetA; - float offsetB; - - if (lineTurnsLeft) { - offsetB = 0; - offsetA = offset; - } else { - offsetA = 0; - offsetB = offset; - } - - // Close previous segement with bevel - if (!startOfLine) { - addCurrentVertex(*currentCoordinate, distance, *prevNormal, offsetA, offsetB, false, - startVertex, triangleStore); - } - - if (currentJoin == LineJoinType::FakeRound) { - // The join angle is sharp enough that a round join would be visible. - // Bevel joins fill the gap between segments with a single pie slice triangle. - // Create a round join by adding multiple pie slices. The join isn't actually round, but - // it looks like it is at the sizes we render lines at. - - // Add more triangles for sharper angles. - // This math is just a good enough approximation. It isn't "correct". - const int n = std::floor((0.5 - (cosHalfAngle - 0.5)) * 8); - - for (int m = 0; m < n; m++) { - auto approxFractionalJoinNormal = util::unit(*nextNormal * ((m + 1.0) / (n + 1.0)) + *prevNormal); - addPieSliceVertex(*currentCoordinate, distance, approxFractionalJoinNormal, lineTurnsLeft, startVertex, triangleStore); - } - - addPieSliceVertex(*currentCoordinate, distance, joinNormal, lineTurnsLeft, startVertex, triangleStore); - - for (int k = n - 1; k >= 0; k--) { - auto approxFractionalJoinNormal = util::unit(*prevNormal * ((k + 1.0) / (n + 1.0)) + *nextNormal); - addPieSliceVertex(*currentCoordinate, distance, approxFractionalJoinNormal, lineTurnsLeft, startVertex, triangleStore); - } - } - - // Start next segment - if (nextCoordinate) { - addCurrentVertex(*currentCoordinate, distance, *nextNormal, -offsetA, -offsetB, - false, startVertex, triangleStore); - } - - } else if (!middleVertex && currentCap == LineCapType::Butt) { - if (!startOfLine) { - // Close previous segment with a butt - addCurrentVertex(*currentCoordinate, distance, *prevNormal, 0, 0, false, - startVertex, triangleStore); - } - - // Start next segment with a butt - if (nextCoordinate) { - addCurrentVertex(*currentCoordinate, distance, *nextNormal, 0, 0, false, - startVertex, triangleStore); - } - - } else if (!middleVertex && currentCap == LineCapType::Square) { - if (!startOfLine) { - // Close previous segment with a square cap - addCurrentVertex(*currentCoordinate, distance, *prevNormal, 1, 1, false, - startVertex, triangleStore); - - // The segment is done. Unset vertices to disconnect segments. - e1 = e2 = -1; - } - - // Start next segment - if (nextCoordinate) { - addCurrentVertex(*currentCoordinate, distance, *nextNormal, -1, -1, false, - startVertex, triangleStore); - } - - } else if (middleVertex ? currentJoin == LineJoinType::Round : currentCap == LineCapType::Round) { - if (!startOfLine) { - // Close previous segment with a butt - addCurrentVertex(*currentCoordinate, distance, *prevNormal, 0, 0, false, - startVertex, triangleStore); - - // Add round cap or linejoin at end of segment - addCurrentVertex(*currentCoordinate, distance, *prevNormal, 1, 1, true, startVertex, - triangleStore); - - // The segment is done. Unset vertices to disconnect segments. - e1 = e2 = -1; - } - - // Start next segment with a butt - if (nextCoordinate) { - // Add round cap before first segment - addCurrentVertex(*currentCoordinate, distance, *nextNormal, -1, -1, true, - startVertex, triangleStore); - - addCurrentVertex(*currentCoordinate, distance, *nextNormal, 0, 0, false, - startVertex, triangleStore); - } - } - - if (isSharpCorner && i < len - 1) { - const auto nextSegmentLength = util::dist(*currentCoordinate, *nextCoordinate); - if (nextSegmentLength > 2 * sharpCornerOffset) { - GeometryCoordinate newCurrentVertex = *currentCoordinate + convertPoint(util::round(convertPoint(*nextCoordinate - *currentCoordinate) * (sharpCornerOffset / nextSegmentLength))); - distance += util::dist(newCurrentVertex, *currentCoordinate); - addCurrentVertex(newCurrentVertex, distance, *nextNormal, 0, 0, false, startVertex, triangleStore); - currentCoordinate = newCurrentVertex; - } - } - - startOfLine = false; - } - - const std::size_t endVertex = vertices.vertexSize(); - const std::size_t vertexCount = endVertex - startVertex; - - if (segments.empty() || segments.back().vertexLength + vertexCount > std::numeric_limits::max()) { - segments.emplace_back(startVertex, triangles.indexSize()); - } - - auto& segment = segments.back(); - assert(segment.vertexLength <= std::numeric_limits::max()); - uint16_t index = segment.vertexLength; - - for (const auto& triangle : triangleStore) { - triangles.emplace_back(index + triangle.a, index + triangle.b, index + triangle.c); - } - - segment.vertexLength += vertexCount; - segment.indexLength += triangleStore.size() * 3; -} - -void LineBucket::addCurrentVertex(const GeometryCoordinate& currentCoordinate, - double &distance, - const Point& normal, - double endLeft, - double endRight, - bool round, - std::size_t startVertex, - std::vector& triangleStore) { - Point extrude = normal; - if (endLeft) - extrude = extrude - (util::perp(normal) * endLeft); - vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, { round, false }, endLeft, distance * LINE_DISTANCE_SCALE)); - e3 = vertices.vertexSize() - 1 - startVertex; - if (e1 >= 0 && e2 >= 0) { - triangleStore.emplace_back(e1, e2, e3); - } - e1 = e2; - e2 = e3; - - extrude = normal * -1.0; - if (endRight) - extrude = extrude - (util::perp(normal) * endRight); - vertices.emplace_back(LineProgram::layoutVertex(currentCoordinate, extrude, { round, true }, -endRight, distance * LINE_DISTANCE_SCALE)); - e3 = vertices.vertexSize() - 1 - startVertex; - if (e1 >= 0 && e2 >= 0) { - triangleStore.emplace_back(e1, e2, e3); - } - e1 = e2; - e2 = e3; - - // There is a maximum "distance along the line" that we can store in the buffers. - // When we get close to the distance, reset it to zero and add the vertex again with - // a distance of zero. The max distance is determined by the number of bits we allocate - // to `linesofar`. - if (distance > MAX_LINE_DISTANCE / 2.0f) { - distance = 0; - addCurrentVertex(currentCoordinate, distance, normal, endLeft, endRight, round, startVertex, triangleStore); - } -} - -void LineBucket::addPieSliceVertex(const GeometryCoordinate& currentVertex, - double distance, - const Point& extrude, - bool lineTurnsLeft, - std::size_t startVertex, - std::vector& triangleStore) { - Point flippedExtrude = extrude * (lineTurnsLeft ? -1.0 : 1.0); - vertices.emplace_back(LineProgram::layoutVertex(currentVertex, flippedExtrude, { false, lineTurnsLeft }, 0, distance * LINE_DISTANCE_SCALE)); - e3 = vertices.vertexSize() - 1 - startVertex; - if (e1 >= 0 && e2 >= 0) { - triangleStore.emplace_back(e1, e2, e3); - } - - if (lineTurnsLeft) { - e2 = e3; - } else { - e1 = e3; - } -} - -void LineBucket::upload(gl::Context& context) { - vertexBuffer = context.createVertexBuffer(std::move(vertices)); - indexBuffer = context.createIndexBuffer(std::move(triangles)); - - for (auto& pair : paintPropertyBinders) { - pair.second.upload(context); - } - - uploaded = true; -} - -void LineBucket::render(Painter& painter, - PaintParameters& parameters, - const RenderLayer& layer, - const RenderTile& tile) { - painter.renderLine(parameters, *this, *layer.as(), tile); -} - -bool LineBucket::hasData() const { - return !segments.empty(); -} - -template -static float get(const RenderLineLayer& layer, const std::map& paintPropertyBinders) { - auto it = paintPropertyBinders.find(layer.getID()); - if (it == paintPropertyBinders.end() || !it->second.statistics().max()) { - return layer.evaluated.get().constantOr(Property::defaultValue()); - } else { - return *it->second.statistics().max(); - } -} - -float LineBucket::getLineWidth(const RenderLineLayer& layer) const { - float lineWidth = layer.evaluated.get(); - float gapWidth = get(layer, paintPropertyBinders); - - if (gapWidth) { - return gapWidth + 2 * lineWidth; - } else { - return lineWidth; - } -} - -float LineBucket::getQueryRadius(const RenderLayer& layer) const { - if (!layer.is()) { - return 0; - } - - auto lineLayer = layer.as(); - - const std::array& translate = lineLayer->evaluated.get(); - float offset = get(*lineLayer, paintPropertyBinders); - return getLineWidth(*lineLayer) / 2.0 + std::abs(offset) + util::length(translate[0], translate[1]); -} - - -} // namespace mbgl diff --git a/src/mbgl/renderer/line_bucket.hpp b/src/mbgl/renderer/line_bucket.hpp deleted file mode 100644 index c319548714..0000000000 --- a/src/mbgl/renderer/line_bucket.hpp +++ /dev/null @@ -1,67 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace mbgl { - -class BucketParameters; -class RenderLineLayer; - -class LineBucket : public Bucket { -public: - LineBucket(const BucketParameters&, - const std::vector&, - const style::LineLayoutProperties&); - - void addFeature(const GeometryTileFeature&, - const GeometryCollection&) override; - bool hasData() const override; - - void upload(gl::Context&) override; - void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; - - float getQueryRadius(const RenderLayer&) const override; - - style::LineLayoutProperties::PossiblyEvaluated layout; - - gl::VertexVector vertices; - gl::IndexVector triangles; - gl::SegmentVector segments; - - optional> vertexBuffer; - optional> indexBuffer; - - std::map paintPropertyBinders; - -private: - void addGeometry(const GeometryCoordinates&, FeatureType); - - struct TriangleElement { - TriangleElement(uint16_t a_, uint16_t b_, uint16_t c_) : a(a_), b(b_), c(c_) {} - uint16_t a, b, c; - }; - void addCurrentVertex(const GeometryCoordinate& currentVertex, double& distance, - const Point& normal, double endLeft, double endRight, bool round, - std::size_t startVertex, std::vector& triangleStore); - void addPieSliceVertex(const GeometryCoordinate& currentVertex, double distance, - const Point& extrude, bool lineTurnsLeft, std::size_t startVertex, - std::vector& triangleStore); - - std::ptrdiff_t e1; - std::ptrdiff_t e2; - std::ptrdiff_t e3; - - const uint32_t overscaling; - - float getLineWidth(const RenderLineLayer& layer) const; -}; - -} // namespace mbgl diff --git a/src/mbgl/renderer/painter.cpp b/src/mbgl/renderer/painter.cpp index 51770b07b1..0c5e0e764a 100644 --- a/src/mbgl/renderer/painter.cpp +++ b/src/mbgl/renderer/painter.cpp @@ -15,10 +15,10 @@ #include #include -#include -#include +#include +#include #include -#include +#include #include #include diff --git a/src/mbgl/renderer/painter_background.cpp b/src/mbgl/renderer/painter_background.cpp deleted file mode 100644 index 7cd9cbac5f..0000000000 --- a/src/mbgl/renderer/painter_background.cpp +++ /dev/null @@ -1,82 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -using namespace style; - -void Painter::renderBackground(PaintParameters& parameters, const RenderBackgroundLayer& layer) { - // Note that for bottommost layers without a pattern, the background color is drawn with - // glClear rather than this method. - const BackgroundPaintProperties::Evaluated& background = layer.evaluated; - - style::FillPaintProperties::Evaluated properties; - properties.get() = background.get(); - properties.get() = { background.get() }; - properties.get() = { background.get() }; - - const FillProgram::PaintPropertyBinders paintAttibuteData(properties, 0); - - if (!background.get().to.empty()) { - optional imagePosA = spriteAtlas->getPattern(background.get().from); - optional imagePosB = spriteAtlas->getPattern(background.get().to); - - if (!imagePosA || !imagePosB) - return; - - spriteAtlas->bind(true, context, 0); - - for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) { - parameters.programs.fillPattern.draw( - context, - gl::Triangles(), - depthModeForSublayer(0, gl::DepthMode::ReadOnly), - gl::StencilMode::disabled(), - colorModeForRenderPass(), - FillPatternUniforms::values( - matrixForTile(tileID), - context.viewport.getCurrentValue().size, - *imagePosA, - *imagePosB, - background.get(), - tileID, - state - ), - tileVertexBuffer, - quadTriangleIndexBuffer, - tileTriangleSegments, - paintAttibuteData, - properties, - state.getZoom() - ); - } - } else { - for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) { - parameters.programs.fill.draw( - context, - gl::Triangles(), - depthModeForSublayer(0, gl::DepthMode::ReadOnly), - gl::StencilMode::disabled(), - colorModeForRenderPass(), - FillProgram::UniformValues { - uniforms::u_matrix::Value{ matrixForTile(tileID) }, - uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, - }, - tileVertexBuffer, - quadTriangleIndexBuffer, - tileTriangleSegments, - paintAttibuteData, - properties, - state.getZoom() - ); - } - } -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/painter_circle.cpp b/src/mbgl/renderer/painter_circle.cpp deleted file mode 100644 index 7c9194f6dd..0000000000 --- a/src/mbgl/renderer/painter_circle.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -using namespace style; - -void Painter::renderCircle(PaintParameters& parameters, - CircleBucket& bucket, - const RenderCircleLayer& layer, - const RenderTile& tile) { - if (pass == RenderPass::Opaque) { - return; - } - - const CirclePaintProperties::Evaluated& properties = layer.evaluated; - const bool scaleWithMap = properties.get() == CirclePitchScaleType::Map; - - parameters.programs.circle.draw( - context, - gl::Triangles(), - depthModeForSublayer(0, gl::DepthMode::ReadOnly), - frame.mapMode == MapMode::Still - ? stencilModeForClipping(tile.clip) - : gl::StencilMode::disabled(), - colorModeForRenderPass(), - CircleProgram::UniformValues { - uniforms::u_matrix::Value{ - tile.translatedMatrix(properties.get(), - properties.get(), - state) - }, - uniforms::u_scale_with_map::Value{ scaleWithMap }, - uniforms::u_extrude_scale::Value{ scaleWithMap - ? std::array {{ - pixelsToGLUnits[0] * state.getCameraToCenterDistance(), - pixelsToGLUnits[1] * state.getCameraToCenterDistance() - }} - : pixelsToGLUnits } - }, - *bucket.vertexBuffer, - *bucket.indexBuffer, - bucket.segments, - bucket.paintPropertyBinders.at(layer.getID()), - properties, - state.getZoom() - ); -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/painter_clipping.cpp b/src/mbgl/renderer/painter_clipping.cpp deleted file mode 100644 index 0d3b5f1504..0000000000 --- a/src/mbgl/renderer/painter_clipping.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include -#include -#include -#include - -namespace mbgl { - -void Painter::renderClippingMask(const UnwrappedTileID& tileID, const ClipID& clip) { - static const style::FillPaintProperties::Evaluated properties {}; - static const FillProgram::PaintPropertyBinders paintAttibuteData(properties, 0); - programs->fill.draw( - context, - gl::Triangles(), - gl::DepthMode::disabled(), - gl::StencilMode { - gl::StencilMode::Always(), - static_cast(clip.reference.to_ulong()), - 0b11111111, - gl::StencilMode::Keep, - gl::StencilMode::Keep, - gl::StencilMode::Replace - }, - gl::ColorMode::disabled(), - FillProgram::UniformValues { - uniforms::u_matrix::Value{ matrixForTile(tileID) }, - uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, - }, - tileVertexBuffer, - quadTriangleIndexBuffer, - tileTriangleSegments, - paintAttibuteData, - properties, - state.getZoom() - ); -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/painter_debug.cpp b/src/mbgl/renderer/painter_debug.cpp deleted file mode 100644 index 37fa3bcb12..0000000000 --- a/src/mbgl/renderer/painter_debug.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -using namespace style; - -void Painter::renderTileDebug(const RenderTile& renderTile) { - if (frame.debugOptions == MapDebugOptions::NoDebug) - return; - - MBGL_DEBUG_GROUP(context, std::string { "debug " } + util::toString(renderTile.id)); - - static const style::PaintProperties<>::Evaluated properties {}; - static const DebugProgram::PaintPropertyBinders paintAttibuteData(properties, 0); - - auto draw = [&] (Color color, const auto& vertexBuffer, const auto& indexBuffer, const auto& segments, auto drawMode) { - programs->debug.draw( - context, - drawMode, - gl::DepthMode::disabled(), - stencilModeForClipping(renderTile.clip), - gl::ColorMode::unblended(), - DebugProgram::UniformValues { - uniforms::u_matrix::Value{ renderTile.matrix }, - uniforms::u_color::Value{ color } - }, - vertexBuffer, - indexBuffer, - segments, - paintAttibuteData, - properties, - state.getZoom() - ); - }; - - if (frame.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) { - Tile& tile = renderTile.tile; - if (!tile.debugBucket || tile.debugBucket->renderable != tile.isRenderable() || - tile.debugBucket->complete != tile.isComplete() || - !(tile.debugBucket->modified == tile.modified) || - !(tile.debugBucket->expires == tile.expires) || - tile.debugBucket->debugMode != frame.debugOptions) { - tile.debugBucket = std::make_unique( - tile.id, tile.isRenderable(), tile.isComplete(), tile.modified, - tile.expires, frame.debugOptions, context); - } - - draw(Color::white(), - *tile.debugBucket->vertexBuffer, - *tile.debugBucket->indexBuffer, - tile.debugBucket->segments, - gl::Lines { 4.0f * frame.pixelRatio }); - - draw(Color::black(), - *tile.debugBucket->vertexBuffer, - *tile.debugBucket->indexBuffer, - tile.debugBucket->segments, - gl::Lines { 2.0f * frame.pixelRatio }); - } - - if (frame.debugOptions & MapDebugOptions::TileBorders) { - draw(Color::red(), - tileVertexBuffer, - tileBorderIndexBuffer, - tileBorderSegments, - gl::LineStrip { 4.0f * frame.pixelRatio }); - } -} - -#ifndef NDEBUG -void Painter::renderClipMasks(PaintParameters&) { - context.setStencilMode(gl::StencilMode::disabled()); - context.setDepthMode(gl::DepthMode::disabled()); - context.setColorMode(gl::ColorMode::unblended()); - context.program = 0; - -#if not MBGL_USE_GLES2 - // Reset the value in case someone else changed it, or it's dirty. - context.pixelTransferStencil = gl::value::PixelTransferStencil::Default; - - // Read the stencil buffer - const auto viewport = context.viewport.getCurrentValue(); - auto image = - context.readFramebuffer(viewport.size, false); - - // Scale the Stencil buffer to cover the entire color space. - auto it = image.data.get(); - auto end = it + viewport.size.width * viewport.size.height; - const auto factor = 255.0f / *std::max_element(it, end); - for (; it != end; ++it) { - *it *= factor; - } - - context.pixelZoom = { 1, 1 }; - context.rasterPos = { -1, -1, 0, 1 }; - context.drawPixels(image); -#endif // MBGL_USE_GLES2 -} - -void Painter::renderDepthBuffer(PaintParameters&) { - context.setStencilMode(gl::StencilMode::disabled()); - context.setDepthMode(gl::DepthMode::disabled()); - context.setColorMode(gl::ColorMode::unblended()); - context.program = 0; - -#if not MBGL_USE_GLES2 - // Scales the values in the depth buffer so that they cover the entire grayscale range. This - // makes it easier to spot tiny differences. - const float base = 1.0f / (1.0f - depthRangeSize); - context.pixelTransferDepth = { base, 1.0f - base }; - - // Read the stencil buffer - auto viewport = context.viewport.getCurrentValue(); - auto image = - context.readFramebuffer(viewport.size, false); - - context.pixelZoom = { 1, 1 }; - context.rasterPos = { -1, -1, 0, 1 }; - context.drawPixels(image); -#endif // MBGL_USE_GLES2 -} -#endif // NDEBUG - -} // namespace mbgl diff --git a/src/mbgl/renderer/painter_fill.cpp b/src/mbgl/renderer/painter_fill.cpp deleted file mode 100644 index 622f6386ef..0000000000 --- a/src/mbgl/renderer/painter_fill.cpp +++ /dev/null @@ -1,140 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -using namespace style; - -void Painter::renderFill(PaintParameters& parameters, - FillBucket& bucket, - const RenderFillLayer& layer, - const RenderTile& tile) { - const FillPaintProperties::Evaluated& properties = layer.evaluated; - - if (!properties.get().from.empty()) { - if (pass != RenderPass::Translucent) { - return; - } - - optional imagePosA = spriteAtlas->getPattern(properties.get().from); - optional imagePosB = spriteAtlas->getPattern(properties.get().to); - - if (!imagePosA || !imagePosB) { - return; - } - - spriteAtlas->bind(true, context, 0); - - auto draw = [&] (uint8_t sublayer, - auto& program, - const auto& drawMode, - const auto& indexBuffer, - const auto& segments) { - program.draw( - context, - drawMode, - depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite), - stencilModeForClipping(tile.clip), - colorModeForRenderPass(), - FillPatternUniforms::values( - tile.translatedMatrix(properties.get(), - properties.get(), - state), - context.viewport.getCurrentValue().size, - *imagePosA, - *imagePosB, - properties.get(), - tile.id, - state - ), - *bucket.vertexBuffer, - indexBuffer, - segments, - bucket.paintPropertyBinders.at(layer.getID()), - properties, - state.getZoom() - ); - }; - - draw(0, - parameters.programs.fillPattern, - gl::Triangles(), - *bucket.triangleIndexBuffer, - bucket.triangleSegments); - - if (!properties.get() || !layer.unevaluated.get().isUndefined()) { - return; - } - - draw(2, - parameters.programs.fillOutlinePattern, - gl::Lines { 2.0f }, - *bucket.lineIndexBuffer, - bucket.lineSegments); - } else { - auto draw = [&] (uint8_t sublayer, - auto& program, - const auto& drawMode, - const auto& indexBuffer, - const auto& segments) { - program.draw( - context, - drawMode, - depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite), - stencilModeForClipping(tile.clip), - colorModeForRenderPass(), - FillProgram::UniformValues { - uniforms::u_matrix::Value{ - tile.translatedMatrix(properties.get(), - properties.get(), - state) - }, - uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, - }, - *bucket.vertexBuffer, - indexBuffer, - segments, - bucket.paintPropertyBinders.at(layer.getID()), - properties, - state.getZoom() - ); - }; - - if (properties.get() && !layer.unevaluated.get().isUndefined() && pass == RenderPass::Translucent) { - draw(2, - parameters.programs.fillOutline, - gl::Lines { 2.0f }, - *bucket.lineIndexBuffer, - bucket.lineSegments); - } - - // Only draw the fill when it's opaque and we're drawing opaque fragments, - // or when it's translucent and we're drawing translucent fragments. - if ((properties.get().constantOr(Color()).a >= 1.0f - && properties.get().constantOr(0) >= 1.0f) == (pass == RenderPass::Opaque)) { - draw(1, - parameters.programs.fill, - gl::Triangles(), - *bucket.triangleIndexBuffer, - bucket.triangleSegments); - } - - if (properties.get() && layer.unevaluated.get().isUndefined() && pass == RenderPass::Translucent) { - draw(2, - parameters.programs.fillOutline, - gl::Lines { 2.0f }, - *bucket.lineIndexBuffer, - bucket.lineSegments); - } - } -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/painter_fill_extrusion.cpp b/src/mbgl/renderer/painter_fill_extrusion.cpp deleted file mode 100644 index af98cae569..0000000000 --- a/src/mbgl/renderer/painter_fill_extrusion.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -using namespace style; - -void Painter::renderFillExtrusion(PaintParameters& parameters, - FillExtrusionBucket& bucket, - const RenderFillExtrusionLayer& layer, - const RenderTile& tile) { - const FillExtrusionPaintProperties::Evaluated& properties = layer.evaluated; - - if (pass == RenderPass::Opaque) { - return; - } - - if (!properties.get().from.empty()) { - optional imagePosA = - spriteAtlas->getPattern(properties.get().from); - optional imagePosB = - spriteAtlas->getPattern(properties.get().to); - - if (!imagePosA || !imagePosB) { - return; - } - - spriteAtlas->bind(true, context, 0); - - parameters.programs.fillExtrusionPattern.draw( - context, - gl::Triangles(), - depthModeForSublayer(0, gl::DepthMode::ReadWrite), - gl::StencilMode::disabled(), - colorModeForRenderPass(), - FillExtrusionPatternUniforms::values( - tile.translatedClipMatrix(properties.get(), - properties.get(), - state), - *imagePosA, - *imagePosB, - properties.get(), - tile.id, - state, - -std::pow(2, tile.id.canonical.z) / util::tileSize / 8.0f, - evaluatedLight - ), - *bucket.vertexBuffer, - *bucket.indexBuffer, - bucket.triangleSegments, - bucket.paintPropertyBinders.at(layer.getID()), - properties, - state.getZoom()); - - } else { - parameters.programs.fillExtrusion.draw( - context, - gl::Triangles(), - depthModeForSublayer(0, gl::DepthMode::ReadWrite), - gl::StencilMode::disabled(), - colorModeForRenderPass(), - FillExtrusionUniforms::values( - tile.translatedClipMatrix(properties.get(), - properties.get(), - state), - state, - evaluatedLight - ), - *bucket.vertexBuffer, - *bucket.indexBuffer, - bucket.triangleSegments, - bucket.paintPropertyBinders.at(layer.getID()), - properties, - state.getZoom()); - }; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/painter_line.cpp b/src/mbgl/renderer/painter_line.cpp deleted file mode 100644 index 4d7a27d0f6..0000000000 --- a/src/mbgl/renderer/painter_line.cpp +++ /dev/null @@ -1,91 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -using namespace style; - -void Painter::renderLine(PaintParameters& parameters, - LineBucket& bucket, - const RenderLineLayer& layer, - const RenderTile& tile) { - if (pass == RenderPass::Opaque) { - return; - } - - const LinePaintProperties::Evaluated& properties = layer.evaluated; - - auto draw = [&] (auto& program, auto&& uniformValues) { - program.draw( - context, - gl::Triangles(), - depthModeForSublayer(0, gl::DepthMode::ReadOnly), - stencilModeForClipping(tile.clip), - colorModeForRenderPass(), - std::move(uniformValues), - *bucket.vertexBuffer, - *bucket.indexBuffer, - bucket.segments, - bucket.paintPropertyBinders.at(layer.getID()), - properties, - state.getZoom() - ); - }; - - if (!properties.get().from.empty()) { - const LinePatternCap cap = bucket.layout.get() == LineCapType::Round - ? LinePatternCap::Round : LinePatternCap::Square; - LinePatternPos posA = lineAtlas->getDashPosition(properties.get().from, cap); - LinePatternPos posB = lineAtlas->getDashPosition(properties.get().to, cap); - - lineAtlas->bind(context, 0); - - draw(parameters.programs.lineSDF, - LineSDFProgram::uniformValues( - properties, - frame.pixelRatio, - tile, - state, - pixelsToGLUnits, - posA, - posB, - layer.dashLineWidth, - lineAtlas->getSize().width)); - - } else if (!properties.get().from.empty()) { - optional posA = spriteAtlas->getPattern(properties.get().from); - optional posB = spriteAtlas->getPattern(properties.get().to); - - if (!posA || !posB) - return; - - spriteAtlas->bind(true, context, 0); - - draw(parameters.programs.linePattern, - LinePatternProgram::uniformValues( - properties, - tile, - state, - pixelsToGLUnits, - *posA, - *posB)); - - } else { - draw(parameters.programs.line, - LineProgram::uniformValues( - properties, - tile, - state, - pixelsToGLUnits)); - } -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/painter_raster.cpp b/src/mbgl/renderer/painter_raster.cpp deleted file mode 100644 index fbe025b5b0..0000000000 --- a/src/mbgl/renderer/painter_raster.cpp +++ /dev/null @@ -1,88 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -using namespace style; - -static float saturationFactor(float saturation) { - if (saturation > 0) { - return 1 - 1 / (1.001 - saturation); - } else { - return -saturation; - } -} - -static float contrastFactor(float contrast) { - if (contrast > 0) { - return 1 / (1 - contrast); - } else { - return 1 + contrast; - } -} - -static std::array spinWeights(float spin) { - spin *= util::DEG2RAD; - float s = std::sin(spin); - float c = std::cos(spin); - std::array spin_weights = {{ - (2 * c + 1) / 3, - (-std::sqrt(3.0f) * s - c + 1) / 3, - (std::sqrt(3.0f) * s - c + 1) / 3 - }}; - return spin_weights; -} - -void Painter::renderRaster(PaintParameters& parameters, - RasterBucket& bucket, - const RenderRasterLayer& layer, - const RenderTile& tile) { - if (pass != RenderPass::Translucent) - return; - if (!bucket.hasData()) - return; - - const RasterPaintProperties::Evaluated& properties = layer.evaluated; - const RasterProgram::PaintPropertyBinders paintAttributeData(properties, 0); - - assert(bucket.texture); - context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear); - context.bindTexture(*bucket.texture, 1, gl::TextureFilter::Linear); - - parameters.programs.raster.draw( - context, - gl::Triangles(), - depthModeForSublayer(0, gl::DepthMode::ReadOnly), - gl::StencilMode::disabled(), - colorModeForRenderPass(), - RasterProgram::UniformValues { - uniforms::u_matrix::Value{ tile.matrix }, - uniforms::u_image0::Value{ 0 }, - uniforms::u_image1::Value{ 1 }, - uniforms::u_opacity::Value{ properties.get() }, - uniforms::u_fade_t::Value{ 1 }, - uniforms::u_brightness_low::Value{ properties.get() }, - uniforms::u_brightness_high::Value{ properties.get() }, - uniforms::u_saturation_factor::Value{ saturationFactor(properties.get()) }, - uniforms::u_contrast_factor::Value{ contrastFactor(properties.get()) }, - uniforms::u_spin_weights::Value{ spinWeights(properties.get()) }, - uniforms::u_buffer_scale::Value{ 1.0f }, - uniforms::u_scale_parent::Value{ 1.0f }, - uniforms::u_tl_parent::Value{ std::array {{ 0.0f, 0.0f }} }, - }, - rasterVertexBuffer, - quadTriangleIndexBuffer, - rasterSegments, - paintAttributeData, - properties, - state.getZoom() - ); -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/painter_symbol.cpp b/src/mbgl/renderer/painter_symbol.cpp deleted file mode 100644 index 5a66d1e62f..0000000000 --- a/src/mbgl/renderer/painter_symbol.cpp +++ /dev/null @@ -1,165 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace mbgl { - -using namespace style; - -void Painter::renderSymbol(PaintParameters& parameters, - SymbolBucket& bucket, - const RenderSymbolLayer& layer, - const RenderTile& tile) { - if (pass == RenderPass::Opaque) { - return; - } - - const auto& layout = bucket.layout; - - frameHistory.bind(context, 1); - - auto draw = [&] (auto& program, - auto&& uniformValues, - const auto& buffers, - const auto& symbolSizeBinder, - const SymbolPropertyValues& values_, - const auto& binders, - const auto& paintProperties) - { - // We clip symbols to their tile extent in still mode. - const bool needsClipping = frame.mapMode == MapMode::Still; - - program.draw( - context, - gl::Triangles(), - values_.pitchAlignment == AlignmentType::Map - ? depthModeForSublayer(0, gl::DepthMode::ReadOnly) - : gl::DepthMode::disabled(), - needsClipping - ? stencilModeForClipping(tile.clip) - : gl::StencilMode::disabled(), - colorModeForRenderPass(), - std::move(uniformValues), - *buffers.vertexBuffer, - *symbolSizeBinder, - values_.layoutSize, - *buffers.indexBuffer, - buffers.segments, - binders, - paintProperties, - state.getZoom() - ); - }; - - if (bucket.hasIconData()) { - auto values = layer.iconPropertyValues(layout); - auto paintPropertyValues = layer.iconPaintProperties(); - - SpriteAtlas& atlas = *bucket.spriteAtlas; - const bool iconScaled = layout.get().constantOr(1.0) != 1.0 || - frame.pixelRatio != atlas.getPixelRatio() || - bucket.iconsNeedLinear; - const bool iconTransformed = values.rotationAlignment == AlignmentType::Map || state.getPitch() != 0; - atlas.bind(bucket.sdfIcons || state.isChanging() || iconScaled || iconTransformed, context, 0); - - const Size texsize = atlas.getSize(); - - if (bucket.sdfIcons) { - if (values.hasHalo) { - draw(parameters.programs.symbolIconSDF, - SymbolSDFIconProgram::uniformValues(false, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo), - bucket.icon, - bucket.iconSizeBinder, - values, - bucket.paintPropertyBinders.at(layer.getID()).first, - paintPropertyValues); - } - - if (values.hasFill) { - draw(parameters.programs.symbolIconSDF, - SymbolSDFIconProgram::uniformValues(false, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill), - bucket.icon, - bucket.iconSizeBinder, - values, - bucket.paintPropertyBinders.at(layer.getID()).first, - paintPropertyValues); - } - } else { - draw(parameters.programs.symbolIcon, - SymbolIconProgram::uniformValues(false, values, texsize, pixelsToGLUnits, tile, state), - bucket.icon, - bucket.iconSizeBinder, - values, - bucket.paintPropertyBinders.at(layer.getID()).first, - paintPropertyValues); - } - } - - if (bucket.hasTextData()) { - glyphAtlas->bind(context, 0); - - auto values = layer.textPropertyValues(layout); - auto paintPropertyValues = layer.textPaintProperties(); - - const Size texsize = glyphAtlas->getSize(); - - if (values.hasHalo) { - draw(parameters.programs.symbolGlyph, - SymbolSDFTextProgram::uniformValues(true, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo), - bucket.text, - bucket.textSizeBinder, - values, - bucket.paintPropertyBinders.at(layer.getID()).second, - paintPropertyValues); - } - - if (values.hasFill) { - draw(parameters.programs.symbolGlyph, - SymbolSDFTextProgram::uniformValues(true, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill), - bucket.text, - bucket.textSizeBinder, - values, - bucket.paintPropertyBinders.at(layer.getID()).second, - paintPropertyValues); - } - } - - if (bucket.hasCollisionBoxData()) { - static const style::PaintProperties<>::Evaluated properties {}; - static const CollisionBoxProgram::PaintPropertyBinders paintAttributeData(properties, 0); - - programs->collisionBox.draw( - context, - gl::Lines { 1.0f }, - gl::DepthMode::disabled(), - gl::StencilMode::disabled(), - colorModeForRenderPass(), - CollisionBoxProgram::UniformValues { - uniforms::u_matrix::Value{ tile.matrix }, - uniforms::u_scale::Value{ std::pow(2.0f, float(state.getZoom() - tile.tile.id.overscaledZ)) }, - uniforms::u_zoom::Value{ float(state.getZoom() * 10) }, - uniforms::u_maxzoom::Value{ float((tile.id.canonical.z + 1) * 10) }, - }, - *bucket.collisionBox.vertexBuffer, - *bucket.collisionBox.indexBuffer, - bucket.collisionBox.segments, - paintAttributeData, - properties, - state.getZoom() - ); - } -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_background.cpp b/src/mbgl/renderer/painters/painter_background.cpp new file mode 100644 index 0000000000..fbd44b4480 --- /dev/null +++ b/src/mbgl/renderer/painters/painter_background.cpp @@ -0,0 +1,82 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +void Painter::renderBackground(PaintParameters& parameters, const RenderBackgroundLayer& layer) { + // Note that for bottommost layers without a pattern, the background color is drawn with + // glClear rather than this method. + const BackgroundPaintProperties::Evaluated& background = layer.evaluated; + + style::FillPaintProperties::Evaluated properties; + properties.get() = background.get(); + properties.get() = { background.get() }; + properties.get() = { background.get() }; + + const FillProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + + if (!background.get().to.empty()) { + optional imagePosA = spriteAtlas->getPattern(background.get().from); + optional imagePosB = spriteAtlas->getPattern(background.get().to); + + if (!imagePosA || !imagePosB) + return; + + spriteAtlas->bind(true, context, 0); + + for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) { + parameters.programs.fillPattern.draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadOnly), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + FillPatternUniforms::values( + matrixForTile(tileID), + context.viewport.getCurrentValue().size, + *imagePosA, + *imagePosB, + background.get(), + tileID, + state + ), + tileVertexBuffer, + quadTriangleIndexBuffer, + tileTriangleSegments, + paintAttibuteData, + properties, + state.getZoom() + ); + } + } else { + for (const auto& tileID : util::tileCover(state, state.getIntegerZoom())) { + parameters.programs.fill.draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadOnly), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + FillProgram::UniformValues { + uniforms::u_matrix::Value{ matrixForTile(tileID) }, + uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, + }, + tileVertexBuffer, + quadTriangleIndexBuffer, + tileTriangleSegments, + paintAttibuteData, + properties, + state.getZoom() + ); + } + } +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_circle.cpp b/src/mbgl/renderer/painters/painter_circle.cpp new file mode 100644 index 0000000000..0bca8ee94f --- /dev/null +++ b/src/mbgl/renderer/painters/painter_circle.cpp @@ -0,0 +1,57 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +void Painter::renderCircle(PaintParameters& parameters, + CircleBucket& bucket, + const RenderCircleLayer& layer, + const RenderTile& tile) { + if (pass == RenderPass::Opaque) { + return; + } + + const CirclePaintProperties::Evaluated& properties = layer.evaluated; + const bool scaleWithMap = properties.get() == CirclePitchScaleType::Map; + + parameters.programs.circle.draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadOnly), + frame.mapMode == MapMode::Still + ? stencilModeForClipping(tile.clip) + : gl::StencilMode::disabled(), + colorModeForRenderPass(), + CircleProgram::UniformValues { + uniforms::u_matrix::Value{ + tile.translatedMatrix(properties.get(), + properties.get(), + state) + }, + uniforms::u_scale_with_map::Value{ scaleWithMap }, + uniforms::u_extrude_scale::Value{ scaleWithMap + ? std::array {{ + pixelsToGLUnits[0] * state.getCameraToCenterDistance(), + pixelsToGLUnits[1] * state.getCameraToCenterDistance() + }} + : pixelsToGLUnits } + }, + *bucket.vertexBuffer, + *bucket.indexBuffer, + bucket.segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() + ); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_clipping.cpp b/src/mbgl/renderer/painters/painter_clipping.cpp new file mode 100644 index 0000000000..0d3b5f1504 --- /dev/null +++ b/src/mbgl/renderer/painters/painter_clipping.cpp @@ -0,0 +1,37 @@ +#include +#include +#include +#include + +namespace mbgl { + +void Painter::renderClippingMask(const UnwrappedTileID& tileID, const ClipID& clip) { + static const style::FillPaintProperties::Evaluated properties {}; + static const FillProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + programs->fill.draw( + context, + gl::Triangles(), + gl::DepthMode::disabled(), + gl::StencilMode { + gl::StencilMode::Always(), + static_cast(clip.reference.to_ulong()), + 0b11111111, + gl::StencilMode::Keep, + gl::StencilMode::Keep, + gl::StencilMode::Replace + }, + gl::ColorMode::disabled(), + FillProgram::UniformValues { + uniforms::u_matrix::Value{ matrixForTile(tileID) }, + uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, + }, + tileVertexBuffer, + quadTriangleIndexBuffer, + tileTriangleSegments, + paintAttibuteData, + properties, + state.getZoom() + ); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_debug.cpp b/src/mbgl/renderer/painters/painter_debug.cpp new file mode 100644 index 0000000000..a108cd2d00 --- /dev/null +++ b/src/mbgl/renderer/painters/painter_debug.cpp @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +void Painter::renderTileDebug(const RenderTile& renderTile) { + if (frame.debugOptions == MapDebugOptions::NoDebug) + return; + + MBGL_DEBUG_GROUP(context, std::string { "debug " } + util::toString(renderTile.id)); + + static const style::PaintProperties<>::Evaluated properties {}; + static const DebugProgram::PaintPropertyBinders paintAttibuteData(properties, 0); + + auto draw = [&] (Color color, const auto& vertexBuffer, const auto& indexBuffer, const auto& segments, auto drawMode) { + programs->debug.draw( + context, + drawMode, + gl::DepthMode::disabled(), + stencilModeForClipping(renderTile.clip), + gl::ColorMode::unblended(), + DebugProgram::UniformValues { + uniforms::u_matrix::Value{ renderTile.matrix }, + uniforms::u_color::Value{ color } + }, + vertexBuffer, + indexBuffer, + segments, + paintAttibuteData, + properties, + state.getZoom() + ); + }; + + if (frame.debugOptions & (MapDebugOptions::Timestamps | MapDebugOptions::ParseStatus)) { + Tile& tile = renderTile.tile; + if (!tile.debugBucket || tile.debugBucket->renderable != tile.isRenderable() || + tile.debugBucket->complete != tile.isComplete() || + !(tile.debugBucket->modified == tile.modified) || + !(tile.debugBucket->expires == tile.expires) || + tile.debugBucket->debugMode != frame.debugOptions) { + tile.debugBucket = std::make_unique( + tile.id, tile.isRenderable(), tile.isComplete(), tile.modified, + tile.expires, frame.debugOptions, context); + } + + draw(Color::white(), + *tile.debugBucket->vertexBuffer, + *tile.debugBucket->indexBuffer, + tile.debugBucket->segments, + gl::Lines { 4.0f * frame.pixelRatio }); + + draw(Color::black(), + *tile.debugBucket->vertexBuffer, + *tile.debugBucket->indexBuffer, + tile.debugBucket->segments, + gl::Lines { 2.0f * frame.pixelRatio }); + } + + if (frame.debugOptions & MapDebugOptions::TileBorders) { + draw(Color::red(), + tileVertexBuffer, + tileBorderIndexBuffer, + tileBorderSegments, + gl::LineStrip { 4.0f * frame.pixelRatio }); + } +} + +#ifndef NDEBUG +void Painter::renderClipMasks(PaintParameters&) { + context.setStencilMode(gl::StencilMode::disabled()); + context.setDepthMode(gl::DepthMode::disabled()); + context.setColorMode(gl::ColorMode::unblended()); + context.program = 0; + +#if not MBGL_USE_GLES2 + // Reset the value in case someone else changed it, or it's dirty. + context.pixelTransferStencil = gl::value::PixelTransferStencil::Default; + + // Read the stencil buffer + const auto viewport = context.viewport.getCurrentValue(); + auto image = + context.readFramebuffer(viewport.size, false); + + // Scale the Stencil buffer to cover the entire color space. + auto it = image.data.get(); + auto end = it + viewport.size.width * viewport.size.height; + const auto factor = 255.0f / *std::max_element(it, end); + for (; it != end; ++it) { + *it *= factor; + } + + context.pixelZoom = { 1, 1 }; + context.rasterPos = { -1, -1, 0, 1 }; + context.drawPixels(image); +#endif // MBGL_USE_GLES2 +} + +void Painter::renderDepthBuffer(PaintParameters&) { + context.setStencilMode(gl::StencilMode::disabled()); + context.setDepthMode(gl::DepthMode::disabled()); + context.setColorMode(gl::ColorMode::unblended()); + context.program = 0; + +#if not MBGL_USE_GLES2 + // Scales the values in the depth buffer so that they cover the entire grayscale range. This + // makes it easier to spot tiny differences. + const float base = 1.0f / (1.0f - depthRangeSize); + context.pixelTransferDepth = { base, 1.0f - base }; + + // Read the stencil buffer + auto viewport = context.viewport.getCurrentValue(); + auto image = + context.readFramebuffer(viewport.size, false); + + context.pixelZoom = { 1, 1 }; + context.rasterPos = { -1, -1, 0, 1 }; + context.drawPixels(image); +#endif // MBGL_USE_GLES2 +} +#endif // NDEBUG + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_fill.cpp b/src/mbgl/renderer/painters/painter_fill.cpp new file mode 100644 index 0000000000..782fba3d42 --- /dev/null +++ b/src/mbgl/renderer/painters/painter_fill.cpp @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +void Painter::renderFill(PaintParameters& parameters, + FillBucket& bucket, + const RenderFillLayer& layer, + const RenderTile& tile) { + const FillPaintProperties::Evaluated& properties = layer.evaluated; + + if (!properties.get().from.empty()) { + if (pass != RenderPass::Translucent) { + return; + } + + optional imagePosA = spriteAtlas->getPattern(properties.get().from); + optional imagePosB = spriteAtlas->getPattern(properties.get().to); + + if (!imagePosA || !imagePosB) { + return; + } + + spriteAtlas->bind(true, context, 0); + + auto draw = [&] (uint8_t sublayer, + auto& program, + const auto& drawMode, + const auto& indexBuffer, + const auto& segments) { + program.draw( + context, + drawMode, + depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite), + stencilModeForClipping(tile.clip), + colorModeForRenderPass(), + FillPatternUniforms::values( + tile.translatedMatrix(properties.get(), + properties.get(), + state), + context.viewport.getCurrentValue().size, + *imagePosA, + *imagePosB, + properties.get(), + tile.id, + state + ), + *bucket.vertexBuffer, + indexBuffer, + segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() + ); + }; + + draw(0, + parameters.programs.fillPattern, + gl::Triangles(), + *bucket.triangleIndexBuffer, + bucket.triangleSegments); + + if (!properties.get() || !layer.unevaluated.get().isUndefined()) { + return; + } + + draw(2, + parameters.programs.fillOutlinePattern, + gl::Lines { 2.0f }, + *bucket.lineIndexBuffer, + bucket.lineSegments); + } else { + auto draw = [&] (uint8_t sublayer, + auto& program, + const auto& drawMode, + const auto& indexBuffer, + const auto& segments) { + program.draw( + context, + drawMode, + depthModeForSublayer(sublayer, gl::DepthMode::ReadWrite), + stencilModeForClipping(tile.clip), + colorModeForRenderPass(), + FillProgram::UniformValues { + uniforms::u_matrix::Value{ + tile.translatedMatrix(properties.get(), + properties.get(), + state) + }, + uniforms::u_world::Value{ context.viewport.getCurrentValue().size }, + }, + *bucket.vertexBuffer, + indexBuffer, + segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() + ); + }; + + if (properties.get() && !layer.unevaluated.get().isUndefined() && pass == RenderPass::Translucent) { + draw(2, + parameters.programs.fillOutline, + gl::Lines { 2.0f }, + *bucket.lineIndexBuffer, + bucket.lineSegments); + } + + // Only draw the fill when it's opaque and we're drawing opaque fragments, + // or when it's translucent and we're drawing translucent fragments. + if ((properties.get().constantOr(Color()).a >= 1.0f + && properties.get().constantOr(0) >= 1.0f) == (pass == RenderPass::Opaque)) { + draw(1, + parameters.programs.fill, + gl::Triangles(), + *bucket.triangleIndexBuffer, + bucket.triangleSegments); + } + + if (properties.get() && layer.unevaluated.get().isUndefined() && pass == RenderPass::Translucent) { + draw(2, + parameters.programs.fillOutline, + gl::Lines { 2.0f }, + *bucket.lineIndexBuffer, + bucket.lineSegments); + } + } +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_fill_extrusion.cpp b/src/mbgl/renderer/painters/painter_fill_extrusion.cpp new file mode 100644 index 0000000000..c00597ab40 --- /dev/null +++ b/src/mbgl/renderer/painters/painter_fill_extrusion.cpp @@ -0,0 +1,87 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +void Painter::renderFillExtrusion(PaintParameters& parameters, + FillExtrusionBucket& bucket, + const RenderFillExtrusionLayer& layer, + const RenderTile& tile) { + const FillExtrusionPaintProperties::Evaluated& properties = layer.evaluated; + + if (pass == RenderPass::Opaque) { + return; + } + + if (!properties.get().from.empty()) { + optional imagePosA = + spriteAtlas->getPattern(properties.get().from); + optional imagePosB = + spriteAtlas->getPattern(properties.get().to); + + if (!imagePosA || !imagePosB) { + return; + } + + spriteAtlas->bind(true, context, 0); + + parameters.programs.fillExtrusionPattern.draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadWrite), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + FillExtrusionPatternUniforms::values( + tile.translatedClipMatrix(properties.get(), + properties.get(), + state), + *imagePosA, + *imagePosB, + properties.get(), + tile.id, + state, + -std::pow(2, tile.id.canonical.z) / util::tileSize / 8.0f, + evaluatedLight + ), + *bucket.vertexBuffer, + *bucket.indexBuffer, + bucket.triangleSegments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom()); + + } else { + parameters.programs.fillExtrusion.draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadWrite), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + FillExtrusionUniforms::values( + tile.translatedClipMatrix(properties.get(), + properties.get(), + state), + state, + evaluatedLight + ), + *bucket.vertexBuffer, + *bucket.indexBuffer, + bucket.triangleSegments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom()); + }; +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_line.cpp b/src/mbgl/renderer/painters/painter_line.cpp new file mode 100644 index 0000000000..20a16750d2 --- /dev/null +++ b/src/mbgl/renderer/painters/painter_line.cpp @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +void Painter::renderLine(PaintParameters& parameters, + LineBucket& bucket, + const RenderLineLayer& layer, + const RenderTile& tile) { + if (pass == RenderPass::Opaque) { + return; + } + + const LinePaintProperties::Evaluated& properties = layer.evaluated; + + auto draw = [&] (auto& program, auto&& uniformValues) { + program.draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadOnly), + stencilModeForClipping(tile.clip), + colorModeForRenderPass(), + std::move(uniformValues), + *bucket.vertexBuffer, + *bucket.indexBuffer, + bucket.segments, + bucket.paintPropertyBinders.at(layer.getID()), + properties, + state.getZoom() + ); + }; + + if (!properties.get().from.empty()) { + const LinePatternCap cap = bucket.layout.get() == LineCapType::Round + ? LinePatternCap::Round : LinePatternCap::Square; + LinePatternPos posA = lineAtlas->getDashPosition(properties.get().from, cap); + LinePatternPos posB = lineAtlas->getDashPosition(properties.get().to, cap); + + lineAtlas->bind(context, 0); + + draw(parameters.programs.lineSDF, + LineSDFProgram::uniformValues( + properties, + frame.pixelRatio, + tile, + state, + pixelsToGLUnits, + posA, + posB, + layer.dashLineWidth, + lineAtlas->getSize().width)); + + } else if (!properties.get().from.empty()) { + optional posA = spriteAtlas->getPattern(properties.get().from); + optional posB = spriteAtlas->getPattern(properties.get().to); + + if (!posA || !posB) + return; + + spriteAtlas->bind(true, context, 0); + + draw(parameters.programs.linePattern, + LinePatternProgram::uniformValues( + properties, + tile, + state, + pixelsToGLUnits, + *posA, + *posB)); + + } else { + draw(parameters.programs.line, + LineProgram::uniformValues( + properties, + tile, + state, + pixelsToGLUnits)); + } +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_raster.cpp b/src/mbgl/renderer/painters/painter_raster.cpp new file mode 100644 index 0000000000..5d98fcf860 --- /dev/null +++ b/src/mbgl/renderer/painters/painter_raster.cpp @@ -0,0 +1,88 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mbgl { + +using namespace style; + +static float saturationFactor(float saturation) { + if (saturation > 0) { + return 1 - 1 / (1.001 - saturation); + } else { + return -saturation; + } +} + +static float contrastFactor(float contrast) { + if (contrast > 0) { + return 1 / (1 - contrast); + } else { + return 1 + contrast; + } +} + +static std::array spinWeights(float spin) { + spin *= util::DEG2RAD; + float s = std::sin(spin); + float c = std::cos(spin); + std::array spin_weights = {{ + (2 * c + 1) / 3, + (-std::sqrt(3.0f) * s - c + 1) / 3, + (std::sqrt(3.0f) * s - c + 1) / 3 + }}; + return spin_weights; +} + +void Painter::renderRaster(PaintParameters& parameters, + RasterBucket& bucket, + const RenderRasterLayer& layer, + const RenderTile& tile) { + if (pass != RenderPass::Translucent) + return; + if (!bucket.hasData()) + return; + + const RasterPaintProperties::Evaluated& properties = layer.evaluated; + const RasterProgram::PaintPropertyBinders paintAttributeData(properties, 0); + + assert(bucket.texture); + context.bindTexture(*bucket.texture, 0, gl::TextureFilter::Linear); + context.bindTexture(*bucket.texture, 1, gl::TextureFilter::Linear); + + parameters.programs.raster.draw( + context, + gl::Triangles(), + depthModeForSublayer(0, gl::DepthMode::ReadOnly), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + RasterProgram::UniformValues { + uniforms::u_matrix::Value{ tile.matrix }, + uniforms::u_image0::Value{ 0 }, + uniforms::u_image1::Value{ 1 }, + uniforms::u_opacity::Value{ properties.get() }, + uniforms::u_fade_t::Value{ 1 }, + uniforms::u_brightness_low::Value{ properties.get() }, + uniforms::u_brightness_high::Value{ properties.get() }, + uniforms::u_saturation_factor::Value{ saturationFactor(properties.get()) }, + uniforms::u_contrast_factor::Value{ contrastFactor(properties.get()) }, + uniforms::u_spin_weights::Value{ spinWeights(properties.get()) }, + uniforms::u_buffer_scale::Value{ 1.0f }, + uniforms::u_scale_parent::Value{ 1.0f }, + uniforms::u_tl_parent::Value{ std::array {{ 0.0f, 0.0f }} }, + }, + rasterVertexBuffer, + quadTriangleIndexBuffer, + rasterSegments, + paintAttributeData, + properties, + state.getZoom() + ); +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/painters/painter_symbol.cpp b/src/mbgl/renderer/painters/painter_symbol.cpp new file mode 100644 index 0000000000..8147a933bc --- /dev/null +++ b/src/mbgl/renderer/painters/painter_symbol.cpp @@ -0,0 +1,165 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace mbgl { + +using namespace style; + +void Painter::renderSymbol(PaintParameters& parameters, + SymbolBucket& bucket, + const RenderSymbolLayer& layer, + const RenderTile& tile) { + if (pass == RenderPass::Opaque) { + return; + } + + const auto& layout = bucket.layout; + + frameHistory.bind(context, 1); + + auto draw = [&] (auto& program, + auto&& uniformValues, + const auto& buffers, + const auto& symbolSizeBinder, + const SymbolPropertyValues& values_, + const auto& binders, + const auto& paintProperties) + { + // We clip symbols to their tile extent in still mode. + const bool needsClipping = frame.mapMode == MapMode::Still; + + program.draw( + context, + gl::Triangles(), + values_.pitchAlignment == AlignmentType::Map + ? depthModeForSublayer(0, gl::DepthMode::ReadOnly) + : gl::DepthMode::disabled(), + needsClipping + ? stencilModeForClipping(tile.clip) + : gl::StencilMode::disabled(), + colorModeForRenderPass(), + std::move(uniformValues), + *buffers.vertexBuffer, + *symbolSizeBinder, + values_.layoutSize, + *buffers.indexBuffer, + buffers.segments, + binders, + paintProperties, + state.getZoom() + ); + }; + + if (bucket.hasIconData()) { + auto values = layer.iconPropertyValues(layout); + auto paintPropertyValues = layer.iconPaintProperties(); + + SpriteAtlas& atlas = *bucket.spriteAtlas; + const bool iconScaled = layout.get().constantOr(1.0) != 1.0 || + frame.pixelRatio != atlas.getPixelRatio() || + bucket.iconsNeedLinear; + const bool iconTransformed = values.rotationAlignment == AlignmentType::Map || state.getPitch() != 0; + atlas.bind(bucket.sdfIcons || state.isChanging() || iconScaled || iconTransformed, context, 0); + + const Size texsize = atlas.getSize(); + + if (bucket.sdfIcons) { + if (values.hasHalo) { + draw(parameters.programs.symbolIconSDF, + SymbolSDFIconProgram::uniformValues(false, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo), + bucket.icon, + bucket.iconSizeBinder, + values, + bucket.paintPropertyBinders.at(layer.getID()).first, + paintPropertyValues); + } + + if (values.hasFill) { + draw(parameters.programs.symbolIconSDF, + SymbolSDFIconProgram::uniformValues(false, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill), + bucket.icon, + bucket.iconSizeBinder, + values, + bucket.paintPropertyBinders.at(layer.getID()).first, + paintPropertyValues); + } + } else { + draw(parameters.programs.symbolIcon, + SymbolIconProgram::uniformValues(false, values, texsize, pixelsToGLUnits, tile, state), + bucket.icon, + bucket.iconSizeBinder, + values, + bucket.paintPropertyBinders.at(layer.getID()).first, + paintPropertyValues); + } + } + + if (bucket.hasTextData()) { + glyphAtlas->bind(context, 0); + + auto values = layer.textPropertyValues(layout); + auto paintPropertyValues = layer.textPaintProperties(); + + const Size texsize = glyphAtlas->getSize(); + + if (values.hasHalo) { + draw(parameters.programs.symbolGlyph, + SymbolSDFTextProgram::uniformValues(true, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Halo), + bucket.text, + bucket.textSizeBinder, + values, + bucket.paintPropertyBinders.at(layer.getID()).second, + paintPropertyValues); + } + + if (values.hasFill) { + draw(parameters.programs.symbolGlyph, + SymbolSDFTextProgram::uniformValues(true, values, texsize, pixelsToGLUnits, tile, state, SymbolSDFPart::Fill), + bucket.text, + bucket.textSizeBinder, + values, + bucket.paintPropertyBinders.at(layer.getID()).second, + paintPropertyValues); + } + } + + if (bucket.hasCollisionBoxData()) { + static const style::PaintProperties<>::Evaluated properties {}; + static const CollisionBoxProgram::PaintPropertyBinders paintAttributeData(properties, 0); + + programs->collisionBox.draw( + context, + gl::Lines { 1.0f }, + gl::DepthMode::disabled(), + gl::StencilMode::disabled(), + colorModeForRenderPass(), + CollisionBoxProgram::UniformValues { + uniforms::u_matrix::Value{ tile.matrix }, + uniforms::u_scale::Value{ std::pow(2.0f, float(state.getZoom() - tile.tile.id.overscaledZ)) }, + uniforms::u_zoom::Value{ float(state.getZoom() * 10) }, + uniforms::u_maxzoom::Value{ float((tile.id.canonical.z + 1) * 10) }, + }, + *bucket.collisionBox.vertexBuffer, + *bucket.collisionBox.indexBuffer, + bucket.collisionBox.segments, + paintAttributeData, + properties, + state.getZoom() + ); + } +} + +} // namespace mbgl diff --git a/src/mbgl/renderer/raster_bucket.cpp b/src/mbgl/renderer/raster_bucket.cpp deleted file mode 100644 index ee8ef24071..0000000000 --- a/src/mbgl/renderer/raster_bucket.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include -#include - -namespace mbgl { - -using namespace style; - -RasterBucket::RasterBucket(UnassociatedImage&& image_) : image(std::move(image_)) { -} - -void RasterBucket::upload(gl::Context& context) { - texture = context.createTexture(std::move(image)); - uploaded = true; -} - -void RasterBucket::render(Painter& painter, - PaintParameters& parameters, - const RenderLayer& layer, - const RenderTile& tile) { - painter.renderRaster(parameters, *this, *layer.as(), tile); -} - -bool RasterBucket::hasData() const { - return true; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/raster_bucket.hpp b/src/mbgl/renderer/raster_bucket.hpp deleted file mode 100644 index 334954e3f4..0000000000 --- a/src/mbgl/renderer/raster_bucket.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -namespace mbgl { - -class RasterBucket : public Bucket { -public: - RasterBucket(UnassociatedImage&&); - - void upload(gl::Context&) override; - void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; - bool hasData() const override; - - UnassociatedImage image; - optional texture; -}; - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_background_layer.cpp b/src/mbgl/renderer/render_background_layer.cpp deleted file mode 100644 index a0c3fe81b2..0000000000 --- a/src/mbgl/renderer/render_background_layer.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include -#include -#include - -namespace mbgl { - -RenderBackgroundLayer::RenderBackgroundLayer(Immutable _impl) - : RenderLayer(style::LayerType::Background, _impl) { -} - -const style::BackgroundLayer::Impl& RenderBackgroundLayer::impl() const { - return static_cast(*baseImpl); -} - -std::unique_ptr RenderBackgroundLayer::createBucket(const BucketParameters &, - const std::vector &) const { - assert(false); - return nullptr; -} - -void RenderBackgroundLayer::cascade(const CascadeParameters ¶meters) { - unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); -} - -void RenderBackgroundLayer::evaluate(const PropertyEvaluationParameters ¶meters) { - evaluated = unevaluated.evaluate(parameters); - - passes = evaluated.get() > 0 ? RenderPass::Translucent - : RenderPass::None; -} - -bool RenderBackgroundLayer::hasTransition() const { - return unevaluated.hasTransition(); -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_background_layer.hpp b/src/mbgl/renderer/render_background_layer.hpp deleted file mode 100644 index 7eabf47345..0000000000 --- a/src/mbgl/renderer/render_background_layer.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace mbgl { - -class RenderBackgroundLayer: public RenderLayer { -public: - RenderBackgroundLayer(Immutable); - ~RenderBackgroundLayer() final = default; - - void cascade(const CascadeParameters&) override; - void evaluate(const PropertyEvaluationParameters&) override; - bool hasTransition() const override; - - std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; - - // Paint properties - style::BackgroundPaintProperties::Unevaluated unevaluated; - style::BackgroundPaintProperties::Evaluated evaluated; - - const style::BackgroundLayer::Impl& impl() const; -}; - -template <> -inline bool RenderLayer::is() const { - return type == style::LayerType::Background; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_circle_layer.cpp b/src/mbgl/renderer/render_circle_layer.cpp deleted file mode 100644 index 5afe7682f2..0000000000 --- a/src/mbgl/renderer/render_circle_layer.cpp +++ /dev/null @@ -1,66 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -RenderCircleLayer::RenderCircleLayer(Immutable _impl) - : RenderLayer(style::LayerType::Circle, _impl) { -} - -const style::CircleLayer::Impl& RenderCircleLayer::impl() const { - return static_cast(*baseImpl); -} - -std::unique_ptr RenderCircleLayer::createBucket(const BucketParameters& parameters, const std::vector& layers) const { - return std::make_unique(parameters, layers); -} - -void RenderCircleLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); -} - -void RenderCircleLayer::evaluate(const PropertyEvaluationParameters& parameters) { - evaluated = unevaluated.evaluate(parameters); - - passes = ((evaluated.get().constantOr(1) > 0 || - evaluated.get().constantOr(1) > 0) - && (evaluated.get().constantOr(Color::black()).a > 0 || - evaluated.get().constantOr(Color::black()).a > 0) - && (evaluated.get().constantOr(1) > 0 || - evaluated.get().constantOr(1) > 0)) - ? RenderPass::Translucent : RenderPass::None; -} - -bool RenderCircleLayer::hasTransition() const { - return unevaluated.hasTransition(); -} - -bool RenderCircleLayer::queryIntersectsFeature( - const GeometryCoordinates& queryGeometry, - const GeometryTileFeature& feature, - const float zoom, - const float bearing, - const float pixelsToTileUnits) const { - - // Translate query geometry - auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( - queryGeometry, - evaluated.get(), - evaluated.get(), - bearing, - pixelsToTileUnits); - - // Evaluate function - auto circleRadius = evaluated.get() - .evaluate(feature, zoom, style::CircleRadius::defaultValue()) - * pixelsToTileUnits; - - // Test intersection - return util::polygonIntersectsBufferedMultiPoint(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries(), circleRadius); -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_circle_layer.hpp b/src/mbgl/renderer/render_circle_layer.hpp deleted file mode 100644 index 2b517912c9..0000000000 --- a/src/mbgl/renderer/render_circle_layer.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace mbgl { - -class RenderCircleLayer: public RenderLayer { -public: - RenderCircleLayer(Immutable); - ~RenderCircleLayer() final = default; - - void cascade(const CascadeParameters&) override; - void evaluate(const PropertyEvaluationParameters&) override; - bool hasTransition() const override; - - bool queryIntersectsFeature( - const GeometryCoordinates&, - const GeometryTileFeature&, - const float, - const float, - const float) const override; - - std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; - - // Paint properties - style::CirclePaintProperties::Unevaluated unevaluated; - style::CirclePaintProperties::Evaluated evaluated; - - const style::CircleLayer::Impl& impl() const; -}; - -template <> -inline bool RenderLayer::is() const { - return type == style::LayerType::Circle; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_custom_layer.cpp b/src/mbgl/renderer/render_custom_layer.cpp deleted file mode 100644 index 8cedda2417..0000000000 --- a/src/mbgl/renderer/render_custom_layer.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include -#include -#include - -namespace mbgl { - -RenderCustomLayer::RenderCustomLayer(Immutable _impl) - : RenderLayer(style::LayerType::Custom, _impl) { -} - -const style::CustomLayer::Impl& RenderCustomLayer::impl() const { - return static_cast(*baseImpl); -} - -void RenderCustomLayer::evaluate(const PropertyEvaluationParameters&) { - passes = RenderPass::Translucent; -} - -bool RenderCustomLayer::hasTransition() const { - return false; -} - -std::unique_ptr RenderCustomLayer::createBucket(const BucketParameters&, const std::vector&) const { - assert(false); - return nullptr; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_custom_layer.hpp b/src/mbgl/renderer/render_custom_layer.hpp deleted file mode 100644 index d448433092..0000000000 --- a/src/mbgl/renderer/render_custom_layer.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#pragma once - -#include -#include - -namespace mbgl { - -class RenderCustomLayer: public RenderLayer { -public: - RenderCustomLayer(Immutable); - ~RenderCustomLayer() final = default; - - void cascade(const CascadeParameters&) final {} - void evaluate(const PropertyEvaluationParameters&) override; - bool hasTransition() const override; - - std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const final; - - const style::CustomLayer::Impl& impl() const; -}; - -template <> -inline bool RenderLayer::is() const { - return type == style::LayerType::Custom; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_fill_extrusion_layer.cpp b/src/mbgl/renderer/render_fill_extrusion_layer.cpp deleted file mode 100644 index 3142384fc6..0000000000 --- a/src/mbgl/renderer/render_fill_extrusion_layer.cpp +++ /dev/null @@ -1,54 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -RenderFillExtrusionLayer::RenderFillExtrusionLayer(Immutable _impl) - : RenderLayer(style::LayerType::FillExtrusion, _impl) { -} - -const style::FillExtrusionLayer::Impl& RenderFillExtrusionLayer::impl() const { - return static_cast(*baseImpl); -} - -std::unique_ptr RenderFillExtrusionLayer::createBucket(const BucketParameters& parameters, const std::vector& layers) const { - return std::make_unique(parameters, layers); -} - -void RenderFillExtrusionLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); -} - -void RenderFillExtrusionLayer::evaluate(const PropertyEvaluationParameters& parameters) { - evaluated = unevaluated.evaluate(parameters); - - passes = (evaluated.get() > 0) ? RenderPass::Translucent - : RenderPass::None; -} - -bool RenderFillExtrusionLayer::hasTransition() const { - return unevaluated.hasTransition(); -} - -bool RenderFillExtrusionLayer::queryIntersectsFeature( - const GeometryCoordinates& queryGeometry, - const GeometryTileFeature& feature, - const float, - const float bearing, - const float pixelsToTileUnits) const { - - auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( - queryGeometry, - evaluated.get(), - evaluated.get(), - bearing, - pixelsToTileUnits); - - return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries()); -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_fill_extrusion_layer.hpp b/src/mbgl/renderer/render_fill_extrusion_layer.hpp deleted file mode 100644 index f6166495c6..0000000000 --- a/src/mbgl/renderer/render_fill_extrusion_layer.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace mbgl { - -class RenderFillExtrusionLayer: public RenderLayer { -public: - RenderFillExtrusionLayer(Immutable); - ~RenderFillExtrusionLayer() final = default; - - void cascade(const CascadeParameters&) override; - void evaluate(const PropertyEvaluationParameters&) override; - bool hasTransition() const override; - - bool queryIntersectsFeature( - const GeometryCoordinates&, - const GeometryTileFeature&, - const float, - const float, - const float) const override; - - std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; - - // Paint properties - style::FillExtrusionPaintProperties::Unevaluated unevaluated; - style::FillExtrusionPaintProperties::Evaluated evaluated; - - const style::FillExtrusionLayer::Impl& impl() const; -}; - -template <> -inline bool RenderLayer::is() const { - return type == style::LayerType::FillExtrusion; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_fill_layer.cpp b/src/mbgl/renderer/render_fill_layer.cpp deleted file mode 100644 index 8bed153b41..0000000000 --- a/src/mbgl/renderer/render_fill_layer.cpp +++ /dev/null @@ -1,70 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -RenderFillLayer::RenderFillLayer(Immutable _impl) - : RenderLayer(style::LayerType::Fill, _impl) { -} - -const style::FillLayer::Impl& RenderFillLayer::impl() const { - return static_cast(*baseImpl); -} - -std::unique_ptr RenderFillLayer::createBucket(const BucketParameters& parameters, const std::vector& layers) const { - return std::make_unique(parameters, layers); -} - -void RenderFillLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); -} - -void RenderFillLayer::evaluate(const PropertyEvaluationParameters& parameters) { - evaluated = unevaluated.evaluate(parameters); - - if (unevaluated.get().isUndefined()) { - evaluated.get() = evaluated.get(); - } - - passes = RenderPass::None; - - if (evaluated.get()) { - passes |= RenderPass::Translucent; - } - - if (!unevaluated.get().isUndefined() - || evaluated.get().constantOr(Color()).a < 1.0f - || evaluated.get().constantOr(0) < 1.0f) { - passes |= RenderPass::Translucent; - } else { - passes |= RenderPass::Opaque; - } -} - -bool RenderFillLayer::hasTransition() const { - return unevaluated.hasTransition(); -} - -bool RenderFillLayer::queryIntersectsFeature( - const GeometryCoordinates& queryGeometry, - const GeometryTileFeature& feature, - const float, - const float bearing, - const float pixelsToTileUnits) const { - - auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( - queryGeometry, - evaluated.get(), - evaluated.get(), - bearing, - pixelsToTileUnits); - - return util::polygonIntersectsMultiPolygon(translatedQueryGeometry.value_or(queryGeometry), feature.getGeometries()); -} - - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_fill_layer.hpp b/src/mbgl/renderer/render_fill_layer.hpp deleted file mode 100644 index d26ca10b44..0000000000 --- a/src/mbgl/renderer/render_fill_layer.hpp +++ /dev/null @@ -1,39 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace mbgl { - -class RenderFillLayer: public RenderLayer { -public: - RenderFillLayer(Immutable); - ~RenderFillLayer() final = default; - - void cascade(const CascadeParameters&) override; - void evaluate(const PropertyEvaluationParameters&) override; - bool hasTransition() const override; - - bool queryIntersectsFeature( - const GeometryCoordinates&, - const GeometryTileFeature&, - const float, - const float, - const float) const override; - - std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; - - // Paint properties - style::FillPaintProperties::Unevaluated unevaluated; - style::FillPaintProperties::Evaluated evaluated; - - const style::FillLayer::Impl& impl() const; -}; - -template <> -inline bool RenderLayer::is() const { - return type == style::LayerType::Fill; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_layer.cpp b/src/mbgl/renderer/render_layer.cpp index ca4999e606..cf7f772e16 100644 --- a/src/mbgl/renderer/render_layer.cpp +++ b/src/mbgl/renderer/render_layer.cpp @@ -1,12 +1,12 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include namespace mbgl { @@ -62,4 +62,4 @@ bool RenderLayer::needsRendering(float zoom) const { && baseImpl->maxZoom >= zoom; } -} // namespace mbgl \ No newline at end of file +} // namespace mbgl diff --git a/src/mbgl/renderer/render_line_layer.cpp b/src/mbgl/renderer/render_line_layer.cpp deleted file mode 100644 index 2c1b5a686d..0000000000 --- a/src/mbgl/renderer/render_line_layer.cpp +++ /dev/null @@ -1,116 +0,0 @@ -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -RenderLineLayer::RenderLineLayer(Immutable _impl) - : RenderLayer(style::LayerType::Line, _impl) { -} - -const style::LineLayer::Impl& RenderLineLayer::impl() const { - return static_cast(*baseImpl); -} - -std::unique_ptr RenderLineLayer::createBucket(const BucketParameters& parameters, const std::vector& layers) const { - return std::make_unique(parameters, layers, impl().layout); -} - -void RenderLineLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); -} - -void RenderLineLayer::evaluate(const PropertyEvaluationParameters& parameters) { - // for scaling dasharrays - auto dashArrayParams = parameters; - dashArrayParams.z = std::floor(dashArrayParams.z); - dashLineWidth = unevaluated.evaluate(dashArrayParams); - - evaluated = unevaluated.evaluate(parameters); - - passes = (evaluated.get().constantOr(1.0) > 0 - && evaluated.get().constantOr(Color::black()).a > 0 - && evaluated.get() > 0) - ? RenderPass::Translucent : RenderPass::None; -} - -bool RenderLineLayer::hasTransition() const { - return unevaluated.hasTransition(); -} - -optional offsetLine(const GeometryCollection& rings, const double offset) { - if (offset == 0) return {}; - - GeometryCollection newRings; - Point zero(0, 0); - for (const auto& ring : rings) { - newRings.emplace_back(); - auto& newRing = newRings.back(); - - for (auto i = ring.begin(); i != ring.end(); i++) { - auto& p = *i; - - Point aToB = i == ring.begin() ? - zero : - util::perp(util::unit(convertPoint(p - *(i - 1)))); - Point bToC = i + 1 == ring.end() ? - zero : - util::perp(util::unit(convertPoint(*(i + 1) - p))); - Point extrude = util::unit(aToB + bToC); - - const double cosHalfAngle = extrude.x * bToC.x + extrude.y * bToC.y; - extrude *= (1.0 / cosHalfAngle); - - newRing.push_back(convertPoint(extrude * offset) + p); - } - } - - return newRings; -} - -bool RenderLineLayer::queryIntersectsFeature( - const GeometryCoordinates& queryGeometry, - const GeometryTileFeature& feature, - const float zoom, - const float bearing, - const float pixelsToTileUnits) const { - - // Translate query geometry - auto translatedQueryGeometry = FeatureIndex::translateQueryGeometry( - queryGeometry, - evaluated.get(), - evaluated.get(), - bearing, - pixelsToTileUnits); - - // Evaluate function - auto offset = evaluated.get() - .evaluate(feature, zoom, style::LineOffset::defaultValue()) * pixelsToTileUnits; - - // Apply offset to geometry - auto offsetGeometry = offsetLine(feature.getGeometries(), offset); - - // Test intersection - const float halfWidth = getLineWidth(feature, zoom) / 2.0 * pixelsToTileUnits; - return util::polygonIntersectsBufferedMultiLine( - translatedQueryGeometry.value_or(queryGeometry), - offsetGeometry.value_or(feature.getGeometries()), - halfWidth); -} - -float RenderLineLayer::getLineWidth(const GeometryTileFeature& feature, const float zoom) const { - float lineWidth = evaluated.get(); - float gapWidth = evaluated.get() - .evaluate(feature, zoom, style::LineGapWidth::defaultValue()); - if (gapWidth) { - return gapWidth + 2 * lineWidth; - } else { - return lineWidth; - } -} - - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_line_layer.hpp b/src/mbgl/renderer/render_line_layer.hpp deleted file mode 100644 index 0276e6a6d9..0000000000 --- a/src/mbgl/renderer/render_line_layer.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace mbgl { - -class RenderLineLayer: public RenderLayer { -public: - RenderLineLayer(Immutable); - ~RenderLineLayer() final = default; - - void cascade(const CascadeParameters&) override; - void evaluate(const PropertyEvaluationParameters&) override; - bool hasTransition() const override; - - bool queryIntersectsFeature( - const GeometryCoordinates&, - const GeometryTileFeature&, - const float, - const float, - const float) const override; - - std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; - - // Paint properties - style::LinePaintProperties::Unevaluated unevaluated; - style::LinePaintProperties::Evaluated evaluated; - - const style::LineLayer::Impl& impl() const; - - // Special case - float dashLineWidth = 1; - -private: - float getLineWidth(const GeometryTileFeature&, const float) const; -}; - -template <> -inline bool RenderLayer::is() const { - return type == style::LayerType::Line; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_raster_layer.cpp b/src/mbgl/renderer/render_raster_layer.cpp deleted file mode 100644 index 04a52325e9..0000000000 --- a/src/mbgl/renderer/render_raster_layer.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include -#include -#include - -namespace mbgl { - -RenderRasterLayer::RenderRasterLayer(Immutable _impl) - : RenderLayer(style::LayerType::Raster, _impl) { -} - -const style::RasterLayer::Impl& RenderRasterLayer::impl() const { - return static_cast(*baseImpl); -} - -std::unique_ptr RenderRasterLayer::createBucket(const BucketParameters&, const std::vector&) const { - assert(false); - return nullptr; -} - -void RenderRasterLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); -} - -void RenderRasterLayer::evaluate(const PropertyEvaluationParameters& parameters) { - evaluated = unevaluated.evaluate(parameters); - - passes = evaluated.get() > 0 ? RenderPass::Translucent : RenderPass::None; -} - -bool RenderRasterLayer::hasTransition() const { - return unevaluated.hasTransition(); -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_raster_layer.hpp b/src/mbgl/renderer/render_raster_layer.hpp deleted file mode 100644 index 50c213aa26..0000000000 --- a/src/mbgl/renderer/render_raster_layer.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include -#include - -namespace mbgl { - -class RenderRasterLayer: public RenderLayer { -public: - RenderRasterLayer(Immutable); - ~RenderRasterLayer() final = default; - - void cascade(const CascadeParameters&) override; - void evaluate(const PropertyEvaluationParameters&) override; - bool hasTransition() const override; - - std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; - - // Paint properties - style::RasterPaintProperties::Unevaluated unevaluated; - style::RasterPaintProperties::Evaluated evaluated; - - const style::RasterLayer::Impl& impl() const; -}; - -template <> -inline bool RenderLayer::is() const { - return type == style::LayerType::Raster; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_symbol_layer.cpp b/src/mbgl/renderer/render_symbol_layer.cpp deleted file mode 100644 index 5e07b84481..0000000000 --- a/src/mbgl/renderer/render_symbol_layer.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -namespace mbgl { - -RenderSymbolLayer::RenderSymbolLayer(Immutable _impl) - : RenderLayer(style::LayerType::Symbol, _impl) { -} - -const style::SymbolLayer::Impl& RenderSymbolLayer::impl() const { - return static_cast(*baseImpl); -} - -std::unique_ptr RenderSymbolLayer::createBucket(const BucketParameters&, const std::vector&) const { - assert(false); // Should be calling createLayout() instead. - return nullptr; -} - -std::unique_ptr RenderSymbolLayer::createLayout(const BucketParameters& parameters, - const std::vector& group, - const GeometryTileLayer& layer, - GlyphDependencies& glyphDependencies, - IconDependencies& iconDependencies) const { - return std::make_unique(parameters, - group, - layer, - iconDependencies, - glyphDependencies); -} - -void RenderSymbolLayer::cascade(const CascadeParameters& parameters) { - unevaluated = impl().cascading.cascade(parameters, std::move(unevaluated)); -} - -void RenderSymbolLayer::evaluate(const PropertyEvaluationParameters& parameters) { - evaluated = unevaluated.evaluate(parameters); - - auto hasIconOpacity = evaluated.get().constantOr(Color::black()).a > 0 || - evaluated.get().constantOr(Color::black()).a > 0; - auto hasTextOpacity = evaluated.get().constantOr(Color::black()).a > 0 || - evaluated.get().constantOr(Color::black()).a > 0; - - passes = ((evaluated.get().constantOr(1) > 0 && hasIconOpacity && iconSize > 0) - || (evaluated.get().constantOr(1) > 0 && hasTextOpacity && textSize > 0)) - ? RenderPass::Translucent : RenderPass::None; -} - -bool RenderSymbolLayer::hasTransition() const { - return unevaluated.hasTransition(); -} - -style::IconPaintProperties::Evaluated RenderSymbolLayer::iconPaintProperties() const { - return style::IconPaintProperties::Evaluated { - evaluated.get(), - evaluated.get(), - evaluated.get(), - evaluated.get(), - evaluated.get(), - evaluated.get(), - evaluated.get() - }; -} - -style::TextPaintProperties::Evaluated RenderSymbolLayer::textPaintProperties() const { - return style::TextPaintProperties::Evaluated { - evaluated.get(), - evaluated.get(), - evaluated.get(), - evaluated.get(), - evaluated.get(), - evaluated.get(), - evaluated.get() - }; -} - - -style::SymbolPropertyValues RenderSymbolLayer::iconPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated& layout_) const { - return style::SymbolPropertyValues { - layout_.get(), // icon-pitch-alignment is not yet implemented; inherit the rotation alignment - layout_.get(), - layout_.get(), - evaluated.get(), - evaluated.get(), - iconSize, - 1.0f, - evaluated.get().constantOr(Color::black()).a > 0 && - evaluated.get().constantOr(1), - evaluated.get().constantOr(Color::black()).a > 0 - }; -} - -style::SymbolPropertyValues RenderSymbolLayer::textPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated& layout_) const { - return style::SymbolPropertyValues { - layout_.get(), - layout_.get(), - layout_.get(), - evaluated.get(), - evaluated.get(), - textSize, - 24.0f, - evaluated.get().constantOr(Color::black()).a > 0 && - evaluated.get().constantOr(1), - evaluated.get().constantOr(Color::black()).a > 0 - }; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/render_symbol_layer.hpp b/src/mbgl/renderer/render_symbol_layer.hpp deleted file mode 100644 index ba1b047663..0000000000 --- a/src/mbgl/renderer/render_symbol_layer.hpp +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace mbgl { - -namespace style { - -// {icon,text}-specific paint-property packs for use in the symbol Programs. -// Since each program deals either with icons or text, using a smaller property set -// lets us avoid unnecessarily binding attributes for properties the program wouldn't use. -class IconPaintProperties : public PaintProperties< - IconOpacity, - IconColor, - IconHaloColor, - IconHaloWidth, - IconHaloBlur, - IconTranslate, - IconTranslateAnchor -> {}; - -class TextPaintProperties : public PaintProperties< - TextOpacity, - TextColor, - TextHaloColor, - TextHaloWidth, - TextHaloBlur, - TextTranslate, - TextTranslateAnchor -> {}; - -// Repackaging evaluated values from SymbolLayoutProperties + SymbolPaintProperties -// for genericity over icons vs. text. -class SymbolPropertyValues { -public: - // Layout - AlignmentType pitchAlignment; - AlignmentType rotationAlignment; - PossiblyEvaluatedPropertyValue layoutSize; - - // Paint - std::array translate; - TranslateAnchorType translateAnchor; - float paintSize; - - float sdfScale; // Constant (1.0 or 24.0) - - bool hasHalo; - bool hasFill; -}; - -} // namespace style - -class BucketParameters; -class SymbolLayout; -class GeometryTileLayer; - -class RenderSymbolLayer: public RenderLayer { -public: - RenderSymbolLayer(Immutable); - ~RenderSymbolLayer() final = default; - - void cascade(const CascadeParameters&) override; - void evaluate(const PropertyEvaluationParameters&) override; - bool hasTransition() const override; - - style::IconPaintProperties::Evaluated iconPaintProperties() const; - style::TextPaintProperties::Evaluated textPaintProperties() const; - - style::SymbolPropertyValues iconPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated&) const; - style::SymbolPropertyValues textPropertyValues(const style::SymbolLayoutProperties::PossiblyEvaluated&) const; - - std::unique_ptr createBucket(const BucketParameters&, const std::vector&) const override; - std::unique_ptr createLayout(const BucketParameters&, const std::vector&, - const GeometryTileLayer&, GlyphDependencies&, IconDependencies&) const; - - // Paint properties - style::SymbolPaintProperties::Unevaluated unevaluated; - style::SymbolPaintProperties::Evaluated evaluated; - - float iconSize = 1.0f; - float textSize = 16.0f; - - const style::SymbolLayer::Impl& impl() const; -}; - -template <> -inline bool RenderLayer::is() const { - return type == style::LayerType::Symbol; -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/symbol_bucket.cpp b/src/mbgl/renderer/symbol_bucket.cpp deleted file mode 100644 index 9b016c16f9..0000000000 --- a/src/mbgl/renderer/symbol_bucket.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include -#include -#include -#include -#include - -namespace mbgl { - -using namespace style; - -SymbolBucket::SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated layout_, - const std::map>& layerPaintProperties, - const style::DataDrivenPropertyValue& textSize, - const style::DataDrivenPropertyValue& iconSize, - float zoom, - bool sdfIcons_, - bool iconsNeedLinear_) - : layout(std::move(layout_)), - sdfIcons(sdfIcons_), - iconsNeedLinear(iconsNeedLinear_ || iconSize.isDataDriven() || !iconSize.isZoomConstant()), - textSizeBinder(SymbolSizeBinder::create(zoom, textSize, TextSize::defaultValue())), - iconSizeBinder(SymbolSizeBinder::create(zoom, iconSize, IconSize::defaultValue())) { - - for (const auto& pair : layerPaintProperties) { - paintPropertyBinders.emplace( - std::piecewise_construct, - std::forward_as_tuple(pair.first), - std::forward_as_tuple( - std::piecewise_construct, - std::forward_as_tuple(pair.second.first, zoom), - std::forward_as_tuple(pair.second.second, zoom))); - } -} - -void SymbolBucket::upload(gl::Context& context) { - if (hasTextData()) { - text.vertexBuffer = context.createVertexBuffer(std::move(text.vertices)); - text.indexBuffer = context.createIndexBuffer(std::move(text.triangles)); - textSizeBinder->upload(context); - } - - if (hasIconData()) { - icon.vertexBuffer = context.createVertexBuffer(std::move(icon.vertices)); - icon.indexBuffer = context.createIndexBuffer(std::move(icon.triangles)); - iconSizeBinder->upload(context); - } - - if (!collisionBox.vertices.empty()) { - collisionBox.vertexBuffer = context.createVertexBuffer(std::move(collisionBox.vertices)); - collisionBox.indexBuffer = context.createIndexBuffer(std::move(collisionBox.lines)); - } - - for (auto& pair : paintPropertyBinders) { - pair.second.first.upload(context); - pair.second.second.upload(context); - } - - uploaded = true; -} - -void SymbolBucket::render(Painter& painter, - PaintParameters& parameters, - const RenderLayer& layer, - const RenderTile& tile) { - painter.renderSymbol(parameters, *this, *layer.as(), tile); -} - -bool SymbolBucket::hasData() const { - assert(false); // Should be calling SymbolLayout::has{Text,Icon,CollisonBox}Data() instead. - return false; -} - -bool SymbolBucket::hasTextData() const { - return !text.segments.empty(); -} - -bool SymbolBucket::hasIconData() const { - return !icon.segments.empty(); -} - -bool SymbolBucket::hasCollisionBoxData() const { - return !collisionBox.segments.empty(); -} - -} // namespace mbgl diff --git a/src/mbgl/renderer/symbol_bucket.hpp b/src/mbgl/renderer/symbol_bucket.hpp deleted file mode 100644 index f7e4bcfa20..0000000000 --- a/src/mbgl/renderer/symbol_bucket.hpp +++ /dev/null @@ -1,77 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -namespace mbgl { - -class SymbolBucket : public Bucket { -public: - SymbolBucket(style::SymbolLayoutProperties::PossiblyEvaluated, - const std::map>&, - const style::DataDrivenPropertyValue& textSize, - const style::DataDrivenPropertyValue& iconSize, - float zoom, - bool sdfIcons, - bool iconsNeedLinear); - - void upload(gl::Context&) override; - void render(Painter&, PaintParameters&, const RenderLayer&, const RenderTile&) override; - bool hasData() const override; - bool hasTextData() const; - bool hasIconData() const; - bool hasCollisionBoxData() const; - - const style::SymbolLayoutProperties::PossiblyEvaluated layout; - const bool sdfIcons; - const bool iconsNeedLinear; - - std::map> paintPropertyBinders; - - std::unique_ptr textSizeBinder; - - struct TextBuffer { - gl::VertexVector vertices; - gl::IndexVector triangles; - gl::SegmentVector segments; - - optional> vertexBuffer; - optional> indexBuffer; - } text; - - std::unique_ptr iconSizeBinder; - - struct IconBuffer { - gl::VertexVector vertices; - gl::IndexVector triangles; - gl::SegmentVector segments; - - optional> vertexBuffer; - optional> indexBuffer; - } icon; - - struct CollisionBoxBuffer { - gl::VertexVector vertices; - gl::IndexVector lines; - gl::SegmentVector segments; - - optional> vertexBuffer; - optional> indexBuffer; - } collisionBox; - - SpriteAtlas* spriteAtlas = nullptr; -}; - -} // namespace mbgl diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp index 0dcb110443..5f67d495bd 100644 --- a/src/mbgl/style/style.cpp +++ b/src/mbgl/style/style.cpp @@ -28,14 +28,14 @@ #include #include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include #include #include #include diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp index b8dc86555b..3da429ddf6 100644 --- a/src/mbgl/tile/geometry_tile.cpp +++ b/src/mbgl/tile/geometry_tile.cpp @@ -6,10 +6,10 @@ #include #include #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include #include diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp index 121960fb81..19f9532886 100644 --- a/src/mbgl/tile/geometry_tile_worker.cpp +++ b/src/mbgl/tile/geometry_tile_worker.cpp @@ -9,8 +9,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include diff --git a/src/mbgl/tile/raster_tile.cpp b/src/mbgl/tile/raster_tile.cpp index 796517b8fa..bd27ae63ca 100644 --- a/src/mbgl/tile/raster_tile.cpp +++ b/src/mbgl/tile/raster_tile.cpp @@ -7,7 +7,7 @@ #include #include #include -#include +#include #include namespace mbgl { diff --git a/src/mbgl/tile/raster_tile_worker.cpp b/src/mbgl/tile/raster_tile_worker.cpp index 8c1fc2f673..86fb5f181d 100644 --- a/src/mbgl/tile/raster_tile_worker.cpp +++ b/src/mbgl/tile/raster_tile_worker.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include diff --git a/src/mbgl/tile/tile.cpp b/src/mbgl/tile/tile.cpp index 0adc151a64..d731b8d111 100644 --- a/src/mbgl/tile/tile.cpp +++ b/src/mbgl/tile/tile.cpp @@ -1,6 +1,6 @@ #include #include -#include +#include #include #include #include diff --git a/test/gl/bucket.test.cpp b/test/gl/bucket.test.cpp index e21d82321d..e0ca635ddf 100644 --- a/test/gl/bucket.test.cpp +++ b/test/gl/bucket.test.cpp @@ -1,9 +1,9 @@ #include -#include -#include -#include -#include +#include +#include +#include +#include #include #include diff --git a/test/tile/raster_tile.test.cpp b/test/tile/raster_tile.test.cpp index f841a82e68..e363b73609 100644 --- a/test/tile/raster_tile.test.cpp +++ b/test/tile/raster_tile.test.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include using namespace mbgl; diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp index a966f3b706..2eafa4699e 100644 --- a/test/tile/vector_tile.test.cpp +++ b/test/tile/vector_tile.test.cpp @@ -10,7 +10,7 @@ #include #include #include -#include +#include #include #include #include -- cgit v1.2.1