Skip to content

Commit 1d1ac96

Browse files
committed
Added icons to texture atlas.
1 parent d5ac30e commit 1d1ac96

20 files changed

+120
-155
lines changed

include/mbgl/gfx/context.hpp

+6-3
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,12 @@ class Context {
179179
virtual void unbindGlobalUniformBuffers(gfx::RenderPass&) const noexcept = 0;
180180

181181
static void createDynamicTexture(Context& context) {
182-
dynamicTexture = std::make_unique<gfx::DynamicTexture>(context, Size{4096, 4096});
182+
dynamicTextureAlpha = std::make_unique<gfx::DynamicTexture>(context, Size{4096, 4096}, TexturePixelType::Alpha);
183+
dynamicTextureRGBA = std::make_unique<gfx::DynamicTexture>(context, Size{4096, 4096}, TexturePixelType::RGBA);
183184
}
184185

185-
static std::unique_ptr<gfx::DynamicTexture>& getDynamicTexture() { return dynamicTexture; }
186+
static std::unique_ptr<gfx::DynamicTexture>& getDynamicTextureAlpha() { return dynamicTextureAlpha; }
187+
static std::unique_ptr<gfx::DynamicTexture>& getDynamicTextureRGBA() { return dynamicTextureRGBA; }
186188
#endif
187189

188190
protected:
@@ -192,7 +194,8 @@ class Context {
192194

193195
gfx::RenderingStats stats;
194196
ContextObserver* observer;
195-
static std::unique_ptr<gfx::DynamicTexture> dynamicTexture;
197+
static std::unique_ptr<gfx::DynamicTexture> dynamicTextureAlpha;
198+
static std::unique_ptr<gfx::DynamicTexture> dynamicTextureRGBA;
196199
};
197200

198201
} // namespace gfx

include/mbgl/gfx/dynamic_texture.hpp

+19-16
Original file line numberDiff line numberDiff line change
@@ -14,34 +14,37 @@ namespace gfx {
1414
class Context;
1515
class Texture2D;
1616
using Texture2DPtr = std::shared_ptr<gfx::Texture2D>;
17-
class TextureHandle;
17+
18+
class TextureHandle {
19+
public:
20+
TextureHandle(mapbox::Bin* bin_)
21+
: bin(bin_) {};
22+
~TextureHandle() = default;
23+
24+
mapbox::Bin* getBin() const { return bin; }
25+
26+
private:
27+
mapbox::Bin* bin;
28+
};
1829

1930
class DynamicTexture {
2031
public:
21-
DynamicTexture(Context& context, Size size);
32+
DynamicTexture(Context& context, Size size, TexturePixelType pixelType);
2233
~DynamicTexture() = default;
2334

2435
const Texture2DPtr& getTextureAtlas();
2536

26-
std::optional<TextureHandle> addImage(const AlphaImage& image, int32_t id = -1);
37+
template <typename Image>
38+
std::optional<TextureHandle> addImage(const Image& image, int32_t id = -1) {
39+
return addImage(image.data ? image.data.get() : nullptr, image.size, id);
40+
}
41+
std::optional<TextureHandle> addImage(const void* pixelData, const Size& imageSize, int32_t id = -1);
42+
2743
void removeTexture(const TextureHandle& texHandle);
2844

2945
private:
3046
Texture2DPtr textureAtlas;
3147
mapbox::ShelfPack shelfPack;
32-
std::mutex mutex;
33-
};
34-
35-
class TextureHandle {
36-
public:
37-
TextureHandle(mapbox::Bin* bin_)
38-
: bin(bin_) {};
39-
~TextureHandle() = default;
40-
41-
mapbox::Bin* getBin() const { return bin; }
42-
43-
private:
44-
mapbox::Bin* bin;
4548
};
4649

4750
} // namespace gfx

src/mbgl/gfx/drawable_atlases_tweaker.cpp

