Custom drawable layer v2 (#1754)

This commit is contained in:
Stefan Karschti
2023-10-26 21:36:50 +03:00
committed by GitHub
parent 619408d09d
commit 40e283cdbb
26 changed files with 672 additions and 227 deletions

View File

@@ -201,9 +201,10 @@ public:
/// 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;

View File

@@ -1,5 +1,6 @@
#pragma once
#include <mbgl/util/geometry.hpp>
#include <mbgl/tile/geometry_tile_data.hpp>
#include <mbgl/style/types.hpp>
#include <mbgl/gfx/vertex_vector.hpp>
@@ -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<PolylineGeneratorDistances> lineDistances;
uint32_t overscaling{1};
std::optional<PolylineGeneratorDistances> clipDistances;
};
template <class PolylineLayoutVertex, class PolylineSegment>
@@ -100,4 +101,4 @@ private:
};
} // namespace gfx
} // namespace mbgl
} // namespace mbgl

View File

@@ -6,30 +6,107 @@
#include <mbgl/renderer/update_parameters.hpp>
#include <mbgl/renderer/render_tree.hpp>
#include <mbgl/renderer/change_request.hpp>
#include <mbgl/gfx/drawable_builder.hpp>
#include <array>
#include <memory>
#include <optional>
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<UpdateParameters>&,
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>& 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<gfx::DrawableBuilder> 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>& updateParameters;
const RenderTree& renderTree;
UniqueChangeRequestVec& changes;
private:
std::unique_ptr<gfx::DrawableBuilder> builder;
std::optional<OverscaledTileID> tileID;
LineOptions lineOptions;
};
class CustomDrawableLayer final : public Layer {
public:
CustomDrawableLayer(const std::string& id, std::unique_ptr<CustomDrawableLayerHost> host);

View File

@@ -1,10 +1,10 @@
#pragma once
#include <mbgl/util/string.hpp>
#include <mapbox/compatibility/value.hpp>
#include <optional>
#include <unordered_map>
namespace mbgl {

View File

@@ -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",

View File

@@ -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,

View File

@@ -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

View File

@@ -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 <mbgl/layermanager/layer_factory.hpp>
#include <mbgl/style/layer.hpp>
#include <mbgl/style/layers/custom_drawable_layer.hpp>
#include <mbgl/util/constants.hpp>
#include <memory>
#include <cmath>
class ExampleCustomDrawableStyleLayerHost;
@implementation ExampleCustomDrawableStyleLayer
- (instancetype)initWithIdentifier:(NSString *)identifier {
auto layer = std::make_unique<mbgl::style::CustomDrawableLayer>(identifier.UTF8String,
std::make_unique<ExampleCustomDrawableStyleLayerHost>(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;
};

View File

@@ -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",

View File

@@ -0,0 +1,10 @@
#import "MLNFoundation.h"
#import "MLNStyleValue.h"
#import "MLNStyleLayer.h"
#import "MLNGeometry.h"
@interface MLNCustomDrawableStyleLayer : MLNStyleLayer
- (instancetype)initWithIdentifier:(NSString *)identifier;
@end

View File

@@ -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 <mbgl/layermanager/custom_drawable_layer_factory.hpp>
#include <mbgl/style/layers/custom_drawable_layer.hpp>
#include <memory>
#include <cmath>
@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<mbgl::style::CustomDrawableLayer>(identifier.UTF8String,
/// std::make_unique<ExampleCustomDrawableStyleLayerHost>(self));
/// return self = [super initWithPendingLayer:std::move(layer)];
/// }
///
- (instancetype)initWithIdentifier:(NSString *)identifier {
auto layer = std::make_unique<mbgl::style::CustomDrawableLayer>(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

View File

@@ -0,0 +1,15 @@
#pragma once
#include "MLNStyleLayer_Private.h"
#include <mbgl/layermanager/custom_drawable_layer_factory.hpp>
namespace mbgl {
class CustomDrawableStyleLayerPeerFactory : public LayerPeerFactory, public mbgl::CustomDrawableLayerFactory {
// LayerPeerFactory overrides.
LayerFactory* getCoreLayerFactory() final { return this; }
virtual MLNStyleLayer* createPeer(style::Layer*) final;
};
} // namespace mbgl

View File

@@ -14,6 +14,10 @@
#import "MLNOpenGLStyleLayer_Private.h"
#endif
#if MLN_DRAWABLE_RENDERER
#import "MLNCustomDrawableStyleLayer_Private.h"
#endif
#include <vector>
namespace mbgl {
@@ -69,6 +73,14 @@ LayerManagerDarwin::LayerManagerDarwin() {
#elif !defined(MBGL_LAYER_CUSTOM_DISABLE_ALL) && !MLN_RENDER_BACKEND_METAL
addLayerType(std::make_unique<OpenGLStyleLayerPeerFactory>());
#endif
#if MLN_DRAWABLE_RENDERER
#if defined(MLN_LAYER_CUSTOM_DRAWABLE_DISABLE_RUNTIME)
addLayerTypeCoreOnly(std::make_unique<CustomDrawableLayerFactory>());
#elif !defined(MLN_LAYER_CUSTOM_DRAWABLE_DISABLE_ALL)
addLayerType(std::make_unique<CustomDrawableStyleLayerPeerFactory>());
#endif
#endif
}
LayerManagerDarwin::~LayerManagerDarwin() = default;

View File

@@ -17,6 +17,10 @@
#import "LimeGreenStyleLayer.h"
#endif
#if MLN_DRAWABLE_RENDERER
#import "ExampleCustomDrawableStyleLayer.h"
#endif
#import "MBXFrameTimeGraphView.h"
#import "MLNMapView_Experimental.h"
#import <objc/runtime.h>
@@ -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 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
@"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 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
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 @@ CLLocationCoordinate2D randomWorldCoordinate(void) {
[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[] = {

View File

@@ -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

View File

@@ -70,7 +70,7 @@ void DrawableBuilder::Impl::setupForPolylines(gfx::DrawableBuilder& builder) {
gfx::VertexAttributeArray attrs;
using VertexVector = gfx::VertexVector<LineLayoutVertex>;
std::shared_ptr<VertexVector> verts = std::make_shared<VertexVector>(polylineVertices);
std::shared_ptr<VertexVector> verts = std::make_shared<VertexVector>(std::move(polylineVertices));
if (const auto& attr = attrs.add(idVertexAttribName)) {
attr->setSharedRawData(verts,

View File

@@ -65,6 +65,16 @@ public:
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<int16_t> p, Point<double> e, bool round, bool up, int8_t dir, int32_t linesofar = 0);

View File

@@ -227,7 +227,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
false,
startVertex,
triangleStore,
options.lineDistances);
options.clipDistances);
prevCoordinate = newPrevVertex;
}
}
@@ -279,7 +279,7 @@ void PolylineGenerator<PLV, PS>::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<PLV, PS>::generate(const GeometryCoordinates& coordinates
false,
startVertex,
triangleStore,
options.lineDistances);
options.clipDistances);
addCurrentVertex(*currentCoordinate,
distance,
@@ -312,7 +312,7 @@ void PolylineGenerator<PLV, PS>::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<PLV, PS>::generate(const GeometryCoordinates& coordinates
false,
startVertex,
triangleStore,
options.lineDistances);
options.clipDistances);
}
if (currentJoin == style::LineJoinType::FakeRound) {
@@ -369,7 +369,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
lineTurnsLeft,
startVertex,
triangleStore,
options.lineDistances);
options.clipDistances);
}
}
@@ -383,7 +383,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
false,
startVertex,
triangleStore,
options.lineDistances);
options.clipDistances);
}
} else if (!middleVertex && currentCap == style::LineCapType::Butt) {
@@ -397,7 +397,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
false,
startVertex,
triangleStore,
options.lineDistances);
options.clipDistances);
}
// Start next segment with a butt
@@ -410,7 +410,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
false,
startVertex,
triangleStore,
options.lineDistances);
options.clipDistances);
}
} else if (!middleVertex && currentCap == style::LineCapType::Square) {
@@ -424,7 +424,7 @@ void PolylineGenerator<PLV, PS>::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<PLV, PS>::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<PLV, PS>::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<PLV, PS>::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<PLV, PS>::generate(const GeometryCoordinates& coordinates
true,
startVertex,
triangleStore,
options.lineDistances);
options.clipDistances);
addCurrentVertex(*currentCoordinate,
distance,
@@ -492,7 +492,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
false,
startVertex,
triangleStore,
options.lineDistances);
options.clipDistances);
}
}
@@ -512,7 +512,7 @@ void PolylineGenerator<PLV, PS>::generate(const GeometryCoordinates& coordinates
false,
startVertex,
triangleStore,
options.lineDistances);
options.clipDistances);
currentCoordinate = newCurrentVertex;
}
}

