core: rename mbgl directories to mln (#4511)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
119
include/mln/renderer/change_request.hpp
Normal file
119
include/mln/renderer/change_request.hpp
Normal file
@@ -0,0 +1,119 @@
|
||||
#pragma once
|
||||
|
||||
#include <mln/util/color.hpp>
|
||||
#include <mln/util/identity.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace mln {
|
||||
class ChangeRequest;
|
||||
class LayerGroupBase;
|
||||
class TileLayerGroup;
|
||||
class RenderOrchestrator;
|
||||
class RenderTarget;
|
||||
|
||||
using ChangeRequestPtr = std::shared_ptr<ChangeRequest>;
|
||||
using UniqueChangeRequest = std::unique_ptr<ChangeRequest>;
|
||||
using UniqueChangeRequestVec = std::vector<UniqueChangeRequest>;
|
||||
using LayerGroupBasePtr = std::shared_ptr<LayerGroupBase>;
|
||||
using RenderTargetPtr = std::shared_ptr<RenderTarget>;
|
||||
|
||||
namespace gfx {
|
||||
class Drawable;
|
||||
using DrawablePtr = std::shared_ptr<Drawable>;
|
||||
} // namespace gfx
|
||||
|
||||
/**
|
||||
Base class for changes to be made to the scene
|
||||
*/
|
||||
class ChangeRequest {
|
||||
protected:
|
||||
ChangeRequest() = default;
|
||||
|
||||
public:
|
||||
virtual ~ChangeRequest() = default;
|
||||
|
||||
virtual void execute(RenderOrchestrator &) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
Base for change requests based on an ID reference
|
||||
*/
|
||||
class RefChangeRequest : public ChangeRequest {
|
||||
protected:
|
||||
RefChangeRequest(util::SimpleIdentity id_)
|
||||
: id(id_) {}
|
||||
RefChangeRequest(const RefChangeRequest &) = default;
|
||||
|
||||
util::SimpleIdentity id;
|
||||
};
|
||||
|
||||
/**
|
||||
Add a new layer group to the scene
|
||||
*/
|
||||
class AddLayerGroupRequest : public ChangeRequest {
|
||||
public:
|
||||
AddLayerGroupRequest(LayerGroupBasePtr layerGroup_);
|
||||
AddLayerGroupRequest(AddLayerGroupRequest &&other);
|
||||
|
||||
void execute(RenderOrchestrator &) override;
|
||||
|
||||
protected:
|
||||
LayerGroupBasePtr layerGroup;
|
||||
};
|
||||
|
||||
/**
|
||||
Remove a layer group from the scene
|
||||
*/
|
||||
class RemoveLayerGroupRequest : public ChangeRequest {
|
||||
public:
|
||||
RemoveLayerGroupRequest(LayerGroupBasePtr layerGroup_)
|
||||
: layerGroup(std::move(layerGroup_)) {}
|
||||
RemoveLayerGroupRequest(const RemoveLayerGroupRequest &) = default;
|
||||
|
||||
void execute(RenderOrchestrator &) override;
|
||||
|
||||
protected:
|
||||
LayerGroupBasePtr layerGroup;
|
||||
};
|
||||
|
||||
class UpdateLayerGroupIndexRequest : public ChangeRequest {
|
||||
public:
|
||||
UpdateLayerGroupIndexRequest(LayerGroupBasePtr, int32_t newLayerIndex_);
|
||||
UpdateLayerGroupIndexRequest(const UpdateLayerGroupIndexRequest &) = delete;
|
||||
|
||||
void execute(RenderOrchestrator &) override;
|
||||
|
||||
protected:
|
||||
LayerGroupBasePtr layerGroup;
|
||||
int32_t newLayerIndex;
|
||||
};
|
||||
|
||||
/**
|
||||
Add a new render target to the scene
|
||||
*/
|
||||
class AddRenderTargetRequest : public ChangeRequest {
|
||||
public:
|
||||
AddRenderTargetRequest(RenderTargetPtr renderTarget_);
|
||||
|
||||
void execute(RenderOrchestrator &) override;
|
||||
|
||||
protected:
|
||||
RenderTargetPtr renderTarget;
|
||||
};
|
||||
|
||||
/**
|
||||
Remove a render target from the scene
|
||||
*/
|
||||
class RemoveRenderTargetRequest : public ChangeRequest {
|
||||
public:
|
||||
RemoveRenderTargetRequest(RenderTargetPtr renderTarget_);
|
||||
|
||||
void execute(RenderOrchestrator &) override;
|
||||
|
||||
protected:
|
||||
RenderTargetPtr renderTarget;
|
||||
};
|
||||
|
||||
} // namespace mln
|
||||
325
include/mln/renderer/layer_group.hpp
Normal file
325
include/mln/renderer/layer_group.hpp
Normal file
@@ -0,0 +1,325 @@
|
||||
#pragma once
|
||||
|
||||
#include <mln/gfx/drawable.hpp>
|
||||
#include <mln/gfx/context.hpp>
|
||||
#include <mln/renderer/render_pass.hpp>
|
||||
#include <mln/tile/tile_id.hpp>
|
||||
#include <mln/util/identity.hpp>
|
||||
#include <mln/util/logging.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace mln {
|
||||
class LayerGroupBase;
|
||||
class PaintParameters;
|
||||
class RenderOrchestrator;
|
||||
class RenderTile;
|
||||
class RenderTree;
|
||||
class TileLayerGroup;
|
||||
|
||||
using LayerGroupBasePtr = std::shared_ptr<LayerGroupBase>;
|
||||
using RenderTiles = std::shared_ptr<const std::vector<std::reference_wrapper<const RenderTile>>>;
|
||||
|
||||
namespace gfx {
|
||||
class Context;
|
||||
class Drawable;
|
||||
class UploadPass;
|
||||
|
||||
using DrawablePtr = std::shared_ptr<Drawable>;
|
||||
using UniqueDrawable = std::unique_ptr<Drawable>;
|
||||
} // namespace gfx
|
||||
|
||||
class LayerTweaker;
|
||||
using LayerTweakerPtr = std::shared_ptr<LayerTweaker>;
|
||||
using LayerTweakerWeakPtr = std::weak_ptr<LayerTweaker>;
|
||||
|
||||
/**
|
||||
A layer-like group of drawables, not a group of layers.
|
||||
*/
|
||||
class LayerGroupBase : public util::SimpleIdentifiable {
|
||||
public:
|
||||
enum class Type : uint8_t {
|
||||
LayerGroup = 0,
|
||||
TileLayerGroup,
|
||||
|
||||
Invalid = 255
|
||||
};
|
||||
|
||||
protected:
|
||||
LayerGroupBase(int32_t layerIndex, std::string name = std::string(), Type type = Type::Invalid);
|
||||
|
||||
public:
|
||||
LayerGroupBase(const LayerGroupBase&) = delete;
|
||||
LayerGroupBase& operator=(const LayerGroupBase&) = delete;
|
||||
~LayerGroupBase() override = default;
|
||||
|
||||
/// Whether the drawables should be drawn
|
||||
bool getEnabled() const { return enabled; }
|
||||
void setEnabled(bool value) { enabled = value; }
|
||||
|
||||
/// Get the type of layer group
|
||||
Type getType() const noexcept { return type; }
|
||||
|
||||
/// Get the name of the layer group
|
||||
const std::string& getName() const { return name; }
|
||||
/// Set the name of the layer group
|
||||
void setName(std::string value) { name = std::move(value); }
|
||||
|
||||
/// Get the layer index
|
||||
int32_t getLayerIndex() const { return layerIndex; }
|
||||
|
||||
/// Update the layer index to a new value
|
||||
virtual void updateLayerIndex(int32_t value) { layerIndex = value; }
|
||||
|
||||
/// Get the number of drawables contained
|
||||
virtual std::size_t getDrawableCount() const = 0;
|
||||
|
||||
/// Whether the number of drawables contained is zero
|
||||
bool empty() const { return getDrawableCount() == 0; }
|
||||
|
||||
/// Clear the drawable collection
|
||||
virtual std::size_t clearDrawables() = 0;
|
||||
|
||||
/// Add a drawable
|
||||
void addDrawable(gfx::UniqueDrawable&);
|
||||
|
||||
/// Called before starting each frame
|
||||
virtual void preRender(RenderOrchestrator&, PaintParameters&) {}
|
||||
/// Called during the upload pass
|
||||
virtual void upload(gfx::UploadPass&) {}
|
||||
/// Called during each render pass
|
||||
virtual void render(RenderOrchestrator&, PaintParameters&) {}
|
||||
/// Called at the end of each frame
|
||||
virtual void postRender(RenderOrchestrator&, PaintParameters&) {}
|
||||
|
||||
/// Attach a tweaker to be run on this layer group for each frame.
|
||||
/// Tweaker lifetime is controlled by the render layer and drawables, the layer group retains a weak reference.
|
||||
void addLayerTweaker(const LayerTweakerPtr& tweaker) { layerTweakers.emplace_back(tweaker); }
|
||||
|
||||
void runTweakers(const RenderTree&, PaintParameters&);
|
||||
|
||||
/// Get the uniform buffers attached to this layer group
|
||||
virtual const gfx::UniformBufferArray& getUniformBuffers() const = 0;
|
||||
|
||||
/// Get the mutable uniform buffer array attached to this layer group
|
||||
virtual gfx::UniformBufferArray& mutableUniformBuffers() = 0;
|
||||
|
||||
/// Set observer
|
||||
void setObserver(gfx::ContextObserver* observer_) { observer = observer_ ? observer_ : &gfx::nullObserver; }
|
||||
|
||||
protected:
|
||||
const Type type;
|
||||
bool enabled = true;
|
||||
int32_t layerIndex;
|
||||
std::vector<LayerTweakerWeakPtr> layerTweakers;
|
||||
std::string name;
|
||||
gfx::ContextObserver* observer;
|
||||
};
|
||||
|
||||
/**
|
||||
A layer group for tile-based drawables.
|
||||
*/
|
||||
class TileLayerGroup : public LayerGroupBase {
|
||||
public:
|
||||
TileLayerGroup(int32_t layerIndex, std::size_t initialCapacity, std::string name);
|
||||
~TileLayerGroup() override;
|
||||
|
||||
std::size_t getDrawableCount() const override;
|
||||
std::size_t getDrawableCount(mln::RenderPass, const OverscaledTileID&) const;
|
||||
|
||||
std::vector<gfx::UniqueDrawable> removeDrawables(mln::RenderPass, const OverscaledTileID&);
|
||||
void addDrawable(mln::RenderPass, const OverscaledTileID&, gfx::UniqueDrawable&&);
|
||||
|
||||
template <typename Func /* void(gfx::Drawable&) */>
|
||||
std::size_t visitDrawables(Func f) {
|
||||
assert(drawablesByTile.size() == sortedDrawables.size());
|
||||
unordered_set<gfx::Drawable*> drawablesFailed;
|
||||
for (auto* drawable : sortedDrawables) {
|
||||
try {
|
||||
f(*drawable);
|
||||
} catch (...) {
|
||||
drawablesFailed.insert(drawable);
|
||||
observer->onRenderError(std::current_exception());
|
||||
}
|
||||
}
|
||||
if (drawablesFailed.size() > 0) {
|
||||
removeDrawablesIf([&](gfx::Drawable& drawable) { return drawablesFailed.contains(&drawable); });
|
||||
}
|
||||
return sortedDrawables.size();
|
||||
}
|
||||
|
||||
template <typename Func /* bool(gfx::Drawable&) */>
|
||||
std::size_t removeDrawablesIf(Func f) {
|
||||
const auto oldSize = drawablesByTile.size();
|
||||
for (auto i = drawablesByTile.begin(); i != drawablesByTile.end();) {
|
||||
auto& drawable = i->second;
|
||||
if (!f(*drawable)) {
|
||||
// Not removed, keep going
|
||||
++i;
|
||||
} else {
|
||||
// Removed, take it out of the collections
|
||||
sortedDrawables.erase(drawable.get());
|
||||
i = drawablesByTile.erase(i);
|
||||
}
|
||||
assert(drawablesByTile.size() == sortedDrawables.size());
|
||||
}
|
||||
return (oldSize - drawablesByTile.size());
|
||||
}
|
||||
|
||||
/// Call the provided function for each drawable for the given tile
|
||||
template <typename Func /* void(gfx::Drawable&) */>
|
||||
std::size_t visitDrawables(mln::RenderPass pass, const OverscaledTileID& tileID, Func f) {
|
||||
assert(drawablesByTile.size() == sortedDrawables.size());
|
||||
unordered_set<gfx::Drawable*> drawablesFailed;
|
||||
auto range = drawablesByTile.equal_range({pass, tileID});
|
||||
std::for_each(range.first, range.second, [&f, &drawablesFailed, this](const auto& pair) {
|
||||
try {
|
||||
f(*pair.second);
|
||||
} catch (...) {
|
||||
drawablesFailed.insert(pair.second.get());
|
||||
observer->onRenderError(std::current_exception());
|
||||
}
|
||||
});
|
||||
if (drawablesFailed.size() > 0) {
|
||||
removeDrawablesIf([&](gfx::Drawable& drawable) { return drawablesFailed.contains(&drawable); });
|
||||
range = drawablesByTile.equal_range({pass, tileID});
|
||||
}
|
||||
return std::distance(range.first, range.second);
|
||||
}
|
||||
|
||||
std::size_t clearDrawables() override;
|
||||
|
||||
void setStencilTiles(RenderTiles);
|
||||
|
||||
void updateLayerIndex(int32_t value) override { layerIndex = value; }
|
||||
|
||||
protected:
|
||||
// When stencil clipping is enabled for the layer, this is the set
|
||||
// of tile IDs that need to be rendered to the stencil buffer.
|
||||
RenderTiles stencilTiles;
|
||||
|
||||
struct TileLayerGroupTileKey {
|
||||
mln::RenderPass renderPass;
|
||||
OverscaledTileID tileID;
|
||||
bool operator==(const TileLayerGroupTileKey& other) const {
|
||||
return renderPass == other.renderPass && tileID == other.tileID;
|
||||
}
|
||||
struct hash {
|
||||
size_t operator()(const TileLayerGroupTileKey& k) const {
|
||||
return (std::hash<mln::RenderPass>()(k.renderPass) ^ std::hash<OverscaledTileID>()(k.tileID) << 1);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
private:
|
||||
using TileMap = std::unordered_multimap<TileLayerGroupTileKey, gfx::UniqueDrawable, TileLayerGroupTileKey::hash>;
|
||||
TileMap drawablesByTile;
|
||||
|
||||
using DrawableMap = std::set<gfx::Drawable*, gfx::DrawableLessByPriority>;
|
||||
DrawableMap sortedDrawables;
|
||||
};
|
||||
|
||||
/**
|
||||
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;
|
||||
|
||||
std::size_t getDrawableCount() const override;
|
||||
std::size_t getDrawableCount(mln::RenderPass) const;
|
||||
|
||||
std::vector<gfx::UniqueDrawable> removeDrawables(mln::RenderPass);
|
||||
void addDrawable(gfx::UniqueDrawable&&);
|
||||
|
||||
template <typename Func /* void(gfx::Drawable&) */>
|
||||
std::size_t visitDrawables(Func f) {
|
||||
unordered_set<gfx::Drawable*> drawablesFailed;
|
||||
for (auto& item : drawables) {
|
||||
if (item) {
|
||||
try {
|
||||
f(*item);
|
||||
} catch (...) {
|
||||
drawablesFailed.insert(item.get());
|
||||
observer->onRenderError(std::current_exception());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (drawablesFailed.size() > 0) {
|
||||
removeDrawablesIf([&](gfx::Drawable& drawable) { return drawablesFailed.contains(&drawable); });
|
||||
}
|
||||
return drawables.size();
|
||||
}
|
||||
|
||||
template <typename Func /* bool(gfx::Drawable&) */>
|
||||
std::size_t removeDrawablesIf(Func f) {
|
||||
decltype(drawables) newSet;
|
||||
const auto oldSize = drawables.size();
|
||||
while (!drawables.empty()) {
|
||||
// set members are immutable, since changes could affect its position, so extract each item
|
||||
gfx::UniqueDrawable drawable = std::move(drawables.extract(drawables.begin()).value());
|
||||
if (!f(*drawable)) {
|
||||
// Not removed, keep it, but in a new set so that if the key value
|
||||
// has increased, we don't see it again during this iteration.
|
||||
newSet.emplace_hint(newSet.end(), std::move(drawable));
|
||||
}
|
||||
}
|
||||
std::swap(drawables, newSet);
|
||||
return (oldSize - drawables.size());
|
||||
}
|
||||
|
||||
std::size_t clearDrawables() override;
|
||||
|
||||
void updateLayerIndex(int32_t value) override { layerIndex = value; }
|
||||
|
||||
protected:
|
||||
using DrawableCollection = std::set<gfx::UniqueDrawable, gfx::DrawableLessByPriority>;
|
||||
DrawableCollection drawables;
|
||||
};
|
||||
|
||||
template <typename Func /* void(gfx::Drawable&) */>
|
||||
void visitLayerGroupDrawables(mln::LayerGroupBase& layerGroup, Func dg) {
|
||||
switch (layerGroup.getType()) {
|
||||
case LayerGroupBase::Type::LayerGroup: {
|
||||
static_cast<LayerGroup&>(layerGroup).visitDrawables(dg);
|
||||
break;
|
||||
}
|
||||
case LayerGroupBase::Type::TileLayerGroup: {
|
||||
static_cast<TileLayerGroup&>(layerGroup).visitDrawables(dg);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
#ifndef NDEBUG
|
||||
mln::Log::Error(mln::Event::Render,
|
||||
"Unknown layer group type: " + std::to_string(static_cast<uint8_t>(layerGroup.getType())));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Func /* bool(gfx::Drawable&) */>
|
||||
std::size_t removeLayerGroupDrawablesIf(mln::LayerGroupBase& layerGroup, Func dg) {
|
||||
switch (layerGroup.getType()) {
|
||||
case LayerGroupBase::Type::LayerGroup: {
|
||||
return static_cast<LayerGroup&>(layerGroup).removeDrawablesIf(dg);
|
||||
}
|
||||
case LayerGroupBase::Type::TileLayerGroup: {
|
||||
return static_cast<TileLayerGroup&>(layerGroup).removeDrawablesIf(dg);
|
||||
}
|
||||
default: {
|
||||
#ifndef NDEBUG
|
||||
mln::Log::Error(mln::Event::Render,
|
||||
"Unknown layer group type: " + std::to_string(static_cast<uint8_t>(layerGroup.getType())));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mln
|
||||
79
include/mln/renderer/layer_tweaker.hpp
Normal file
79
include/mln/renderer/layer_tweaker.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include <mln/shaders/layer_ubo.hpp>
|
||||
#include <mln/shaders/shader_source.hpp>
|
||||
#include <mln/util/immutable.hpp>
|
||||
#include <mln/util/containers.hpp>
|
||||
#include <mln/util/mat4.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace mln {
|
||||
|
||||
namespace gfx {
|
||||
class Drawable;
|
||||
class UniformBuffer;
|
||||
using UniformBufferPtr = std::shared_ptr<UniformBuffer>;
|
||||
} // namespace gfx
|
||||
|
||||
namespace style {
|
||||
class LayerProperties;
|
||||
enum class TranslateAnchorType : bool;
|
||||
} // namespace style
|
||||
|
||||
class LayerGroupBase;
|
||||
class PaintParameters;
|
||||
class RenderTree;
|
||||
class TransformState;
|
||||
class UnwrappedTileID;
|
||||
|
||||
/**
|
||||
Base class for layer tweakers, which manipulate layer group per frame
|
||||
*/
|
||||
class LayerTweaker {
|
||||
protected:
|
||||
LayerTweaker(std::string id, Immutable<style::LayerProperties> properties);
|
||||
|
||||
public:
|
||||
LayerTweaker() = delete;
|
||||
virtual ~LayerTweaker() = default;
|
||||
|
||||
const std::string& getID() const { return id; }
|
||||
|
||||
virtual void execute(LayerGroupBase&, const PaintParameters&) = 0;
|
||||
|
||||
void updateProperties(Immutable<style::LayerProperties>);
|
||||
|
||||
/// Calculate matrices for this tile.
|
||||
/// @param nearClipped If true, the near plane is moved further to enhance depth buffer precision.
|
||||
/// @param inViewportPixelUnits If false, the translation is scaled based on the current zoom.
|
||||
static mat4 getTileMatrix(const UnwrappedTileID&,
|
||||
const PaintParameters&,
|
||||
const std::array<float, 2>& translation,
|
||||
style::TranslateAnchorType,
|
||||
bool nearClipped,
|
||||
bool inViewportPixelUnits,
|
||||
const gfx::Drawable& drawable,
|
||||
bool aligned = false);
|
||||
|
||||
protected:
|
||||
/// Determine whether this tweaker should apply to the given drawable
|
||||
bool checkTweakDrawable(const gfx::Drawable&) const;
|
||||
|
||||
/// Multiplies with the projection matrix (either default, near clipped or aligned) for the given drawable
|
||||
static void multiplyWithProjectionMatrix(/*in-out*/ mat4& matrix,
|
||||
const PaintParameters& parameters,
|
||||
const gfx::Drawable& drawable,
|
||||
bool nearClipped,
|
||||
bool aligned);
|
||||
|
||||
std::string id;
|
||||
Immutable<style::LayerProperties> evaluatedProperties;
|
||||
|
||||
// Indicates that the evaluated properties have changed
|
||||
bool propertiesUpdated = true;
|
||||
};
|
||||
|
||||
} // namespace mln
|
||||
43
include/mln/renderer/query.hpp
Normal file
43
include/mln/renderer/query.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#include <mln/style/filter.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
namespace mln {
|
||||
|
||||
/**
|
||||
* Options for query rendered features.
|
||||
*/
|
||||
class RenderedQueryOptions {
|
||||
public:
|
||||
RenderedQueryOptions(std::optional<std::vector<std::string>> layerIDs_ = std::nullopt,
|
||||
std::optional<style::Filter> filter_ = std::nullopt)
|
||||
: layerIDs(std::move(layerIDs_)),
|
||||
filter(std::move(filter_)) {}
|
||||
|
||||
/** layerIDs to include in the query */
|
||||
std::optional<std::vector<std::string>> layerIDs;
|
||||
|
||||
std::optional<style::Filter> filter;
|
||||
};
|
||||
|
||||
/**
|
||||
* Options for query source features
|
||||
*/
|
||||
class SourceQueryOptions {
|
||||
public:
|
||||
SourceQueryOptions(std::optional<std::vector<std::string>> sourceLayers_ = std::nullopt,
|
||||
std::optional<style::Filter> filter_ = std::nullopt)
|
||||
: sourceLayers(std::move(sourceLayers_)),
|
||||
filter(std::move(filter_)) {}
|
||||
|
||||
/// Required for VectorSource, ignored for GeoJSONSource
|
||||
std::optional<std::vector<std::string>> sourceLayers;
|
||||
|
||||
std::optional<style::Filter> filter;
|
||||
};
|
||||
|
||||
} // namespace mln
|
||||
88
include/mln/renderer/render_target.hpp
Normal file
88
include/mln/renderer/render_target.hpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
|
||||
#include <mln/gfx/types.hpp>
|
||||
#include <mln/util/size.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace mln {
|
||||
|
||||
namespace gfx {
|
||||
class Context;
|
||||
class Texture2D;
|
||||
class OffscreenTexture;
|
||||
class UploadPass;
|
||||
using Texture2DPtr = std::shared_ptr<Texture2D>;
|
||||
} // namespace gfx
|
||||
|
||||
class LayerGroupBase;
|
||||
class PaintParameters;
|
||||
class RenderOrchestrator;
|
||||
class RenderTree;
|
||||
|
||||
using LayerGroupBasePtr = std::shared_ptr<LayerGroupBase>;
|
||||
|
||||
/// Render target class
|
||||
class RenderTarget {
|
||||
public:
|
||||
RenderTarget(gfx::Context& context, const Size size, const gfx::TextureChannelDataType type);
|
||||
~RenderTarget();
|
||||
|
||||
/// Get the render target texture
|
||||
const gfx::Texture2DPtr& getTexture();
|
||||
|
||||
/// @brief Add a layer group to the render target
|
||||
/// @param replace Flag to replace if exists
|
||||
/// @return whether added
|
||||
bool addLayerGroup(LayerGroupBasePtr, bool replace);
|
||||
|
||||
/// @brief Remove a layer group
|
||||
/// @param layerIndex index of the layer to remove
|
||||
/// @return whether removed
|
||||
bool removeLayerGroup(const int32_t layerIndex);
|
||||
|
||||
/// Get the layer group count
|
||||
size_t numLayerGroups() const noexcept;
|
||||
|
||||
/// @brief Get a specific layer group by index
|
||||
/// @param layerIndex index
|
||||
/// @return the layer group if existent, otherwise a shared null pointer
|
||||
const LayerGroupBasePtr& getLayerGroup(const int32_t layerIndex) const;
|
||||
|
||||
/// Execute the given function for each contained layer group
|
||||
template <typename Func /* void(LayerGroupBase&) */>
|
||||
void visitLayerGroups(Func f) {
|
||||
for (auto& pair : layerGroupsByLayerIndex) {
|
||||
if (pair.second) {
|
||||
f(*pair.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Execute the given function for each contained layer group in reversed order
|
||||
template <typename Func /* void(LayerGroupBase&) */>
|
||||
void visitLayerGroupsReversed(Func f) {
|
||||
for (auto rit = layerGroupsByLayerIndex.rbegin(); rit != layerGroupsByLayerIndex.rend(); ++rit) {
|
||||
if (rit->second) {
|
||||
f(*rit->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Upload the layer groups
|
||||
void upload(gfx::UploadPass& uploadPass);
|
||||
|
||||
/// Render the layer groups
|
||||
void render(RenderOrchestrator&, const RenderTree&, PaintParameters&);
|
||||
|
||||
protected:
|
||||
gfx::Context& context;
|
||||
std::unique_ptr<gfx::OffscreenTexture> offscreenTexture;
|
||||
using LayerGroupMap = std::map<int32_t, LayerGroupBasePtr>;
|
||||
LayerGroupMap layerGroupsByLayerIndex;
|
||||
};
|
||||
|
||||
} // namespace mln
|
||||
129
include/mln/renderer/renderer.hpp
Normal file
129
include/mln/renderer/renderer.hpp
Normal file
@@ -0,0 +1,129 @@
|
||||
#pragma once
|
||||
|
||||
#include <mln/renderer/query.hpp>
|
||||
#include <mln/annotation/annotation.hpp>
|
||||
#include <mln/util/geo.hpp>
|
||||
#include <mln/util/geojson.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace mln {
|
||||
|
||||
class RendererObserver;
|
||||
class RenderedQueryOptions;
|
||||
class SourceQueryOptions;
|
||||
class UpdateParameters;
|
||||
|
||||
namespace gfx {
|
||||
class RendererBackend;
|
||||
} // namespace gfx
|
||||
|
||||
struct PlacedSymbolData {
|
||||
/// Contents of the label
|
||||
std::u16string key;
|
||||
/// If symbol contains text, text collision box in viewport coordinates
|
||||
std::optional<mapbox::geometry::box<float>> textCollisionBox;
|
||||
/// If symbol contains icon, icon collision box in viewport coordinates
|
||||
std::optional<mapbox::geometry::box<float>> iconCollisionBox;
|
||||
/// Symbol text was placed
|
||||
bool textPlaced;
|
||||
/// Symbol icon was placed
|
||||
bool iconPlaced;
|
||||
/// Symbol text or icon collision box intersects tile borders
|
||||
bool intersectsTileBorder;
|
||||
/// Viewport padding ({viewportPadding, viewportPadding} is a coordinate of the tile's top-left corner)
|
||||
float viewportPadding;
|
||||
/// Layer id (leader of the symbol layout group)
|
||||
std::string layer;
|
||||
};
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
Renderer(gfx::RendererBackend&,
|
||||
float pixelRatio_,
|
||||
const std::optional<std::string>& localFontFamily = std::nullopt);
|
||||
~Renderer();
|
||||
|
||||
void markContextLost();
|
||||
|
||||
void setObserver(RendererObserver*);
|
||||
|
||||
void render(const std::shared_ptr<UpdateParameters>&);
|
||||
|
||||
/// Feature queries
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions& options = {}) const;
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenCoordinate& point,
|
||||
const RenderedQueryOptions& options = {}) const;
|
||||
std::vector<Feature> queryRenderedFeatures(const ScreenBox& box, const RenderedQueryOptions& options = {}) const;
|
||||
std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions& options = {}) const;
|
||||
AnnotationIDs queryPointAnnotations(const ScreenBox& box) const;
|
||||
AnnotationIDs queryShapeAnnotations(const ScreenBox& box) const;
|
||||
AnnotationIDs getAnnotationIDs(const std::vector<Feature>&) const;
|
||||
|
||||
/// Feature extension query
|
||||
FeatureExtensionValue queryFeatureExtensions(
|
||||
const std::string& sourceID,
|
||||
const Feature& feature,
|
||||
const std::string& extension,
|
||||
const std::string& extensionField,
|
||||
const std::optional<std::map<std::string, Value>>& args = std::nullopt) const;
|
||||
|
||||
void setFeatureState(const std::string& sourceID,
|
||||
const std::optional<std::string>& sourceLayerID,
|
||||
const std::string& featureID,
|
||||
const FeatureState& state);
|
||||
|
||||
void getFeatureState(FeatureState& state,
|
||||
const std::string& sourceID,
|
||||
const std::optional<std::string>& sourceLayerID,
|
||||
const std::string& featureID) const;
|
||||
|
||||
FeatureState getFeatureState(const std::string& sourceID,
|
||||
const std::optional<std::string>& sourceLayerID,
|
||||
const std::string& featureID) const;
|
||||
|
||||
void removeFeatureState(const std::string& sourceID,
|
||||
const std::optional<std::string>& sourceLayerID,
|
||||
const std::optional<std::string>& featureID,
|
||||
const std::optional<std::string>& stateKey);
|
||||
|
||||
// Debug
|
||||
void dumpDebugLogs();
|
||||
|
||||
/**
|
||||
* @brief In Tile map mode, enables or disables collecting of the placed
|
||||
* symbols data, which can be obtained with `getPlacedSymbolsData()`.
|
||||
*
|
||||
* The placed symbols data collecting is disabled by default.
|
||||
*/
|
||||
void collectPlacedSymbolData(bool enable);
|
||||
|
||||
/**
|
||||
* @brief If collecting of the placed symbols data is enabled, returns the
|
||||
* reference to the `PlacedSymbolData` vector holding the collected data.
|
||||
*
|
||||
* Note: the returned vector gets re-populated at every `render()` call.
|
||||
*
|
||||
* @return collected placed symbols data
|
||||
*/
|
||||
const std::vector<PlacedSymbolData>& getPlacedSymbolsData() const;
|
||||
|
||||
// Memory
|
||||
void setTileCacheEnabled(bool);
|
||||
bool getTileCacheEnabled() const;
|
||||
void reduceMemoryUse();
|
||||
void clearData();
|
||||
|
||||
#if MLN_RENDER_BACKEND_OPENGL
|
||||
void enableAndroidEmulatorGoldfishMitigation(bool enable);
|
||||
#endif
|
||||
|
||||
private:
|
||||
class Impl;
|
||||
std::unique_ptr<Impl> impl;
|
||||
};
|
||||
|
||||
} // namespace mln
|
||||
37
include/mln/renderer/renderer_frontend.hpp
Normal file
37
include/mln/renderer/renderer_frontend.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <mln/gfx/drawable.hpp>
|
||||
#include <mln/actor/scheduler.hpp>
|
||||
|
||||
namespace mln {
|
||||
|
||||
class RendererObserver;
|
||||
class UpdateParameters;
|
||||
|
||||
/// The RenderFrontend is the bridge between the Map and
|
||||
/// platform used to update and observe the Renderer
|
||||
///
|
||||
/// It hides any threading specifics and always replies on
|
||||
/// the original thread.
|
||||
class RendererFrontend {
|
||||
public:
|
||||
virtual ~RendererFrontend() = default;
|
||||
|
||||
/// Must synchronously clean up the Renderer if set
|
||||
virtual void reset() = 0;
|
||||
|
||||
/// Implementer must bind the renderer observer to the renderer in a
|
||||
/// appropriate manner so that the callbacks occur on the main thread
|
||||
virtual void setObserver(RendererObserver&) = 0;
|
||||
|
||||
/// Coalescing updates is up to the implementer
|
||||
virtual void update(std::shared_ptr<UpdateParameters>) = 0;
|
||||
|
||||
virtual const TaggedScheduler& getThreadPool() const = 0;
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
} // namespace mln
|
||||
89
include/mln/renderer/renderer_observer.hpp
Normal file
89
include/mln/renderer/renderer_observer.hpp
Normal file
@@ -0,0 +1,89 @@
|
||||
#pragma once
|
||||
|
||||
#include <mln/tile/tile_id.hpp>
|
||||
#include <mln/util/font_stack.hpp>
|
||||
#include <mln/gfx/rendering_stats.hpp>
|
||||
#include <mln/text/glyph_range.hpp>
|
||||
#include <mln/tile/tile_operation.hpp>
|
||||
#include <mln/gfx/backend.hpp>
|
||||
#include <mln/shaders/shader_source.hpp>
|
||||
#include <mln/util/symbol_error_observer.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
namespace mln {
|
||||
|
||||
namespace gfx {
|
||||
class ShaderRegistry;
|
||||
}
|
||||
|
||||
class RendererObserver : public SymbolErrorObserver {
|
||||
public:
|
||||
~RendererObserver() override = default;
|
||||
|
||||
enum class RenderMode : uint32_t {
|
||||
Partial,
|
||||
Full
|
||||
};
|
||||
|
||||
/// Signals that a repaint is required
|
||||
virtual void onInvalidate() {}
|
||||
|
||||
/// Resource failed to download / parse
|
||||
virtual void onResourceError(std::exception_ptr) {}
|
||||
|
||||
/// First frame
|
||||
virtual void onWillStartRenderingMap() {}
|
||||
|
||||
/// Start of frame, initial is the first frame for this map
|
||||
virtual void onWillStartRenderingFrame() {}
|
||||
|
||||
/// End of frame, booleans flags that a repaint is required and that placement changed.
|
||||
virtual void onDidFinishRenderingFrame(RenderMode, bool /*repaint*/, bool /*placementChanged*/) {}
|
||||
|
||||
/// End of frame, booleans flags that a repaint is required and that placement changed.
|
||||
virtual void onDidFinishRenderingFrame(RenderMode mode,
|
||||
bool repaint,
|
||||
bool placementChanged,
|
||||
double /*frameEncodingTime*/,
|
||||
double /*frameRenderingTime*/) {
|
||||
onDidFinishRenderingFrame(mode, repaint, placementChanged);
|
||||
}
|
||||
|
||||
virtual void onDidFinishRenderingFrame(RenderMode mode,
|
||||
bool repaint,
|
||||
bool placementChanged,
|
||||
const gfx::RenderingStats& stats) {
|
||||
onDidFinishRenderingFrame(mode, repaint, placementChanged, stats.encodingTime, stats.renderingTime);
|
||||
}
|
||||
|
||||
/// Final frame
|
||||
virtual void onDidFinishRenderingMap() {}
|
||||
|
||||
/// Style is missing an image
|
||||
using StyleImageMissingCallback = std::function<void()>;
|
||||
virtual void onStyleImageMissing(const std::string&, const StyleImageMissingCallback& done) { done(); }
|
||||
virtual void onRemoveUnusedStyleImages(const std::vector<std::string>&) {}
|
||||
|
||||
// Entry point for custom shader registration
|
||||
virtual void onRegisterShaders(gfx::ShaderRegistry&) {};
|
||||
virtual void onPreCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
virtual void onPostCompileShader(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
virtual void onShaderCompileFailed(shaders::BuiltIn, gfx::Backend::Type, const std::string&) {}
|
||||
|
||||
// Glyph loading
|
||||
virtual void onGlyphsLoaded(const FontStack&, const GlyphRange&) {}
|
||||
virtual void onGlyphsError(const FontStack&, const GlyphRange&, std::exception_ptr) {}
|
||||
virtual void onGlyphsRequested(const FontStack&, const GlyphRange&) {}
|
||||
|
||||
// Tile loading
|
||||
virtual void onTileAction(TileOperation, const OverscaledTileID&, const std::string&) {}
|
||||
|
||||
/// Render layer or drawable failed
|
||||
virtual void onRenderError(std::exception_ptr) {}
|
||||
};
|
||||
|
||||
} // namespace mln
|
||||
35
include/mln/renderer/renderer_state.hpp
Normal file
35
include/mln/renderer/renderer_state.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <mln/map/camera.hpp>
|
||||
#include <mln/util/geo.hpp>
|
||||
|
||||
namespace mln {
|
||||
|
||||
class UpdateParameters;
|
||||
|
||||
/**
|
||||
* RendererState acts as a Memento object that is able to extract data out of
|
||||
* UpdateParameters (an opaque object from the public API perspective).
|
||||
*/
|
||||
class RendererState {
|
||||
public:
|
||||
/// Obtains a CameraOptions out of a given UpdateParameters object.
|
||||
static CameraOptions getCameraOptions(const UpdateParameters&, const EdgeInsets& = {});
|
||||
|
||||
/// Returns whether an image with the given ID exists from a given UpdateParamters object.
|
||||
static bool hasImage(const UpdateParameters&, const std::string& id);
|
||||
|
||||
/// Returns whether a layer with the given ID exists from a given UpdateParamters object.
|
||||
static bool hasLayer(const UpdateParameters&, const std::string& id);
|
||||
|
||||
/// Returns whether a source with the given ID exists from a given UpdateParamters object.
|
||||
static bool hasSource(const UpdateParameters&, const std::string& id);
|
||||
|
||||
/// Obtains the geographical coordinate out of a given screen coordinate.
|
||||
static ScreenCoordinate pixelForLatLng(const UpdateParameters&, const LatLng&);
|
||||
|
||||
/// Obtains the screen coordinate out of a given geographical coordinate.
|
||||
static LatLng latLngForPixel(const UpdateParameters&, const ScreenCoordinate&);
|
||||
};
|
||||
|
||||
} // namespace mln
|
||||
Reference in New Issue
Block a user