Raster Layer (images) (#1223)

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: mwilsnd <mwilsnd@gmail.com>
This commit is contained in:
Stefan Karschti
2023-06-09 21:22:52 +03:00
committed by Bart Louwers
parent 52b9e099e5
commit d590ea97a8
28 changed files with 586 additions and 267 deletions

View File

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

View File

@@ -7,6 +7,7 @@
#include <mbgl/util/identity.hpp>
#include <mbgl/util/traits.hpp>
#include <mbgl/gfx/texture2d.hpp>
#include <mbgl/gfx/drawable_data.hpp>
#include <cstdint>
#include <memory>
@@ -167,6 +168,9 @@ public:
static_cast<float>(components[3])};
}
virtual const std::optional<UniqueDrawableData>& 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<UniqueDrawableData> drawableData{};
struct Impl;
std::unique_ptr<Impl> impl;

View File

@@ -0,0 +1,17 @@
#pragma once
#include <memory>
namespace mbgl {
namespace gfx {
class DrawableData {
public:
virtual ~DrawableData() = default;
};
using UniqueDrawableData = std::unique_ptr<DrawableData>;
} // namespace gfx
} // namespace mbgl

View File

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

View File

@@ -8,14 +8,14 @@
namespace mbgl {
class ChangeRequest;
class LayerGroup;
class LayerGroupBase;
class TileLayerGroup;
class RenderOrchestrator;
using ChangeRequestPtr = std::shared_ptr<ChangeRequest>;
using UniqueChangeRequest = std::unique_ptr<ChangeRequest>;
using UniqueChangeRequestVec = std::vector<UniqueChangeRequest>;
using LayerGroupPtr = std::shared_ptr<LayerGroup>;
using LayerGroupBasePtr = std::shared_ptr<LayerGroupBase>;
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;
};

View File

