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:
committed by
Bart Louwers
parent
52b9e099e5
commit
d590ea97a8
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
17
include/mbgl/gfx/drawable_data.hpp
Normal file
17
include/mbgl/gfx/drawable_data.hpp
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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&,
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
23
src/mbgl/gfx/image_drawable_data.hpp
Normal file
23
src/mbgl/gfx/image_drawable_data.hpp
Normal 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
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
AddLayerGroupRequest::AddLayerGroupRequest(LayerGroupPtr layerGroup_, bool canReplace)
|
||||
AddLayerGroupRequest::AddLayerGroupRequest(LayerGroupBasePtr layerGroup_, bool canReplace)
|
||||
: layerGroup(std::move(layerGroup_)),
|
||||
replace(canReplace) {}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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:
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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}},
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
|
||||
124
src/mbgl/renderer/tile_layer_group.cpp
Normal file
124
src/mbgl/renderer/tile_layer_group.cpp
Normal 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
|
||||
Reference in New Issue
Block a user