diff --git a/CMakeLists.txt b/CMakeLists.txt index e2db1e680..5c760b88b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -141,6 +141,7 @@ list(APPEND INCLUDE_FILES ${PROJECT_SOURCE_DIR}/include/mbgl/annotation/annotation.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/backend_scope.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable.hpp + ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_data.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_impl.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_builder.hpp ${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_tweaker.hpp @@ -384,6 +385,7 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/draw_mode.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/draw_scope.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/image_drawable_data.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_builder.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_builder_impl.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_tweaker.cpp @@ -526,6 +528,7 @@ list(APPEND SRC_FILES ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager_observer.hpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layer_group.cpp + ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/tile_layer_group.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layer_tweaker.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/background_layer_tweaker.cpp ${PROJECT_SOURCE_DIR}/src/mbgl/renderer/layers/background_layer_tweaker.hpp diff --git a/include/mbgl/gfx/drawable.hpp b/include/mbgl/gfx/drawable.hpp index bda93e5e6..2041f6405 100644 --- a/include/mbgl/gfx/drawable.hpp +++ b/include/mbgl/gfx/drawable.hpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include @@ -167,6 +168,9 @@ public: static_cast(components[3])}; } + virtual const std::optional& getData() const { return drawableData; } + virtual void setData(UniqueDrawableData&& value) { drawableData = std::move(value); } + protected: bool enabled = true; bool needsStencil = false; @@ -179,6 +183,7 @@ protected: int32_t lineWidth = 1; int32_t subLayerIndex = 0; DepthMaskType depthType; // = DepthMaskType::ReadOnly; + std::optional drawableData{}; struct Impl; std::unique_ptr impl; diff --git a/include/mbgl/gfx/drawable_data.hpp b/include/mbgl/gfx/drawable_data.hpp new file mode 100644 index 000000000..d596c5944 --- /dev/null +++ b/include/mbgl/gfx/drawable_data.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +namespace mbgl { + +namespace gfx { + +class DrawableData { +public: + virtual ~DrawableData() = default; +}; + +using UniqueDrawableData = std::unique_ptr; + +} // namespace gfx +} // namespace mbgl diff --git a/include/mbgl/gl/layer_group_gl.hpp b/include/mbgl/gl/layer_group_gl.hpp index b44ba9f84..6b3a83fa6 100644 --- a/include/mbgl/gl/layer_group_gl.hpp +++ b/include/mbgl/gl/layer_group_gl.hpp @@ -19,5 +19,19 @@ public: protected: }; +/** + A layer group for non-tile-based drawables + */ +class LayerGroupGL : public LayerGroup { +public: + LayerGroupGL(int32_t layerIndex, std::size_t initialCapacity, std::string name); + ~LayerGroupGL() override {} + + void upload(gfx::UploadPass&) override; + void render(RenderOrchestrator&, PaintParameters&) override; + +protected: +}; + } // namespace gl } // namespace mbgl diff --git a/include/mbgl/renderer/change_request.hpp b/include/mbgl/renderer/change_request.hpp index 918c014f6..5d3ddf4a5 100644 --- a/include/mbgl/renderer/change_request.hpp +++ b/include/mbgl/renderer/change_request.hpp @@ -8,14 +8,14 @@ namespace mbgl { class ChangeRequest; -class LayerGroup; +class LayerGroupBase; class TileLayerGroup; class RenderOrchestrator; using ChangeRequestPtr = std::shared_ptr; using UniqueChangeRequest = std::unique_ptr; using UniqueChangeRequestVec = std::vector; -using LayerGroupPtr = std::shared_ptr; +using LayerGroupBasePtr = std::shared_ptr; namespace gfx { class Drawable; @@ -52,13 +52,13 @@ protected: */ class AddLayerGroupRequest : public ChangeRequest { public: - AddLayerGroupRequest(LayerGroupPtr layerGroup_, bool canReplace); + AddLayerGroupRequest(LayerGroupBasePtr layerGroup_, bool canReplace); AddLayerGroupRequest(AddLayerGroupRequest &&other); void execute(RenderOrchestrator &) override; protected: - LayerGroupPtr layerGroup; + LayerGroupBasePtr layerGroup; bool replace; }; diff --git a/include/mbgl/renderer/layer_group.hpp b/include/mbgl/renderer/layer_group.hpp index 1e81b0571..6806c8e8b 100644 --- a/include/mbgl/renderer/layer_group.hpp +++ b/include/mbgl/renderer/layer_group.hpp @@ -10,12 +10,12 @@ #include namespace mbgl { -class LayerGroup; +class LayerGroupBase; class PaintParameters; class RenderOrchestrator; class TileLayerGroup; -using LayerGroupPtr = std::shared_ptr; +using LayerGroupBasePtr = std::shared_ptr; namespace gfx { class Context; @@ -32,13 +32,14 @@ using LayerTweakerPtr = std::shared_ptr; /** A layer-like group of drawables, not a group of layers. */ -class LayerGroup : public util::SimpleIdentifiable { +class LayerGroupBase : public util::SimpleIdentifiable { protected: - LayerGroup(int32_t layerIndex, std::string name = std::string()); + LayerGroupBase(int32_t layerIndex, std::string name = std::string()); public: - LayerGroup(const LayerGroup&) = delete; - LayerGroup& operator=(const LayerGroup&) = delete; + LayerGroupBase(const LayerGroupBase&) = delete; + LayerGroupBase& operator=(const LayerGroupBase&) = delete; + virtual ~LayerGroupBase() = default; /// Whether the drawables should be drawn bool getEnabled() const { return enabled; } @@ -84,7 +85,7 @@ protected: /** A layer group for tile-based drawables. */ -class TileLayerGroup : public LayerGroup { +class TileLayerGroup : public LayerGroupBase { public: TileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name); ~TileLayerGroup() override; @@ -112,4 +113,31 @@ protected: std::unique_ptr impl; }; +/** + A layer group for non-tile-based drawables. + */ +class LayerGroup : public LayerGroupBase { +public: + LayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name); + ~LayerGroup() override; + + void updateLayerIndex(int32_t newLayerIndex); + + std::size_t getDrawableCount() const override; + std::size_t getDrawableCount(mbgl::RenderPass) const; + + std::vector removeDrawables(mbgl::RenderPass); + void addDrawable(gfx::UniqueDrawable&&); + + void observeDrawables(std::function) override; + void observeDrawables(std::function) const override; + void observeDrawables(std::function) override; + + std::size_t clearDrawables(); + +protected: + struct Impl; + std::unique_ptr impl; +}; + } // namespace mbgl diff --git a/include/mbgl/renderer/layer_tweaker.hpp b/include/mbgl/renderer/layer_tweaker.hpp index bd10c3f7c..518b7276b 100644 --- a/include/mbgl/renderer/layer_tweaker.hpp +++ b/include/mbgl/renderer/layer_tweaker.hpp @@ -11,7 +11,7 @@ class LayerProperties; enum class TranslateAnchorType : bool; } // namespace style class TransformState; -class LayerGroup; +class LayerGroupBase; class PaintParameters; class RenderTree; class UnwrappedTileID; @@ -29,7 +29,7 @@ public: LayerTweaker() = delete; virtual ~LayerTweaker() = default; - virtual void execute(LayerGroup&, const RenderTree&, const PaintParameters&) = 0; + virtual void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) = 0; protected: static mat4 getTileMatrix(const UnwrappedTileID&, diff --git a/src/mbgl/gfx/context.hpp b/src/mbgl/gfx/context.hpp index 63f6bea0c..fd811a23d 100644 --- a/src/mbgl/gfx/context.hpp +++ b/src/mbgl/gfx/context.hpp @@ -18,7 +18,9 @@ namespace mbgl { class PaintParameters; class ProgramParameters; class TileLayerGroup; +class LayerGroup; using TileLayerGroupPtr = std::shared_ptr; +using LayerGroupPtr = std::shared_ptr; namespace gfx { @@ -115,11 +117,14 @@ public: /// Get the generic shader with the specified name virtual gfx::ShaderProgramBasePtr getGenericShader(gfx::ShaderRegistry&, const std::string& name) = 0; - /// Create a layer group implementation + /// Create a tile layer group implementation virtual TileLayerGroupPtr createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) = 0; + /// Create a layer group implementation + virtual LayerGroupPtr createLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) = 0; + /// Create a texture virtual Texture2DPtr createTexture2D() = 0; }; diff --git a/src/mbgl/gfx/image_drawable_data.hpp b/src/mbgl/gfx/image_drawable_data.hpp new file mode 100644 index 000000000..340105708 --- /dev/null +++ b/src/mbgl/gfx/image_drawable_data.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include +#include + +#include + +namespace mbgl { + +namespace gfx { + +class ImageDrawableData : public DrawableData { +public: + ImageDrawableData(mat4 matrix_) + : matrix(matrix_) {} + + mat4 matrix; +}; + +using UniqueImageDrawableData = std::unique_ptr; + +} // namespace gfx +} // namespace mbgl diff --git a/src/mbgl/gl/context.cpp b/src/mbgl/gl/context.cpp index 8c766a7c0..d74e1380a 100644 --- a/src/mbgl/gl/context.cpp +++ b/src/mbgl/gl/context.cpp @@ -477,6 +477,10 @@ TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t return std::make_shared(layerIndex, initialCapacity, std::move(name)); } +LayerGroupPtr Context::createLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) { + return std::make_shared(layerIndex, initialCapacity, std::move(name)); +} + gfx::Texture2DPtr Context::createTexture2D() { return std::make_shared(*this); } diff --git a/src/mbgl/gl/context.hpp b/src/mbgl/gl/context.hpp index ae3d4c4fa..1ee51691f 100644 --- a/src/mbgl/gl/context.hpp +++ b/src/mbgl/gl/context.hpp @@ -111,6 +111,8 @@ public: TileLayerGroupPtr createTileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) override; + LayerGroupPtr createLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) override; + gfx::Texture2DPtr createTexture2D() override; private: diff --git a/src/mbgl/gl/layer_group_gl.cpp b/src/mbgl/gl/layer_group_gl.cpp index 419abe3f3..bc3c165b6 100644 --- a/src/mbgl/gl/layer_group_gl.cpp +++ b/src/mbgl/gl/layer_group_gl.cpp @@ -47,8 +47,8 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) if (getDrawableCount()) { #if !defined(NDEBUG) - const auto label = getName() + (getName().empty() ? "" : "-") + "tile-clip-masks"; - const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); + const auto label_clip = getName() + (getName().empty() ? "" : "-") + "tile-clip-masks"; + const auto debugGroupClip = parameters.encoder->createDebugGroup(label_clip.c_str()); #endif // Collect the tile IDs relevant to stenciling and update the stencil buffer, if necessary. @@ -63,8 +63,8 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) } #if !defined(NDEBUG) - const auto label = getName() + (getName().empty() ? "" : "-") + "render"; - const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); + const auto label_render = getName() + (getName().empty() ? "" : "-") + "render"; + const auto debugGroupRender = parameters.encoder->createDebugGroup(label_render.c_str()); #endif observeDrawables([&](gfx::Drawable& drawable) { @@ -82,6 +82,84 @@ void TileLayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) } } +#if !defined(NDEBUG) + std::string label_tile; + if (const auto& tileID = drawable.getTileID()) { + label_tile = drawable.getName() + "/" + util::toString(*tileID); + } + const auto labelPtr = (label_tile.empty() ? drawable.getName() : label_tile).c_str(); + const auto debugGroupTile = parameters.encoder->createDebugGroup(labelPtr); +#endif + + drawable.draw(parameters); + }); +} + +LayerGroupGL::LayerGroupGL(int32_t layerIndex_, std::size_t initialCapacity, std::string name_) + : LayerGroup(layerIndex_, initialCapacity, std::move(name_)) {} + +void LayerGroupGL::upload(gfx::UploadPass& uploadPass) { + if (!enabled) { + return; + } + + observeDrawables([&](gfx::Drawable& drawable) { + if (!drawable.getEnabled()) { + return; + } + + auto& drawableGL = static_cast(drawable); + +#if !defined(NDEBUG) + std::string label; + if (const auto& tileID = drawable.getTileID()) { + label = drawable.getName() + "/" + util::toString(*tileID); + } + const auto labelPtr = (label.empty() ? drawable.getName() : label).c_str(); + const auto debugGroup = uploadPass.createDebugGroup(labelPtr); +#endif + + drawableGL.upload(uploadPass); + }); +} + +void LayerGroupGL::render(RenderOrchestrator&, PaintParameters& parameters) { + if (!enabled) { + return; + } + + if (getDrawableCount()) { +#if !defined(NDEBUG) + const auto label = getName() + (getName().empty() ? "" : "-") + "tile-clip-masks"; + const auto debugGroup = parameters.encoder->createDebugGroup(label.c_str()); +#endif + + // Collect the tile IDs relevant to stenciling and update the stencil buffer, if necessary. + std::set tileIDs; + observeDrawables([&](const gfx::Drawable& drawable) { + if (drawable.getEnabled() && drawable.getNeedsStencil() && drawable.getTileID() && + drawable.hasRenderPass(parameters.pass)) { + tileIDs.emplace(drawable.getTileID()->toUnwrapped()); + } + }); + parameters.renderTileClippingMasks(tileIDs); + } + + observeDrawables([&](gfx::Drawable& drawable) { + if (!drawable.getEnabled() || !drawable.hasRenderPass(parameters.pass)) { + return; + } + + // If this drawable can render either opaque or translucent... + if (drawable.hasAllRenderPasses(RenderPass::Opaque | RenderPass::Translucent)) { + // Render it only in the translucent pass if we're below the cutoff, and only in the opaque pass otherwise + // (parameters.currentLayer >= parameters.opaquePassCutoff) ? RenderPass::Opaque : RenderPass::Translucent; + if ((parameters.currentLayer < parameters.opaquePassCutoff && parameters.pass != RenderPass::Translucent) || + (parameters.currentLayer >= parameters.opaquePassCutoff && parameters.pass != RenderPass::Opaque)) { + return; + } + } + #if !defined(NDEBUG) std::string label; if (const auto& tileID = drawable.getTileID()) { diff --git a/src/mbgl/renderer/change_request.cpp b/src/mbgl/renderer/change_request.cpp index fef923e72..79636b217 100644 --- a/src/mbgl/renderer/change_request.cpp +++ b/src/mbgl/renderer/change_request.cpp @@ -3,7 +3,7 @@ namespace mbgl { -AddLayerGroupRequest::AddLayerGroupRequest(LayerGroupPtr layerGroup_, bool canReplace) +AddLayerGroupRequest::AddLayerGroupRequest(LayerGroupBasePtr layerGroup_, bool canReplace) : layerGroup(std::move(layerGroup_)), replace(canReplace) {} diff --git a/src/mbgl/renderer/layer_group.cpp b/src/mbgl/renderer/layer_group.cpp index 0b212f4a8..be40972bb 100644 --- a/src/mbgl/renderer/layer_group.cpp +++ b/src/mbgl/renderer/layer_group.cpp @@ -8,86 +8,50 @@ namespace mbgl { -struct TileLayerGroupTileKey { - mbgl::RenderPass renderPass; - OverscaledTileID tileID; - bool operator==(const TileLayerGroupTileKey& other) const { - return renderPass == other.renderPass && tileID == other.tileID; - } - struct hash { - size_t operator()(const mbgl::TileLayerGroupTileKey& k) const { - return (std::hash()(k.renderPass) ^ std::hash()(k.tileID) << 1); - } - }; +struct LayerGroup::Impl { + Impl(std::size_t capacity) { drawables.reserve(capacity); } + + using DrawableCollection = std::vector; + DrawableCollection drawables; }; -struct TileLayerGroup::Impl { - Impl(std::size_t capacity) - : tileDrawables(capacity) {} - - using TileMap = std::unordered_multimap; - TileMap tileDrawables; -}; - -LayerGroup::LayerGroup(int32_t layerIndex_, std::string name_) - : layerIndex(layerIndex_), - name(std::move(name_)) {} - -TileLayerGroup::TileLayerGroup(int32_t layerIndex_, std::size_t initialCapacity, std::string name_) - : LayerGroup(layerIndex_, std::move(name_)), +LayerGroup::LayerGroup(int32_t layerIndex_, std::size_t initialCapacity, std::string name_) + : LayerGroupBase(layerIndex_, std::move(name_)), impl(std::make_unique(initialCapacity)) {} -TileLayerGroup::~TileLayerGroup() {} +LayerGroup::~LayerGroup() {} -void TileLayerGroup::updateLayerIndex(int32_t newLayerIndex) { +void LayerGroup::updateLayerIndex(int32_t newLayerIndex) { layerIndex = newLayerIndex; } -std::size_t TileLayerGroup::getDrawableCount() const { - return impl->tileDrawables.size(); +std::size_t LayerGroup::getDrawableCount() const { + return impl->drawables.size(); } -static const gfx::UniqueDrawable no_tile; - -std::size_t TileLayerGroup::getDrawableCount(mbgl::RenderPass pass, const OverscaledTileID& id) const { - const auto range = impl->tileDrawables.equal_range({pass, id}); - return std::distance(range.first, range.second); +void LayerGroup::addDrawable(gfx::UniqueDrawable&& drawable) { + impl->drawables.emplace_back(std::move(drawable)); } -std::vector TileLayerGroup::removeDrawables(mbgl::RenderPass pass, const OverscaledTileID& id) { - const auto range = impl->tileDrawables.equal_range({pass, id}); - std::vector result(std::distance(range.first, range.second)); - std::transform( - std::make_move_iterator(range.first), std::make_move_iterator(range.second), result.begin(), [](auto&& pair) { - return std::move(pair.second); - }); - impl->tileDrawables.erase(range.first, range.second); - return result; -} - -void TileLayerGroup::addDrawable(mbgl::RenderPass pass, const OverscaledTileID& id, gfx::UniqueDrawable&& drawable) { - impl->tileDrawables.insert(std::make_pair(TileLayerGroupTileKey{pass, id}, std::move(drawable))); -} - -void TileLayerGroup::observeDrawables(std::function f) { - for (auto& pair : impl->tileDrawables) { - if (pair.second) { - f(*pair.second); +void LayerGroup::observeDrawables(std::function f) { + for (const auto& item : impl->drawables) { + if (item) { + f(*item); } } } -void TileLayerGroup::observeDrawables(std::function f) const { - for (const auto& pair : impl->tileDrawables) { - if (pair.second) { - f(*pair.second); +void LayerGroup::observeDrawables(std::function f) const { + for (const auto& item : impl->drawables) { + if (item) { + f(*item); } } } -void TileLayerGroup::observeDrawables(std::function f) { - for (auto i = impl->tileDrawables.begin(); i != impl->tileDrawables.end();) { - auto& drawable = i->second; +void LayerGroup::observeDrawables(std::function f) { + for (auto i = impl->drawables.begin(); i != impl->drawables.end();) { + auto& drawable = *i; if (drawable) { f(drawable); } @@ -96,28 +60,14 @@ void TileLayerGroup::observeDrawables(std::function ++i; } else { // Removed, take it out of the map - i = impl->tileDrawables.erase(i); + i = impl->drawables.erase(i); } } } -void TileLayerGroup::observeDrawables(mbgl::RenderPass pass, - const OverscaledTileID& tileID, - std::function&& f) { - const auto range = impl->tileDrawables.equal_range({pass, tileID}); - std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); }); -} - -void TileLayerGroup::observeDrawables(mbgl::RenderPass pass, - const OverscaledTileID& tileID, - std::function&& f) const { - const auto range = impl->tileDrawables.equal_range({pass, tileID}); - std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); }); -} - -std::size_t TileLayerGroup::clearDrawables() { - const auto count = impl->tileDrawables.size(); - impl->tileDrawables.clear(); +std::size_t LayerGroup::clearDrawables() { + const auto count = impl->drawables.size(); + impl->drawables.clear(); return count; } diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.cpp b/src/mbgl/renderer/layers/background_layer_tweaker.cpp index d69b1f103..e5fab773e 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.cpp @@ -51,7 +51,7 @@ static constexpr std::string_view BackgroundPatternShaderName = "BackgroundPatte static constexpr std::string_view BackgroundDrawableUBOName = "BackgroundDrawableUBO"; static constexpr std::string_view BackgroundLayerUBOName = "BackgroundLayerUBO"; -void BackgroundLayerTweaker::execute(LayerGroup& layerGroup, const RenderTree&, const PaintParameters& parameters) { +void BackgroundLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree&, const PaintParameters& parameters) { const auto& state = parameters.state; auto& context = parameters.context; diff --git a/src/mbgl/renderer/layers/background_layer_tweaker.hpp b/src/mbgl/renderer/layers/background_layer_tweaker.hpp index a6a62d9ce..19d974306 100644 --- a/src/mbgl/renderer/layers/background_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/background_layer_tweaker.hpp @@ -25,7 +25,7 @@ public: public: ~BackgroundLayerTweaker() override = default; - void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override; + void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; protected: }; diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp index 5f6c007e4..f4d4ad26c 100644 --- a/src/mbgl/renderer/layers/circle_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.cpp @@ -44,7 +44,7 @@ static constexpr std::string_view CircleDrawableUBOName = "CircleDrawableUBO"; static constexpr std::string_view CirclePaintParamsUBOName = "CirclePaintParamsUBO"; static constexpr std::string_view CircleEvaluatedPropsUBOName = "CircleEvaluatedPropsUBO"; -void CircleLayerTweaker::execute(LayerGroup& layerGroup, +void CircleLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { const auto& evaluated = static_cast(*evaluatedProperties).evaluated; diff --git a/src/mbgl/renderer/layers/circle_layer_tweaker.hpp b/src/mbgl/renderer/layers/circle_layer_tweaker.hpp index 6116275c6..878f17a77 100644 --- a/src/mbgl/renderer/layers/circle_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/circle_layer_tweaker.hpp @@ -20,7 +20,7 @@ public: public: ~CircleLayerTweaker() override = default; - void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override; + void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; protected: gfx::UniformBufferPtr paintParamsUniformBuffer; diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp index cfbcdb3aa..91b6c86c0 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.cpp @@ -45,7 +45,7 @@ struct alignas(16) FillDrawableUBO { }; static_assert(sizeof(FillDrawableUBO) == 208); -void FillLayerTweaker::execute(LayerGroup& layerGroup, +void FillLayerTweaker::execute(LayerGroupBase& layerGroup, const RenderTree& renderTree, const PaintParameters& parameters) { const auto& props = static_cast(*evaluatedProperties); diff --git a/src/mbgl/renderer/layers/fill_layer_tweaker.hpp b/src/mbgl/renderer/layers/fill_layer_tweaker.hpp index 92a601520..bd765df8f 100644 --- a/src/mbgl/renderer/layers/fill_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/fill_layer_tweaker.hpp @@ -15,7 +15,7 @@ public: public: ~FillLayerTweaker() override = default; - void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override; + void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; }; } // namespace mbgl diff --git a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp index da3eef0df..4c7495cca 100644 --- a/src/mbgl/renderer/layers/raster_layer_tweaker.cpp +++ b/src/mbgl/renderer/layers/raster_layer_tweaker.cpp @@ -7,6 +7,8 @@ #include #include #include +#include +#include namespace mbgl { @@ -30,18 +32,12 @@ struct alignas(16) RasterDrawableUBO { static_assert(sizeof(RasterDrawableUBO) == 128); static_assert(sizeof(RasterDrawableUBO) % 16 == 0); -void RasterLayerTweaker::execute([[maybe_unused]] LayerGroup& layerGroup, +void RasterLayerTweaker::execute([[maybe_unused]] LayerGroupBase& layerGroup, [[maybe_unused]] const RenderTree& renderTree, [[maybe_unused]] const PaintParameters& parameters) { const auto& evaluated = static_cast(*evaluatedProperties).evaluated; layerGroup.observeDrawables([&](gfx::Drawable& drawable) { - if (!drawable.getTileID()) { - return; - } - const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); - const auto matrix = parameters.matrixForTile(tileID, !parameters.state.isChanging()); - auto spinWeights = [](float spin) -> std::array { spin = util::deg2radf(spin); float s = std::sin(spin); @@ -65,6 +61,23 @@ void RasterLayerTweaker::execute([[maybe_unused]] LayerGroup& layerGroup, } }; + mat4 matrix; + if (!drawable.getTileID()) { + // this is an image drawable + if (const auto& data = drawable.getData()) { + const gfx::ImageDrawableData& imageData = static_cast(*data.value()); + + matrix = imageData.matrix; + } else { + Log::Error(Event::General, "Invalid raster layer drawable: neither tile id nor image data is set."); + return; + } + } else { + // this is a tile drawable + const UnwrappedTileID tileID = drawable.getTileID()->toUnwrapped(); + matrix = parameters.matrixForTile(tileID, !parameters.state.isChanging()); + } + RasterDrawableUBO drawableUBO{/*.matrix = */ util::cast(matrix), /*.spin_weigths = */ spinWeights(evaluated.get()), /*.tl_parent = */ {{0.0f, 0.0f}}, diff --git a/src/mbgl/renderer/layers/raster_layer_tweaker.hpp b/src/mbgl/renderer/layers/raster_layer_tweaker.hpp index 1dae27832..e03a55199 100644 --- a/src/mbgl/renderer/layers/raster_layer_tweaker.hpp +++ b/src/mbgl/renderer/layers/raster_layer_tweaker.hpp @@ -20,7 +20,7 @@ public: public: ~RasterLayerTweaker() override = default; - void execute(LayerGroup&, const RenderTree&, const PaintParameters&) override; + void execute(LayerGroupBase&, const RenderTree&, const PaintParameters&) override; protected: gfx::UniformBufferPtr evaluatedPropsUniformBuffer = nullptr; diff --git a/src/mbgl/renderer/layers/render_raster_layer.cpp b/src/mbgl/renderer/layers/render_raster_layer.cpp index f67eeefd3..c20979899 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.cpp +++ b/src/mbgl/renderer/layers/render_raster_layer.cpp @@ -15,6 +15,7 @@ #include #include #include +#include namespace mbgl { @@ -230,17 +231,11 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, stats.tileDrawablesRemoved += tileLayerGroup->getDrawableCount(); tileLayerGroup->clearDrawables(); } - return; - } - - // Set up a layer group - if (!tileLayerGroup) { - tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID()); - if (!tileLayerGroup) { - return; + if (imageLayerGroup) { + // stats.tileDrawablesRemoved += layerScene->getDrawableCount(); + imageLayerGroup->clearDrawables(); } - tileLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); - changes.emplace_back(std::make_unique(tileLayerGroup, /*canReplace=*/true)); + return; } auto renderPass = RenderPass::Translucent; @@ -255,41 +250,193 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, const gfx::TextureFilterType filter = evaluated.get() == RasterResamplingType::Nearest ? gfx::TextureFilterType::Nearest : gfx::TextureFilterType::Linear; - (void)filter; - if (imageData && !imageData->bucket->needsUpload()) { - // TODO: implement arbitrary image - // RasterBucket& bucket = *imageData->bucket; - assert(imageData->bucket->texture); + auto createBuilder = [&context, &renderPass, this]() -> std::unique_ptr { + std::unique_ptr builder{context.createDrawableBuilder("raster")}; + builder->setShader(rasterShader); + builder->setRenderPass(renderPass); + builder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None); + builder->setSubLayerIndex(0); + builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite + : gfx::DepthMaskType::ReadOnly); + builder->setCullFaceMode(gfx::CullFaceMode::disabled()); + builder->setVertexAttrName("a_pos"); - // size_t i = 0; - for (const auto& matrix_ : imageData->matrices) { - /*draw(matrix_, - *bucket.vertexBuffer, - *bucket.indexBuffer, - bucket.segments, - RasterProgram::TextureBindings{ - textures::image0::Value{bucket.texture->getResource(), filter}, - textures::image1::Value{bucket.texture->getResource(), filter}, - }, - std::to_string(i++));*/ - (void)matrix_; + return builder; + }; + + auto setTextures = [&context, &filter, this](std::unique_ptr& builder, RasterBucket& bucket) { + // textures + auto location0 = rasterShader->getSamplerLocation("u_image0"); + if (location0.has_value()) { + std::shared_ptr tex0 = context.createTexture2D(); + tex0->setImage(bucket.image); + tex0->setSamplerConfiguration({filter, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); + builder->setTexture(tex0, location0.value()); + } + auto location1 = rasterShader->getSamplerLocation("u_image1"); + if (location1.has_value()) { + std::shared_ptr tex1 = context.createTexture2D(); + tex1->setImage(bucket.image); + tex1->setSamplerConfiguration({filter, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp}); + builder->setTexture(tex1, location1.value()); + } + }; + + auto buildTileDrawables = [&setTextures](std::unique_ptr& builder, RasterBucket& bucket) { + auto buildRenderData = [](const TileMask& mask, + std::vector>& vertices, + std::vector>& attributes, + std::vector& indices, + std::vector>& segments) { + constexpr const uint16_t vertexLength = 4; + + // Create the vertex buffer for the specified tile mask. + for (const auto& id : mask) { + // Create a quad for every masked tile. + const int32_t vertexExtent = util::EXTENT >> id.z; + + const Point tlVertex = {static_cast(id.x * vertexExtent), + static_cast(id.y * vertexExtent)}; + const Point brVertex = {static_cast(tlVertex.x + vertexExtent), + static_cast(tlVertex.y + vertexExtent)}; + + 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.size(), indices.size()); + } + + vertices.emplace_back(std::array{{tlVertex.x, tlVertex.y}}); + attributes.emplace_back(std::array{{tlVertex.x, tlVertex.y}}); + + vertices.emplace_back(std::array{{brVertex.x, tlVertex.y}}); + attributes.emplace_back(std::array{{brVertex.x, tlVertex.y}}); + + vertices.emplace_back(std::array{{tlVertex.x, brVertex.y}}); + attributes.emplace_back(std::array{{tlVertex.x, brVertex.y}}); + + vertices.emplace_back(std::array{{brVertex.x, brVertex.y}}); + attributes.emplace_back(std::array{{brVertex.x, brVertex.y}}); + + auto& segment = segments.back(); + assert(segment.vertexLength <= std::numeric_limits::max()); + const auto offset = static_cast(segment.vertexLength); + + // 0, 1, 2 + // 1, 2, 3 + indices.insert(indices.end(), + {offset, static_cast(offset + 1), static_cast(offset + 2u)}); + indices.insert(indices.end(), + {static_cast(offset + 1), + static_cast(offset + 2), + static_cast(offset + 3)}); + + segment.vertexLength += vertexLength; + segment.indexLength += 6; + } + }; + + std::vector> vertices, attributes; + std::vector indices; + std::vector> segments; + buildRenderData(bucket.mask, vertices, attributes, indices, segments); + builder->addVertices(vertices, 0, vertices.size()); + builder->setSegments(gfx::Triangles(), indices, segments); + + // attributes + { + gfx::VertexAttributeArray vertexAttrs; + if (auto& attr = vertexAttrs.getOrAdd("a_texture_pos")) { + std::size_t index{0}; + for (auto& a : attributes) { + attr->set(index++, {a[0], a[1]}); + } + } + builder->setVertexAttributes(std::move(vertexAttrs)); + } + + // textures + setTextures(builder, bucket); + }; + + auto buildImageDrawables = [&setTextures](std::unique_ptr& builder, RasterBucket& bucket) { + std::vector> vertices(bucket.vertices.vector().size()); + std::transform( + bucket.vertices.vector().begin(), bucket.vertices.vector().end(), vertices.begin(), [](const auto& x) { + return x.a1; + }); + builder->addVertices(vertices, 0, vertices.size()); + + builder->setSegments(gfx::Triangles(), + bucket.indices.vector(), + reinterpret_cast>&>(bucket.segments)); + + // attributes + { + gfx::VertexAttributeArray vertexAttrs; + if (auto& attr = vertexAttrs.getOrAdd("a_texture_pos")) { + std::size_t index{0}; + for (auto& v : bucket.vertices.vector()) { + attr->set(index++, {v.a2[0], v.a2[1]}); + } + } + builder->setVertexAttributes(std::move(vertexAttrs)); + } + + // textures + setTextures(builder, bucket); + }; + + if (imageData) { + RasterBucket& bucket = *imageData->bucket; + if (!bucket.vertices.empty()) { + if (imageLayerGroup) { + imageLayerGroup->clearDrawables(); + } else { + // Set up a layer group + imageLayerGroup = context.createLayerGroup(layerIndex, /*initialCapacity=*/64, getID()); + imageLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); + changes.emplace_back(std::make_unique(imageLayerGroup, /*canReplace=*/true)); + } + + auto builder = createBuilder(); + for (const auto& matrix_ : imageData->matrices) { + buildImageDrawables(builder, bucket); + + // finish + builder->flush(); + for (auto& drawable : builder->clearDrawables()) { + drawable->setData(std::make_unique(matrix_)); + imageLayerGroup->addDrawable(std::move(drawable)); + ++stats.tileDrawablesAdded; + } + } } } else if (renderTiles) { - tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) { - // Has this tile dropped out of the cover set? - if (const auto it = std::find_if(renderTiles->begin(), - renderTiles->end(), - [&drawable](const auto& renderTile) { - return drawable->getTileID() == renderTile.get().getOverscaledTileID(); - }); - it == renderTiles->end()) { - // remove it - drawable.reset(); - ++stats.tileDrawablesRemoved; - } - }); + if (tileLayerGroup) { + tileLayerGroup->observeDrawables([&](gfx::UniqueDrawable& drawable) { + // Has this tile dropped out of the cover set? + if (const auto it = std::find_if(renderTiles->begin(), + renderTiles->end(), + [&drawable](const auto& renderTile) { + return drawable->getTileID() == + renderTile.get().getOverscaledTileID(); + }); + it == renderTiles->end()) { + // remove it + drawable.reset(); + ++stats.tileDrawablesRemoved; + } + }); + } else { + // Set up a tile layer group + tileLayerGroup = context.createTileLayerGroup(layerIndex, /*initialCapacity=*/64, getID()); + tileLayerGroup->setLayerTweaker(std::make_shared(evaluatedProperties)); + changes.emplace_back(std::make_unique(tileLayerGroup, /*canReplace=*/true)); + } + auto builder = createBuilder(); for (const RenderTile& tile : *renderTiles) { const auto& tileID = tile.getOverscaledTileID(); auto* bucket_ = tile.getBucket(*baseImpl); @@ -297,109 +444,12 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders, continue; } auto& bucket = static_cast(*bucket_); - if (!bucket.hasData()) continue; if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) continue; if (bucket.image) { - std::unique_ptr builder{context.createDrawableBuilder("raster")}; - builder->setShader(rasterShader); - builder->setRenderPass(renderPass); - builder->setColorAttrMode(gfx::DrawableBuilder::ColorAttrMode::None); - builder->setSubLayerIndex(0); - builder->setDepthType((renderPass == RenderPass::Opaque) ? gfx::DepthMaskType::ReadWrite - : gfx::DepthMaskType::ReadOnly); - builder->setCullFaceMode(gfx::CullFaceMode::disabled()); - builder->setVertexAttrName("a_pos"); - - // render data - auto buildRenderData = [](const TileMask& mask, - std::vector>& vertices, - std::vector>& attributes, - std::vector& indices, - std::vector>& segments) { - constexpr const uint16_t vertexLength = 4; - - // Create the vertex buffer for the specified tile mask. - for (const auto& id : mask) { - // Create a quad for every masked tile. - const int32_t vertexExtent = util::EXTENT >> id.z; - - const Point tlVertex = {static_cast(id.x * vertexExtent), - static_cast(id.y * vertexExtent)}; - const Point brVertex = {static_cast(tlVertex.x + vertexExtent), - static_cast(tlVertex.y + vertexExtent)}; - - 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.size(), indices.size()); - } - - vertices.emplace_back(std::array{{tlVertex.x, tlVertex.y}}); - attributes.emplace_back(std::array{{tlVertex.x, tlVertex.y}}); - - vertices.emplace_back(std::array{{brVertex.x, tlVertex.y}}); - attributes.emplace_back(std::array{{brVertex.x, tlVertex.y}}); - - vertices.emplace_back(std::array{{tlVertex.x, brVertex.y}}); - attributes.emplace_back(std::array{{tlVertex.x, brVertex.y}}); - - vertices.emplace_back(std::array{{brVertex.x, brVertex.y}}); - attributes.emplace_back(std::array{{brVertex.x, brVertex.y}}); - - auto& segment = segments.back(); - assert(segment.vertexLength <= std::numeric_limits::max()); - const auto offset = static_cast(segment.vertexLength); - - // 0, 1, 2 - // 1, 2, 3 - indices.insert(indices.end(), - {offset, static_cast(offset + 1), static_cast(offset + 2u)}); - indices.insert(indices.end(), - {static_cast(offset + 1), - static_cast(offset + 2), - static_cast(offset + 3)}); - - segment.vertexLength += vertexLength; - segment.indexLength += 6; - } - }; - - std::vector> vertices, attributes; - std::vector indices; - std::vector> segments; - buildRenderData(bucket.mask, vertices, attributes, indices, segments); - builder->addVertices(vertices, 0, vertices.size()); - builder->setSegments(gfx::Triangles(), indices, segments); - - // attributes - { - gfx::VertexAttributeArray vertexAttrs; - if (auto& attr = vertexAttrs.getOrAdd("a_texture_pos")) { - std::size_t index{0}; - for (auto& a : attributes) { - attr->set(index++, {a[0], a[1]}); - } - } - builder->setVertexAttributes(std::move(vertexAttrs)); - } - - // textures - // TODO: move texture creation into gfx::Context - std::shared_ptr tex0 = context.createTexture2D(); - tex0->setImage(bucket.image).create(); - auto location0 = rasterShader->getSamplerLocation("u_image0"); - if (location0.has_value()) { - builder->setTexture(tex0, location0.value()); - } - std::shared_ptr tex1 = context.createTexture2D(); - tex1->setImage(bucket.image).create(); - auto location1 = rasterShader->getSamplerLocation("u_image1"); - if (location1.has_value()) { - builder->setTexture(tex1, location1.value()); - } + buildTileDrawables(builder, bucket); // finish builder->flush(); diff --git a/src/mbgl/renderer/layers/render_raster_layer.hpp b/src/mbgl/renderer/layers/render_raster_layer.hpp index 394b2759c..303ec5cbc 100644 --- a/src/mbgl/renderer/layers/render_raster_layer.hpp +++ b/src/mbgl/renderer/layers/render_raster_layer.hpp @@ -3,6 +3,7 @@ #include #include #include +#include namespace mbgl { @@ -42,6 +43,7 @@ private: std::shared_ptr rasterProgram; gfx::ShaderProgramBasePtr rasterShader; + LayerGroupPtr imageLayerGroup; }; } // namespace mbgl diff --git a/src/mbgl/renderer/render_orchestrator.cpp b/src/mbgl/renderer/render_orchestrator.cpp index 33f1a05fa..d09fcd297 100644 --- a/src/mbgl/renderer/render_orchestrator.cpp +++ b/src/mbgl/renderer/render_orchestrator.cpp @@ -791,7 +791,7 @@ const gfx::DrawablePtr& RenderOrchestrator::getDrawable(const util::SimpleIdenti return (hit != drawables.end()) ? hit->second : noDrawable; } -void RenderOrchestrator::onRemoveLayerGroup(LayerGroup&) {} +void RenderOrchestrator::onRemoveLayerGroup(LayerGroupBase&) {} void RenderOrchestrator::updateLayerGroupOrder() { // In the event layer indices change for layer groups, we must re-sort them @@ -803,9 +803,9 @@ void RenderOrchestrator::updateLayerGroupOrder() { layerGroupOrderDirty = false; } -bool RenderOrchestrator::addLayerGroup(LayerGroupPtr layerGroup, const bool replace) { +bool RenderOrchestrator::addLayerGroup(LayerGroupBasePtr layerGroup, const bool replace) { const auto index = layerGroup->getLayerIndex(); - const auto result = layerGroupsByLayerIndex.insert(std::make_pair(index, LayerGroupPtr{})); + const auto result = layerGroupsByLayerIndex.insert(std::make_pair(index, LayerGroupBasePtr{})); if (result.second) { // added result.first->second = std::move(layerGroup); @@ -837,14 +837,14 @@ size_t RenderOrchestrator::numLayerGroups() const noexcept { return layerGroupsByLayerIndex.size(); } -static const LayerGroupPtr no_group; +static const LayerGroupBasePtr no_group; -const LayerGroupPtr& RenderOrchestrator::getLayerGroup(const int32_t layerIndex) const { +const LayerGroupBasePtr& RenderOrchestrator::getLayerGroup(const int32_t layerIndex) const { const auto hit = layerGroupsByLayerIndex.find(layerIndex); return (hit == layerGroupsByLayerIndex.end()) ? no_group : hit->second; } -void RenderOrchestrator::observeLayerGroups(std::function f) { +void RenderOrchestrator::observeLayerGroups(std::function f) { for (auto& pair : layerGroupsByLayerIndex) { if (pair.second) { f(*pair.second); @@ -852,7 +852,7 @@ void RenderOrchestrator::observeLayerGroups(std::function f) } } -void RenderOrchestrator::observeLayerGroups(std::function f) const { +void RenderOrchestrator::observeLayerGroups(std::function f) const { for (const auto& pair : layerGroupsByLayerIndex) { if (pair.second) { f(*pair.second); diff --git a/src/mbgl/renderer/render_orchestrator.hpp b/src/mbgl/renderer/render_orchestrator.hpp index 16aabb426..b61ac739f 100644 --- a/src/mbgl/renderer/render_orchestrator.hpp +++ b/src/mbgl/renderer/render_orchestrator.hpp @@ -103,12 +103,12 @@ public: const gfx::DrawablePtr& getDrawable(const util::SimpleIdentity&); - bool addLayerGroup(LayerGroupPtr, bool replace); + bool addLayerGroup(LayerGroupBasePtr, bool replace); bool removeLayerGroup(const int32_t layerIndex); size_t numLayerGroups() const noexcept; - const LayerGroupPtr& getLayerGroup(const int32_t layerIndex) const; - void observeLayerGroups(std::function); - void observeLayerGroups(std::function) const; + const LayerGroupBasePtr& getLayerGroup(const int32_t layerIndex) const; + void observeLayerGroups(std::function); + void observeLayerGroups(std::function) const; void updateLayers(gfx::ShaderRegistry&, gfx::Context&, @@ -154,7 +154,7 @@ private: /// Move changes into the pending set, clearing the provided collection void addChanges(UniqueChangeRequestVec&); - void onRemoveLayerGroup(LayerGroup&); + void onRemoveLayerGroup(LayerGroupBase&); void updateLayerGroupOrder(); @@ -192,7 +192,7 @@ private: DrawableMap drawables; std::vector> pendingChanges; - using LayerGroupMap = std::map; + using LayerGroupMap = std::map; LayerGroupMap layerGroupsByLayerIndex; bool layerGroupOrderDirty = false; }; diff --git a/src/mbgl/renderer/renderer_impl.cpp b/src/mbgl/renderer/renderer_impl.cpp index d81aa230c..fd84fc35b 100644 --- a/src/mbgl/renderer/renderer_impl.cpp +++ b/src/mbgl/renderer/renderer_impl.cpp @@ -104,7 +104,7 @@ void Renderer::Impl::render(const RenderTree& renderTree) { orchestrator.processChanges(); // Run layer tweakers to update any dynamic elements - orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { + orchestrator.observeLayerGroups([&](LayerGroupBase& layerGroup) { if (layerGroup.getLayerTweaker()) { layerGroup.getLayerTweaker()->execute(layerGroup, renderTree, parameters); } @@ -131,7 +131,7 @@ void Renderer::Impl::render(const RenderTree& renderTree) { renderTree.getPatternAtlas().upload(*uploadPass); // Give the layers a chance to upload - orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.upload(*uploadPass); }); + orchestrator.observeLayerGroups([&](LayerGroupBase& layerGroup) { layerGroup.upload(*uploadPass); }); } // - 3D PASS @@ -189,7 +189,7 @@ void Renderer::Impl::render(const RenderTree& renderTree) { PaintParameters::depthEpsilon; // draw layer groups, opaque pass - orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { + orchestrator.observeLayerGroups([&](LayerGroupBase& layerGroup) { layerGroup.render(orchestrator, parameters); parameters.currentLayer++; }); @@ -203,7 +203,7 @@ void Renderer::Impl::render(const RenderTree& renderTree) { PaintParameters::depthEpsilon; // draw layer groups, translucent pass - orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { + orchestrator.observeLayerGroups([&](LayerGroupBase& layerGroup) { layerGroup.render(orchestrator, parameters); if (parameters.currentLayer != 0) { parameters.currentLayer--; @@ -328,7 +328,8 @@ void Renderer::Impl::render(const RenderTree& renderTree) { #endif // Give the layers a chance to do cleanup - orchestrator.observeLayerGroups([&](LayerGroup& layerGroup) { layerGroup.postRender(orchestrator, parameters); }); + orchestrator.observeLayerGroups( + [&](LayerGroupBase& layerGroup) { layerGroup.postRender(orchestrator, parameters); }); // Ends the RenderPass parameters.renderPass.reset(); diff --git a/src/mbgl/renderer/tile_layer_group.cpp b/src/mbgl/renderer/tile_layer_group.cpp new file mode 100644 index 000000000..4326fa4b9 --- /dev/null +++ b/src/mbgl/renderer/tile_layer_group.cpp @@ -0,0 +1,124 @@ +#include + +#include +#include +#include + +#include + +namespace mbgl { + +struct TileLayerGroupTileKey { + mbgl::RenderPass renderPass; + OverscaledTileID tileID; + bool operator==(const TileLayerGroupTileKey& other) const { + return renderPass == other.renderPass && tileID == other.tileID; + } + struct hash { + size_t operator()(const mbgl::TileLayerGroupTileKey& k) const { + return (std::hash()(k.renderPass) ^ std::hash()(k.tileID) << 1); + } + }; +}; + +struct TileLayerGroup::Impl { + Impl(std::size_t capacity) + : tileDrawables(capacity) {} + + using TileMap = std::unordered_multimap; + TileMap tileDrawables; +}; + +LayerGroupBase::LayerGroupBase(int32_t layerIndex_, std::string name_) + : layerIndex(layerIndex_), + name(std::move(name_)) {} + +TileLayerGroup::TileLayerGroup(int32_t layerIndex_, std::size_t initialCapacity, std::string name_) + : LayerGroupBase(layerIndex_, std::move(name_)), + impl(std::make_unique(initialCapacity)) {} + +TileLayerGroup::~TileLayerGroup() {} + +void TileLayerGroup::updateLayerIndex(int32_t newLayerIndex) { + layerIndex = newLayerIndex; +} + +std::size_t TileLayerGroup::getDrawableCount() const { + return impl->tileDrawables.size(); +} + +static const gfx::UniqueDrawable no_tile; + +std::size_t TileLayerGroup::getDrawableCount(mbgl::RenderPass pass, const OverscaledTileID& id) const { + const auto range = impl->tileDrawables.equal_range({pass, id}); + return std::distance(range.first, range.second); +} + +std::vector TileLayerGroup::removeDrawables(mbgl::RenderPass pass, const OverscaledTileID& id) { + const auto range = impl->tileDrawables.equal_range({pass, id}); + std::vector result(std::distance(range.first, range.second)); + std::transform( + std::make_move_iterator(range.first), std::make_move_iterator(range.second), result.begin(), [](auto&& pair) { + return std::move(pair.second); + }); + impl->tileDrawables.erase(range.first, range.second); + return result; +} + +void TileLayerGroup::addDrawable(mbgl::RenderPass pass, const OverscaledTileID& id, gfx::UniqueDrawable&& drawable) { + impl->tileDrawables.insert(std::make_pair(TileLayerGroupTileKey{pass, id}, std::move(drawable))); +} + +void TileLayerGroup::observeDrawables(std::function f) { + for (auto& pair : impl->tileDrawables) { + if (pair.second) { + f(*pair.second); + } + } +} + +void TileLayerGroup::observeDrawables(std::function f) const { + for (const auto& pair : impl->tileDrawables) { + if (pair.second) { + f(*pair.second); + } + } +} + +void TileLayerGroup::observeDrawables(std::function f) { + for (auto i = impl->tileDrawables.begin(); i != impl->tileDrawables.end();) { + auto& drawable = i->second; + if (drawable) { + f(drawable); + } + if (drawable) { + // Not removed, keep going + ++i; + } else { + // Removed, take it out of the map + i = impl->tileDrawables.erase(i); + } + } +} + +void TileLayerGroup::observeDrawables(mbgl::RenderPass pass, + const OverscaledTileID& tileID, + std::function&& f) { + const auto range = impl->tileDrawables.equal_range({pass, tileID}); + std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); }); +} + +void TileLayerGroup::observeDrawables(mbgl::RenderPass pass, + const OverscaledTileID& tileID, + std::function&& f) const { + const auto range = impl->tileDrawables.equal_range({pass, tileID}); + std::for_each(range.first, range.second, [&f](const auto& pair) { f(*pair.second); }); +} + +std::size_t TileLayerGroup::clearDrawables() { + const auto count = impl->tileDrawables.size(); + impl->tileDrawables.clear(); + return count; +} + +} // namespace mbgl