diff --git a/include/mbgl/gfx/drawable_builder.hpp b/include/mbgl/gfx/drawable_builder.hpp index e1ece18c5ee..d5cca13c424 100644 --- a/include/mbgl/gfx/drawable_builder.hpp +++ b/include/mbgl/gfx/drawable_builder.hpp @@ -201,9 +201,10 @@ class DrawableBuilder { /// Add a polyline. If the last point equals the first it will be closed, otherwise open void addPolyline(const GeometryCoordinates& coordinates, const gfx::PolylineGeneratorOptions&); -protected: + /// return the curent vertex count std::size_t curVertexCount() const; +protected: /// Create an instance of the appropriate drawable type virtual UniqueDrawable createDrawable() const = 0; diff --git a/include/mbgl/gfx/polyline_generator.hpp b/include/mbgl/gfx/polyline_generator.hpp index b54562c6777..f257523156f 100644 --- a/include/mbgl/gfx/polyline_generator.hpp +++ b/include/mbgl/gfx/polyline_generator.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -40,8 +41,8 @@ struct PolylineGeneratorOptions { style::LineCapType beginCap{style::LineCapType::Butt}; style::LineCapType endCap{style::LineCapType::Butt}; float roundLimit{1.f}; - uint32_t overscaling{1}; // TODO: what is this??? - std::optional lineDistances; + uint32_t overscaling{1}; + std::optional clipDistances; }; template @@ -100,4 +101,4 @@ class PolylineGenerator { }; } // namespace gfx -} // namespace mbgl \ No newline at end of file +} // namespace mbgl diff --git a/include/mbgl/style/layers/custom_drawable_layer.hpp b/include/mbgl/style/layers/custom_drawable_layer.hpp index 0856e919728..561a922d099 100644 --- a/include/mbgl/style/layers/custom_drawable_layer.hpp +++ b/include/mbgl/style/layers/custom_drawable_layer.hpp @@ -6,30 +6,107 @@ #include #include #include +#include #include #include +#include namespace mbgl { namespace style { class CustomDrawableLayerHost { +public: + class Interface; + public: virtual ~CustomDrawableLayerHost() = default; virtual void initialize() = 0; - virtual void update(RenderLayer& proxyLayer, - gfx::ShaderRegistry& shaders, - gfx::Context& context, - const TransformState& state, - const std::shared_ptr&, - const RenderTree& renderTree, - UniqueChangeRequestVec& changes) = 0; + virtual void update(Interface& interface) = 0; virtual void deinitialize() = 0; }; +class CustomDrawableLayerHost::Interface { +public: + struct LineOptions { + Color color; + float blur = 0.f; + float opacity = 1.f; + float gapWidth = 0.f; + float offset = 0.f; + float width = 1.f; + gfx::PolylineGeneratorOptions geometry; + }; + +public: + /// @brief Construct a new Interface object (internal core use only) + Interface(RenderLayer& layer, + LayerGroupBasePtr& layerGroup, + gfx::ShaderRegistry& shaders, + gfx::Context& context, + const TransformState& state, + const std::shared_ptr& updateParameters, + const RenderTree& renderTree, + UniqueChangeRequestVec& changes); + /** + * @brief Get the drawable count + * + * @return std::size_t + */ + std::size_t getDrawableCount() const; + + /** + * @brief Set the Tile ID + * + * @param tileID + */ + void setTileID(OverscaledTileID tileID); + + /** + * @brief Set the line options + * + * @param options + */ + void setLineOptions(const LineOptions& options); + + /** + * @brief Add a polyline + * + * @param coordinates + * @param options Polyline options + */ + void addPolyline(const GeometryCoordinates& coordinates); + + /** + * @brief Finishe the current drawable building session + * + */ + void finish(); + +protected: + gfx::ShaderPtr lineShaderDefault() const; + + std::unique_ptr createBuilder(const std::string& name, gfx::ShaderPtr shader) const; + +public: + RenderLayer& layer; + LayerGroupBasePtr& layerGroup; + gfx::ShaderRegistry& shaders; + gfx::Context& context; + const TransformState& state; + const std::shared_ptr& updateParameters; + const RenderTree& renderTree; + UniqueChangeRequestVec& changes; + +private: + std::unique_ptr builder; + std::optional tileID; + LineOptions lineOptions; +}; + class CustomDrawableLayer final : public Layer { public: CustomDrawableLayer(const std::string& id, std::unique_ptr host); diff --git a/include/mbgl/util/feature.hpp b/include/mbgl/util/feature.hpp index 4f295643851..85313865530 100644 --- a/include/mbgl/util/feature.hpp +++ b/include/mbgl/util/feature.hpp @@ -1,10 +1,10 @@ #pragma once #include - #include #include +#include namespace mbgl { diff --git a/platform/BUILD.bazel b/platform/BUILD.bazel index 7f77fff1c41..71ae8fe7976 100644 --- a/platform/BUILD.bazel +++ b/platform/BUILD.bazel @@ -15,6 +15,11 @@ objc_library( "//conditions:default": [ "//platform/darwin:darwin_objcpp_opengl_srcs", ], + }) + select({ + "//:legacy_renderer": [], + "//conditions:default": [ + "//platform/darwin:darwin_objcpp_custom_drawable_srcs", + ], }), copts = CPP_FLAGS + MAPLIBRE_FLAGS + [ "-fcxx-modules", @@ -165,6 +170,28 @@ objc_library( ], ) +objc_library( + name = "app_custom_drawable_layer_objcpp_srcs", + srcs = [ + "//platform/darwin:app/ExampleCustomDrawableStyleLayer.h", + "//platform/darwin:app/ExampleCustomDrawableStyleLayer.mm", + ], + copts = CPP_FLAGS + MAPLIBRE_FLAGS + WARNING_FLAGS["ios"] + [ + "-fcxx-modules", + "-fmodules", + "-Wno-c99-extensions", + "-Wno-gnu-zero-variadic-macro-arguments", + "-Wno-gnu-conditional-omitted-operand", + "-Wno-gnu-statement-expression", + "-Wno-deprecated-declarations", + ], + visibility = ["//visibility:public"], + deps = [ + "//:mbgl-core", + ":ios-sdk", + ], +) + objc_library( name = "iosapp", srcs = [ @@ -183,7 +210,6 @@ objc_library( includes = [ "darwin/app", "darwin/src", - "ios/src", ], sdk_frameworks = [ ] + select({ @@ -196,7 +222,12 @@ objc_library( visibility = ["//visibility:public"], deps = [ ":ios-sdk", - ], + ] + select({ + "//:legacy_renderer": [], + "//conditions:default": [ + ":app_custom_drawable_layer_objcpp_srcs", + ], + }), ) objc_library( @@ -242,6 +273,11 @@ sh_binary( "//conditions:default": [ "//platform/darwin:darwin_objcpp_opengl_srcs", ], + }) + select({ + "//:legacy_renderer": [], + "//conditions:default": [ + "//platform/darwin:darwin_objcpp_custom_drawable_srcs", + ], }), deps = [ "//platform/darwin:generated_code", diff --git a/platform/darwin/BUILD.bazel b/platform/darwin/BUILD.bazel index 72eb895cd6f..79edfbee25b 100644 --- a/platform/darwin/BUILD.bazel +++ b/platform/darwin/BUILD.bazel @@ -6,6 +6,7 @@ load( "MLN_DARWIN_PRIVATE_HEADERS", "MLN_DARWIN_PUBLIC_OBJCPP_SOURCE", "MLN_DARWIN_PUBLIC_OBJCPP_OPENGL_SOURCE", + "MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE", "MLN_DARWIN_PUBLIC_OBJC_SOURCE", "MLN_GENERATED_DARWIN_STYLE_HEADERS", "MLN_GENERATED_DARWIN_STYLE_PUBLIC_HEADERS", @@ -47,6 +48,12 @@ filegroup( visibility = ["//visibility:public"], ) +filegroup( + name = "darwin_objcpp_custom_drawable_srcs", + srcs = MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE, + visibility = ["//visibility:public"], +) + filegroup( name = "darwin_objc_srcs", srcs = MLN_DARWIN_PUBLIC_OBJC_SOURCE, @@ -324,12 +331,15 @@ exports_files( "test/MLNSDKTestHelpers.swift", "app/LimeGreenStyleLayer.h", "app/LimeGreenStyleLayer.m", + "app/ExampleCustomDrawableStyleLayer.h", + "app/ExampleCustomDrawableStyleLayer.mm", "include/mbgl/util/image+MLNAdditions.hpp", "scripts/check-public-symbols.js", "scripts/check-public-symbols.sh", ] + MLN_DARWIN_PUBLIC_OBJC_SOURCE + MLN_DARWIN_PUBLIC_OBJCPP_SOURCE + MLN_DARWIN_PUBLIC_OBJCPP_OPENGL_SOURCE + + MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE + MLN_DARWIN_PRIVATE_HEADERS + MLN_DARWIN_OBJC_HEADERS + MLN_DARWIN_OBJCPP_HEADERS, diff --git a/platform/darwin/app/ExampleCustomDrawableStyleLayer.h b/platform/darwin/app/ExampleCustomDrawableStyleLayer.h new file mode 100644 index 00000000000..2c5e558bc89 --- /dev/null +++ b/platform/darwin/app/ExampleCustomDrawableStyleLayer.h @@ -0,0 +1,12 @@ +#import "Mapbox.h" + +#import "MLNFoundation.h" +#import "MLNStyleValue.h" +#import "MLNStyleLayer.h" +#import "MLNGeometry.h" + +@interface ExampleCustomDrawableStyleLayer : MLNStyleLayer + +- (instancetype)initWithIdentifier:(NSString *)identifier; + +@end diff --git a/platform/darwin/app/ExampleCustomDrawableStyleLayer.mm b/platform/darwin/app/ExampleCustomDrawableStyleLayer.mm new file mode 100644 index 00000000000..2c4d8842901 --- /dev/null +++ b/platform/darwin/app/ExampleCustomDrawableStyleLayer.mm @@ -0,0 +1,100 @@ +#import "ExampleCustomDrawableStyleLayer.h" +#import "MLNStyleLayer.h" + +#import "MLNCustomDrawableStyleLayer_Private.h" +#import "MLNStyle_Private.h" +#import "MLNStyleLayer_Private.h" +#import "MLNGeometry_Private.h" + +#include +#include +#include +#include + +#include +#include + +class ExampleCustomDrawableStyleLayerHost; + +@implementation ExampleCustomDrawableStyleLayer + +- (instancetype)initWithIdentifier:(NSString *)identifier { + auto layer = std::make_unique(identifier.UTF8String, + std::make_unique(self)); + return self = [super initWithPendingLayer:std::move(layer)]; +} + + +@end + +class ExampleCustomDrawableStyleLayerHost : public mbgl::style::CustomDrawableLayerHost { +public: + ExampleCustomDrawableStyleLayerHost(ExampleCustomDrawableStyleLayer *styleLayer) { + layerRef = styleLayer; + layer = nil; + } + + void initialize() override { + if (layerRef == nil) return; + else if (layer == nil) layer = layerRef; + } + + void update(Interface& interface) override { + + // if we have built our drawable(s) already, either update or skip + if (interface.getDrawableCount()) + return; + + // set tile + interface.setTileID({11, 327, 791}); + + // add polylines + using namespace mbgl; + + constexpr auto numLines = 6; + Interface::LineOptions options[numLines] { + {/*color=*/Color::red(), /*blur=*/0.0f, /*opacity=*/1.0f, /*gapWidth=*/0.0f, /*offset=*/0.0f, /*width=*/8.0f, {} }, + {/*color=*/Color::blue(), /*blur=*/4.0f, /*opacity=*/1.0f, /*gapWidth=*/2.0f, /*offset=*/-1.0f, /*width=*/4.0f, {} }, + {/*color=*/Color(1.f, 0.5f, 0, 0.5f), /*blur=*/16.0f, /*opacity=*/1.0f, /*gapWidth=*/1.0f, /*offset=*/2.0f, /*width=*/16.0f, {} }, + {/*color=*/Color(1.f, 1.f, 0, 0.3f), /*blur=*/2.0f, /*opacity=*/1.0f, /*gapWidth=*/1.0f, /*offset=*/-2.0f, /*width=*/2.0f, {} }, + {/*color=*/Color::black(), /*blur=*/0.5f, /*opacity=*/0.5f, /*gapWidth=*/1.0f, /*offset=*/0.5f, /*width=*/0.5f, {} }, + {/*color=*/Color(1.f, 0, 1.f, 0.2f), /*blur=*/24.0f, /*opacity=*/0.5f, /*gapWidth=*/1.0f, /*offset=*/-5.0f, /*width=*/24.0f, {} }, + }; + for(auto& opt: options) { + opt.geometry.beginCap = style::LineCapType::Round; + opt.geometry.endCap = style::LineCapType::Round; + opt.geometry.joinType = style::LineJoinType::Round; + } + + constexpr auto numPoints = 100; + GeometryCoordinates polyline; + for (auto ipoint{0}; ipoint < numPoints; ++ipoint) { + polyline.emplace_back(ipoint * util::EXTENT / numPoints, std::sin(ipoint * 2 * M_PI / numPoints) * util::EXTENT / numLines / 2.f); + } + + for (auto index {0}; index < numLines; ++index) { + for(auto &p : polyline) { + p.y += util::EXTENT / numLines; + } + + // set property values + interface.setLineOptions(options[index]); + + // add polyline + interface.addPolyline(polyline); + } + + // finish + interface.finish(); + } + + void deinitialize() override { + if (layer == nil) return; + + layerRef = layer; + layer = nil; + } +private: + __weak ExampleCustomDrawableStyleLayer * layerRef; + ExampleCustomDrawableStyleLayer * layer = nil; +}; diff --git a/platform/darwin/bazel/files.bzl b/platform/darwin/bazel/files.bzl index 8ed70ea2dc8..df83c141247 100644 --- a/platform/darwin/bazel/files.bzl +++ b/platform/darwin/bazel/files.bzl @@ -208,6 +208,11 @@ MLN_DARWIN_PUBLIC_OBJCPP_OPENGL_SOURCE = [ "src/MLNOpenGLStyleLayer.h", "src/MLNOpenGLStyleLayer.mm", ] +MLN_DARWIN_PUBLIC_OBJCPP_CUSTOM_DRAWABLE_SOURCE = [ + "src/MLNCustomDrawableStyleLayer_Private.h", + "src/MLNCustomDrawableStyleLayer.h", + "src/MLNCustomDrawableStyleLayer.mm", +] MLN_DARWIN_PUBLIC_OBJC_SOURCE = [ "src/MLNAttributedExpression.m", "src/MLNClockDirectionFormatter.m", diff --git a/platform/darwin/src/MLNCustomDrawableStyleLayer.h b/platform/darwin/src/MLNCustomDrawableStyleLayer.h new file mode 100644 index 00000000000..6c581b3730a --- /dev/null +++ b/platform/darwin/src/MLNCustomDrawableStyleLayer.h @@ -0,0 +1,10 @@ +#import "MLNFoundation.h" +#import "MLNStyleValue.h" +#import "MLNStyleLayer.h" +#import "MLNGeometry.h" + +@interface MLNCustomDrawableStyleLayer : MLNStyleLayer + +- (instancetype)initWithIdentifier:(NSString *)identifier; + +@end diff --git a/platform/darwin/src/MLNCustomDrawableStyleLayer.mm b/platform/darwin/src/MLNCustomDrawableStyleLayer.mm new file mode 100644 index 00000000000..be3698b1316 --- /dev/null +++ b/platform/darwin/src/MLNCustomDrawableStyleLayer.mm @@ -0,0 +1,39 @@ +#import "MLNCustomDrawableStyleLayer.h" +#import "MLNStyleLayer.h" + +#import "MLNCustomDrawableStyleLayer_Private.h" +#import "MLNStyle_Private.h" +#import "MLNStyleLayer_Private.h" +#import "MLNGeometry_Private.h" + +#include +#include + +#include +#include + +@implementation MLNCustomDrawableStyleLayer + +/// @note +/// Inherit MLNCustomDrawableStyleLayer class and override initWithIdentifier method to create and attach a valid CustomDrawableLayerHost instance +/// Example: +/// - (instancetype)initWithIdentifier:(NSString *)identifier { +/// auto layer = std::make_unique(identifier.UTF8String, +/// std::make_unique(self)); +/// return self = [super initWithPendingLayer:std::move(layer)]; +/// } +/// +- (instancetype)initWithIdentifier:(NSString *)identifier { + auto layer = std::make_unique(identifier.UTF8String, nullptr); + return self = [super initWithPendingLayer:std::move(layer)]; +} + +@end + +namespace mbgl { + +MLNStyleLayer* CustomDrawableStyleLayerPeerFactory::createPeer(style::Layer* rawLayer) { + return [[MLNCustomDrawableStyleLayer alloc] initWithRawLayer:rawLayer]; +} + +} // namespace mbgl diff --git a/platform/darwin/src/MLNCustomDrawableStyleLayer_Private.h b/platform/darwin/src/MLNCustomDrawableStyleLayer_Private.h new file mode 100644 index 00000000000..9b03bbbd9e2 --- /dev/null +++ b/platform/darwin/src/MLNCustomDrawableStyleLayer_Private.h @@ -0,0 +1,15 @@ +#pragma once + +#include "MLNStyleLayer_Private.h" + +#include + +namespace mbgl { + +class CustomDrawableStyleLayerPeerFactory : public LayerPeerFactory, public mbgl::CustomDrawableLayerFactory { + // LayerPeerFactory overrides. + LayerFactory* getCoreLayerFactory() final { return this; } + virtual MLNStyleLayer* createPeer(style::Layer*) final; +}; + +} // namespace mbgl diff --git a/platform/darwin/src/MLNStyleLayerManager.mm b/platform/darwin/src/MLNStyleLayerManager.mm index 29a1a711d97..ff9ebd3a7ae 100644 --- a/platform/darwin/src/MLNStyleLayerManager.mm +++ b/platform/darwin/src/MLNStyleLayerManager.mm @@ -14,6 +14,10 @@ #import "MLNOpenGLStyleLayer_Private.h" #endif +#if MLN_DRAWABLE_RENDERER +#import "MLNCustomDrawableStyleLayer_Private.h" +#endif + #include namespace mbgl { @@ -69,6 +73,14 @@ #elif !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL) && !MLN_RENDER_BACKEND_METAL addLayerType(std::make_unique()); #endif + +#if MLN_DRAWABLE_RENDERER +#if defined(MLN_LAYER_CUSTOM_DRAWABLE_DISABLE_RUNTIME) + addLayerTypeCoreOnly(std::make_unique()); +#elif !defined(MLN_LAYER_CUSTOM_DRAWABLE_DISABLE_ALL) + addLayerType(std::make_unique()); +#endif +#endif } LayerManagerDarwin::~LayerManagerDarwin() = default; diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index 66b702c58a2..37247a23632 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -17,6 +17,10 @@ #import "LimeGreenStyleLayer.h" #endif +#if MLN_DRAWABLE_RENDERER +#import "ExampleCustomDrawableStyleLayer.h" +#endif + #import "MBXFrameTimeGraphView.h" #import "MLNMapView_Experimental.h" #import @@ -108,6 +112,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) { MBXSettingsRuntimeStylingDDSPolygon, MBXSettingsRuntimeStylingCustomLatLonGrid, MBXSettingsRuntimeStylingLineGradient, +#if MLN_DRAWABLE_RENDERER + MBXSettingsRuntimeStylingCustomDrawableLayer, +#endif }; typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) { @@ -441,6 +448,9 @@ - (void)dismissSettings:(__unused id)sender @"Dynamically Style Polygon", @"Add Custom Lat/Lon Grid", @"Style Route line with gradient", +#if MLN_DRAWABLE_RENDERER + @"Add Custom Drawable Layer", +#endif ]]; break; case MBXSettingsMiscellaneous: @@ -666,6 +676,11 @@ - (void)performActionForSettingAtIndexPath:(NSIndexPath *)indexPath case MBXSettingsRuntimeStylingLineGradient: [self styleLineGradient]; break; +#if MLN_DRAWABLE_RENDERER + case MBXSettingsRuntimeStylingCustomDrawableLayer: + [self addCustomDrawableLayer]; + break; +#endif default: NSAssert(NO, @"All runtime styling setting rows should be implemented"); break; @@ -1564,6 +1579,18 @@ - (void)styleLineGradient [self.mapView.style addLayer:routeLayer]; } +#if MLN_DRAWABLE_RENDERER +- (void)addCustomDrawableLayer +{ + // Create a CustomLayer that uses the Drawable/Builder toolkit to generate and render geometry + ExampleCustomDrawableStyleLayer* layer = [[ExampleCustomDrawableStyleLayer alloc] initWithIdentifier:@"custom-drawable-layer"]; + + if (layer) { + [self.mapView.style addLayer:layer]; + } +} +#endif + - (void)styleRouteLine { CLLocationCoordinate2D coords[] = { diff --git a/platform/ios/src/Mapbox.template.h b/platform/ios/src/Mapbox.template.h index 6554eae0ec6..43ac29b78b1 100644 --- a/platform/ios/src/Mapbox.template.h +++ b/platform/ios/src/Mapbox.template.h @@ -77,3 +77,6 @@ FOUNDATION_EXPORT MLN_EXPORT const unsigned char MapboxVersionString[]; #import "NSPredicate+MLNAdditions.h" #import "NSValue+MLNAdditions.h" #import "MLNUserLocationAnnotationViewStyle.h" +#if MLN_DRAWABLE_RENDERER +#import "MLNCustomDrawableStyleLayer.h" +#endif diff --git a/src/mbgl/gfx/drawable_builder_impl.cpp b/src/mbgl/gfx/drawable_builder_impl.cpp index 9ed34d8eda9..46e7ffa43fd 100644 --- a/src/mbgl/gfx/drawable_builder_impl.cpp +++ b/src/mbgl/gfx/drawable_builder_impl.cpp @@ -70,7 +70,7 @@ void DrawableBuilder::Impl::setupForPolylines(gfx::DrawableBuilder& builder) { gfx::VertexAttributeArray attrs; using VertexVector = gfx::VertexVector; - std::shared_ptr verts = std::make_shared(polylineVertices); + std::shared_ptr verts = std::make_shared(std::move(polylineVertices)); if (const auto& attr = attrs.add(idVertexAttribName)) { attr->setSharedRawData(verts, diff --git a/src/mbgl/gfx/drawable_builder_impl.hpp b/src/mbgl/gfx/drawable_builder_impl.hpp index 292519aba08..da12d46d674 100644 --- a/src/mbgl/gfx/drawable_builder_impl.hpp +++ b/src/mbgl/gfx/drawable_builder_impl.hpp @@ -65,6 +65,16 @@ class DrawableBuilder::Impl { return std::max(rawVerticesCount, std::max(vertices.elements(), polylineVertices.elements())); } + void clear() { + vertices.clear(); + rawVertices.clear(); + rawVerticesCount = 0; + polylineVertices.clear(); + polylineIndexes.clear(); + buildIndexes.clear(); + segments.clear(); + } + private: LineLayoutVertex layoutVertex( Point p, Point e, bool round, bool up, int8_t dir, int32_t linesofar = 0); diff --git a/src/mbgl/gfx/polyline_generator.cpp b/src/mbgl/gfx/polyline_generator.cpp index 51ccdf52e3c..beac5d57765 100644 --- a/src/mbgl/gfx/polyline_generator.cpp +++ b/src/mbgl/gfx/polyline_generator.cpp @@ -227,7 +227,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); prevCoordinate = newPrevVertex; } } @@ -279,7 +279,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); } else if (middleVertex && currentJoin == style::LineJoinType::FlipBevel) { // miter is too big, flip the direction to make a beveled join @@ -302,7 +302,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); addCurrentVertex(*currentCoordinate, distance, @@ -312,7 +312,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); } else if (middleVertex && (currentJoin == style::LineJoinType::Bevel || currentJoin == style::LineJoinType::FakeRound)) { const bool lineTurnsLeft = (prevNormal->x * nextNormal->y - prevNormal->y * nextNormal->x) > 0; @@ -338,7 +338,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); } if (currentJoin == style::LineJoinType::FakeRound) { @@ -369,7 +369,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates lineTurnsLeft, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); } } @@ -383,7 +383,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); } } else if (!middleVertex && currentCap == style::LineCapType::Butt) { @@ -397,7 +397,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); } // Start next segment with a butt @@ -410,7 +410,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); } } else if (!middleVertex && currentCap == style::LineCapType::Square) { @@ -424,7 +424,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); // The segment is done. Unset vertices to disconnect segments. e1 = e2 = -1; @@ -440,7 +440,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); } } else if (middleVertex ? currentJoin == style::LineJoinType::Round : currentCap == style::LineCapType::Round) { @@ -454,7 +454,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); // Add round cap or linejoin at end of segment addCurrentVertex(*currentCoordinate, @@ -465,7 +465,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates true, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); // The segment is done. Unset vertices to disconnect segments. e1 = e2 = -1; @@ -482,7 +482,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates true, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); addCurrentVertex(*currentCoordinate, distance, @@ -492,7 +492,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); } } @@ -512,7 +512,7 @@ void PolylineGenerator::generate(const GeometryCoordinates& coordinates false, startVertex, triangleStore, - options.lineDistances); + options.clipDistances); currentCoordinate = newCurrentVertex; } } diff --git a/src/mbgl/gl/drawable_gl_builder.cpp b/src/mbgl/gl/drawable_gl_builder.cpp index 22bf7921427..f1269e9e363 100644 --- a/src/mbgl/gl/drawable_gl_builder.cpp +++ b/src/mbgl/gl/drawable_gl_builder.cpp @@ -39,11 +39,10 @@ void DrawableGLBuilder::init() { if (!impl->sharedIndexes && !impl->buildIndexes.empty()) { impl->sharedIndexes = std::make_shared(std::move(impl->buildIndexes)); } + assert(impl->sharedIndexes && impl->sharedIndexes->elements()); drawableGL.setIndexData(std::move(impl->sharedIndexes), std::move(impl->segments)); - impl->buildIndexes.clear(); - impl->segments.clear(); - impl->vertices.clear(); + impl->clear(); textures.clear(); } diff --git a/src/mbgl/mtl/drawable_builder.cpp b/src/mbgl/mtl/drawable_builder.cpp index 4144f802be9..741db0a78f7 100644 --- a/src/mbgl/mtl/drawable_builder.cpp +++ b/src/mbgl/mtl/drawable_builder.cpp @@ -27,6 +27,7 @@ void DrawableBuilder::init() { if (impl->rawVerticesCount) { auto raw = impl->rawVertices; drawable.setVertices(std::move(raw), impl->rawVerticesCount, impl->rawVerticesType); + impl->rawVerticesCount = 0; } else { const auto& verts = impl->vertices.vector(); constexpr auto vertSize = sizeof(std::remove_reference::type::value_type); @@ -41,9 +42,7 @@ void DrawableBuilder::init() { assert(impl->sharedIndexes && impl->sharedIndexes->elements()); drawable.setIndexData(std::move(impl->sharedIndexes), std::move(impl->segments)); - impl->buildIndexes.clear(); - impl->segments.clear(); - impl->vertices.clear(); + impl->clear(); textures.clear(); } diff --git a/src/mbgl/renderer/buckets/line_bucket.cpp b/src/mbgl/renderer/buckets/line_bucket.cpp index 5458074b834..5e2825b1b34 100644 --- a/src/mbgl/renderer/buckets/line_bucket.cpp +++ b/src/mbgl/renderer/buckets/line_bucket.cpp @@ -99,7 +99,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates, total_length += util::dist(coordinates[i], coordinates[i + 1]); } - options.lineDistances = gfx::PolylineGeneratorDistances{ + options.clipDistances = gfx::PolylineGeneratorDistances{ *numericValue(clip_start_it->second), *numericValue(clip_end_it->second), total_length}; } diff --git a/src/mbgl/renderer/layers/render_custom_drawable_layer.cpp b/src/mbgl/renderer/layers/render_custom_drawable_layer.cpp index b05965a750c..c6f22075692 100644 --- a/src/mbgl/renderer/layers/render_custom_drawable_layer.cpp +++ b/src/mbgl/renderer/layers/render_custom_drawable_layer.cpp @@ -52,10 +52,6 @@ bool RenderCustomDrawableLayer::hasCrossfade() const { return false; } -void RenderCustomDrawableLayer::markContextDestroyed() { - contextDestroyed = true; -} - void RenderCustomDrawableLayer::prepare(const LayerPrepareParameters&) {} #if MLN_LEGACY_RENDERER @@ -84,9 +80,12 @@ void RenderCustomDrawableLayer::update(gfx::ShaderRegistry& shaders, // delegate the call to the custom layer if (host) { - host->update(*this, shaders, context, state, updateParameters, renderTree, changes); + CustomDrawableLayerHost::Interface interface( + *this, layerGroup, shaders, context, state, updateParameters, renderTree, changes); + host->update(interface); } } + #endif } // namespace mbgl diff --git a/src/mbgl/renderer/layers/render_custom_drawable_layer.hpp b/src/mbgl/renderer/layers/render_custom_drawable_layer.hpp index bd03b6e8ec8..9a4591a0616 100644 --- a/src/mbgl/renderer/layers/render_custom_drawable_layer.hpp +++ b/src/mbgl/renderer/layers/render_custom_drawable_layer.hpp @@ -25,14 +25,12 @@ class RenderCustomDrawableLayer final : public RenderLayer { void evaluate(const PropertyEvaluationParameters&) override; bool hasTransition() const override; bool hasCrossfade() const override; - void markContextDestroyed() override; void prepare(const LayerPrepareParameters&) override; #if MLN_LEGACY_RENDERER void render(PaintParameters&) override; #endif - bool contextDestroyed = false; std::shared_ptr host; }; diff --git a/src/mbgl/style/layers/custom_drawable_layer.cpp b/src/mbgl/style/layers/custom_drawable_layer.cpp index a70dd0d9b85..17e16921f8e 100644 --- a/src/mbgl/style/layers/custom_drawable_layer.cpp +++ b/src/mbgl/style/layers/custom_drawable_layer.cpp @@ -1,7 +1,20 @@ #include #include + #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include namespace mbgl { namespace style { @@ -53,5 +66,185 @@ const LayerTypeInfo* CustomDrawableLayer::Impl::staticTypeInfo() noexcept { return &typeInfoCustomDrawable; } +// CustomDrawableLayerHost::Interface + +class LineDrawableTweaker : public gfx::DrawableTweaker { +public: + LineDrawableTweaker(const shaders::LinePropertiesUBO& properties) + : linePropertiesUBO(properties) {} + ~LineDrawableTweaker() override = default; + + void init(gfx::Drawable&) override{}; + + void execute(gfx::Drawable& drawable, const PaintParameters& parameters) override { + if (!drawable.getTileID().has_value()) { + return; + } + + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + const auto zoom = parameters.state.getZoom(); + mat4 tileMatrix; + parameters.state.matrixFor(/*out*/ tileMatrix, tileID); + + const auto matrix = LayerTweaker::getTileMatrix( + tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, false); + + static const StringIdentity idLineUBOName = stringIndexer().get("LineUBO"); + const shaders::LineUBO lineUBO{ + /*matrix = */ util::cast(matrix), + /*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, + /*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, zoom), + /*device_pixel_ratio = */ parameters.pixelRatio}; + + static const StringIdentity idLinePropertiesUBOName = stringIndexer().get("LinePropertiesUBO"); + + static const StringIdentity idLineInterpolationUBOName = stringIndexer().get("LineInterpolationUBO"); + const shaders::LineInterpolationUBO lineInterpolationUBO{/*color_t =*/0.f, + /*blur_t =*/0.f, + /*opacity_t =*/0.f, + /*gapwidth_t =*/0.f, + /*offset_t =*/0.f, + /*width_t =*/0.f, + 0, + 0}; + auto& uniforms = drawable.mutableUniformBuffers(); + uniforms.createOrUpdate(idLineUBOName, &lineUBO, parameters.context); + uniforms.createOrUpdate(idLinePropertiesUBOName, &linePropertiesUBO, parameters.context); + uniforms.createOrUpdate(idLineInterpolationUBOName, &lineInterpolationUBO, parameters.context); + +#if MLN_RENDER_BACKEND_METAL + static const StringIdentity idExpressionInputsUBOName = stringIndexer().get("ExpressionInputsUBO"); + const auto expressionUBO = LayerTweaker::buildExpressionUBO(zoom, parameters.frameCount); + uniforms.createOrUpdate(idExpressionInputsUBOName, &expressionUBO, parameters.context); + + static const StringIdentity idLinePermutationUBOName = stringIndexer().get("LinePermutationUBO"); + const shaders::LinePermutationUBO permutationUBO = { + /* .color = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .blur = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .opacity = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .gapwidth = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .offset = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .width = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .floorwidth = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .pattern_from = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .pattern_to = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, + /* .overdrawInspector = */ false, + /* .pad = */ 0, + 0, + 0, + 0}; + uniforms.createOrUpdate(idLinePermutationUBOName, &permutationUBO, parameters.context); +#endif // MLN_RENDER_BACKEND_METAL + }; + +private: + shaders::LinePropertiesUBO linePropertiesUBO; +}; + +CustomDrawableLayerHost::Interface::Interface(RenderLayer& layer_, + LayerGroupBasePtr& layerGroup_, + gfx::ShaderRegistry& shaders_, + gfx::Context& context_, + const TransformState& state_, + const std::shared_ptr& updateParameters_, + const RenderTree& renderTree_, + UniqueChangeRequestVec& changes_) + : layer(layer_), + layerGroup(layerGroup_), + shaders(shaders_), + context(context_), + state(state_), + updateParameters(updateParameters_), + renderTree(renderTree_), + changes(changes_) { + // ensure we have a default layer group set up + if (!layerGroup) { + if (auto aLayerGroup = context.createTileLayerGroup( + /*layerIndex*/ layer.getLayerIndex(), /*initialCapacity=*/64, layer.getID())) { + changes.emplace_back(std::make_unique(aLayerGroup)); + layerGroup = std::move(aLayerGroup); + } + } +} + +std::size_t CustomDrawableLayerHost::Interface::getDrawableCount() const { + return layerGroup->getDrawableCount(); +} + +void CustomDrawableLayerHost::Interface::setTileID(OverscaledTileID tileID_) { + tileID = tileID_; +} + +void CustomDrawableLayerHost::Interface::setLineOptions(const LineOptions& options) { + finish(); + lineOptions = options; +} + +void CustomDrawableLayerHost::Interface::addPolyline(const GeometryCoordinates& coordinates) { + if (!builder) { + builder = createBuilder("thick-lines", lineShaderDefault()); + } else { + // TODO: check builder + } + builder->addPolyline(coordinates, lineOptions.geometry); +} + +void CustomDrawableLayerHost::Interface::finish() { + if (builder && builder->curVertexCount()) { + // create tweaker + const shaders::LinePropertiesUBO linePropertiesUBO{lineOptions.color, + lineOptions.blur, + lineOptions.opacity, + lineOptions.gapWidth, + lineOptions.offset, + lineOptions.width, + 0, + 0, + 0}; + + auto tweaker = std::make_shared(linePropertiesUBO); + + // finish + builder->flush(); + for (auto& drawable : builder->clearDrawables()) { + assert(tileID.has_value()); + drawable->setTileID(tileID.value()); + drawable->addTweaker(tweaker); + + TileLayerGroup* tileLayerGroup = static_cast(layerGroup.get()); + tileLayerGroup->addDrawable(RenderPass::Translucent, tileID.value(), std::move(drawable)); + } + } +} + +gfx::ShaderPtr CustomDrawableLayerHost::Interface::lineShaderDefault() const { + gfx::ShaderGroupPtr lineShaderGroup = shaders.getShaderGroup("LineShader"); + + const std::unordered_set propertiesAsUniforms{ + stringIndexer().get("a_color"), + stringIndexer().get("a_blur"), + stringIndexer().get("a_opacity"), + stringIndexer().get("a_gapwidth"), + stringIndexer().get("a_offset"), + stringIndexer().get("a_width"), + }; + + return lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms); +} + +std::unique_ptr CustomDrawableLayerHost::Interface::createBuilder(const std::string& name, + gfx::ShaderPtr shader) const { + std::unique_ptr builder_ = context.createDrawableBuilder(name); + builder_->setShader(std::static_pointer_cast(shader)); + builder_->setSubLayerIndex(0); + builder_->setEnableDepth(false); + builder_->setColorMode(gfx::ColorMode::alphaBlended()); + builder_->setCullFaceMode(gfx::CullFaceMode::disabled()); + builder_->setEnableStencil(false); + builder_->setRenderPass(RenderPass::Translucent); + + return builder_; +} + } // namespace style } // namespace mbgl diff --git a/test/api/custom_drawable_layer.test.cpp b/test/api/custom_drawable_layer.test.cpp index 990d7bceb75..5673cbe1422 100644 --- a/test/api/custom_drawable_layer.test.cpp +++ b/test/api/custom_drawable_layer.test.cpp @@ -13,207 +13,106 @@ #if MLN_DRAWABLE_RENDERER #include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include +#include #include - -using namespace mbgl; -using namespace mbgl::style; - -class TestDrawableTweaker : public gfx::DrawableTweaker { -public: - TestDrawableTweaker() {} - ~TestDrawableTweaker() override = default; - - void init(gfx::Drawable&) override{}; - - void execute(gfx::Drawable& drawable, const PaintParameters& parameters) override { - if (!drawable.getTileID().has_value()) { - return; - } - - const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); - const auto zoom = parameters.state.getZoom(); - mat4 tileMatrix; - parameters.state.matrixFor(/*out*/ tileMatrix, tileID); - - const auto matrix = LayerTweaker::getTileMatrix( - tileID, parameters, {{0, 0}}, style::TranslateAnchorType::Viewport, false, false, false); - - static const StringIdentity idLineUBOName = stringIndexer().get("LineUBO"); - const shaders::LineUBO lineUBO{ - /*matrix = */ util::cast(matrix), - /*units_to_pixels = */ {1.0f / parameters.pixelsToGLUnits[0], 1.0f / parameters.pixelsToGLUnits[1]}, - /*ratio = */ 1.0f / tileID.pixelsToTileUnits(1.0f, zoom), - /*device_pixel_ratio = */ parameters.pixelRatio}; - - static const StringIdentity idLinePropertiesUBOName = stringIndexer().get("LinePropertiesUBO"); - const shaders::LinePropertiesUBO linePropertiesUBO{/*color =*/Color(1.f, 0.f, 1.f, 1.f), - /*blur =*/0.f, - /*opacity =*/1.f, - /*gapwidth =*/0.f, - /*offset =*/0.f, - /*width =*/8.f, - 0, - 0, - 0}; - - static const StringIdentity idLineInterpolationUBOName = stringIndexer().get("LineInterpolationUBO"); - const shaders::LineInterpolationUBO lineInterpolationUBO{/*color_t =*/0.f, - /*blur_t =*/0.f, - /*opacity_t =*/0.f, - /*gapwidth_t =*/0.f, - /*offset_t =*/0.f, - /*width_t =*/0.f, - 0, - 0}; - auto& uniforms = drawable.mutableUniformBuffers(); - uniforms.createOrUpdate(idLineUBOName, &lineUBO, parameters.context); - uniforms.createOrUpdate(idLinePropertiesUBOName, &linePropertiesUBO, parameters.context); - uniforms.createOrUpdate(idLineInterpolationUBOName, &lineInterpolationUBO, parameters.context); - -#if MLN_RENDER_BACKEND_METAL - static const StringIdentity idExpressionInputsUBOName = stringIndexer().get("ExpressionInputsUBO"); - const auto expressionUBO = LayerTweaker::buildExpressionUBO(zoom, parameters.frameCount); - uniforms.createOrUpdate(idExpressionInputsUBOName, &expressionUBO, parameters.context); - - static const StringIdentity idLinePermutationUBOName = stringIndexer().get("LinePermutationUBO"); - const shaders::LinePermutationUBO permutationUBO = { - /* .color = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, - /* .blur = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, - /* .opacity = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, - /* .gapwidth = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, - /* .offset = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, - /* .width = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, - /* .floorwidth = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, - /* .pattern_from = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, - /* .pattern_to = */ {/*.source=*/shaders::AttributeSource::Constant, /*.expression=*/{}}, - /* .overdrawInspector = */ false, - /* .pad = */ 0, - 0, - 0, - 0}; - uniforms.createOrUpdate(idLinePermutationUBOName, &permutationUBO, parameters.context); -#endif // MLN_RENDER_BACKEND_METAL - }; -}; +#include class TestDrawableLayer : public mbgl::style::CustomDrawableLayerHost { public: void initialize() override {} - /** - * @brief Create Drawables for the Custom Drawable Layer - * - * @param proxyLayer - * @param shaders - * @param context - * @param state - * @param updateParameters - * @param renderTree - * @param changes - */ - void update(RenderLayer& proxyLayer, - gfx::ShaderRegistry& shaders, - gfx::Context& context, - [[maybe_unused]] const TransformState& state, - [[maybe_unused]] const std::shared_ptr& updateParameters, - [[maybe_unused]] const RenderTree& renderTree, - UniqueChangeRequestVec& changes) override { - // Set up a layer group - if (!layerGroup) { - if (auto layerGroup_ = context.createTileLayerGroup( - /*layerIndex*/ proxyLayer.getLayerIndex(), /*initialCapacity=*/2, proxyLayer.getID())) { - changes.emplace_back(std::make_unique(layerGroup_)); - layerGroup = std::move(layerGroup_); - } - } - - if (!layerGroup) return; - - // if we have build our drawable(s) already, either update or skip - if (layerGroup->getDrawableCount()) return; - - // create drawable(s) - const OverscaledTileID tileID{11, 327, 791}; - - auto createLineBuilder = [&](const std::string& name, - gfx::ShaderPtr shader) -> std::unique_ptr { - std::unique_ptr builder = context.createDrawableBuilder(name); - builder->setShader(std::static_pointer_cast(shader)); - builder->setSubLayerIndex(0); - builder->setEnableDepth(false); - builder->setColorMode(gfx::ColorMode::alphaBlended()); - builder->setCullFaceMode(gfx::CullFaceMode::disabled()); - builder->setEnableStencil(false); - builder->setRenderPass(RenderPass::Translucent); + void update(Interface& interface) override { + // if we have built our drawable(s) already, either update or skip + if (interface.getDrawableCount()) return; - return builder; - }; - - gfx::ShaderGroupPtr lineShaderGroup = shaders.getShaderGroup("LineShader"); - - const std::unordered_set propertiesAsUniforms{ - stringIndexer().get("a_color"), - stringIndexer().get("a_blur"), - stringIndexer().get("a_opacity"), - stringIndexer().get("a_gapwidth"), - stringIndexer().get("a_offset"), - stringIndexer().get("a_width"), - }; - - auto shader = lineShaderGroup->getOrCreateShader(context, propertiesAsUniforms); - auto builder = createLineBuilder("thick-lines", shader); - - auto* tileLayerGroup = static_cast(layerGroup.get()); + // set tile + interface.setTileID({11, 327, 791}); // add polylines - const auto size{util::EXTENT}; - GeometryCoordinates geom{{0, 0}, {size, 0}, {0, size}, {size, size}, {size / 3, size / 3}}; + using namespace mbgl; + + constexpr auto numLines = 6; + Interface::LineOptions options[numLines]{ + {/*color=*/Color::red(), + /*blur=*/0.0f, + /*opacity=*/1.0f, + /*gapWidth=*/0.0f, + /*offset=*/0.0f, + /*width=*/8.0f, + {}}, + {/*color=*/Color::blue(), + /*blur=*/4.0f, + /*opacity=*/1.0f, + /*gapWidth=*/2.0f, + /*offset=*/-1.0f, + /*width=*/4.0f, + {}}, + {/*color=*/Color(1.f, 0.5f, 0, 0.5f), + /*blur=*/16.0f, + /*opacity=*/1.0f, + /*gapWidth=*/1.0f, + /*offset=*/2.0f, + /*width=*/16.0f, + {}}, + {/*color=*/Color(1.f, 1.f, 0, 0.3f), + /*blur=*/2.0f, + /*opacity=*/1.0f, + /*gapWidth=*/1.0f, + /*offset=*/-2.0f, + /*width=*/2.0f, + {}}, + {/*color=*/Color::black(), + /*blur=*/0.5f, + /*opacity=*/0.5f, + /*gapWidth=*/1.0f, + /*offset=*/0.5f, + /*width=*/0.5f, + {}}, + {/*color=*/Color(1.f, 0, 1.f, 0.2f), + /*blur=*/24.0f, + /*opacity=*/0.5f, + /*gapWidth=*/1.0f, + /*offset=*/-5.0f, + /*width=*/24.0f, + {}}, + }; + for (auto& opt : options) { + opt.geometry.beginCap = style::LineCapType::Round; + opt.geometry.endCap = style::LineCapType::Round; + opt.geometry.joinType = style::LineJoinType::Round; + } - gfx::PolylineGeneratorOptions options; - options.beginCap = style::LineCapType::Round; - options.endCap = style::LineCapType::Round; - options.joinType = style::LineJoinType::Round; - builder->addPolyline(geom, options); + constexpr auto numPoints = 100; + GeometryCoordinates polyline; + for (auto ipoint{0}; ipoint < numPoints; ++ipoint) { + polyline.emplace_back(ipoint * util::EXTENT / numPoints, + std::sin(ipoint * 2 * M_PI / numPoints) * util::EXTENT / numLines / 2.f); + } - // create tweaker - auto tweaker = std::make_shared(); + for (auto index{0}; index < numLines; ++index) { + for (auto& p : polyline) { + p.y += util::EXTENT / numLines; + } - // finish - builder->flush(); - for (auto& drawable : builder->clearDrawables()) { - drawable->setTileID(tileID); - drawable->addTweaker(tweaker); + // set property values + interface.setLineOptions(options[index]); - tileLayerGroup->addDrawable(RenderPass::Translucent, tileID, std::move(drawable)); + // add polyline + interface.addPolyline(polyline); } - } - void deinitialize() override { - // layerGroup->reset(); + // finish + interface.finish(); } -private: - std::shared_ptr layerGroup; + void deinitialize() override {} }; TEST(CustomDrawableLayer, Basic) { + using namespace mbgl; + using namespace mbgl::style; + util::RunLoop loop; HeadlessFrontend frontend{1}; diff --git a/test/fixtures/custom_drawable_layer/basic/expected.png b/test/fixtures/custom_drawable_layer/basic/expected.png index 11898f329ef..4aa9e67a43c 100644 Binary files a/test/fixtures/custom_drawable_layer/basic/expected.png and b/test/fixtures/custom_drawable_layer/basic/expected.png differ