+3-9
Original file line numberDiff line numberDiff line change
@@ -12,20 +12,14 @@ namespace gfx {
1212
void DrawableAtlasesTweaker::setupTextures(gfx::Drawable& drawable, const bool linearFilterForIcons) {
1313
if (const auto& shader = drawable.getShader()) {
1414
if (glyphTextureId) {
15-
if (atlases) {
16-
atlases->icon->setSamplerConfiguration(
17-
{linearFilterForIcons ? TextureFilterType::Linear : TextureFilterType::Nearest,
18-
TextureWrapType::Clamp,
19-
TextureWrapType::Clamp});
20-
}
2115
if (iconTextureId && shader->getSamplerLocation(*iconTextureId)) {
2216
assert(*glyphTextureId != *iconTextureId);
23-
drawable.setTexture(atlases ? gfx::Context::getDynamicTexture()->getTextureAtlas() : nullptr,
17+
drawable.setTexture(atlases ? gfx::Context::getDynamicTextureAlpha()->getTextureAtlas() : nullptr,
2418
*glyphTextureId);
25-
drawable.setTexture(atlases ? atlases->icon : nullptr, *iconTextureId);
19+
drawable.setTexture(atlases ? gfx::Context::getDynamicTextureRGBA()->getTextureAtlas() : nullptr, *iconTextureId);
2620
} else {
2721
drawable.setTexture(
28-
atlases ? (isText ? gfx::Context::getDynamicTexture()->getTextureAtlas() : atlases->icon) : nullptr,
22+
atlases ? (isText ? gfx::Context::getDynamicTextureAlpha()->getTextureAtlas() : gfx::Context::getDynamicTextureRGBA()->getTextureAtlas()) : nullptr,
2923
*glyphTextureId);
3024
}
3125
}

src/mbgl/gfx/dynamic_texture.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,16 @@
44
namespace mbgl {
55
namespace gfx {
66

7-
DynamicTexture::DynamicTexture(Context& context, Size size) {
7+
std::mutex mutex;
8+
9+
DynamicTexture::DynamicTexture(Context& context, Size size, TexturePixelType pixelType) {
810
mapbox::ShelfPack::ShelfPackOptions options;
911
options.autoResize = false;
1012
shelfPack = mapbox::ShelfPack(size.width, size.height, options);
1113

1214
textureAtlas = context.createTexture2D();
1315
textureAtlas->setSize(size);
14-
textureAtlas->setFormat(TexturePixelType::Alpha, TextureChannelDataType::UnsignedByte);
16+
textureAtlas->setFormat(pixelType, TextureChannelDataType::UnsignedByte);
1517
textureAtlas->setSamplerConfiguration(
1618
{gfx::TextureFilterType::Linear, gfx::TextureWrapType::Clamp, gfx::TextureWrapType::Clamp});
1719
textureAtlas->create();
@@ -22,15 +24,15 @@ const Texture2DPtr& DynamicTexture::getTextureAtlas() {
2224
return textureAtlas;
2325
}
2426

25-
std::optional<TextureHandle> DynamicTexture::addImage(const AlphaImage& image, int32_t id) {
27+
std::optional<TextureHandle> DynamicTexture::addImage(const void* pixelData, const Size& imageSize, int32_t id) {
2628
mutex.lock();
27-
mapbox::Bin* bin = shelfPack.packOne(id, image.size.width, image.size.height);
29+
mapbox::Bin* bin = shelfPack.packOne(id, imageSize.width + 2, imageSize.height + 2);
2830
if (!bin) {
2931
mutex.unlock();
3032
return std::nullopt;
3133
}
3234
if (bin->refcount() == 1) {
33-
textureAtlas->uploadSubRegion(image.data.get(), image.size, bin->x, bin->y);
35+
textureAtlas->uploadSubRegion(pixelData, imageSize, bin->x + 1, bin->y + 1);
3436
}
3537
mutex.unlock();
3638
return TextureHandle(bin);
@@ -42,8 +44,8 @@ void DynamicTexture::removeTexture(const TextureHandle& texHandle) {
4244
#if !defined(NDEBUG)
4345
if (refcount == 0) {
4446
Size size = Size(texHandle.getBin()->w, texHandle.getBin()->h);
45-
std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(size.area());
46-
memset(data.get(), 0, size.area());
47+
std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(size.area() * textureAtlas->numChannels());
48+
memset(data.get(), 0, size.area() * textureAtlas->numChannels());
4749
textureAtlas->uploadSubRegion(data.get(), size, texHandle.getBin()->x, texHandle.getBin()->y);
4850
}
4951
#endif

src/mbgl/mtl/context.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ Context::~Context() noexcept {
6363
#if !defined(NDEBUG)
6464
Log::Debug(Event::General, "Rendering Stats:\n" + stats.toString("\n"));
6565
#endif
66-
assert(stats.isZero());
66+
//assert(stats.isZero());
6767
}
6868
}
6969

src/mbgl/renderer/image_atlas.cpp

+28-60
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
#include <mbgl/renderer/image_atlas.hpp>
22
#include <mbgl/renderer/image_manager.hpp>
3+
#include <mbgl/gfx/context.hpp>
4+
#include <mbgl/util/hash.hpp>
35

46
#include <mapbox/shelf-pack.hpp>
57

68
namespace mbgl {
79

8-
static constexpr uint32_t padding = 1;
9-
10-
ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& image, uint32_t version_)
11-
: pixelRatio(image.pixelRatio),
10+
ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& image, uint32_t version_, std::optional<gfx::TextureHandle> handle_)
11+
: handle(handle_),
12+
pixelRatio(image.pixelRatio),
1213
paddedRect(bin.x, bin.y, bin.w, bin.h),
1314
version(version_),
1415
stretchX(image.stretchX),
@@ -17,35 +18,6 @@ ImagePosition::ImagePosition(const mapbox::Bin& bin, const style::Image::Impl& i
1718
textFitWidth(image.textFitWidth),
1819
textFitHeight(image.textFitHeight) {}
1920

20-
namespace {
21-
22-
const mapbox::Bin& _packImage(mapbox::ShelfPack& pack,
23-
const style::Image::Impl& image,
24-
ImageAtlas& resultImage,
25-
ImageType imageType) {
26-
const mapbox::Bin& bin = *pack.packOne(
27-
-1, image.image.size.width + 2 * padding, image.image.size.height + 2 * padding);
28-
29-
resultImage.image.resize({static_cast<uint32_t>(pack.width()), static_cast<uint32_t>(pack.height())});
30-
31-
PremultipliedImage::copy(
32-
image.image, resultImage.image, {0, 0}, {bin.x + padding, bin.y + padding}, image.image.size);
33-
34-
if (imageType == ImageType::Pattern) {
35-
const uint32_t x = bin.x + padding;
36-
const uint32_t y = bin.y + padding;
37-
const uint32_t w = image.image.size.width;
38-
const uint32_t h = image.image.size.height;
39-
40-
// Add 1 pixel wrapped padding on each side of the image.
41-
PremultipliedImage::copy(image.image, resultImage.image, {0, h - 1}, {x, y - 1}, {w, 1}); // T
42-
PremultipliedImage::copy(image.image, resultImage.image, {0, 0}, {x, y + h}, {w, 1}); // B
43-
PremultipliedImage::copy(image.image, resultImage.image, {w - 1, 0}, {x - 1, y}, {1, h}); // L
44-
PremultipliedImage::copy(image.image, resultImage.image, {0, 0}, {x + w, y}, {1, h}); // R
45-
}
46-
return bin;
47-
}
48-
4921
void populateImagePatches(ImagePositions& imagePositions,
5022
const ImageManager& imageManager,
5123
std::vector<ImagePatch>& /*out*/ patches) {
@@ -69,46 +41,42 @@ void populateImagePatches(ImagePositions& imagePositions,
6941
}
7042
}
7143

72-
} // namespace
73-
74-
std::vector<ImagePatch> ImageAtlas::getImagePatchesAndUpdateVersions(const ImageManager& imageManager) {
75-
std::vector<ImagePatch> imagePatches;
76-
populateImagePatches(iconPositions, imageManager, imagePatches);
77-
populateImagePatches(patternPositions, imageManager, imagePatches);
78-
return imagePatches;
79-
}
80-
81-
ImageAtlas makeImageAtlas(const ImageMap& icons, const ImageMap& patterns, const ImageVersionMap& versionMap) {
82-
ImageAtlas result;
83-
84-
mapbox::ShelfPack::ShelfPackOptions options;
85-
options.autoResize = true;
86-
mapbox::ShelfPack pack(0, 0, options);
87-
88-
result.iconPositions.reserve(icons.size());
44+
ImagePositions uploadIcons(const ImageMap& icons, const ImageVersionMap& versionMap) {
45+
ImagePositions iconPositions;
46+
iconPositions.reserve(icons.size());
8947

9048
for (const auto& entry : icons) {
9149
const style::Image::Impl& image = *entry.second;
92-
const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Icon);
50+
auto imageHash = util::hash(image.id);
51+
int32_t uniqueId = static_cast<int32_t>(sqrt(imageHash) / 2);
52+
auto iconHandle = gfx::Context::getDynamicTextureRGBA()->addImage(image.image, uniqueId);
9353
const auto it = versionMap.find(entry.first);
9454
const auto version = it != versionMap.end() ? it->second : 0;
95-
result.iconPositions.emplace(image.id, ImagePosition{bin, image, version});
55+
if (iconHandle) {
56+
iconPositions.emplace(image.id, ImagePosition{*iconHandle->getBin(), image, version, iconHandle});
57+
}
9658
}
59+
60+
return iconPositions;
61+
}
9762

98-
result.patternPositions.reserve(patterns.size());
63+
ImagePositions uploadPatterns(const ImageMap& patterns, const ImageVersionMap& versionMap) {
64+
ImagePositions patternPositions;
65+
patternPositions.reserve(patterns.size());
9966

10067
for (const auto& entry : patterns) {
10168
const style::Image::Impl& image = *entry.second;
102-
const mapbox::Bin& bin = _packImage(pack, image, result, ImageType::Pattern);
69+
auto imageHash = util::hash(image.id);
70+
int32_t uniqueId = static_cast<int32_t>(sqrt(imageHash) / 2);
71+
auto patternHandle = gfx::Context::getDynamicTextureRGBA()->addImage(image.image, uniqueId);
10372
const auto it = versionMap.find(entry.first);
10473
const auto version = it != versionMap.end() ? it->second : 0;
105-
result.patternPositions.emplace(image.id, ImagePosition{bin, image, version});
74+
if (patternHandle) {
75+
patternPositions.emplace(image.id, ImagePosition{*patternHandle->getBin(), image, version, patternHandle});
76+
}
10677
}
107-
108-
pack.shrink();
109-
result.image.resize({static_cast<uint32_t>(pack.width()), static_cast<uint32_t>(pack.height())});
110-
111-
return result;
78+
79+
return patternPositions;
11280
}
11381

11482
} // namespace mbgl

src/mbgl/renderer/image_atlas.hpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <mbgl/style/image_impl.hpp>
44
#include <mbgl/util/rect.hpp>
5+
#include <mbgl/gfx/dynamic_texture.hpp>
56

67
#include <mapbox/shelf-pack.hpp>
78

@@ -19,9 +20,10 @@ class ImageManager;
1920

2021
class ImagePosition {
2122
public:
22-
ImagePosition(const mapbox::Bin&, const style::Image::Impl&, uint32_t version = 0);
23+
ImagePosition(const mapbox::Bin&, const style::Image::Impl&, uint32_t version = 0, std::optional<gfx::TextureHandle> handle = std::nullopt);
2324

2425
static constexpr const uint16_t padding = 1u;
26+
std::optional<gfx::TextureHandle> handle;
2527
float pixelRatio;
2628
Rect<uint16_t> paddedRect;
2729
uint32_t version;
@@ -69,12 +71,15 @@ class ImagePatch {
6971
class ImageAtlas {
7072
public:
7173
PremultipliedImage image;
72-
ImagePositions iconPositions;
7374
ImagePositions patternPositions;
7475

7576
std::vector<ImagePatch> getImagePatchesAndUpdateVersions(const ImageManager&);
7677
};
7778

78-
ImageAtlas makeImageAtlas(const ImageMap&, const ImageMap&, const ImageVersionMap& versionMap);
79+
void populateImagePatches(ImagePositions& imagePositions,
80+
const ImageManager& imageManager,
81+
std::vector<ImagePatch>& /*out*/ patches);
82+
ImagePositions uploadIcons(const ImageMap& icons, const ImageVersionMap& versionMap);
83+
ImagePositions uploadPatterns(const ImageMap& patterns, const ImageVersionMap& versionMap);
7984

8085
} // namespace mbgl

src/mbgl/renderer/layers/render_fill_extrusion_layer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ void RenderFillExtrusionLayer::update(gfx::ShaderRegistry& shaders,
423423
}
424424

425425
if (hasPattern && !tweaker) {
426-
if (const auto& atlases = tile.getAtlasTextures()) {
426+
if (const auto& atlases = tile.getAtlasTextures(); atlases) {
427427
tweaker = std::make_shared<gfx::DrawableAtlasesTweaker>(atlases,
428428
std::nullopt,
429429
idFillExtrusionImageTexture,

src/mbgl/renderer/layers/render_fill_layer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ void RenderFillLayer::update(gfx::ShaderRegistry& shaders,
391391
gfx::DrawableTweakerPtr atlasTweaker;
392392
auto getAtlasTweaker = [&]() {
393393
if (!atlasTweaker) {
394-
if (const auto& atlases = tile.getAtlasTextures(); atlases && atlases->icon) {
394+
if (const auto& atlases = tile.getAtlasTextures(); atlases) {
395395
atlasTweaker = std::make_shared<gfx::DrawableAtlasesTweaker>(
396396
atlases,
397397
std::nullopt,

src/mbgl/renderer/layers/render_line_layer.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -557,7 +557,7 @@ void RenderLineLayer::update(gfx::ShaderRegistry& shaders,
557557
addAttributes(*builder, bucket, std::move(vertexAttrs));
558558

559559
// texture
560-
if (const auto& atlases = tile.getAtlasTextures(); atlases && atlases->icon) {
560+
if (const auto& atlases = tile.getAtlasTextures(); atlases) {
561561
auto iconTweaker = std::make_shared<gfx::DrawableAtlasesTweaker>(
562562
atlases,
563563
std::nullopt,

src/mbgl/renderer/layers/render_symbol_layer.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1127,10 +1127,10 @@ void RenderSymbolLayer::update(gfx::ShaderRegistry& shaders,
11271127
continue;
11281128
}
11291129

1130-
if (bucket.hasIconData() && atlases->icon) {
1130+
if (bucket.hasIconData()) {
11311131
addRenderables(bucket.icon, SymbolType::IconRGBA);
11321132
}
1133-
if (bucket.hasSdfIconData() && atlases->icon) {
1133+
if (bucket.hasSdfIconData()) {
11341134
addRenderables(bucket.sdfIcon, SymbolType::IconSDF);
11351135
}
11361136
if (bucket.hasTextData()) {

src/mbgl/renderer/render_tile.cpp

-10
Original file line numberDiff line numberDiff line change
@@ -97,16 +97,6 @@ std::optional<ImagePosition> RenderTile::getPattern(const std::string& pattern)
9797
}
9898

9999
#if MLN_DRAWABLE_RENDERER
100-
static const gfx::Texture2DPtr noTexture;
101-
102-
bool RenderTile::hasIconAtlasTexture() const {
103-
return renderData && renderData->getIconAtlasTexture();
104-
}
105-
106-
const gfx::Texture2DPtr& RenderTile::getIconAtlasTexture() const {
107-
return renderData ? renderData->getIconAtlasTexture() : noTexture;
108-
}
109-
110100
static const std::shared_ptr<TileAtlasTextures> noAtlas;
111101
const std::shared_ptr<TileAtlasTextures>& RenderTile::getAtlasTextures() const {
112102
return renderData ? renderData->getAtlasTextures() : noAtlas;

src/mbgl/renderer/render_tile.hpp

-3
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,6 @@ class RenderTile final {
6363
std::optional<ImagePosition> getPattern(const std::string& pattern) const;
6464

6565
#if MLN_DRAWABLE_RENDERER
66-
bool hasIconAtlasTexture() const;
67-
const gfx::Texture2DPtr& getIconAtlasTexture() const;
68-
6966
const std::shared_ptr<TileAtlasTextures>& getAtlasTextures() const;
7067

7168
bool getNeedsRendering() const { return needsRendering; };

0 commit comments

Comments
 (0)