@@ -10,12 +10,12 @@
#include <vector>
namespace mbgl {
class LayerGroup;
class LayerGroupBase;
class PaintParameters;
class RenderOrchestrator;
class TileLayerGroup;
using LayerGroupPtr = std::shared_ptr<LayerGroup>;
using LayerGroupBasePtr = std::shared_ptr<LayerGroupBase>;
namespace gfx {
class Context;
@@ -32,13 +32,14 @@ using LayerTweakerPtr = std::shared_ptr<LayerTweaker>;
/**
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> 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<gfx::UniqueDrawable> removeDrawables(mbgl::RenderPass);
void addDrawable(gfx::UniqueDrawable&&);
void observeDrawables(std::function<void(gfx::Drawable&)>) override;
void observeDrawables(std::function<void(const gfx::Drawable&)>) const override;
void observeDrawables(std::function<void(gfx::UniqueDrawable&)>) override;
std::size_t clearDrawables();
protected:
struct Impl;
std::unique_ptr<Impl> impl;
};
} // namespace mbgl

View File

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

View File

@@ -18,7 +18,9 @@ namespace mbgl {
class PaintParameters;
class ProgramParameters;
class TileLayerGroup;
class LayerGroup;
using TileLayerGroupPtr = std::shared_ptr<TileLayerGroup>;
using LayerGroupPtr = std::shared_ptr<LayerGroup>;
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;
};

View File

@@ -0,0 +1,23 @@
#pragma once
#include <mbgl/gfx/drawable_data.hpp>
#include <mbgl/util/mat4.hpp>
#include <memory>
namespace mbgl {
namespace gfx {
class ImageDrawableData : public DrawableData {
public:
ImageDrawableData(mat4 matrix_)
: matrix(matrix_) {}
mat4 matrix;
};
using UniqueImageDrawableData = std::unique_ptr<ImageDrawableData>;
} // namespace gfx
} // namespace mbgl

View File

@@ -477,6 +477,10 @@ TileLayerGroupPtr Context::createTileLayerGroup(int32_t layerIndex, std::size_t
return std::make_shared<TileLayerGroupGL>(layerIndex, initialCapacity, std::move(name));
}
LayerGroupPtr Context::createLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name) {
return std::make_shared<LayerGroupGL>(layerIndex, initialCapacity, std::move(name));
}
gfx::Texture2DPtr Context::createTexture2D() {
return std::make_shared<gl::Texture2D>(*this);
}

View File

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

View File

@@ -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<gl::DrawableGL&>(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<UnwrappedTileID> 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()) {

View File

@@ -3,7 +3,7 @@
namespace mbgl {
AddLayerGroupRequest::AddLayerGroupRequest(LayerGroupPtr layerGroup_, bool canReplace)
AddLayerGroupRequest::AddLayerGroupRequest(LayerGroupBasePtr layerGroup_, bool canReplace)
: layerGroup(std::move(layerGroup_)),
replace(canReplace) {}

View File

@@ -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<mbgl::RenderPass>()(k.renderPass) ^ std::hash<OverscaledTileID>()(k.tileID) << 1);
}
};
struct LayerGroup::Impl {
Impl(std::size_t capacity) { drawables.reserve(capacity); }
using DrawableCollection = std::vector<gfx::UniqueDrawable>;
DrawableCollection drawables;
};
struct TileLayerGroup::Impl {
Impl(std::size_t capacity)
: tileDrawables(capacity) {}
using TileMap = std::unordered_multimap<TileLayerGroupTileKey, gfx::UniqueDrawable, TileLayerGroupTileKey::hash>;
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<Impl>(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<gfx::UniqueDrawable> TileLayerGroup::removeDrawables(mbgl::RenderPass pass, const OverscaledTileID& id) {
const auto range = impl->tileDrawables.equal_range({pass, id});
std::vector<gfx::UniqueDrawable> 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<void(gfx::Drawable&)> f) {
for (auto& pair : impl->tileDrawables) {
if (pair.second) {
f(*pair.second);
void LayerGroup::observeDrawables(std::function<void(gfx::Drawable&)> f) {
for (const auto& item : impl->drawables) {
if (item) {
f(*item);
}
}
}
void TileLayerGroup::observeDrawables(std::function<void(const gfx::Drawable&)> f) const {
for (const auto& pair : impl->tileDrawables) {
if (pair.second) {
f(*pair.second);
void LayerGroup::observeDrawables(std::function<void(const gfx::Drawable&)> f) const {
for (const auto& item : impl->drawables) {
if (item) {
f(*item);
}
}
}
void TileLayerGroup::observeDrawables(std::function<void(gfx::UniqueDrawable&)> f) {
for (auto i = impl->tileDrawables.begin(); i != impl->tileDrawables.end();) {
auto& drawable = i->second;
void LayerGroup::observeDrawables(std::function<void(gfx::UniqueDrawable&)> 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<void(gfx::UniqueDrawable&)>
++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<void(gfx::Drawable&)>&& 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<void(const gfx::Drawable&)>&& 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;
}

View File

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

View File

@@ -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:
};

View File

@@ -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<const CircleLayerProperties&>(*evaluatedProperties).evaluated;

View File

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

View File

@@ -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<const FillLayerProperties&>(*evaluatedProperties);

View File

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

View File

@@ -7,6 +7,8 @@
#include <mbgl/renderer/render_tree.hpp>
#include <mbgl/style/layers/raster_layer_properties.hpp>
#include <mbgl/util/convert.hpp>
#include <mbgl/gfx/image_drawable_data.hpp>
#include <mbgl/util/logging.hpp>
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<const RasterLayerProperties&>(*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<float, 4> {
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<const gfx::ImageDrawableData&>(*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<float>(matrix),
/*.spin_weigths = */ spinWeights(evaluated.get<RasterHueRotate>()),
/*.tl_parent = */ {{0.0f, 0.0f}},

View File

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

View File

@@ -15,6 +15,7 @@
#include <mbgl/math/angles.hpp>
#include <mbgl/style/layers/raster_layer_impl.hpp>
#include <mbgl/shaders/shader_program_base.hpp>
#include <mbgl/gfx/image_drawable_data.hpp>
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<RasterLayerTweaker>(evaluatedProperties));
changes.emplace_back(std::make_unique<AddLayerGroupRequest>(tileLayerGroup, /*canReplace=*/true));
return;
}
auto renderPass = RenderPass::Translucent;
@@ -255,41 +250,193 @@ void RenderRasterLayer::update(gfx::ShaderRegistry& shaders,
const gfx::TextureFilterType filter = evaluated.get<RasterResampling>() == 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<gfx::DrawableBuilder> {
std::unique_ptr<gfx::DrawableBuilder> 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<gfx::DrawableBuilder>& builder, RasterBucket& bucket) {
// textures
auto location0 = rasterShader->getSamplerLocation("u_image0");
if (location0.has_value()) {
std::shared_ptr<gfx::Texture2D> 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<gfx::Texture2D> 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<gfx::DrawableBuilder>& builder, RasterBucket& bucket) {
auto buildRenderData = [](const TileMask& mask,
std::vector<std::array<int16_t, 2>>& vertices,
std::vector<std::array<int16_t, 2>>& attributes,
std::vector<uint16_t>& indices,
std::vector<Segment<void>>& 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<int16_t> tlVertex = {static_cast<int16_t>(id.x * vertexExtent),
static_cast<int16_t>(id.y * vertexExtent)};
const Point<int16_t> brVertex = {static_cast<int16_t>(tlVertex.x + vertexExtent),
static_cast<int16_t>(tlVertex.y + vertexExtent)};
if (segments.empty() ||
(segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::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<int16_t, 2>{{tlVertex.x, tlVertex.y}});
attributes.emplace_back(std::array<int16_t, 2>{{tlVertex.x, tlVertex.y}});
vertices.emplace_back(std::array<int16_t, 2>{{brVertex.x, tlVertex.y}});
attributes.emplace_back(std::array<int16_t, 2>{{brVertex.x, tlVertex.y}});
vertices.emplace_back(std::array<int16_t, 2>{{tlVertex.x, brVertex.y}});
attributes.emplace_back(std::array<int16_t, 2>{{tlVertex.x, brVertex.y}});
vertices.emplace_back(std::array<int16_t, 2>{{brVertex.x, brVertex.y}});
attributes.emplace_back(std::array<int16_t, 2>{{brVertex.x, brVertex.y}});
auto& segment = segments.back();
assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
const auto offset = static_cast<uint16_t>(segment.vertexLength);
// 0, 1, 2
// 1, 2, 3
indices.insert(indices.end(),
{offset, static_cast<uint16_t>(offset + 1), static_cast<uint16_t>(offset + 2u)});
indices.insert(indices.end(),
{static_cast<uint16_t>(offset + 1),
static_cast<uint16_t>(offset + 2),
static_cast<uint16_t>(offset + 3)});
segment.vertexLength += vertexLength;
segment.indexLength += 6;
}
};
std::vector<std::array<int16_t, 2>> vertices, attributes;
std::vector<uint16_t> indices;
std::vector<Segment<void>> 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<gfx::VertexAttribute::int2>(index++, {a[0], a[1]});
}
}
builder->setVertexAttributes(std::move(vertexAttrs));
}
// textures
setTextures(builder, bucket);
};
auto buildImageDrawables = [&setTextures](std::unique_ptr<gfx::DrawableBuilder>& builder, RasterBucket& bucket) {
std::vector<std::array<int16_t, 2>> 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<const std::vector<Segment<void>>&>(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<gfx::VertexAttribute::int2>(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<RasterLayerTweaker>(evaluatedProperties));
changes.emplace_back(std::make_unique<AddLayerGroupRequest>(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<gfx::ImageDrawableData>(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<RasterLayerTweaker>(evaluatedProperties));
changes.emplace_back(std::make_unique<AddLayerGroupRequest>(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<RasterBucket&>(*bucket_);
if (!bucket.hasData()) continue;
if (tileLayerGroup->getDrawableCount(renderPass, tileID) > 0) continue;
if (bucket.image) {
std::unique_ptr<gfx::DrawableBuilder> 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<std::array<int16_t, 2>>& vertices,
std::vector<std::array<int16_t, 2>>& attributes,
std::vector<uint16_t>& indices,
std::vector<Segment<void>>& 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<int16_t> tlVertex = {static_cast<int16_t>(id.x * vertexExtent),
static_cast<int16_t>(id.y * vertexExtent)};
const Point<int16_t> brVertex = {static_cast<int16_t>(tlVertex.x + vertexExtent),
static_cast<int16_t>(tlVertex.y + vertexExtent)};
if (segments.empty() ||
(segments.back().vertexLength + vertexLength > std::numeric_limits<uint16_t>::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<int16_t, 2>{{tlVertex.x, tlVertex.y}});
attributes.emplace_back(std::array<int16_t, 2>{{tlVertex.x, tlVertex.y}});
vertices.emplace_back(std::array<int16_t, 2>{{brVertex.x, tlVertex.y}});
attributes.emplace_back(std::array<int16_t, 2>{{brVertex.x, tlVertex.y}});
vertices.emplace_back(std::array<int16_t, 2>{{tlVertex.x, brVertex.y}});
attributes.emplace_back(std::array<int16_t, 2>{{tlVertex.x, brVertex.y}});
vertices.emplace_back(std::array<int16_t, 2>{{brVertex.x, brVertex.y}});
attributes.emplace_back(std::array<int16_t, 2>{{brVertex.x, brVertex.y}});
auto& segment = segments.back();
assert(segment.vertexLength <= std::numeric_limits<uint16_t>::max());
const auto offset = static_cast<uint16_t>(segment.vertexLength);
// 0, 1, 2
// 1, 2, 3
indices.insert(indices.end(),
{offset, static_cast<uint16_t>(offset + 1), static_cast<uint16_t>(offset + 2u)});
indices.insert(indices.end(),
{static_cast<uint16_t>(offset + 1),
static_cast<uint16_t>(offset + 2),
static_cast<uint16_t>(offset + 3)});
segment.vertexLength += vertexLength;
segment.indexLength += 6;
}
};
std::vector<std::array<int16_t, 2>> vertices, attributes;
std::vector<uint16_t> indices;
std::vector<Segment<void>> 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<gfx::VertexAttribute::int2>(index++, {a[0], a[1]});
}
}
builder->setVertexAttributes(std::move(vertexAttrs));
}
// textures
// TODO: move texture creation into gfx::Context
std::shared_ptr<gfx::Texture2D> 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<gfx::Texture2D> 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();

View File

@@ -3,6 +3,7 @@
#include <mbgl/renderer/render_layer.hpp>
#include <mbgl/style/layers/raster_layer_impl.hpp>
#include <mbgl/style/layers/raster_layer_properties.hpp>
#include <mbgl/gfx/context.hpp>
namespace mbgl {
@@ -42,6 +43,7 @@ private:
std::shared_ptr<RasterProgram> rasterProgram;
gfx::ShaderProgramBasePtr rasterShader;
LayerGroupPtr imageLayerGroup;
};
} // namespace mbgl

View File

@@ -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<void(LayerGroup&)> f) {
void RenderOrchestrator::observeLayerGroups(std::function<void(LayerGroupBase&)> f) {
for (auto& pair : layerGroupsByLayerIndex) {
if (pair.second) {
f(*pair.second);
@@ -852,7 +852,7 @@ void RenderOrchestrator::observeLayerGroups(std::function<void(LayerGroup&)> f)
}
}
void RenderOrchestrator::observeLayerGroups(std::function<void(const LayerGroup&)> f) const {
void RenderOrchestrator::observeLayerGroups(std::function<void(const LayerGroupBase&)> f) const {
for (const auto& pair : layerGroupsByLayerIndex) {
if (pair.second) {
f(*pair.second);

View File

@@ -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(LayerGroup&)>);
void observeLayerGroups(std::function<void(const LayerGroup&)>) const;
const LayerGroupBasePtr& getLayerGroup(const int32_t layerIndex) const;
void observeLayerGroups(std::function<void(LayerGroupBase&)>);
void observeLayerGroups(std::function<void(const LayerGroupBase&)>) 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<std::unique_ptr<ChangeRequest>> pendingChanges;
using LayerGroupMap = std::map<int32_t, LayerGroupPtr>;
using LayerGroupMap = std::map<int32_t, LayerGroupBasePtr>;
LayerGroupMap layerGroupsByLayerIndex;
bool layerGroupOrderDirty = false;
};

View File

@@ -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();

View File

@@ -0,0 +1,124 @@
#include <mbgl/renderer/layer_group.hpp>
#include <mbgl/gfx/upload_pass.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/render_orchestrator.hpp>
#include <unordered_map>
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<mbgl::RenderPass>()(k.renderPass) ^ std::hash<OverscaledTileID>()(k.tileID) << 1);
}
};
};
struct TileLayerGroup::Impl {
Impl(std::size_t capacity)
: tileDrawables(capacity) {}
using TileMap = std::unordered_multimap<TileLayerGroupTileKey, gfx::UniqueDrawable, TileLayerGroupTileKey::hash>;
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<Impl>(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<gfx::UniqueDrawable> TileLayerGroup::removeDrawables(mbgl::RenderPass pass, const OverscaledTileID& id) {
const auto range = impl->tileDrawables.equal_range({pass, id});
std::vector<gfx::UniqueDrawable> 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<void(gfx::Drawable&)> f) {
for (auto& pair : impl->tileDrawables) {
if (pair.second) {
f(*pair.second);
}
}
}
void TileLayerGroup::observeDrawables(std::function<void(const gfx::Drawable&)> f) const {
for (const auto& pair : impl->tileDrawables) {
if (pair.second) {
f(*pair.second);
}
}
}
void TileLayerGroup::observeDrawables(std::function<void(gfx::UniqueDrawable&)> 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<void(gfx::Drawable&)>&& 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<void(const gfx::Drawable&)>&& 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