Implement dynamic texture atlas (#3198)
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Bart Louwers <bart@emeel.net> Co-authored-by: Bart Louwers <bart.louwers@gmail.com>
@@ -157,6 +157,8 @@ list(APPEND INCLUDE_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_tweaker.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_tweaker.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_atlases_tweaker.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_atlases_tweaker.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_custom_layer_host_tweaker.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/drawable_custom_layer_host_tweaker.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/dynamic_texture.hpp
|
||||||
|
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/dynamic_texture_atlas.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/gpu_expression.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/gpu_expression.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_buffer.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/uniform_buffer.hpp
|
||||||
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/vertex_attribute.hpp
|
${PROJECT_SOURCE_DIR}/include/mbgl/gfx/vertex_attribute.hpp
|
||||||
@@ -175,6 +177,8 @@ list(APPEND SRC_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_builder_impl.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_builder_impl.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_atlases_tweaker.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_atlases_tweaker.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_custom_layer_host_tweaker.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/drawable_custom_layer_host_tweaker.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/dynamic_texture.cpp
|
||||||
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/dynamic_texture_atlas.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/gpu_expression.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/gpu_expression.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/hillshade_prepare_drawable_data.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/hillshade_prepare_drawable_data.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/image_drawable_data.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/gfx/image_drawable_data.hpp
|
||||||
@@ -616,8 +620,6 @@ list(APPEND SRC_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/data_driven_property_evaluator.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/data_driven_property_evaluator.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/group_by_layout.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/group_by_layout.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/group_by_layout.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/group_by_layout.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_atlas.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_atlas.hpp
|
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/renderer/image_manager.hpp
|
${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/image_manager_observer.hpp
|
||||||
@@ -881,8 +883,6 @@ list(APPEND SRC_FILES
|
|||||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/get_anchors.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/text/get_anchors.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/get_anchors.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/text/get_anchors.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_atlas.cpp
|
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_atlas.hpp
|
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_manager.cpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_manager.cpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_manager.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_manager.hpp
|
||||||
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_manager_observer.hpp
|
${PROJECT_SOURCE_DIR}/src/mbgl/text/glyph_manager_observer.hpp
|
||||||
|
|||||||
@@ -286,8 +286,6 @@ MLN_CORE_SOURCE = [
|
|||||||
"src/mbgl/renderer/data_driven_property_evaluator.hpp",
|
"src/mbgl/renderer/data_driven_property_evaluator.hpp",
|
||||||
"src/mbgl/renderer/group_by_layout.cpp",
|
"src/mbgl/renderer/group_by_layout.cpp",
|
||||||
"src/mbgl/renderer/group_by_layout.hpp",
|
"src/mbgl/renderer/group_by_layout.hpp",
|
||||||
"src/mbgl/renderer/image_atlas.cpp",
|
|
||||||
"src/mbgl/renderer/image_atlas.hpp",
|
|
||||||
"src/mbgl/renderer/image_manager.cpp",
|
"src/mbgl/renderer/image_manager.cpp",
|
||||||
"src/mbgl/renderer/image_manager.hpp",
|
"src/mbgl/renderer/image_manager.hpp",
|
||||||
"src/mbgl/renderer/image_manager_observer.hpp",
|
"src/mbgl/renderer/image_manager_observer.hpp",
|
||||||
@@ -528,8 +526,6 @@ MLN_CORE_SOURCE = [
|
|||||||
"src/mbgl/text/get_anchors.cpp",
|
"src/mbgl/text/get_anchors.cpp",
|
||||||
"src/mbgl/text/get_anchors.hpp",
|
"src/mbgl/text/get_anchors.hpp",
|
||||||
"src/mbgl/text/glyph.cpp",
|
"src/mbgl/text/glyph.cpp",
|
||||||
"src/mbgl/text/glyph_atlas.cpp",
|
|
||||||
"src/mbgl/text/glyph_atlas.hpp",
|
|
||||||
"src/mbgl/text/glyph_manager.cpp",
|
"src/mbgl/text/glyph_manager.cpp",
|
||||||
"src/mbgl/text/glyph_manager.hpp",
|
"src/mbgl/text/glyph_manager.hpp",
|
||||||
"src/mbgl/text/glyph_manager_observer.hpp",
|
"src/mbgl/text/glyph_manager_observer.hpp",
|
||||||
@@ -944,6 +940,8 @@ MLN_DRAWABLES_SOURCE = [
|
|||||||
"src/mbgl/gfx/drawable_builder_impl.cpp",
|
"src/mbgl/gfx/drawable_builder_impl.cpp",
|
||||||
"src/mbgl/gfx/drawable_atlases_tweaker.cpp",
|
"src/mbgl/gfx/drawable_atlases_tweaker.cpp",
|
||||||
"src/mbgl/gfx/drawable_custom_layer_host_tweaker.cpp",
|
"src/mbgl/gfx/drawable_custom_layer_host_tweaker.cpp",
|
||||||
|
"src/mbgl/gfx/dynamic_texture.cpp",
|
||||||
|
"src/mbgl/gfx/dynamic_texture_atlas.cpp",
|
||||||
"src/mbgl/gfx/gpu_expression.cpp",
|
"src/mbgl/gfx/gpu_expression.cpp",
|
||||||
"src/mbgl/gfx/hillshade_prepare_drawable_data.hpp",
|
"src/mbgl/gfx/hillshade_prepare_drawable_data.hpp",
|
||||||
"src/mbgl/gfx/image_drawable_data.hpp",
|
"src/mbgl/gfx/image_drawable_data.hpp",
|
||||||
@@ -1000,6 +998,8 @@ MLN_DRAWABLES_HEADERS = [
|
|||||||
"include/mbgl/gfx/drawable_tweaker.hpp",
|
"include/mbgl/gfx/drawable_tweaker.hpp",
|
||||||
"include/mbgl/gfx/drawable_atlases_tweaker.hpp",
|
"include/mbgl/gfx/drawable_atlases_tweaker.hpp",
|
||||||
"include/mbgl/gfx/drawable_custom_layer_host_tweaker.hpp",
|
"include/mbgl/gfx/drawable_custom_layer_host_tweaker.hpp",
|
||||||
|
"include/mbgl/gfx/dynamic_texture.hpp",
|
||||||
|
"include/mbgl/gfx/dynamic_texture_atlas.hpp",
|
||||||
"include/mbgl/gfx/gpu_expression.hpp",
|
"include/mbgl/gfx/gpu_expression.hpp",
|
||||||
"include/mbgl/gfx/uniform_buffer.hpp",
|
"include/mbgl/gfx/uniform_buffer.hpp",
|
||||||
"include/mbgl/gfx/vertex_attribute.hpp",
|
"include/mbgl/gfx/vertex_attribute.hpp",
|
||||||
|
|||||||
81
include/mbgl/gfx/dynamic_texture.hpp
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mbgl/gfx/types.hpp>
|
||||||
|
#include <mbgl/util/image.hpp>
|
||||||
|
#include <mbgl/util/rect.hpp>
|
||||||
|
|
||||||
|
#include <mapbox/shelf-pack.hpp>
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
|
||||||
|
namespace gfx {
|
||||||
|
|
||||||
|
class Context;
|
||||||
|
class Texture2D;
|
||||||
|
using Texture2DPtr = std::shared_ptr<gfx::Texture2D>;
|
||||||
|
|
||||||
|
class TextureHandle {
|
||||||
|
public:
|
||||||
|
TextureHandle(const mapbox::Bin& bin)
|
||||||
|
: id(bin.id),
|
||||||
|
rectangle(bin.x, bin.y, bin.w, bin.h),
|
||||||
|
needsUpload(bin.refcount() == 1) {};
|
||||||
|
~TextureHandle() = default;
|
||||||
|
|
||||||
|
int32_t getId() const { return id; }
|
||||||
|
const Rect<uint16_t>& getRectangle() const { return rectangle; }
|
||||||
|
bool isUploadNeeded() const { return needsUpload; }
|
||||||
|
|
||||||
|
bool operator==(const TextureHandle& other) const { return (id == other.id); }
|
||||||
|
|
||||||
|
struct Hasher {
|
||||||
|
size_t operator()(const TextureHandle& texHandle) const { return texHandle.id; }
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
int32_t id = 0;
|
||||||
|
Rect<uint16_t> rectangle;
|
||||||
|
bool needsUpload = false;
|
||||||
|
|
||||||
|
friend class DynamicTexture;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DynamicTexture {
|
||||||
|
public:
|
||||||
|
DynamicTexture(Context& context, Size size, TexturePixelType pixelType);
|
||||||
|
~DynamicTexture() = default;
|
||||||
|
|
||||||
|
const Texture2DPtr& getTexture() const;
|
||||||
|
TexturePixelType getPixelFormat() const;
|
||||||
|
bool isEmpty() const;
|
||||||
|
|
||||||
|
std::optional<TextureHandle> reserveSize(const Size& size, int32_t uniqueId);
|
||||||
|
void uploadImage(const uint8_t* pixelData, TextureHandle& texHandle);
|
||||||
|
|
||||||
|
template <typename Image>
|
||||||
|
std::optional<TextureHandle> addImage(const Image& image, int32_t uniqueId = -1) {
|
||||||
|
return addImage(image.data ? image.data.get() : nullptr, image.size, uniqueId);
|
||||||
|
}
|
||||||
|
std::optional<TextureHandle> addImage(const uint8_t* pixelData, const Size& imageSize, int32_t uniqueId = -1);
|
||||||
|
|
||||||
|
void uploadDeferredImages();
|
||||||
|
void removeTexture(const TextureHandle& texHandle);
|
||||||
|
|
||||||
|
using ImagesToUpload = std::unordered_map<TextureHandle, std::unique_ptr<uint8_t[]>, TextureHandle::Hasher>;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Texture2DPtr texture;
|
||||||
|
mapbox::ShelfPack shelfPack;
|
||||||
|
int numTextures = 0;
|
||||||
|
bool deferredCreation = false;
|
||||||
|
ImagesToUpload imagesToUpload;
|
||||||
|
std::mutex mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define MLN_DEFER_UPLOAD_ON_RENDER_THREAD (MLN_RENDER_BACKEND_OPENGL || MLN_RENDER_BACKEND_VULKAN)
|
||||||
|
|
||||||
|
} // namespace gfx
|
||||||
|
} // namespace mbgl
|
||||||
49
include/mbgl/gfx/dynamic_texture_atlas.hpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <mbgl/gfx/dynamic_texture.hpp>
|
||||||
|
#include <mbgl/text/glyph.hpp>
|
||||||
|
#include <mbgl/style/image_impl.hpp>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
|
||||||
|
namespace gfx {
|
||||||
|
|
||||||
|
using DynamicTexturePtr = std::shared_ptr<gfx::DynamicTexture>;
|
||||||
|
|
||||||
|
class GlyphAtlas {
|
||||||
|
public:
|
||||||
|
GlyphPositions glyphPositions;
|
||||||
|
std::vector<TextureHandle> textureHandles;
|
||||||
|
DynamicTexturePtr dynamicTexture;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ImageAtlas {
|
||||||
|
public:
|
||||||
|
ImagePositions iconPositions;
|
||||||
|
ImagePositions patternPositions;
|
||||||
|
std::vector<TextureHandle> textureHandles;
|
||||||
|
DynamicTexturePtr dynamicTexture;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DynamicTextureAtlas {
|
||||||
|
public:
|
||||||
|
DynamicTextureAtlas(Context& context_)
|
||||||
|
: context(context_) {}
|
||||||
|
~DynamicTextureAtlas() = default;
|
||||||
|
|
||||||
|
GlyphAtlas uploadGlyphs(const GlyphMap& glyphs);
|
||||||
|
ImageAtlas uploadIconsAndPatterns(const ImageMap& icons,
|
||||||
|
const ImageMap& patterns,
|
||||||
|
const ImageVersionMap& versionMap);
|
||||||
|
|
||||||
|
void removeTextures(const std::vector<TextureHandle>& textureHandles, const DynamicTexturePtr& dynamicTexture);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Context& context;
|
||||||
|
std::vector<DynamicTexturePtr> dynamicTextures;
|
||||||
|
std::unordered_map<TexturePixelType, DynamicTexturePtr> dummyDynamicTexture;
|
||||||
|
std::mutex mutex;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace gfx
|
||||||
|
} // namespace mbgl
|
||||||
@@ -53,6 +53,10 @@ public:
|
|||||||
/// @param image_ Image data to transfer
|
/// @param image_ Image data to transfer
|
||||||
virtual Texture2D& setImage(std::shared_ptr<PremultipliedImage> image_) noexcept = 0;
|
virtual Texture2D& setImage(std::shared_ptr<PremultipliedImage> image_) noexcept = 0;
|
||||||
|
|
||||||
|
/// @brief Get the pixel format of the texture
|
||||||
|
/// @return Pixel format of the texture
|
||||||
|
virtual TexturePixelType getFormat() const noexcept = 0;
|
||||||
|
|
||||||
/// @brief Get the size of the texture
|
/// @brief Get the size of the texture
|
||||||
/// @return Size of the texture
|
/// @return Size of the texture
|
||||||
virtual Size getSize() const noexcept = 0;
|
virtual Size getSize() const noexcept = 0;
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ public: // gfx::Texture2D
|
|||||||
|
|
||||||
Texture2D& setImage(std::shared_ptr<PremultipliedImage> image_) noexcept override;
|
Texture2D& setImage(std::shared_ptr<PremultipliedImage> image_) noexcept override;
|
||||||
|
|
||||||
|
gfx::TexturePixelType getFormat() const noexcept override { return pixelFormat; }
|
||||||
|
|
||||||
Size getSize() const noexcept override { return size; }
|
Size getSize() const noexcept override { return size; }
|
||||||
|
|
||||||
size_t getDataSize() const noexcept override;
|
size_t getDataSize() const noexcept override;
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ public:
|
|||||||
|
|
||||||
gfx::Texture2D& setImage(std::shared_ptr<PremultipliedImage>) noexcept override;
|
gfx::Texture2D& setImage(std::shared_ptr<PremultipliedImage>) noexcept override;
|
||||||
|
|
||||||
|
gfx::TexturePixelType getFormat() const noexcept override { return pixelFormat; }
|
||||||
|
|
||||||
Size getSize() const noexcept override { return size; }
|
Size getSize() const noexcept override { return size; }
|
||||||
|
|
||||||
size_t getDataSize() const noexcept override;
|
size_t getDataSize() const noexcept override;
|
||||||
|
|||||||
@@ -131,4 +131,12 @@ enum class WritingModeType : uint8_t {
|
|||||||
using GlyphDependencies = std::map<FontStack, GlyphIDs>;
|
using GlyphDependencies = std::map<FontStack, GlyphIDs>;
|
||||||
using GlyphRangeDependencies = std::map<FontStack, std::unordered_set<GlyphRange>>;
|
using GlyphRangeDependencies = std::map<FontStack, std::unordered_set<GlyphRange>>;
|
||||||
|
|
||||||
|
struct GlyphPosition {
|
||||||
|
Rect<uint16_t> rect;
|
||||||
|
GlyphMetrics metrics;
|
||||||
|
};
|
||||||
|
|
||||||
|
using GlyphPositionMap = std::map<GlyphID, GlyphPosition>;
|
||||||
|
using GlyphPositions = std::map<FontStackHash, GlyphPositionMap>;
|
||||||
|
|
||||||
} // end namespace mbgl
|
} // end namespace mbgl
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ public:
|
|||||||
gfx::Texture2D& setImage(std::shared_ptr<PremultipliedImage>) noexcept override;
|
gfx::Texture2D& setImage(std::shared_ptr<PremultipliedImage>) noexcept override;
|
||||||
gfx::Texture2D& setUsage(Texture2DUsage) noexcept;
|
gfx::Texture2D& setUsage(Texture2DUsage) noexcept;
|
||||||
|
|
||||||
|
gfx::TexturePixelType getFormat() const noexcept override { return pixelFormat; }
|
||||||
Size getSize() const noexcept override { return size; }
|
Size getSize() const noexcept override { return size; }
|
||||||
size_t getDataSize() const noexcept override;
|
size_t getDataSize() const noexcept override;
|
||||||
size_t getPixelStride() const noexcept override;
|
size_t getPixelStride() const noexcept override;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ filegroup(
|
|||||||
"ignores/**",
|
"ignores/**",
|
||||||
"ios-render-test-runner/**", # iOS only
|
"ios-render-test-runner/**", # iOS only
|
||||||
"expectations/platform-ios/**", # iOS only
|
"expectations/platform-ios/**", # iOS only
|
||||||
|
"expectations/platform-linux/**",
|
||||||
],
|
],
|
||||||
) + select({
|
) + select({
|
||||||
"//:metal_renderer": glob(["expectations/platform-ios-metal/**"]), # iOS Metal only
|
"//:metal_renderer": glob(["expectations/platform-ios-metal/**"]), # iOS Metal only
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 125 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 7.2 KiB |
|
After Width: | Height: | Size: 76 KiB |
|
After Width: | Height: | Size: 24 KiB |
@@ -2,6 +2,7 @@
|
|||||||
"base_test_path": "integration",
|
"base_test_path": "integration",
|
||||||
"cache_path": "cache-style.db",
|
"cache_path": "cache-style.db",
|
||||||
"expectation_paths": [
|
"expectation_paths": [
|
||||||
|
"expectations/platform-linux"
|
||||||
],
|
],
|
||||||
"ignore_paths": [
|
"ignore_paths": [
|
||||||
"ignores/platform-all.json",
|
"ignores/platform-all.json",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"base_test_path": "integration",
|
"base_test_path": "integration",
|
||||||
"cache_path": "cache-style.db",
|
"cache_path": "cache-style.db",
|
||||||
"expectation_paths": [
|
"expectation_paths": [
|
||||||
|
"expectations/platform-linux"
|
||||||
],
|
],
|
||||||
"ignore_paths": [
|
"ignore_paths": [
|
||||||
"ignores/platform-all.json",
|
"ignores/platform-all.json",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"base_test_path": "integration",
|
"base_test_path": "integration",
|
||||||
"cache_path": "cache-style.db",
|
"cache_path": "cache-style.db",
|
||||||
"expectation_paths": [
|
"expectation_paths": [
|
||||||
|
"expectations/platform-windows"
|
||||||
],
|
],
|
||||||
"ignore_paths": [
|
"ignore_paths": [
|
||||||
"ignores/platform-all.json",
|
"ignores/platform-all.json",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"base_test_path": "integration",
|
"base_test_path": "integration",
|
||||||
"cache_path": "cache-style.db",
|
"cache_path": "cache-style.db",
|
||||||
"expectation_paths": [
|
"expectation_paths": [
|
||||||
|
"expectations/platform-windows"
|
||||||
],
|
],
|
||||||
"ignore_paths": [
|
"ignore_paths": [
|
||||||
"ignores/platform-all.json",
|
"ignores/platform-all.json",
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"base_test_path": "integration",
|
"base_test_path": "integration",
|
||||||
"cache_path": "cache-style.db",
|
"cache_path": "cache-style.db",
|
||||||
"expectation_paths": [
|
"expectation_paths": [
|
||||||
|
"expectations/platform-windows"
|
||||||
],
|
],
|
||||||
"ignore_paths": [
|
"ignore_paths": [
|
||||||
"ignores/platform-all.json",
|
"ignores/platform-all.json",
|
||||||
|
|||||||
@@ -202,6 +202,7 @@ int runRenderTests(int argc, char** argv, std::function<void()> testStatus) {
|
|||||||
ignoreReason = it->second;
|
ignoreReason = it->second;
|
||||||
if (ignoreReason.rfind("skip", 0) == 0) {
|
if (ignoreReason.rfind("skip", 0) == 0) {
|
||||||
printf(ANSI_COLOR_GRAY "* skipped %s (%s)" ANSI_COLOR_RESET "\n", id.c_str(), ignoreReason.c_str());
|
printf(ANSI_COLOR_GRAY "* skipped %s (%s)" ANSI_COLOR_RESET "\n", id.c_str(), ignoreReason.c_str());
|
||||||
|
mbgl::Log::Info(mbgl::Event::General, "* skipped " + id + "(" + ignoreReason + ")");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -222,12 +223,14 @@ int runRenderTests(int argc, char** argv, std::function<void()> testStatus) {
|
|||||||
color = "#E8A408";
|
color = "#E8A408";
|
||||||
stats.ignorePassedTests++;
|
stats.ignorePassedTests++;
|
||||||
printf(ANSI_COLOR_YELLOW "* ignore %s (%s)" ANSI_COLOR_RESET "\n", id.c_str(), ignoreReason.c_str());
|
printf(ANSI_COLOR_YELLOW "* ignore %s (%s)" ANSI_COLOR_RESET "\n", id.c_str(), ignoreReason.c_str());
|
||||||
|
mbgl::Log::Info(mbgl::Event::General, "* ignore " + id + " (" + ignoreReason + ")");
|
||||||
} else {
|
} else {
|
||||||
status = "ignored failed";
|
status = "ignored failed";
|
||||||
color = "#9E9E9E";
|
color = "#9E9E9E";
|
||||||
stats.ignoreFailedTests++;
|
stats.ignoreFailedTests++;
|
||||||
printf(
|
printf(
|
||||||
ANSI_COLOR_LIGHT_GRAY "* ignore %s (%s)" ANSI_COLOR_RESET "\n", id.c_str(), ignoreReason.c_str());
|
ANSI_COLOR_LIGHT_GRAY "* ignore %s (%s)" ANSI_COLOR_RESET "\n", id.c_str(), ignoreReason.c_str());
|
||||||
|
mbgl::Log::Info(mbgl::Event::General, "* ignore " + id + " (" + ignoreReason + ")");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Only fail the bots on render errors, this is a CI limitation that
|
// Only fail the bots on render errors, this is a CI limitation that
|
||||||
@@ -244,6 +247,7 @@ int runRenderTests(int argc, char** argv, std::function<void()> testStatus) {
|
|||||||
color = "green";
|
color = "green";
|
||||||
stats.passedTests++;
|
stats.passedTests++;
|
||||||
printf(ANSI_COLOR_GREEN "* passed %s" ANSI_COLOR_RESET "\n", id.c_str());
|
printf(ANSI_COLOR_GREEN "* passed %s" ANSI_COLOR_RESET "\n", id.c_str());
|
||||||
|
mbgl::Log::Info(mbgl::Event::General, "* passed " + id);
|
||||||
} else if (errored) {
|
} else if (errored) {
|
||||||
status = "errored";
|
status = "errored";
|
||||||
color = "red";
|
color = "red";
|
||||||
@@ -251,12 +255,15 @@ int runRenderTests(int argc, char** argv, std::function<void()> testStatus) {
|
|||||||
returnCode = 2;
|
returnCode = 2;
|
||||||
printf(ANSI_COLOR_RED "* errored %s" ANSI_COLOR_RESET "\n", id.c_str());
|
printf(ANSI_COLOR_RED "* errored %s" ANSI_COLOR_RESET "\n", id.c_str());
|
||||||
printf(ANSI_COLOR_RED "* error: %s" ANSI_COLOR_RESET "\n", metadata.errorMessage.c_str());
|
printf(ANSI_COLOR_RED "* error: %s" ANSI_COLOR_RESET "\n", metadata.errorMessage.c_str());
|
||||||
|
mbgl::Log::Info(mbgl::Event::General, "* errored " + id);
|
||||||
|
mbgl::Log::Info(mbgl::Event::General, "* error " + metadata.errorMessage);
|
||||||
} else {
|
} else {
|
||||||
status = "failed";
|
status = "failed";
|
||||||
color = "red";
|
color = "red";
|
||||||
stats.failedTests++;
|
stats.failedTests++;
|
||||||
returnCode = 3;
|
returnCode = 3;
|
||||||
printf(ANSI_COLOR_RED "* failed %s" ANSI_COLOR_RESET "\n", id.c_str());
|
printf(ANSI_COLOR_RED "* failed %s" ANSI_COLOR_RESET "\n", id.c_str());
|
||||||
|
mbgl::Log::Info(mbgl::Event::General, "* failed " + id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,26 +285,32 @@ int runRenderTests(int argc, char** argv, std::function<void()> testStatus) {
|
|||||||
printf(ANSI_COLOR_GREEN "%u passed (%.1lf%%)" ANSI_COLOR_RESET "\n",
|
printf(ANSI_COLOR_GREEN "%u passed (%.1lf%%)" ANSI_COLOR_RESET "\n",
|
||||||
stats.passedTests,
|
stats.passedTests,
|
||||||
100.0 * stats.passedTests / count);
|
100.0 * stats.passedTests / count);
|
||||||
|
mbgl::Log::Info(mbgl::Event::General, std::to_string(stats.passedTests) + " passed tests");
|
||||||
}
|
}
|
||||||
if (stats.ignorePassedTests) {
|
if (stats.ignorePassedTests) {
|
||||||
printf(ANSI_COLOR_YELLOW "%u passed but were ignored (%.1lf%%)" ANSI_COLOR_RESET "\n",
|
printf(ANSI_COLOR_YELLOW "%u passed but were ignored (%.1lf%%)" ANSI_COLOR_RESET "\n",
|
||||||
stats.ignorePassedTests,
|
stats.ignorePassedTests,
|
||||||
100.0 * stats.ignorePassedTests / count);
|
100.0 * stats.ignorePassedTests / count);
|
||||||
|
mbgl::Log::Info(mbgl::Event::General,
|
||||||
|
std::to_string(stats.ignorePassedTests) + " passed tests but were ignored");
|
||||||
}
|
}
|
||||||
if (stats.ignoreFailedTests) {
|
if (stats.ignoreFailedTests) {
|
||||||
printf(ANSI_COLOR_LIGHT_GRAY "%u ignored (%.1lf%%)" ANSI_COLOR_RESET "\n",
|
printf(ANSI_COLOR_LIGHT_GRAY "%u ignored (%.1lf%%)" ANSI_COLOR_RESET "\n",
|
||||||
stats.ignoreFailedTests,
|
stats.ignoreFailedTests,
|
||||||
100.0 * stats.ignoreFailedTests / count);
|
100.0 * stats.ignoreFailedTests / count);
|
||||||
|
mbgl::Log::Info(mbgl::Event::General, std::to_string(stats.ignoreFailedTests) + " ignored tests");
|
||||||
}
|
}
|
||||||
if (stats.failedTests) {
|
if (stats.failedTests) {
|
||||||
printf(ANSI_COLOR_RED "%u failed (%.1lf%%)" ANSI_COLOR_RESET "\n",
|
printf(ANSI_COLOR_RED "%u failed (%.1lf%%)" ANSI_COLOR_RESET "\n",
|
||||||
stats.failedTests,
|
stats.failedTests,
|
||||||
100.0 * stats.failedTests / count);
|
100.0 * stats.failedTests / count);
|
||||||
|
mbgl::Log::Info(mbgl::Event::General, std::to_string(stats.failedTests) + " failed tests");
|
||||||
}
|
}
|
||||||
if (stats.erroredTests) {
|
if (stats.erroredTests) {
|
||||||
printf(ANSI_COLOR_RED "%u errored (%.1lf%%)" ANSI_COLOR_RESET "\n",
|
printf(ANSI_COLOR_RED "%u errored (%.1lf%%)" ANSI_COLOR_RESET "\n",
|
||||||
stats.erroredTests,
|
stats.erroredTests,
|
||||||
100.0 * stats.erroredTests / count);
|
100.0 * stats.erroredTests / count);
|
||||||
|
mbgl::Log::Info(mbgl::Event::General, std::to_string(stats.erroredTests) + " errored tests");
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Results at: %s\n", mbgl::filesystem::canonical(resultPath).generic_string().c_str());
|
printf("Results at: %s\n", mbgl::filesystem::canonical(resultPath).generic_string().c_str());
|
||||||
|
|||||||
@@ -10,11 +10,13 @@ namespace gfx {
|
|||||||
|
|
||||||
void DrawableAtlasesTweaker::setupTextures(gfx::Drawable& drawable, const bool linearFilterForIcons) {
|
void DrawableAtlasesTweaker::setupTextures(gfx::Drawable& drawable, const bool linearFilterForIcons) {
|
||||||
if (const auto& shader = drawable.getShader()) {
|
if (const auto& shader = drawable.getShader()) {
|
||||||
if (glyphTextureId) {
|
if (glyphTextureId && atlases) {
|
||||||
if (atlases) {
|
if (atlases->glyph) {
|
||||||
atlases->glyph->setSamplerConfiguration({.filter = TextureFilterType::Linear,
|
atlases->glyph->setSamplerConfiguration({.filter = TextureFilterType::Linear,
|
||||||
.wrapU = TextureWrapType::Clamp,
|
.wrapU = TextureWrapType::Clamp,
|
||||||
.wrapV = TextureWrapType::Clamp});
|
.wrapV = TextureWrapType::Clamp});
|
||||||
|
}
|
||||||
|
if (atlases->icon) {
|
||||||
atlases->icon->setSamplerConfiguration(
|
atlases->icon->setSamplerConfiguration(
|
||||||
{.filter = linearFilterForIcons ? TextureFilterType::Linear : TextureFilterType::Nearest,
|
{.filter = linearFilterForIcons ? TextureFilterType::Linear : TextureFilterType::Nearest,
|
||||||
.wrapU = TextureWrapType::Clamp,
|
.wrapU = TextureWrapType::Clamp,
|
||||||
|
|||||||
104
src/mbgl/gfx/dynamic_texture.cpp
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
#include <mbgl/gfx/dynamic_texture.hpp>
|
||||||
|
#include <mbgl/gfx/texture2d.hpp>
|
||||||
|
#include <mbgl/gfx/context.hpp>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
namespace gfx {
|
||||||
|
|
||||||
|
DynamicTexture::DynamicTexture(Context& context, Size size, TexturePixelType pixelType) {
|
||||||
|
mapbox::ShelfPack::ShelfPackOptions options;
|
||||||
|
options.autoResize = false;
|
||||||
|
shelfPack = mapbox::ShelfPack(size.width, size.height, options);
|
||||||
|
|
||||||
|
texture = context.createTexture2D();
|
||||||
|
texture->setSize(size);
|
||||||
|
texture->setFormat(pixelType, TextureChannelDataType::UnsignedByte);
|
||||||
|
texture->setSamplerConfiguration(
|
||||||
|
{gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
|
||||||
|
#if MLN_DEFER_UPLOAD_ON_RENDER_THREAD
|
||||||
|
deferredCreation = true;
|
||||||
|
#else
|
||||||
|
texture->create();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
const Texture2DPtr& DynamicTexture::getTexture() const {
|
||||||
|
assert(texture);
|
||||||
|
return texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
TexturePixelType DynamicTexture::getPixelFormat() const {
|
||||||
|
assert(texture);
|
||||||
|
return texture->getFormat();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DynamicTexture::isEmpty() const {
|
||||||
|
return (numTextures == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<TextureHandle> DynamicTexture::reserveSize(const Size& size, int32_t uniqueId) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
mapbox::Bin* bin = shelfPack.packOne(uniqueId, size.width, size.height);
|
||||||
|
if (!bin) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
if (bin->refcount() == 1) {
|
||||||
|
numTextures++;
|
||||||
|
}
|
||||||
|
return TextureHandle(*bin);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicTexture::uploadImage(const uint8_t* pixelData, TextureHandle& texHandle) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
const auto& rect = texHandle.getRectangle();
|
||||||
|
const auto imageSize = Size(rect.w, rect.h);
|
||||||
|
|
||||||
|
#if MLN_DEFER_UPLOAD_ON_RENDER_THREAD
|
||||||
|
auto size = imageSize.area() * texture->getPixelStride();
|
||||||
|
auto imageData = std::make_unique<uint8_t[]>(size);
|
||||||
|
std::copy(pixelData, pixelData + size, imageData.get());
|
||||||
|
imagesToUpload.emplace(texHandle, std::move(imageData));
|
||||||
|
#else
|
||||||
|
texture->uploadSubRegion(pixelData, imageSize, rect.x, rect.y);
|
||||||
|
#endif
|
||||||
|
texHandle.needsUpload = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<TextureHandle> DynamicTexture::addImage(const uint8_t* pixelData,
|
||||||
|
const Size& imageSize,
|
||||||
|
int32_t uniqueId) {
|
||||||
|
auto texHandle = reserveSize(imageSize, uniqueId);
|
||||||
|
if (texHandle && texHandle->isUploadNeeded()) {
|
||||||
|
uploadImage(pixelData, *texHandle);
|
||||||
|
}
|
||||||
|
return texHandle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicTexture::uploadDeferredImages() {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
if (deferredCreation) {
|
||||||
|
texture->create();
|
||||||
|
deferredCreation = false;
|
||||||
|
}
|
||||||
|
for (const auto& pair : imagesToUpload) {
|
||||||
|
const auto& rect = pair.first.getRectangle();
|
||||||
|
texture->uploadSubRegion(pair.second.get(), Size(rect.w, rect.h), rect.x, rect.y);
|
||||||
|
}
|
||||||
|
imagesToUpload.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicTexture::removeTexture(const TextureHandle& texHandle) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
auto* bin = shelfPack.getBin(texHandle.getId());
|
||||||
|
if (!bin) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto refcount = shelfPack.unref(*bin);
|
||||||
|
if (refcount == 0) {
|
||||||
|
numTextures--;
|
||||||
|
imagesToUpload.erase(texHandle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace gfx
|
||||||
|
} // namespace mbgl
|
||||||
256
src/mbgl/gfx/dynamic_texture_atlas.cpp
Normal file
@@ -0,0 +1,256 @@
|
|||||||
|
#include <mbgl/gfx/dynamic_texture_atlas.hpp>
|
||||||
|
#include <mbgl/gfx/context.hpp>
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
namespace mbgl {
|
||||||
|
namespace gfx {
|
||||||
|
|
||||||
|
constexpr const uint16_t extraPadding = 1;
|
||||||
|
constexpr const uint16_t padding = ImagePosition::padding + extraPadding;
|
||||||
|
constexpr const Size startSize = {512, 512};
|
||||||
|
|
||||||
|
Rect<uint16_t> rectWithoutExtraPadding(const Rect<uint16_t>& rect) {
|
||||||
|
return Rect<uint16_t>(
|
||||||
|
rect.x + extraPadding, rect.y + extraPadding, rect.w - 2 * extraPadding, rect.h - 2 * extraPadding);
|
||||||
|
}
|
||||||
|
|
||||||
|
GlyphAtlas DynamicTextureAtlas::uploadGlyphs(const GlyphMap& glyphs) {
|
||||||
|
using GlyphsToUpload = std::vector<std::tuple<TextureHandle, Immutable<Glyph>, FontStackHash>>;
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
|
||||||
|
GlyphAtlas glyphAtlas;
|
||||||
|
if (!glyphs.size()) {
|
||||||
|
glyphAtlas.dynamicTexture = dummyDynamicTexture[TexturePixelType::Alpha];
|
||||||
|
if (!glyphAtlas.dynamicTexture) {
|
||||||
|
glyphAtlas.dynamicTexture = std::make_shared<gfx::DynamicTexture>(
|
||||||
|
context, Size(1, 1), TexturePixelType::Alpha);
|
||||||
|
dummyDynamicTexture[TexturePixelType::Alpha] = glyphAtlas.dynamicTexture;
|
||||||
|
}
|
||||||
|
return glyphAtlas;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t dynTexIndex = 0;
|
||||||
|
Size dynTexSize = startSize;
|
||||||
|
GlyphsToUpload glyphsToUpload;
|
||||||
|
|
||||||
|
while (!glyphAtlas.dynamicTexture) {
|
||||||
|
if (dynTexIndex < dynamicTextures.size()) {
|
||||||
|
glyphAtlas.dynamicTexture = dynamicTextures[dynTexIndex++];
|
||||||
|
} else {
|
||||||
|
glyphAtlas.dynamicTexture = std::make_shared<gfx::DynamicTexture>(
|
||||||
|
context, dynTexSize, TexturePixelType::Alpha);
|
||||||
|
dynTexSize = Size(dynTexSize.width * 2, dynTexSize.height * 2);
|
||||||
|
dynTexIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (glyphAtlas.dynamicTexture->getPixelFormat() != TexturePixelType::Alpha) {
|
||||||
|
glyphAtlas.dynamicTexture = nullptr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasSpace = true;
|
||||||
|
for (const auto& glyphMapEntry : glyphs) {
|
||||||
|
FontStackHash fontStack = glyphMapEntry.first;
|
||||||
|
|
||||||
|
for (const auto& glyphEntry : glyphMapEntry.second) {
|
||||||
|
const auto& glyph = glyphEntry.second;
|
||||||
|
|
||||||
|
if (glyph.has_value() && glyph.value()->bitmap.valid()) {
|
||||||
|
int32_t uniqueId = static_cast<int32_t>(sqrt(fontStack) / 2 + glyph.value()->id);
|
||||||
|
const auto size = Size(glyph.value()->bitmap.size.width + 2 * padding,
|
||||||
|
glyph.value()->bitmap.size.height + 2 * padding);
|
||||||
|
const auto& texHandle = glyphAtlas.dynamicTexture->reserveSize(size, uniqueId);
|
||||||
|
if (!texHandle) {
|
||||||
|
hasSpace = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
glyphsToUpload.emplace_back(std::make_tuple(*texHandle, glyph.value(), fontStack));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasSpace) {
|
||||||
|
for (const auto& [texHandle, glyph, fontStack_] : glyphsToUpload) {
|
||||||
|
glyphAtlas.dynamicTexture->removeTexture(texHandle);
|
||||||
|
}
|
||||||
|
glyphsToUpload.clear();
|
||||||
|
glyphAtlas.dynamicTexture = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dynTexIndex > dynamicTextures.size()) {
|
||||||
|
dynamicTextures.emplace_back(glyphAtlas.dynamicTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto& [texHandle, glyph, fontStack] : glyphsToUpload) {
|
||||||
|
const auto& rect = texHandle.getRectangle();
|
||||||
|
|
||||||
|
if (texHandle.isUploadNeeded()) {
|
||||||
|
AlphaImage paddedImage(Size{rect.w, rect.h});
|
||||||
|
paddedImage.fill(0);
|
||||||
|
AlphaImage::copy(glyph->bitmap, paddedImage, {0, 0}, {padding, padding}, glyph->bitmap.size);
|
||||||
|
|
||||||
|
glyphAtlas.dynamicTexture->uploadImage(paddedImage.data.get(), texHandle);
|
||||||
|
}
|
||||||
|
glyphAtlas.textureHandles.emplace_back(texHandle);
|
||||||
|
glyphAtlas.glyphPositions[fontStack].emplace(glyph->id,
|
||||||
|
GlyphPosition{rectWithoutExtraPadding(rect), glyph->metrics});
|
||||||
|
}
|
||||||
|
return glyphAtlas;
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageAtlas DynamicTextureAtlas::uploadIconsAndPatterns(const ImageMap& icons,
|
||||||
|
const ImageMap& patterns,
|
||||||
|
const ImageVersionMap& versionMap) {
|
||||||
|
using ImagesToUpload = std::vector<std::pair<TextureHandle, Immutable<style::Image::Impl>>>;
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
|
||||||
|
ImageAtlas imageAtlas;
|
||||||
|
if (!icons.size() && !patterns.size()) {
|
||||||
|
imageAtlas.dynamicTexture = dummyDynamicTexture[TexturePixelType::RGBA];
|
||||||
|
if (!imageAtlas.dynamicTexture) {
|
||||||
|
imageAtlas.dynamicTexture = std::make_shared<gfx::DynamicTexture>(
|
||||||
|
context, Size(1, 1), TexturePixelType::RGBA);
|
||||||
|
dummyDynamicTexture[TexturePixelType::RGBA] = imageAtlas.dynamicTexture;
|
||||||
|
}
|
||||||
|
return imageAtlas;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t dynTexIndex = 0;
|
||||||
|
Size dynTexSize = startSize;
|
||||||
|
ImagesToUpload iconsToUpload;
|
||||||
|
ImagesToUpload patternsToUpload;
|
||||||
|
|
||||||
|
iconsToUpload.reserve(icons.size());
|
||||||
|
patternsToUpload.reserve(patterns.size());
|
||||||
|
while (!imageAtlas.dynamicTexture) {
|
||||||
|
if (dynTexIndex < dynamicTextures.size()) {
|
||||||
|
imageAtlas.dynamicTexture = dynamicTextures[dynTexIndex++];
|
||||||
|
} else {
|
||||||
|
imageAtlas.dynamicTexture = std::make_shared<gfx::DynamicTexture>(
|
||||||
|
context, dynTexSize, TexturePixelType::RGBA);
|
||||||
|
dynTexSize = Size(dynTexSize.width * 2, dynTexSize.height * 2);
|
||||||
|
dynTexIndex++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (imageAtlas.dynamicTexture->getPixelFormat() != TexturePixelType::RGBA) {
|
||||||
|
imageAtlas.dynamicTexture = nullptr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hasSpace = true;
|
||||||
|
for (const auto& iconEntry : icons) {
|
||||||
|
const auto& icon = iconEntry.second;
|
||||||
|
|
||||||
|
auto imageHash = util::hash(icon->id);
|
||||||
|
int32_t uniqueId = static_cast<int32_t>(sqrt(imageHash) / 2 + icon->image.size.area());
|
||||||
|
const auto size = Size(icon->image.size.width + 2 * padding, icon->image.size.height + 2 * padding);
|
||||||
|
const auto& texHandle = imageAtlas.dynamicTexture->reserveSize(size, uniqueId);
|
||||||
|
if (!texHandle) {
|
||||||
|
hasSpace = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iconsToUpload.emplace_back(std::make_pair(*texHandle, icon));
|
||||||
|
}
|
||||||
|
if (hasSpace) {
|
||||||
|
for (const auto& patternEntry : patterns) {
|
||||||
|
const auto& pattern = patternEntry.second;
|
||||||
|
|
||||||
|
auto patternHash = util::hash(pattern->id);
|
||||||
|
int32_t uniqueId = static_cast<int32_t>(sqrt(patternHash) / 2 + pattern->image.size.area());
|
||||||
|
const auto size = Size(pattern->image.size.width + 2 * padding,
|
||||||
|
pattern->image.size.height + 2 * padding);
|
||||||
|
const auto& texHandle = imageAtlas.dynamicTexture->reserveSize(size, uniqueId);
|
||||||
|
if (!texHandle) {
|
||||||
|
hasSpace = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
patternsToUpload.emplace_back(std::make_pair(*texHandle, pattern));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasSpace) {
|
||||||
|
for (const auto& [texHandle, icon] : iconsToUpload) {
|
||||||
|
imageAtlas.dynamicTexture->removeTexture(texHandle);
|
||||||
|
}
|
||||||
|
iconsToUpload.clear();
|
||||||
|
for (const auto& [texHandle, pattern] : patternsToUpload) {
|
||||||
|
imageAtlas.dynamicTexture->removeTexture(texHandle);
|
||||||
|
}
|
||||||
|
patternsToUpload.clear();
|
||||||
|
imageAtlas.dynamicTexture = nullptr;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (dynTexIndex > dynamicTextures.size()) {
|
||||||
|
dynamicTextures.emplace_back(imageAtlas.dynamicTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
imageAtlas.iconPositions.reserve(icons.size());
|
||||||
|
for (auto& [texHandle, icon] : iconsToUpload) {
|
||||||
|
const auto& rect = texHandle.getRectangle();
|
||||||
|
|
||||||
|
if (texHandle.isUploadNeeded()) {
|
||||||
|
PremultipliedImage paddedImage(Size{rect.w, rect.h});
|
||||||
|
paddedImage.fill(0);
|
||||||
|
PremultipliedImage::copy(icon->image, paddedImage, {0, 0}, {padding, padding}, icon->image.size);
|
||||||
|
|
||||||
|
imageAtlas.dynamicTexture->uploadImage(paddedImage.data.get(), texHandle);
|
||||||
|
}
|
||||||
|
imageAtlas.textureHandles.emplace_back(texHandle);
|
||||||
|
const auto it = versionMap.find(icon->id);
|
||||||
|
const auto version = it != versionMap.end() ? it->second : 0;
|
||||||
|
imageAtlas.iconPositions.emplace(icon->id, ImagePosition{rectWithoutExtraPadding(rect), *icon, version});
|
||||||
|
}
|
||||||
|
|
||||||
|
imageAtlas.patternPositions.reserve(patterns.size());
|
||||||
|
for (auto& [texHandle, pattern] : patternsToUpload) {
|
||||||
|
const auto& rect = texHandle.getRectangle();
|
||||||
|
|
||||||
|
if (texHandle.isUploadNeeded()) {
|
||||||
|
PremultipliedImage paddedImage(Size{rect.w, rect.h});
|
||||||
|
paddedImage.fill(0);
|
||||||
|
PremultipliedImage::copy(pattern->image, paddedImage, {0, 0}, {padding, padding}, pattern->image.size);
|
||||||
|
|
||||||
|
const uint32_t x = padding;
|
||||||
|
const uint32_t y = padding;
|
||||||
|
const uint32_t w = pattern->image.size.width;
|
||||||
|
const uint32_t h = pattern->image.size.height;
|
||||||
|
|
||||||
|
// Add 1 pixel wrapped padding on each side of the image.
|
||||||
|
PremultipliedImage::copy(pattern->image, paddedImage, {0, h - 1}, {x, y - 1}, {w, 1}); // T
|
||||||
|
PremultipliedImage::copy(pattern->image, paddedImage, {0, 0}, {x, y + h}, {w, 1}); // B
|
||||||
|
PremultipliedImage::copy(pattern->image, paddedImage, {w - 1, 0}, {x - 1, y}, {1, h}); // L
|
||||||
|
PremultipliedImage::copy(pattern->image, paddedImage, {0, 0}, {x + w, y}, {1, h}); // R
|
||||||
|
|
||||||
|
imageAtlas.dynamicTexture->uploadImage(paddedImage.data.get(), texHandle);
|
||||||
|
}
|
||||||
|
imageAtlas.textureHandles.emplace_back(texHandle);
|
||||||
|
const auto it = versionMap.find(pattern->id);
|
||||||
|
const auto version = it != versionMap.end() ? it->second : 0;
|
||||||
|
imageAtlas.patternPositions.emplace(pattern->id,
|
||||||
|
ImagePosition{rectWithoutExtraPadding(rect), *pattern, version});
|
||||||
|
}
|
||||||
|
|
||||||
|
return imageAtlas;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DynamicTextureAtlas::removeTextures(const std::vector<TextureHandle>& textureHandles,
|
||||||
|
const DynamicTexturePtr& dynamicTexture) {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
if (!dynamicTexture) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& texHandle : textureHandles) {
|
||||||
|
dynamicTexture->removeTexture(texHandle);
|
||||||
|
}
|
||||||
|
if (dynamicTexture->isEmpty()) {
|
||||||
|
auto iterator = std::find(dynamicTextures.begin(), dynamicTextures.end(), dynamicTexture);
|
||||||
|
if (iterator != dynamicTextures.end()) {
|
||||||
|
dynamicTextures.erase(iterator);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace gfx
|
||||||
|
} // namespace mbgl
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
#include <mbgl/style/image_impl.hpp>
|
||||||
#include <mbgl/text/glyph_atlas.hpp>
|
#include <mbgl/text/glyph.hpp>
|
||||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||||
#include <mbgl/util/containers.hpp>
|
#include <mbgl/util/containers.hpp>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mbgl/text/quads.hpp>
|
#include <mbgl/text/quads.hpp>
|
||||||
#include <mbgl/text/glyph_atlas.hpp>
|
|
||||||
#include <mbgl/text/collision_feature.hpp>
|
#include <mbgl/text/collision_feature.hpp>
|
||||||
#include <mbgl/style/layers/symbol_layer_properties.hpp>
|
#include <mbgl/style/layers/symbol_layer_properties.hpp>
|
||||||
#include <mbgl/util/bitmask_operations.hpp>
|
#include <mbgl/util/bitmask_operations.hpp>
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include <mbgl/math/angles.hpp>
|
#include <mbgl/math/angles.hpp>
|
||||||
#include <mbgl/renderer/bucket_parameters.hpp>
|
#include <mbgl/renderer/bucket_parameters.hpp>
|
||||||
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
|
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
|
||||||
#include <mbgl/text/get_anchors.hpp>
|
#include <mbgl/text/get_anchors.hpp>
|
||||||
#include <mbgl/text/shaping.hpp>
|
#include <mbgl/text/shaping.hpp>
|
||||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include <mbgl/programs/background_program.hpp>
|
#include <mbgl/programs/background_program.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
|
||||||
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
|
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
|
||||||
#include <mbgl/tile/tile_id.hpp>
|
#include <mbgl/tile/tile_id.hpp>
|
||||||
#include <mbgl/map/transform_state.hpp>
|
#include <mbgl/map/transform_state.hpp>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include <mbgl/programs/fill_extrusion_program.hpp>
|
#include <mbgl/programs/fill_extrusion_program.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
|
||||||
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
|
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
|
||||||
#include <mbgl/tile/tile_id.hpp>
|
#include <mbgl/tile/tile_id.hpp>
|
||||||
#include <mbgl/map/transform_state.hpp>
|
#include <mbgl/map/transform_state.hpp>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include <mbgl/programs/fill_program.hpp>
|
#include <mbgl/programs/fill_program.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
|
||||||
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
|
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
|
||||||
#include <mbgl/tile/tile_id.hpp>
|
#include <mbgl/tile/tile_id.hpp>
|
||||||
#include <mbgl/map/transform_state.hpp>
|
#include <mbgl/map/transform_state.hpp>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include <mbgl/programs/line_program.hpp>
|
#include <mbgl/programs/line_program.hpp>
|
||||||
#include <mbgl/style/layers/line_layer_properties.hpp>
|
#include <mbgl/style/layers/line_layer_properties.hpp>
|
||||||
#include <mbgl/renderer/render_tile.hpp>
|
#include <mbgl/renderer/render_tile.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
|
||||||
#include <mbgl/map/transform_state.hpp>
|
#include <mbgl/map/transform_state.hpp>
|
||||||
#include <mbgl/util/mat2.hpp>
|
#include <mbgl/util/mat2.hpp>
|
||||||
#include <mbgl/geometry/line_atlas.hpp>
|
#include <mbgl/geometry/line_atlas.hpp>
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mbgl/layout/symbol_instance.hpp>
|
#include <mbgl/layout/symbol_instance.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
|
||||||
#include <mbgl/style/image_impl.hpp>
|
#include <mbgl/style/image_impl.hpp>
|
||||||
#include <mbgl/style/layer_impl.hpp>
|
#include <mbgl/style/layer_impl.hpp>
|
||||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
#include <mbgl/renderer/render_tile.hpp>
|
#include <mbgl/renderer/render_tile.hpp>
|
||||||
#include <mbgl/style/layers/symbol_layer_impl.hpp>
|
#include <mbgl/style/layers/symbol_layer_impl.hpp>
|
||||||
#include <mbgl/text/cross_tile_symbol_index.hpp>
|
#include <mbgl/text/cross_tile_symbol_index.hpp>
|
||||||
#include <mbgl/text/glyph_atlas.hpp>
|
|
||||||
#include <mbgl/text/placement.hpp>
|
#include <mbgl/text/placement.hpp>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|||||||
@@ -1,114 +0,0 @@
|
|||||||
#include <mbgl/renderer/image_atlas.hpp>
|
|
||||||
#include <mbgl/renderer/image_manager.hpp>
|
|
||||||
|
|
||||||
#include <mapbox/shelf-pack.hpp>
|
|
||||||
|
|
||||||
namespace mbgl {
|
|
||||||
|
|
||||||
static constexpr uint32_t padding = 1;
|
|
||||||
|
|
||||||
ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& image, uint32_t version_)
|
|
||||||
: pixelRatio(image.pixelRatio),
|
|
||||||
paddedRect(bin.x, bin.y, bin.w, bin.h),
|
|
||||||
version(version_),
|
|
||||||
stretchX(image.stretchX),
|
|
||||||
stretchY(image.stretchY),
|
|
||||||
content(image.content),
|
|
||||||
textFitWidth(image.textFitWidth),
|
|
||||||
textFitHeight(image.textFitHeight) {}
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
const mapbox::Bin& _packImage(mapbox::ShelfPack& pack,
|
|
||||||
const style::Image::Impl& image,
|
|
||||||
ImageAtlas& resultImage,
|
|
||||||
ImageType imageType) {
|
|
||||||
const mapbox::Bin& bin = *pack.packOne(
|
|
||||||
-1, image.image.size.width + 2 * padding, image.image.size.height + 2 * padding);
|
|
||||||
|
|
||||||
resultImage.image.resize({static_cast<uint32_t>(pack.width()), static_cast<uint32_t>(pack.height())});
|
|
||||||
|
|
||||||
PremultipliedImage::copy(
|
|
||||||
image.image, resultImage.image, {0, 0}, {bin.x + padding, bin.y + padding}, image.image.size);
|
|
||||||
|
|
||||||
if (imageType == ImageType::Pattern) {
|
|
||||||
const uint32_t x = bin.x + padding;
|
|
||||||
const uint32_t y = bin.y + padding;
|
|
||||||
const uint32_t w = image.image.size.width;
|
|
||||||
const uint32_t h = image.image.size.height;
|
|
||||||
|
|
||||||
// Add 1 pixel wrapped padding on each side of the image.
|
|
||||||
PremultipliedImage::copy(image.image, resultImage.image, {0, h - 1}, {x, y - 1}, {w, 1}); // T
|
|
||||||
PremultipliedImage::copy(image.image, resultImage.image, {0, 0}, {x, y + h}, {w, 1}); // B
|
|
||||||
PremultipliedImage::copy(image.image, resultImage.image, {w - 1, 0}, {x - 1, y}, {1, h}); // L
|
|
||||||
PremultipliedImage::copy(image.image, resultImage.image, {0, 0}, {x + w, y}, {1, h}); // R
|
|
||||||
}
|
|
||||||
return bin;
|
|
||||||
}
|
|
||||||
|
|
||||||
void populateImagePatches(ImagePositions& imagePositions,
|
|
||||||
const ImageManager& imageManager,
|
|
||||||
std::vector<ImagePatch>& /*out*/ patches) {
|
|
||||||
if (imagePositions.empty()) {
|
|
||||||
imagePositions.reserve(imageManager.updatedImageVersions.size());
|
|
||||||
}
|
|
||||||
for (auto& updatedImageVersion : imageManager.updatedImageVersions) {
|
|
||||||
const std::string& name = updatedImageVersion.first;
|
|
||||||
const uint32_t version = updatedImageVersion.second;
|
|
||||||
const auto it = imagePositions.find(updatedImageVersion.first);
|
|
||||||
if (it != imagePositions.end()) {
|
|
||||||
auto& position = it->second;
|
|
||||||
if (position.version == version) continue;
|
|
||||||
|
|
||||||
const auto updatedImage = imageManager.getSharedImage(name);
|
|
||||||
if (updatedImage == nullptr) continue;
|
|
||||||
|
|
||||||
patches.emplace_back(*updatedImage, position.paddedRect);
|
|
||||||
position.version = version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
std::vector<ImagePatch> ImageAtlas::getImagePatchesAndUpdateVersions(const ImageManager& imageManager) {
|
|
||||||
std::vector<ImagePatch> imagePatches;
|
|
||||||
populateImagePatches(iconPositions, imageManager, imagePatches);
|
|
||||||
populateImagePatches(patternPositions, imageManager, imagePatches);
|
|
||||||
return imagePatches;
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageAtlas makeImageAtlas(const ImageMap& icons, const ImageMap& patterns, const ImageVersionMap& versionMap) {
|
|
||||||
ImageAtlas result;
|
|
||||||
|
|
||||||
mapbox::ShelfPack::ShelfPackOptions options;
|
|
||||||
options.autoResize = true;
|
|
||||||
mapbox::ShelfPack pack(0, 0, options);
|
|
||||||
|
|
||||||
result.iconPositions.reserve(icons.size());
|
|
||||||
|
|
||||||
for (const auto& entry : icons) {
|
|
||||||
const style::Image::Impl& image = *entry.second;
|
|
||||||
const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Icon);
|
|
||||||
const auto it = versionMap.find(entry.first);
|
|
||||||
const auto version = it != versionMap.end() ? it->second : 0;
|
|
||||||
result.iconPositions.emplace(image.id, ImagePosition{bin, image, version});
|
|
||||||
}
|
|
||||||
|
|
||||||
result.patternPositions.reserve(patterns.size());
|
|
||||||
|
|
||||||
for (const auto& entry : patterns) {
|
|
||||||
const style::Image::Impl& image = *entry.second;
|
|
||||||
const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Pattern);
|
|
||||||
const auto it = versionMap.find(entry.first);
|
|
||||||
const auto version = it != versionMap.end() ? it->second : 0;
|
|
||||||
result.patternPositions.emplace(image.id, ImagePosition{bin, image, version});
|
|
||||||
}
|
|
||||||
|
|
||||||
pack.shrink();
|
|
||||||
result.image.resize({static_cast<uint32_t>(pack.width()), static_cast<uint32_t>(pack.height())});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mbgl
|
|
||||||
@@ -1,80 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <mbgl/style/image_impl.hpp>
|
|
||||||
#include <mbgl/util/rect.hpp>
|
|
||||||
|
|
||||||
#include <mapbox/shelf-pack.hpp>
|
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
namespace mbgl {
|
|
||||||
|
|
||||||
namespace gfx {
|
|
||||||
class UploadPass;
|
|
||||||
class Texture;
|
|
||||||
} // namespace gfx
|
|
||||||
|
|
||||||
class ImageManager;
|
|
||||||
|
|
||||||
class ImagePosition {
|
|
||||||
public:
|
|
||||||
ImagePosition(const mapbox::Bin&, const style::Image::Impl&, uint32_t version = 0);
|
|
||||||
|
|
||||||
static constexpr const uint16_t padding = 1u;
|
|
||||||
float pixelRatio;
|
|
||||||
Rect<uint16_t> paddedRect;
|
|
||||||
uint32_t version;
|
|
||||||
style::ImageStretches stretchX;
|
|
||||||
style::ImageStretches stretchY;
|
|
||||||
std::optional<style::ImageContent> content;
|
|
||||||
std::optional<style::TextFit> textFitWidth;
|
|
||||||
std::optional<style::TextFit> textFitHeight;
|
|
||||||
|
|
||||||
std::array<uint16_t, 2> tl() const {
|
|
||||||
return {{static_cast<uint16_t>(paddedRect.x + padding), static_cast<uint16_t>(paddedRect.y + padding)}};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<uint16_t, 2> br() const {
|
|
||||||
return {{static_cast<uint16_t>(paddedRect.x + paddedRect.w - padding),
|
|
||||||
static_cast<uint16_t>(paddedRect.y + paddedRect.h - padding)}};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<uint16_t, 4> tlbr() const {
|
|
||||||
const auto _tl = tl();
|
|
||||||
const auto _br = br();
|
|
||||||
return {{_tl[0], _tl[1], _br[0], _br[1]}};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::array<float, 2> displaySize() const {
|
|
||||||
return {{
|
|
||||||
static_cast<float>(paddedRect.w - padding * 2) / pixelRatio,
|
|
||||||
static_cast<float>(paddedRect.h - padding * 2) / pixelRatio,
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using ImagePositions = mbgl::unordered_map<std::string, ImagePosition>;
|
|
||||||
|
|
||||||
class ImagePatch {
|
|
||||||
public:
|
|
||||||
ImagePatch(Immutable<style::Image::Impl> image_, const Rect<uint16_t>& paddedRect_)
|
|
||||||
: image(std::move(image_)),
|
|
||||||
paddedRect(paddedRect_) {}
|
|
||||||
|
|
||||||
Immutable<style::Image::Impl> image;
|
|
||||||
Rect<uint16_t> paddedRect;
|
|
||||||
};
|
|
||||||
|
|
||||||
class ImageAtlas {
|
|
||||||
public:
|
|
||||||
PremultipliedImage image;
|
|
||||||
ImagePositions iconPositions;
|
|
||||||
ImagePositions patternPositions;
|
|
||||||
|
|
||||||
std::vector<ImagePatch> getImagePatchesAndUpdateVersions(const ImageManager&);
|
|
||||||
};
|
|
||||||
|
|
||||||
ImageAtlas makeImageAtlas(const ImageMap&, const ImageMap&, const ImageVersionMap& versionMap);
|
|
||||||
|
|
||||||
} // namespace mbgl
|
|
||||||
@@ -5,7 +5,6 @@
|
|||||||
#include <mbgl/gfx/line_drawable_data.hpp>
|
#include <mbgl/gfx/line_drawable_data.hpp>
|
||||||
#include <mbgl/geometry/line_atlas.hpp>
|
#include <mbgl/geometry/line_atlas.hpp>
|
||||||
#include <mbgl/programs/line_program.hpp>
|
#include <mbgl/programs/line_program.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
|
||||||
#include <mbgl/renderer/layer_group.hpp>
|
#include <mbgl/renderer/layer_group.hpp>
|
||||||
#include <mbgl/renderer/paint_parameters.hpp>
|
#include <mbgl/renderer/paint_parameters.hpp>
|
||||||
#include <mbgl/renderer/render_tile.hpp>
|
#include <mbgl/renderer/render_tile.hpp>
|
||||||
|
|||||||
@@ -498,11 +498,15 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
|
|||||||
|
|
||||||
if (patternBuilder) {
|
if (patternBuilder) {
|
||||||
patternBuilder->clearTweakers();
|
patternBuilder->clearTweakers();
|
||||||
patternBuilder->addTweaker(getAtlasTweaker());
|
if (const auto& tweaker = getAtlasTweaker()) {
|
||||||
|
patternBuilder->addTweaker(tweaker);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (doOutline && outlinePatternBuilder) {
|
if (doOutline && outlinePatternBuilder) {
|
||||||
outlinePatternBuilder->clearTweakers();
|
outlinePatternBuilder->clearTweakers();
|
||||||
outlinePatternBuilder->addTweaker(getAtlasTweaker());
|
if (const auto& tweaker = getAtlasTweaker()) {
|
||||||
|
outlinePatternBuilder->addTweaker(tweaker);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patternBuilder && bucket.sharedTriangles->elements()) {
|
if (patternBuilder && bucket.sharedTriangles->elements()) {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
#include <mbgl/renderer/tile_render_data.hpp>
|
#include <mbgl/renderer/tile_render_data.hpp>
|
||||||
#include <mbgl/renderer/upload_parameters.hpp>
|
#include <mbgl/renderer/upload_parameters.hpp>
|
||||||
#include <mbgl/style/layers/symbol_layer_impl.hpp>
|
#include <mbgl/style/layers/symbol_layer_impl.hpp>
|
||||||
#include <mbgl/text/glyph_atlas.hpp>
|
|
||||||
#include <mbgl/text/shaping.hpp>
|
#include <mbgl/text/shaping.hpp>
|
||||||
#include <mbgl/tile/geometry_tile.hpp>
|
#include <mbgl/tile/geometry_tile.hpp>
|
||||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#include <mbgl/layout/pattern_layout.hpp>
|
#include <mbgl/layout/pattern_layout.hpp>
|
||||||
#include <mbgl/programs/attributes.hpp>
|
#include <mbgl/programs/attributes.hpp>
|
||||||
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
|
#include <mbgl/renderer/cross_faded_property_evaluator.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
|
||||||
#include <mbgl/renderer/paint_property_statistics.hpp>
|
#include <mbgl/renderer/paint_property_statistics.hpp>
|
||||||
#include <mbgl/renderer/possibly_evaluated_property_value.hpp>
|
#include <mbgl/renderer/possibly_evaluated_property_value.hpp>
|
||||||
#include <mbgl/util/indexed_tuple.hpp>
|
#include <mbgl/util/indexed_tuple.hpp>
|
||||||
|
|||||||
@@ -65,7 +65,9 @@ std::optional<ImagePosition> PatternAtlas::addPattern(const style::Image::Impl&
|
|||||||
|
|
||||||
dirty = true;
|
dirty = true;
|
||||||
|
|
||||||
return patterns.emplace(image.id, Pattern{.bin = bin, .position = {*bin, image}}).first->second.position;
|
return patterns
|
||||||
|
.emplace(image.id, Pattern{.bin = bin, .position = {Rect<uint16_t>(bin->x, bin->y, bin->w, bin->h), image}})
|
||||||
|
.first->second.position;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PatternAtlas::removePattern(const std::string& id) {
|
void PatternAtlas::removePattern(const std::string& id) {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <mapbox/shelf-pack.hpp>
|
#include <mapbox/shelf-pack.hpp>
|
||||||
#include <mbgl/gfx/texture.hpp>
|
#include <mbgl/gfx/texture.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
|
||||||
#include <mbgl/style/image_impl.hpp>
|
#include <mbgl/style/image_impl.hpp>
|
||||||
|
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ void RenderOrchestrator::setObserver(RendererObserver* observer_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(
|
std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(
|
||||||
const std::shared_ptr<UpdateParameters>& updateParameters) {
|
const std::shared_ptr<UpdateParameters>& updateParameters, gfx::DynamicTextureAtlasPtr dynamicTextureAtlas) {
|
||||||
MLN_TRACE_FUNC();
|
MLN_TRACE_FUNC();
|
||||||
|
|
||||||
const auto startTime = util::MonotonicTimer::now().count();
|
const auto startTime = util::MonotonicTimer::now().count();
|
||||||
@@ -194,7 +194,8 @@ std::unique_ptr<RenderTree> RenderOrchestrator::createRenderTree(
|
|||||||
.imageManager = imageManager,
|
.imageManager = imageManager,
|
||||||
.glyphManager = glyphManager,
|
.glyphManager = glyphManager,
|
||||||
.prefetchZoomDelta = updateParameters->prefetchZoomDelta,
|
.prefetchZoomDelta = updateParameters->prefetchZoomDelta,
|
||||||
.threadPool = threadPool};
|
.threadPool = threadPool,
|
||||||
|
.dynamicTextureAtlas = dynamicTextureAtlas};
|
||||||
|
|
||||||
glyphManager->setURL(updateParameters->glyphURL);
|
glyphManager->setURL(updateParameters->glyphURL);
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ namespace gfx {
|
|||||||
class ShaderRegistry;
|
class ShaderRegistry;
|
||||||
class Drawable;
|
class Drawable;
|
||||||
using DrawablePtr = std::shared_ptr<Drawable>;
|
using DrawablePtr = std::shared_ptr<Drawable>;
|
||||||
|
class DynamicTextureAtlas;
|
||||||
|
using DynamicTextureAtlasPtr = std::shared_ptr<gfx::DynamicTextureAtlas>;
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
|
|
||||||
namespace style {
|
namespace style {
|
||||||
@@ -64,7 +66,7 @@ public:
|
|||||||
// TODO: Introduce RenderOrchestratorObserver.
|
// TODO: Introduce RenderOrchestratorObserver.
|
||||||
void setObserver(RendererObserver*);
|
void setObserver(RendererObserver*);
|
||||||
|
|
||||||
std::unique_ptr<RenderTree> createRenderTree(const std::shared_ptr<UpdateParameters>&);
|
std::unique_ptr<RenderTree> createRenderTree(const std::shared_ptr<UpdateParameters>&, gfx::DynamicTextureAtlasPtr);
|
||||||
|
|
||||||
std::vector<Feature> queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions&) const;
|
std::vector<Feature> queryRenderedFeatures(const ScreenLineString&, const RenderedQueryOptions&) const;
|
||||||
std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions&) const;
|
std::vector<Feature> querySourceFeatures(const std::string& sourceID, const SourceQueryOptions&) const;
|
||||||
|
|||||||
@@ -96,24 +96,6 @@ std::optional<ImagePosition> RenderTile::getPattern(const std::string& pattern)
|
|||||||
return renderData->getPattern(pattern);
|
return renderData->getPattern(pattern);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const gfx::Texture2DPtr noTexture;
|
|
||||||
|
|
||||||
bool RenderTile::hasGlyphAtlasTexture() const {
|
|
||||||
return renderData && renderData->getGlyphAtlasTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
const gfx::Texture2DPtr& RenderTile::getGlyphAtlasTexture() const {
|
|
||||||
return renderData ? renderData->getGlyphAtlasTexture() : noTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderTile::hasIconAtlasTexture() const {
|
|
||||||
return renderData && renderData->getIconAtlasTexture();
|
|
||||||
}
|
|
||||||
|
|
||||||
const gfx::Texture2DPtr& RenderTile::getIconAtlasTexture() const {
|
|
||||||
return renderData ? renderData->getIconAtlasTexture() : noTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const std::shared_ptr<TileAtlasTextures> noAtlas;
|
static const std::shared_ptr<TileAtlasTextures> noAtlas;
|
||||||
const std::shared_ptr<TileAtlasTextures>& RenderTile::getAtlasTextures() const {
|
const std::shared_ptr<TileAtlasTextures>& RenderTile::getAtlasTextures() const {
|
||||||
return renderData ? renderData->getAtlasTextures() : noAtlas;
|
return renderData ? renderData->getAtlasTextures() : noAtlas;
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <mbgl/gfx/texture.hpp>
|
#include <mbgl/gfx/texture.hpp>
|
||||||
#include <mbgl/tile/tile_id.hpp>
|
#include <mbgl/tile/tile_id.hpp>
|
||||||
#include <mbgl/util/mat4.hpp>
|
#include <mbgl/util/mat4.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
#include <mbgl/style/image_impl.hpp>
|
||||||
#include <mbgl/style/layer_impl.hpp>
|
#include <mbgl/style/layer_impl.hpp>
|
||||||
#include <mbgl/style/types.hpp>
|
#include <mbgl/style/types.hpp>
|
||||||
|
|
||||||
@@ -60,12 +60,6 @@ public:
|
|||||||
const LayerRenderData* getLayerRenderData(const style::Layer::Impl&) const;
|
const LayerRenderData* getLayerRenderData(const style::Layer::Impl&) const;
|
||||||
std::optional<ImagePosition> getPattern(const std::string& pattern) const;
|
std::optional<ImagePosition> getPattern(const std::string& pattern) const;
|
||||||
|
|
||||||
bool hasGlyphAtlasTexture() const;
|
|
||||||
const gfx::Texture2DPtr& getGlyphAtlasTexture() const;
|
|
||||||
|
|
||||||
bool hasIconAtlasTexture() const;
|
|
||||||
const gfx::Texture2DPtr& getIconAtlasTexture() const;
|
|
||||||
|
|
||||||
const std::shared_ptr<TileAtlasTextures>& getAtlasTextures() const;
|
const std::shared_ptr<TileAtlasTextures>& getAtlasTextures() const;
|
||||||
|
|
||||||
bool getNeedsRendering() const { return needsRendering; };
|
bool getNeedsRendering() const { return needsRendering; };
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <mbgl/annotation/annotation_manager.hpp>
|
#include <mbgl/annotation/annotation_manager.hpp>
|
||||||
#include <mbgl/gfx/backend_scope.hpp>
|
#include <mbgl/gfx/backend_scope.hpp>
|
||||||
|
#include <mbgl/gfx/dynamic_texture_atlas.hpp>
|
||||||
#include <mbgl/gfx/renderer_backend.hpp>
|
#include <mbgl/gfx/renderer_backend.hpp>
|
||||||
#include <mbgl/layermanager/layer_manager.hpp>
|
#include <mbgl/layermanager/layer_manager.hpp>
|
||||||
#include <mbgl/renderer/renderer_impl.hpp>
|
#include <mbgl/renderer/renderer_impl.hpp>
|
||||||
@@ -32,7 +33,13 @@ void Renderer::setObserver(RendererObserver* observer) {
|
|||||||
void Renderer::render(const std::shared_ptr<UpdateParameters>& updateParameters) {
|
void Renderer::render(const std::shared_ptr<UpdateParameters>& updateParameters) {
|
||||||
MLN_TRACE_FUNC();
|
MLN_TRACE_FUNC();
|
||||||
assert(updateParameters);
|
assert(updateParameters);
|
||||||
if (auto renderTree = impl->orchestrator.createRenderTree(updateParameters)) {
|
const bool styleChanged = impl->styleLoaded && !updateParameters->styleLoaded;
|
||||||
|
impl->styleLoaded = updateParameters->styleLoaded;
|
||||||
|
if (!impl->dynamicTextureAtlas || styleChanged) {
|
||||||
|
auto& context = impl->backend.getContext();
|
||||||
|
impl->dynamicTextureAtlas = std::make_unique<gfx::DynamicTextureAtlas>(context);
|
||||||
|
}
|
||||||
|
if (auto renderTree = impl->orchestrator.createRenderTree(updateParameters, impl->dynamicTextureAtlas)) {
|
||||||
renderTree->prepare();
|
renderTree->prepare();
|
||||||
impl->render(*renderTree, updateParameters);
|
impl->render(*renderTree, updateParameters);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ class RenderTree;
|
|||||||
namespace gfx {
|
namespace gfx {
|
||||||
class RendererBackend;
|
class RendererBackend;
|
||||||
class ShadeRegistry;
|
class ShadeRegistry;
|
||||||
|
class DynamicTextureAtlas;
|
||||||
|
using DynamicTextureAtlasPtr = std::shared_ptr<gfx::DynamicTextureAtlas>;
|
||||||
} // namespace gfx
|
} // namespace gfx
|
||||||
|
|
||||||
class Renderer::Impl : public gfx::ContextObserver {
|
class Renderer::Impl : public gfx::ContextObserver {
|
||||||
@@ -50,6 +52,8 @@ private:
|
|||||||
|
|
||||||
const float pixelRatio;
|
const float pixelRatio;
|
||||||
std::unique_ptr<RenderStaticData> staticData;
|
std::unique_ptr<RenderStaticData> staticData;
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas;
|
||||||
|
bool styleLoaded = false;
|
||||||
|
|
||||||
enum class RenderState {
|
enum class RenderState {
|
||||||
Never,
|
Never,
|
||||||
|
|||||||
@@ -15,6 +15,11 @@ class AnnotationManager;
|
|||||||
class ImageManager;
|
class ImageManager;
|
||||||
class GlyphManager;
|
class GlyphManager;
|
||||||
|
|
||||||
|
namespace gfx {
|
||||||
|
class DynamicTextureAtlas;
|
||||||
|
using DynamicTextureAtlasPtr = std::shared_ptr<gfx::DynamicTextureAtlas>;
|
||||||
|
} // namespace gfx
|
||||||
|
|
||||||
class TileParameters {
|
class TileParameters {
|
||||||
public:
|
public:
|
||||||
const float pixelRatio;
|
const float pixelRatio;
|
||||||
@@ -27,6 +32,7 @@ public:
|
|||||||
std::shared_ptr<GlyphManager> glyphManager;
|
std::shared_ptr<GlyphManager> glyphManager;
|
||||||
const uint8_t prefetchZoomDelta;
|
const uint8_t prefetchZoomDelta;
|
||||||
TaggedScheduler threadPool;
|
TaggedScheduler threadPool;
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mbgl
|
} // namespace mbgl
|
||||||
|
|||||||
@@ -9,16 +9,6 @@ TileRenderData::TileRenderData(std::shared_ptr<TileAtlasTextures> atlasTextures_
|
|||||||
|
|
||||||
TileRenderData::~TileRenderData() = default;
|
TileRenderData::~TileRenderData() = default;
|
||||||
|
|
||||||
static gfx::Texture2DPtr noTexture;
|
|
||||||
|
|
||||||
const gfx::Texture2DPtr& TileRenderData::getGlyphAtlasTexture() const {
|
|
||||||
return atlasTextures ? atlasTextures->glyph : noTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
const gfx::Texture2DPtr& TileRenderData::getIconAtlasTexture() const {
|
|
||||||
return atlasTextures ? atlasTextures->icon : noTexture;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<ImagePosition> TileRenderData::getPattern(const std::string&) const {
|
std::optional<ImagePosition> TileRenderData::getPattern(const std::string&) const {
|
||||||
assert(false);
|
assert(false);
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mbgl/gfx/texture.hpp>
|
#include <mbgl/gfx/texture.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
#include <mbgl/style/image_impl.hpp>
|
||||||
#include <mbgl/style/layer_impl.hpp>
|
#include <mbgl/style/layer_impl.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -30,9 +30,6 @@ class TileRenderData {
|
|||||||
public:
|
public:
|
||||||
virtual ~TileRenderData();
|
virtual ~TileRenderData();
|
||||||
|
|
||||||
const gfx::Texture2DPtr& getGlyphAtlasTexture() const;
|
|
||||||
const gfx::Texture2DPtr& getIconAtlasTexture() const;
|
|
||||||
|
|
||||||
const std::shared_ptr<TileAtlasTextures>& getAtlasTextures() const { return atlasTextures; }
|
const std::shared_ptr<TileAtlasTextures>& getAtlasTextures() const { return atlasTextures; }
|
||||||
// To be implemented for concrete tile types.
|
// To be implemented for concrete tile types.
|
||||||
virtual std::optional<ImagePosition> getPattern(const std::string&) const;
|
virtual std::optional<ImagePosition> getPattern(const std::string&) const;
|
||||||
|
|||||||
@@ -2,9 +2,11 @@
|
|||||||
|
|
||||||
#include <mbgl/style/image.hpp>
|
#include <mbgl/style/image.hpp>
|
||||||
#include <mbgl/util/containers.hpp>
|
#include <mbgl/util/containers.hpp>
|
||||||
|
#include <mbgl/util/rect.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <array>
|
||||||
|
|
||||||
namespace mbgl {
|
namespace mbgl {
|
||||||
namespace style {
|
namespace style {
|
||||||
@@ -61,4 +63,52 @@ inline bool operator<(const Immutable<mbgl::style::Image::Impl>& a, const Immuta
|
|||||||
return a->id < b->id;
|
return a->id < b->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ImagePosition {
|
||||||
|
public:
|
||||||
|
ImagePosition(const Rect<uint16_t>& rect, const style::Image::Impl& image, uint32_t version_ = 0)
|
||||||
|
: paddedRect(rect),
|
||||||
|
pixelRatio(image.pixelRatio),
|
||||||
|
stretchX(image.stretchX),
|
||||||
|
stretchY(image.stretchY),
|
||||||
|
content(image.content),
|
||||||
|
textFitWidth(image.textFitWidth),
|
||||||
|
textFitHeight(image.textFitHeight),
|
||||||
|
version(version_) {}
|
||||||
|
|
||||||
|
static constexpr const uint16_t padding = 1u;
|
||||||
|
|
||||||
|
Rect<uint16_t> paddedRect;
|
||||||
|
float pixelRatio;
|
||||||
|
style::ImageStretches stretchX;
|
||||||
|
style::ImageStretches stretchY;
|
||||||
|
std::optional<style::ImageContent> content;
|
||||||
|
std::optional<style::TextFit> textFitWidth;
|
||||||
|
std::optional<style::TextFit> textFitHeight;
|
||||||
|
uint32_t version;
|
||||||
|
|
||||||
|
std::array<uint16_t, 2> tl() const {
|
||||||
|
return {{static_cast<uint16_t>(paddedRect.x + padding), static_cast<uint16_t>(paddedRect.y + padding)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<uint16_t, 2> br() const {
|
||||||
|
return {{static_cast<uint16_t>(paddedRect.x + paddedRect.w - padding),
|
||||||
|
static_cast<uint16_t>(paddedRect.y + paddedRect.h - padding)}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<uint16_t, 4> tlbr() const {
|
||||||
|
const auto _tl = tl();
|
||||||
|
const auto _br = br();
|
||||||
|
return {{_tl[0], _tl[1], _br[0], _br[1]}};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::array<float, 2> displaySize() const {
|
||||||
|
return {{
|
||||||
|
static_cast<float>(paddedRect.w - padding * 2) / pixelRatio,
|
||||||
|
static_cast<float>(paddedRect.h - padding * 2) / pixelRatio,
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using ImagePositions = mbgl::unordered_map<std::string, ImagePosition>;
|
||||||
|
|
||||||
} // namespace mbgl
|
} // namespace mbgl
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
#include <mbgl/text/glyph_atlas.hpp>
|
|
||||||
|
|
||||||
#include <mapbox/shelf-pack.hpp>
|
|
||||||
|
|
||||||
namespace mbgl {
|
|
||||||
|
|
||||||
static constexpr uint32_t padding = 1;
|
|
||||||
|
|
||||||
GlyphAtlas makeGlyphAtlas(const GlyphMap& glyphs) {
|
|
||||||
GlyphAtlas result;
|
|
||||||
|
|
||||||
mapbox::ShelfPack::ShelfPackOptions options;
|
|
||||||
options.autoResize = true;
|
|
||||||
mapbox::ShelfPack pack(0, 0, options);
|
|
||||||
|
|
||||||
for (const auto& glyphMapEntry : glyphs) {
|
|
||||||
FontStackHash fontStack = glyphMapEntry.first;
|
|
||||||
GlyphPositionMap& positions = result.positions[fontStack];
|
|
||||||
|
|
||||||
for (const auto& entry : glyphMapEntry.second) {
|
|
||||||
if (entry.second && (*entry.second)->bitmap.valid()) {
|
|
||||||
const Glyph& glyph = **entry.second;
|
|
||||||
|
|
||||||
const mapbox::Bin& bin = *pack.packOne(
|
|
||||||
-1, glyph.bitmap.size.width + 2 * padding, glyph.bitmap.size.height + 2 * padding);
|
|
||||||
|
|
||||||
result.image.resize({static_cast<uint32_t>(pack.width()), static_cast<uint32_t>(pack.height())});
|
|
||||||
|
|
||||||
AlphaImage::copy(
|
|
||||||
glyph.bitmap, result.image, {0, 0}, {bin.x + padding, bin.y + padding}, glyph.bitmap.size);
|
|
||||||
|
|
||||||
positions.emplace(glyph.id,
|
|
||||||
GlyphPosition{Rect<uint16_t>{static_cast<uint16_t>(bin.x),
|
|
||||||
static_cast<uint16_t>(bin.y),
|
|
||||||
static_cast<uint16_t>(bin.w),
|
|
||||||
static_cast<uint16_t>(bin.h)},
|
|
||||||
glyph.metrics});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pack.shrink();
|
|
||||||
result.image.resize({static_cast<uint32_t>(pack.width()), static_cast<uint32_t>(pack.height())});
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace mbgl
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <mbgl/text/glyph.hpp>
|
|
||||||
|
|
||||||
#include <mapbox/shelf-pack.hpp>
|
|
||||||
|
|
||||||
namespace mbgl {
|
|
||||||
|
|
||||||
struct GlyphPosition {
|
|
||||||
Rect<uint16_t> rect;
|
|
||||||
GlyphMetrics metrics;
|
|
||||||
};
|
|
||||||
|
|
||||||
using GlyphPositionMap = std::map<GlyphID, GlyphPosition>;
|
|
||||||
using GlyphPositions = std::map<FontStackHash, GlyphPositionMap>;
|
|
||||||
|
|
||||||
class GlyphAtlas {
|
|
||||||
public:
|
|
||||||
AlphaImage image;
|
|
||||||
GlyphPositions positions;
|
|
||||||
};
|
|
||||||
|
|
||||||
GlyphAtlas makeGlyphAtlas(const GlyphMap&);
|
|
||||||
|
|
||||||
} // namespace mbgl
|
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <mbgl/style/image_impl.hpp>
|
#include <mbgl/style/image_impl.hpp>
|
||||||
#include <mbgl/style/layers/symbol_layer_properties.hpp>
|
#include <mbgl/style/layers/symbol_layer_properties.hpp>
|
||||||
#include <mbgl/style/types.hpp>
|
#include <mbgl/style/types.hpp>
|
||||||
#include <mbgl/text/glyph_atlas.hpp>
|
#include <mbgl/text/glyph.hpp>
|
||||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
#include <mbgl/style/image_impl.hpp>
|
||||||
#include <mbgl/style/layers/symbol_layer_properties.hpp>
|
#include <mbgl/style/layers/symbol_layer_properties.hpp>
|
||||||
#include <mbgl/style/types.hpp>
|
#include <mbgl/style/types.hpp>
|
||||||
#include <mbgl/text/glyph.hpp>
|
#include <mbgl/text/glyph.hpp>
|
||||||
#include <mbgl/text/glyph_atlas.hpp>
|
|
||||||
#include <mbgl/text/tagged_string.hpp>
|
#include <mbgl/text/tagged_string.hpp>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include <mbgl/renderer/layers/render_custom_layer.hpp>
|
#include <mbgl/renderer/layers/render_custom_layer.hpp>
|
||||||
#include <mbgl/map/transform_state.hpp>
|
#include <mbgl/map/transform_state.hpp>
|
||||||
#include <mbgl/renderer/buckets/symbol_bucket.hpp>
|
#include <mbgl/renderer/buckets/symbol_bucket.hpp>
|
||||||
#include <mbgl/renderer/image_atlas.hpp>
|
|
||||||
#include <mbgl/renderer/layers/render_background_layer.hpp>
|
#include <mbgl/renderer/layers/render_background_layer.hpp>
|
||||||
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
|
#include <mbgl/renderer/layers/render_symbol_layer.hpp>
|
||||||
#include <mbgl/renderer/query.hpp>
|
#include <mbgl/renderer/query.hpp>
|
||||||
@@ -15,15 +14,14 @@
|
|||||||
#include <mbgl/renderer/tile_render_data.hpp>
|
#include <mbgl/renderer/tile_render_data.hpp>
|
||||||
#include <mbgl/style/layer_impl.hpp>
|
#include <mbgl/style/layer_impl.hpp>
|
||||||
#include <mbgl/style/layers/background_layer.hpp>
|
#include <mbgl/style/layers/background_layer.hpp>
|
||||||
#include <mbgl/text/glyph_atlas.hpp>
|
|
||||||
#include <mbgl/tile/geometry_tile_data.hpp>
|
#include <mbgl/tile/geometry_tile_data.hpp>
|
||||||
#include <mbgl/tile/geometry_tile_worker.hpp>
|
#include <mbgl/tile/geometry_tile_worker.hpp>
|
||||||
#include <mbgl/tile/tile_observer.hpp>
|
#include <mbgl/tile/tile_observer.hpp>
|
||||||
#include <mbgl/util/instrumentation.hpp>
|
#include <mbgl/util/instrumentation.hpp>
|
||||||
#include <mbgl/util/logging.hpp>
|
#include <mbgl/util/logging.hpp>
|
||||||
#include <mbgl/util/thread_pool.hpp>
|
#include <mbgl/util/thread_pool.hpp>
|
||||||
|
|
||||||
#include <mbgl/gfx/upload_pass.hpp>
|
#include <mbgl/gfx/upload_pass.hpp>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
namespace mbgl {
|
namespace mbgl {
|
||||||
@@ -44,6 +42,38 @@ LayerRenderData* GeometryTile::LayoutResult::getLayerRenderData(const style::Lay
|
|||||||
return &result;
|
return &result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ImagePatch {
|
||||||
|
public:
|
||||||
|
ImagePatch(Immutable<style::Image::Impl> image_, const Rect<uint16_t>& paddedRect_)
|
||||||
|
: image(std::move(image_)),
|
||||||
|
paddedRect(paddedRect_) {}
|
||||||
|
Immutable<style::Image::Impl> image;
|
||||||
|
Rect<uint16_t> paddedRect;
|
||||||
|
};
|
||||||
|
|
||||||
|
void populateImagePatches(ImagePositions& imagePositions,
|
||||||
|
const ImageManager& imageManager,
|
||||||
|
std::vector<ImagePatch>& /*out*/ patches) {
|
||||||
|
if (imagePositions.empty()) {
|
||||||
|
imagePositions.reserve(imageManager.updatedImageVersions.size());
|
||||||
|
}
|
||||||
|
for (auto& updatedImageVersion : imageManager.updatedImageVersions) {
|
||||||
|
const std::string& name = updatedImageVersion.first;
|
||||||
|
const uint32_t version = updatedImageVersion.second;
|
||||||
|
const auto it = imagePositions.find(updatedImageVersion.first);
|
||||||
|
if (it != imagePositions.end()) {
|
||||||
|
auto& position = it->second;
|
||||||
|
if (position.version == version) continue;
|
||||||
|
|
||||||
|
const auto updatedImage = imageManager.getSharedImage(name);
|
||||||
|
if (updatedImage == nullptr) continue;
|
||||||
|
|
||||||
|
patches.emplace_back(*updatedImage, position.paddedRect);
|
||||||
|
position.version = version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class GeometryTileRenderData final : public TileRenderData {
|
class GeometryTileRenderData final : public TileRenderData {
|
||||||
public:
|
public:
|
||||||
GeometryTileRenderData(std::shared_ptr<GeometryTile::LayoutResult> layoutResult_,
|
GeometryTileRenderData(std::shared_ptr<GeometryTile::LayoutResult> layoutResult_,
|
||||||
@@ -69,9 +99,9 @@ std::optional<ImagePosition> GeometryTileRenderData::getPattern(const std::strin
|
|||||||
MLN_TRACE_FUNC();
|
MLN_TRACE_FUNC();
|
||||||
|
|
||||||
if (layoutResult) {
|
if (layoutResult) {
|
||||||
const auto& iconAtlas = layoutResult->iconAtlas;
|
const auto& patternPositions = layoutResult->imageAtlas.patternPositions;
|
||||||
auto it = iconAtlas.patternPositions.find(pattern);
|
auto it = patternPositions.find(pattern);
|
||||||
if (it != iconAtlas.patternPositions.end()) {
|
if (it != patternPositions.end()) {
|
||||||
return it->second;
|
return it->second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,22 +125,16 @@ void GeometryTileRenderData::upload(gfx::UploadPass& uploadPass) {
|
|||||||
|
|
||||||
assert(atlasTextures);
|
assert(atlasTextures);
|
||||||
|
|
||||||
if (layoutResult->glyphAtlasImage && layoutResult->glyphAtlasImage->valid()) {
|
if (const auto& glyphDynamicTexture = layoutResult->glyphAtlas.dynamicTexture) {
|
||||||
atlasTextures->glyph = uploadPass.getContext().createTexture2D();
|
glyphDynamicTexture->uploadDeferredImages();
|
||||||
atlasTextures->glyph->setSamplerConfiguration({.filter = gfx::TextureFilterType::Linear,
|
atlasTextures->glyph = glyphDynamicTexture->getTexture();
|
||||||
.wrapU = gfx::TextureWrapType::Clamp,
|
}
|
||||||
.wrapV = gfx::TextureWrapType::Clamp});
|
if (const auto& imageDynamicTexture = layoutResult->imageAtlas.dynamicTexture) {
|
||||||
atlasTextures->glyph->upload(*layoutResult->glyphAtlasImage);
|
imageDynamicTexture->uploadDeferredImages();
|
||||||
layoutResult->glyphAtlasImage = {};
|
atlasTextures->icon = imageDynamicTexture->getTexture();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (layoutResult->iconAtlas.image.valid()) {
|
if (!imagePatches.empty()) {
|
||||||
atlasTextures->icon = uploadPass.getContext().createTexture2D();
|
|
||||||
atlasTextures->icon->upload(layoutResult->iconAtlas.image);
|
|
||||||
layoutResult->iconAtlas.image = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (atlasTextures->icon && !imagePatches.empty()) {
|
|
||||||
for (const auto& imagePatch : imagePatches) { // patch updated images.
|
for (const auto& imagePatch : imagePatches) { // patch updated images.
|
||||||
atlasTextures->icon->uploadSubRegion(imagePatch.image->image,
|
atlasTextures->icon->uploadSubRegion(imagePatch.image->image,
|
||||||
imagePatch.paddedRect.x + ImagePosition::padding,
|
imagePatch.paddedRect.x + ImagePosition::padding,
|
||||||
@@ -124,7 +148,9 @@ void GeometryTileRenderData::prepare(const SourcePrepareParameters& parameters)
|
|||||||
MLN_TRACE_FUNC();
|
MLN_TRACE_FUNC();
|
||||||
|
|
||||||
if (!layoutResult) return;
|
if (!layoutResult) return;
|
||||||
imagePatches = layoutResult->iconAtlas.getImagePatchesAndUpdateVersions(parameters.imageManager);
|
imagePatches.clear();
|
||||||
|
populateImagePatches(layoutResult->imageAtlas.iconPositions, parameters.imageManager, imagePatches);
|
||||||
|
populateImagePatches(layoutResult->imageAtlas.patternPositions, parameters.imageManager, imagePatches);
|
||||||
}
|
}
|
||||||
|
|
||||||
Bucket* GeometryTileRenderData::getBucket(const Layer::Impl& layer) const {
|
Bucket* GeometryTileRenderData::getBucket(const Layer::Impl& layer) const {
|
||||||
@@ -136,6 +162,13 @@ const LayerRenderData* GeometryTileRenderData::getLayerRenderData(const style::L
|
|||||||
return layoutResult ? layoutResult->getLayerRenderData(layerImpl) : nullptr;
|
return layoutResult ? layoutResult->getLayerRenderData(layerImpl) : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GeometryTile::LayoutResult::~LayoutResult() {
|
||||||
|
if (dynamicTextureAtlas) {
|
||||||
|
dynamicTextureAtlas->removeTextures(glyphAtlas.textureHandles, glyphAtlas.dynamicTexture);
|
||||||
|
dynamicTextureAtlas->removeTextures(imageAtlas.textureHandles, imageAtlas.dynamicTexture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Correlation between GeometryTile and GeometryTileWorker is safeguarded by two
|
Correlation between GeometryTile and GeometryTileWorker is safeguarded by two
|
||||||
correlation schemes:
|
correlation schemes:
|
||||||
@@ -168,7 +201,8 @@ GeometryTile::GeometryTile(const OverscaledTileID& id_,
|
|||||||
obsolete,
|
obsolete,
|
||||||
parameters.mode,
|
parameters.mode,
|
||||||
parameters.pixelRatio,
|
parameters.pixelRatio,
|
||||||
parameters.debugOptions & MapDebugOptions::Collision),
|
parameters.debugOptions & MapDebugOptions::Collision,
|
||||||
|
parameters.dynamicTextureAtlas),
|
||||||
fileSource(parameters.fileSource),
|
fileSource(parameters.fileSource),
|
||||||
glyphManager(parameters.glyphManager),
|
glyphManager(parameters.glyphManager),
|
||||||
imageManager(parameters.imageManager),
|
imageManager(parameters.imageManager),
|
||||||
@@ -530,7 +564,7 @@ void GeometryTile::setFeatureState(const LayerFeatureStates& states) {
|
|||||||
|
|
||||||
auto bucket = layer.second.bucket;
|
auto bucket = layer.second.bucket;
|
||||||
if (bucket && bucket->hasData()) {
|
if (bucket && bucket->hasData()) {
|
||||||
bucket->update(featureStates, *sourceLayer, layerID, layoutResult->iconAtlas.patternPositions);
|
bucket->update(featureStates, *sourceLayer, layerID, layoutResult->imageAtlas.patternPositions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <mbgl/actor/actor.hpp>
|
#include <mbgl/actor/actor.hpp>
|
||||||
#include <mbgl/geometry/feature_index.hpp>
|
#include <mbgl/geometry/feature_index.hpp>
|
||||||
|
#include <mbgl/gfx/dynamic_texture_atlas.hpp>
|
||||||
#include <mbgl/gfx/texture.hpp>
|
#include <mbgl/gfx/texture.hpp>
|
||||||
#include <mbgl/renderer/image_manager.hpp>
|
#include <mbgl/renderer/image_manager.hpp>
|
||||||
#include <mbgl/text/glyph_manager.hpp>
|
#include <mbgl/text/glyph_manager.hpp>
|
||||||
@@ -22,8 +23,6 @@ class GeometryTileData;
|
|||||||
class RenderLayer;
|
class RenderLayer;
|
||||||
class SourceQueryOptions;
|
class SourceQueryOptions;
|
||||||
class TileParameters;
|
class TileParameters;
|
||||||
class GlyphAtlas;
|
|
||||||
class ImageAtlas;
|
|
||||||
class TileAtlasTextures;
|
class TileAtlasTextures;
|
||||||
|
|
||||||
class GeometryTile : public Tile, public GlyphRequestor, public ImageRequestor {
|
class GeometryTile : public Tile, public GlyphRequestor, public ImageRequestor {
|
||||||
@@ -73,19 +72,24 @@ public:
|
|||||||
public:
|
public:
|
||||||
mbgl::unordered_map<std::string, LayerRenderData> layerRenderData;
|
mbgl::unordered_map<std::string, LayerRenderData> layerRenderData;
|
||||||
std::shared_ptr<FeatureIndex> featureIndex;
|
std::shared_ptr<FeatureIndex> featureIndex;
|
||||||
std::optional<AlphaImage> glyphAtlasImage;
|
gfx::GlyphAtlas glyphAtlas;
|
||||||
ImageAtlas iconAtlas;
|
gfx::ImageAtlas imageAtlas;
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas;
|
||||||
|
|
||||||
LayerRenderData* getLayerRenderData(const style::Layer::Impl&);
|
LayerRenderData* getLayerRenderData(const style::Layer::Impl&);
|
||||||
|
|
||||||
LayoutResult(mbgl::unordered_map<std::string, LayerRenderData> renderData_,
|
LayoutResult(mbgl::unordered_map<std::string, LayerRenderData> renderData_,
|
||||||
std::unique_ptr<FeatureIndex> featureIndex_,
|
std::unique_ptr<FeatureIndex> featureIndex_,
|
||||||
std::optional<AlphaImage> glyphAtlasImage_,
|
gfx::GlyphAtlas glyphAtlas_,
|
||||||
ImageAtlas iconAtlas_)
|
gfx::ImageAtlas imageAtlas_,
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas_)
|
||||||
: layerRenderData(std::move(renderData_)),
|
: layerRenderData(std::move(renderData_)),
|
||||||
featureIndex(std::move(featureIndex_)),
|
featureIndex(std::move(featureIndex_)),
|
||||||
glyphAtlasImage(std::move(glyphAtlasImage_)),
|
glyphAtlas(std::move(glyphAtlas_)),
|
||||||
iconAtlas(std::move(iconAtlas_)) {}
|
imageAtlas(std::move(imageAtlas_)),
|
||||||
|
dynamicTextureAtlas(dynamicTextureAtlas_) {}
|
||||||
|
|
||||||
|
~LayoutResult();
|
||||||
};
|
};
|
||||||
void onLayout(std::shared_ptr<LayoutResult>, uint64_t correlationID);
|
void onLayout(std::shared_ptr<LayoutResult>, uint64_t correlationID);
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,8 @@ GeometryTileWorker::GeometryTileWorker(ActorRef<GeometryTileWorker> self_,
|
|||||||
const std::atomic<bool>& obsolete_,
|
const std::atomic<bool>& obsolete_,
|
||||||
const MapMode mode_,
|
const MapMode mode_,
|
||||||
const float pixelRatio_,
|
const float pixelRatio_,
|
||||||
const bool showCollisionBoxes_)
|
const bool showCollisionBoxes_,
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas_)
|
||||||
: self(std::move(self_)),
|
: self(std::move(self_)),
|
||||||
parent(std::move(parent_)),
|
parent(std::move(parent_)),
|
||||||
scheduler(scheduler_),
|
scheduler(scheduler_),
|
||||||
@@ -46,7 +47,8 @@ GeometryTileWorker::GeometryTileWorker(ActorRef<GeometryTileWorker> self_,
|
|||||||
obsolete(obsolete_),
|
obsolete(obsolete_),
|
||||||
mode(mode_),
|
mode(mode_),
|
||||||
pixelRatio(pixelRatio_),
|
pixelRatio(pixelRatio_),
|
||||||
showCollisionBoxes(showCollisionBoxes_) {}
|
showCollisionBoxes(showCollisionBoxes_),
|
||||||
|
dynamicTextureAtlas(dynamicTextureAtlas_) {}
|
||||||
|
|
||||||
GeometryTileWorker::~GeometryTileWorker() {
|
GeometryTileWorker::~GeometryTileWorker() {
|
||||||
MLN_TRACE_FUNC();
|
MLN_TRACE_FUNC();
|
||||||
@@ -332,7 +334,7 @@ void GeometryTileWorker::onImagesAvailable(ImageMap newIconMap,
|
|||||||
if (imageCorrelationID != imageCorrelationID_) {
|
if (imageCorrelationID != imageCorrelationID_) {
|
||||||
return; // Ignore outdated image request replies.
|
return; // Ignore outdated image request replies.
|
||||||
}
|
}
|
||||||
imageMap = std::move(newIconMap);
|
iconMap = std::move(newIconMap);
|
||||||
patternMap = std::move(newPatternMap);
|
patternMap = std::move(newPatternMap);
|
||||||
versionMap = std::move(newVersionMap);
|
versionMap = std::move(newVersionMap);
|
||||||
pendingImageDependencies.clear();
|
pendingImageDependencies.clear();
|
||||||
@@ -495,19 +497,25 @@ void GeometryTileWorker::finalizeLayout() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MBGL_TIMING_START(watch)
|
MBGL_TIMING_START(watch);
|
||||||
std::optional<AlphaImage> glyphAtlasImage;
|
gfx::ImageAtlas imageAtlas;
|
||||||
ImageAtlas iconAtlas = makeImageAtlas(imageMap, patternMap, versionMap);
|
gfx::GlyphAtlas glyphAtlas;
|
||||||
|
if (dynamicTextureAtlas) {
|
||||||
|
imageAtlas = dynamicTextureAtlas->uploadIconsAndPatterns(iconMap, patternMap, versionMap);
|
||||||
|
}
|
||||||
if (!layouts.empty()) {
|
if (!layouts.empty()) {
|
||||||
GlyphAtlas glyphAtlas = makeGlyphAtlas(glyphMap);
|
if (dynamicTextureAtlas) {
|
||||||
glyphAtlasImage = std::move(glyphAtlas.image);
|
glyphAtlas = dynamicTextureAtlas->uploadGlyphs(glyphMap);
|
||||||
|
}
|
||||||
|
|
||||||
for (auto& layout : layouts) {
|
for (auto& layout : layouts) {
|
||||||
if (obsolete) {
|
if (obsolete) {
|
||||||
|
dynamicTextureAtlas->removeTextures(glyphAtlas.textureHandles, glyphAtlas.dynamicTexture);
|
||||||
|
dynamicTextureAtlas->removeTextures(imageAtlas.textureHandles, imageAtlas.dynamicTexture);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
layout->prepareSymbols(glyphMap, glyphAtlas.positions, imageMap, iconAtlas.iconPositions);
|
layout->prepareSymbols(glyphMap, glyphAtlas.glyphPositions, iconMap, imageAtlas.iconPositions);
|
||||||
|
|
||||||
if (!layout->hasSymbolInstances()) {
|
if (!layout->hasSymbolInstances()) {
|
||||||
continue;
|
continue;
|
||||||
@@ -515,7 +523,7 @@ void GeometryTileWorker::finalizeLayout() {
|
|||||||
|
|
||||||
// layout adds the bucket to buckets
|
// layout adds the bucket to buckets
|
||||||
layout->createBucket(
|
layout->createBucket(
|
||||||
iconAtlas.patternPositions, featureIndex, renderData, firstLoad, showCollisionBoxes, id.canonical);
|
imageAtlas.patternPositions, featureIndex, renderData, firstLoad, showCollisionBoxes, id.canonical);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -530,8 +538,11 @@ void GeometryTileWorker::finalizeLayout() {
|
|||||||
<< id.canonical.y << " Time");
|
<< id.canonical.y << " Time");
|
||||||
|
|
||||||
parent.invoke(&GeometryTile::onLayout,
|
parent.invoke(&GeometryTile::onLayout,
|
||||||
std::make_shared<GeometryTile::LayoutResult>(
|
std::make_shared<GeometryTile::LayoutResult>(std::move(renderData),
|
||||||
std::move(renderData), std::move(featureIndex), std::move(glyphAtlasImage), std::move(iconAtlas)),
|
std::move(featureIndex),
|
||||||
|
std::move(glyphAtlas),
|
||||||
|
std::move(imageAtlas),
|
||||||
|
dynamicTextureAtlas),
|
||||||
correlationID);
|
correlationID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ namespace style {
|
|||||||
class Layer;
|
class Layer;
|
||||||
} // namespace style
|
} // namespace style
|
||||||
|
|
||||||
|
namespace gfx {
|
||||||
|
class DynamicTextureAtlas;
|
||||||
|
using DynamicTextureAtlasPtr = std::shared_ptr<gfx::DynamicTextureAtlas>;
|
||||||
|
} // namespace gfx
|
||||||
|
|
||||||
class GeometryTileWorker {
|
class GeometryTileWorker {
|
||||||
public:
|
public:
|
||||||
GeometryTileWorker(ActorRef<GeometryTileWorker> self,
|
GeometryTileWorker(ActorRef<GeometryTileWorker> self,
|
||||||
@@ -36,7 +41,8 @@ public:
|
|||||||
const std::atomic<bool>&,
|
const std::atomic<bool>&,
|
||||||
MapMode,
|
MapMode,
|
||||||
float pixelRatio,
|
float pixelRatio,
|
||||||
bool showCollisionBoxes_);
|
bool showCollisionBoxes_,
|
||||||
|
gfx::DynamicTextureAtlasPtr);
|
||||||
~GeometryTileWorker();
|
~GeometryTileWorker();
|
||||||
|
|
||||||
void setLayers(std::vector<Immutable<style::LayerProperties>>,
|
void setLayers(std::vector<Immutable<style::LayerProperties>>,
|
||||||
@@ -103,13 +109,15 @@ private:
|
|||||||
GlyphDependencies pendingGlyphDependencies;
|
GlyphDependencies pendingGlyphDependencies;
|
||||||
ImageDependencies pendingImageDependencies;
|
ImageDependencies pendingImageDependencies;
|
||||||
GlyphMap glyphMap;
|
GlyphMap glyphMap;
|
||||||
ImageMap imageMap;
|
ImageMap iconMap;
|
||||||
ImageMap patternMap;
|
ImageMap patternMap;
|
||||||
ImageVersionMap versionMap;
|
ImageVersionMap versionMap;
|
||||||
std::set<std::string> availableImages;
|
std::set<std::string> availableImages;
|
||||||
|
|
||||||
bool showCollisionBoxes;
|
bool showCollisionBoxes;
|
||||||
bool firstLoad = true;
|
bool firstLoad = true;
|
||||||
|
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace mbgl
|
} // namespace mbgl
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <mbgl/test/fake_file_source.hpp>
|
#include <mbgl/test/fake_file_source.hpp>
|
||||||
#include <mbgl/text/glyph_manager.hpp>
|
#include <mbgl/text/glyph_manager.hpp>
|
||||||
#include <mbgl/util/run_loop.hpp>
|
#include <mbgl/util/run_loop.hpp>
|
||||||
|
#include <mbgl/gfx/dynamic_texture_atlas.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -24,11 +25,10 @@ public:
|
|||||||
|
|
||||||
const std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
const std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
||||||
const std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
const std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas;
|
||||||
Tileset tileset{{"https://example.com"}, {0, 22}, "none"};
|
|
||||||
|
|
||||||
TaggedScheduler threadPool;
|
TaggedScheduler threadPool;
|
||||||
|
|
||||||
|
Tileset tileset{{"https://example.com"}, {0, 22}, "none"};
|
||||||
TileParameters tileParameters;
|
TileParameters tileParameters;
|
||||||
style::Style style;
|
style::Style style;
|
||||||
|
|
||||||
@@ -43,7 +43,8 @@ public:
|
|||||||
imageManager,
|
imageManager,
|
||||||
glyphManager,
|
glyphManager,
|
||||||
0,
|
0,
|
||||||
threadPool},
|
threadPool,
|
||||||
|
dynamicTextureAtlas},
|
||||||
style{fileSource, 1, threadPool} {}
|
style{fileSource, 1, threadPool} {}
|
||||||
|
|
||||||
~VectorTileTest() {
|
~VectorTileTest() {
|
||||||
|
|||||||
@@ -44,6 +44,7 @@
|
|||||||
#include <mbgl/renderer/image_manager.hpp>
|
#include <mbgl/renderer/image_manager.hpp>
|
||||||
#include <mbgl/renderer/tile_render_data.hpp>
|
#include <mbgl/renderer/tile_render_data.hpp>
|
||||||
#include <mbgl/text/glyph_manager.hpp>
|
#include <mbgl/text/glyph_manager.hpp>
|
||||||
|
#include <mbgl/gfx/dynamic_texture_atlas.hpp>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
@@ -64,6 +65,7 @@ public:
|
|||||||
AnnotationManager annotationManager{style};
|
AnnotationManager annotationManager{style};
|
||||||
std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
||||||
std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas;
|
||||||
TaggedScheduler threadPool;
|
TaggedScheduler threadPool;
|
||||||
Style style;
|
Style style;
|
||||||
|
|
||||||
@@ -77,7 +79,8 @@ public:
|
|||||||
imageManager,
|
imageManager,
|
||||||
glyphManager,
|
glyphManager,
|
||||||
0,
|
0,
|
||||||
threadPool};
|
threadPool,
|
||||||
|
dynamicTextureAtlas};
|
||||||
};
|
};
|
||||||
|
|
||||||
SourceTest()
|
SourceTest()
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ using namespace mbgl::style;
|
|||||||
TEST(getIconQuads, normal) {
|
TEST(getIconQuads, normal) {
|
||||||
SymbolLayoutProperties::Evaluated layout;
|
SymbolLayoutProperties::Evaluated layout;
|
||||||
Anchor anchor(2.0, 3.0, 0.0, 0);
|
Anchor anchor(2.0, 3.0, 0.0, 0);
|
||||||
ImagePosition image = {mapbox::Bin(-1, 15, 11, 0, 0, 0, 0),
|
ImagePosition image = {Rect<uint16_t>(0, 0, 15, 11), style::Image::Impl("test", PremultipliedImage({1, 1}), 1.0f)};
|
||||||
style::Image::Impl("test", PremultipliedImage({1, 1}), 1.0f)};
|
|
||||||
|
|
||||||
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-6.5f, -4.5f}}, SymbolAnchorType::Center);
|
auto shapedIcon = PositionedIcon::shapeIcon(image, {{-6.5f, -4.5f}}, SymbolAnchorType::Center);
|
||||||
|
|
||||||
@@ -36,7 +35,7 @@ TEST(getIconQuads, normal) {
|
|||||||
|
|
||||||
TEST(getIconQuads, style) {
|
TEST(getIconQuads, style) {
|
||||||
Anchor anchor(0.0, 0.0, 0.0, 0);
|
Anchor anchor(0.0, 0.0, 0.0, 0);
|
||||||
const ImagePosition image = {mapbox::Bin(-1, 20, 20, 0, 0, 0, 0),
|
const ImagePosition image = {Rect<uint16_t>(0, 0, 20, 20),
|
||||||
style::Image::Impl("test", PremultipliedImage({1, 1}), 1.0f)};
|
style::Image::Impl("test", PremultipliedImage({1, 1}), 1.0f)};
|
||||||
|
|
||||||
GeometryCoordinates line;
|
GeometryCoordinates line;
|
||||||
|
|||||||
@@ -120,7 +120,7 @@ void setupShapedText(Shaping& shapedText, float textSize) {
|
|||||||
shapedText.positionedLines.back().positionedGlyphs.emplace_back(glyph);
|
shapedText.positionedLines.back().positionedGlyphs.emplace_back(glyph);
|
||||||
}
|
}
|
||||||
|
|
||||||
void testApplyTextFit(const mapbox::Bin& rectangle,
|
void testApplyTextFit(const Rect<uint16_t>& rectangle,
|
||||||
const style::ImageContent& content,
|
const style::ImageContent& content,
|
||||||
const std::optional<style::TextFit> textFitWidth,
|
const std::optional<style::TextFit> textFitWidth,
|
||||||
const std::optional<style::TextFit> textFitHeight,
|
const std::optional<style::TextFit> textFitHeight,
|
||||||
@@ -159,7 +159,7 @@ TEST(Shaping, applyTextFit) {
|
|||||||
// applyTextFitHorizontal
|
// applyTextFitHorizontal
|
||||||
// This set of tests against applyTextFit starts with a 100x20 image with a 5,5,95,15 content box
|
// This set of tests against applyTextFit starts with a 100x20 image with a 5,5,95,15 content box
|
||||||
// that has been fitted to a 4*4 text with scale 4, resulting in a 16*16 image.
|
// that has been fitted to a 4*4 text with scale 4, resulting in a 16*16 image.
|
||||||
const auto horizontalRectangle = mapbox::Bin(-1, 100, 20, -1, -1, 0, 0);
|
const auto horizontalRectangle = Rect<uint16_t>(0, 0, 100, 20);
|
||||||
const style::ImageContent horizontalContent = {5, 5, 95, 15};
|
const style::ImageContent horizontalContent = {5, 5, 95, 15};
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -207,7 +207,7 @@ TEST(Shaping, applyTextFit) {
|
|||||||
// applyTextFitVertical
|
// applyTextFitVertical
|
||||||
// This set of tests against applyTextFit starts with a 20x100 image with a 5,5,15,95 content box
|
// This set of tests against applyTextFit starts with a 20x100 image with a 5,5,15,95 content box
|
||||||
// that has been fitted to a 4*4 text with scale 4, resulting in a 16*16 image.
|
// that has been fitted to a 4*4 text with scale 4, resulting in a 16*16 image.
|
||||||
const auto verticalRectangle = mapbox::Bin(-1, 20, 100, -1, -1, 0, 0);
|
const auto verticalRectangle = Rect<uint16_t>(0, 0, 20, 100);
|
||||||
const style::ImageContent verticalContent = {5, 5, 15, 95};
|
const style::ImageContent verticalContent = {5, 5, 15, 95};
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <mbgl/annotation/annotation_manager.hpp>
|
#include <mbgl/annotation/annotation_manager.hpp>
|
||||||
#include <mbgl/renderer/image_manager.hpp>
|
#include <mbgl/renderer/image_manager.hpp>
|
||||||
#include <mbgl/text/glyph_manager.hpp>
|
#include <mbgl/text/glyph_manager.hpp>
|
||||||
|
#include <mbgl/gfx/dynamic_texture_atlas.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -29,6 +30,8 @@ public:
|
|||||||
AnnotationManager annotationManager{style};
|
AnnotationManager annotationManager{style};
|
||||||
std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
||||||
std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas;
|
||||||
|
|
||||||
TileParameters tileParameters;
|
TileParameters tileParameters;
|
||||||
style::Style style;
|
style::Style style;
|
||||||
|
|
||||||
@@ -42,7 +45,8 @@ public:
|
|||||||
imageManager,
|
imageManager,
|
||||||
glyphManager,
|
glyphManager,
|
||||||
0,
|
0,
|
||||||
{Scheduler::GetBackground(), uniqueID}},
|
{Scheduler::GetBackground(), uniqueID},
|
||||||
|
dynamicTextureAtlas},
|
||||||
style{fileSource, 1, tileParameters.threadPool} {}
|
style{fileSource, 1, tileParameters.threadPool} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <mbgl/style/style.hpp>
|
#include <mbgl/style/style.hpp>
|
||||||
#include <mbgl/text/glyph_manager.hpp>
|
#include <mbgl/text/glyph_manager.hpp>
|
||||||
#include <mbgl/util/run_loop.hpp>
|
#include <mbgl/util/run_loop.hpp>
|
||||||
|
#include <mbgl/gfx/dynamic_texture_atlas.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -29,6 +30,8 @@ public:
|
|||||||
AnnotationManager annotationManager{style};
|
AnnotationManager annotationManager{style};
|
||||||
std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
||||||
std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas;
|
||||||
|
|
||||||
Tileset tileset{{"https://example.com"}, {0, 22}, "none"};
|
Tileset tileset{{"https://example.com"}, {0, 22}, "none"};
|
||||||
TileParameters tileParameters;
|
TileParameters tileParameters;
|
||||||
style::Style style;
|
style::Style style;
|
||||||
@@ -43,7 +46,8 @@ public:
|
|||||||
imageManager,
|
imageManager,
|
||||||
glyphManager,
|
glyphManager,
|
||||||
0,
|
0,
|
||||||
{Scheduler::GetBackground(), uniqueID}},
|
{Scheduler::GetBackground(), uniqueID},
|
||||||
|
dynamicTextureAtlas},
|
||||||
style{fileSource, 1, tileParameters.threadPool} {}
|
style{fileSource, 1, tileParameters.threadPool} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <mbgl/renderer/buckets/hillshade_bucket.hpp>
|
#include <mbgl/renderer/buckets/hillshade_bucket.hpp>
|
||||||
#include <mbgl/renderer/image_manager.hpp>
|
#include <mbgl/renderer/image_manager.hpp>
|
||||||
#include <mbgl/text/glyph_manager.hpp>
|
#include <mbgl/text/glyph_manager.hpp>
|
||||||
|
#include <mbgl/gfx/dynamic_texture_atlas.hpp>
|
||||||
|
|
||||||
using namespace mbgl;
|
using namespace mbgl;
|
||||||
|
|
||||||
@@ -23,6 +24,8 @@ public:
|
|||||||
AnnotationManager annotationManager{style};
|
AnnotationManager annotationManager{style};
|
||||||
std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
||||||
std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas;
|
||||||
|
|
||||||
Tileset tileset{{"https://example.com"}, {0, 22}, "none"};
|
Tileset tileset{{"https://example.com"}, {0, 22}, "none"};
|
||||||
TileParameters tileParameters;
|
TileParameters tileParameters;
|
||||||
style::Style style;
|
style::Style style;
|
||||||
@@ -37,7 +40,8 @@ public:
|
|||||||
imageManager,
|
imageManager,
|
||||||
glyphManager,
|
glyphManager,
|
||||||
0,
|
0,
|
||||||
{Scheduler::GetBackground(), uniqueID}},
|
{Scheduler::GetBackground(), uniqueID},
|
||||||
|
dynamicTextureAtlas},
|
||||||
style{fileSource, 1, tileParameters.threadPool} {}
|
style{fileSource, 1, tileParameters.threadPool} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <mbgl/renderer/buckets/raster_bucket.hpp>
|
#include <mbgl/renderer/buckets/raster_bucket.hpp>
|
||||||
#include <mbgl/renderer/image_manager.hpp>
|
#include <mbgl/renderer/image_manager.hpp>
|
||||||
#include <mbgl/text/glyph_manager.hpp>
|
#include <mbgl/text/glyph_manager.hpp>
|
||||||
|
#include <mbgl/gfx/dynamic_texture_atlas.hpp>
|
||||||
|
|
||||||
using namespace mbgl;
|
using namespace mbgl;
|
||||||
|
|
||||||
@@ -23,6 +24,8 @@ public:
|
|||||||
AnnotationManager annotationManager{style};
|
AnnotationManager annotationManager{style};
|
||||||
std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
std::shared_ptr<ImageManager> imageManager = std::make_shared<ImageManager>();
|
||||||
std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
std::shared_ptr<GlyphManager> glyphManager = std::make_shared<GlyphManager>();
|
||||||
|
gfx::DynamicTextureAtlasPtr dynamicTextureAtlas;
|
||||||
|
|
||||||
Tileset tileset{{"https://example.com"}, {0, 22}, "none"};
|
Tileset tileset{{"https://example.com"}, {0, 22}, "none"};
|
||||||
TileParameters tileParameters;
|
TileParameters tileParameters;
|
||||||
style::Style style;
|
style::Style style;
|
||||||
@@ -37,7 +40,8 @@ public:
|
|||||||
imageManager,
|
imageManager,
|
||||||
glyphManager,
|
glyphManager,
|
||||||
0,
|
0,
|
||||||
{Scheduler::GetBackground(), uniqueID}},
|
{Scheduler::GetBackground(), uniqueID},
|
||||||
|
dynamicTextureAtlas},
|
||||||
style{fileSource, 1, tileParameters.threadPool} {}
|
style{fileSource, 1, tileParameters.threadPool} {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||