View File

@@ -39,11 +39,10 @@ void DrawableGLBuilder::init() {
if (!impl->sharedIndexes && !impl->buildIndexes.empty()) {
impl->sharedIndexes = std::make_shared<gfx::IndexVectorBase>(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();
}

View File

@@ -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<decltype(verts)>::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();
}

View File

@@ -99,7 +99,7 @@ void LineBucket::addGeometry(const GeometryCoordinates& coordinates,
total_length += util::dist<double>(coordinates[i], coordinates[i + 1]);
}
options.lineDistances = gfx::PolylineGeneratorDistances{
options.clipDistances = gfx::PolylineGeneratorDistances{
*numericValue<double>(clip_start_it->second), *numericValue<double>(clip_end_it->second), total_length};
}

View File

@@ -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

View File

@@ -25,14 +25,12 @@ private:
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<style::CustomDrawableLayerHost> host;
};

View File

@@ -1,7 +1,20 @@
#include <mbgl/style/layers/custom_drawable_layer.hpp>
#include <mbgl/style/layers/custom_drawable_layer_impl.hpp>
#include <mbgl/renderer/layers/render_custom_drawable_layer.hpp>
#include <mbgl/style/layer_observer.hpp>
#include <mbgl/gfx/context.hpp>
#include <mbgl/renderer/change_request.hpp>
#include <mbgl/renderer/layer_group.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/shaders/shader_program_base.hpp>
#include <mbgl/renderer/layer_tweaker.hpp>
#include <mbgl/gfx/drawable.hpp>
#include <mbgl/gfx/drawable_tweaker.hpp>
#include <mbgl/shaders/line_layer_ubo.hpp>
#include <mbgl/util/string_indexer.hpp>
#include <mbgl/util/convert.hpp>
#include <mbgl/util/geometry.hpp>
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<float>(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>& 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<AddLayerGroupRequest>(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<LineDrawableTweaker>(linePropertiesUBO);
// finish
builder->flush();
for (auto& drawable : builder->clearDrawables()) {
assert(tileID.has_value());
drawable->setTileID(tileID.value());
drawable->addTweaker(tweaker);
TileLayerGroup* tileLayerGroup = static_cast<TileLayerGroup*>(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<StringIdentity> 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<gfx::DrawableBuilder> CustomDrawableLayerHost::Interface::createBuilder(const std::string& name,
gfx::ShaderPtr shader) const {
std::unique_ptr<gfx::DrawableBuilder> builder_ = context.createDrawableBuilder(name);
builder_->setShader(std::static_pointer_cast<gfx::ShaderProgramBase>(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

View File

@@ -13,207 +13,106 @@
#if MLN_DRAWABLE_RENDERER
#include <mbgl/style/layers/custom_drawable_layer.hpp>
#include <mbgl/gfx/context.hpp>
#include <mbgl/gfx/drawable.hpp>
#include <mbgl/gfx/drawable_tweaker.hpp>
#include <mbgl/gfx/shader_registry.hpp>
#include <mbgl/gfx/color_mode.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gfx/drawable_builder.hpp>
#include <mbgl/shaders/shader_program_base.hpp>
#include <mbgl/util/string_indexer.hpp>
#include <mbgl/renderer/layer_tweaker.hpp>
#include <mbgl/renderer/layer_group.hpp>
#include <mbgl/renderer/render_tile.hpp>
#include <mbgl/shaders/line_layer_ubo.hpp>
#include <mbgl/util/string_indexer.hpp>
#include <mbgl/util/convert.hpp>
#include <mbgl/util/constants.hpp>
#include <memory>
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<float>(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 <cmath>
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>& 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<AddLayerGroupRequest>(layerGroup_));
layerGroup = std::move(layerGroup_);
}
}
void update(Interface& interface) override {
// if we have built our drawable(s) already, either update or skip
if (interface.getDrawableCount()) return;
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<gfx::DrawableBuilder> {
std::unique_ptr<gfx::DrawableBuilder> builder = context.createDrawableBuilder(name);
builder->setShader(std::static_pointer_cast<gfx::ShaderProgramBase>(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;
};
gfx::ShaderGroupPtr lineShaderGroup = shaders.getShaderGroup("LineShader");
const std::unordered_set<StringIdentity> 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<TileLayerGroup*>(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;
gfx::PolylineGeneratorOptions options;
options.beginCap = style::LineCapType::Round;
options.endCap = style::LineCapType::Round;
options.joinType = style::LineJoinType::Round;
builder->addPolyline(geom, options);
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;
}
// create tweaker
auto tweaker = std::make_shared<TestDrawableTweaker>();
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
builder->flush();
for (auto& drawable : builder->clearDrawables()) {
drawable->setTileID(tileID);
drawable->addTweaker(tweaker);
tileLayerGroup->addDrawable(RenderPass::Translucent, tileID, std::move(drawable));
}
interface.finish();
}
void deinitialize() override {
// layerGroup->reset();
}
private:
std::shared_ptr<TileLayerGroup> layerGroup;
void deinitialize() override {}
};
TEST(CustomDrawableLayer, Basic) {
using namespace mbgl;
using namespace mbgl::style;
util::RunLoop loop;
HeadlessFrontend frontend{1};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 30 KiB