move SpriteAtlas to the SpriteStore backend
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include <mbgl/geometry/sprite_atlas.hpp>
|
||||
#include <mbgl/annotation/sprite_store.hpp>
|
||||
#include <mbgl/platform/gl.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
@@ -18,10 +19,11 @@
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
SpriteAtlas::SpriteAtlas(dimension width_, dimension height_)
|
||||
SpriteAtlas::SpriteAtlas(dimension width_, dimension height_, SpriteStore& store_)
|
||||
: width(width_),
|
||||
height(height_),
|
||||
bin(width_, height_),
|
||||
store(store_),
|
||||
dirty(true) {
|
||||
}
|
||||
|
||||
@@ -89,15 +91,15 @@ Rect<SpriteAtlas::dimension> SpriteAtlas::getImage(const std::string& name, cons
|
||||
|
||||
auto rect_it = images.find(name);
|
||||
if (rect_it != images.end()) {
|
||||
return rect_it->second;
|
||||
return rect_it->second.pos;
|
||||
}
|
||||
|
||||
const SpritePosition &pos = sprite->getSpritePosition(name);
|
||||
if (!pos.width || !pos.height) {
|
||||
auto sprite = store.getSprite(name);
|
||||
if (!sprite) {
|
||||
return Rect<dimension> { 0, 0, 0, 0 };
|
||||
}
|
||||
|
||||
Rect<dimension> rect = allocateImage(pos.width / pos.pixelRatio, pos.height / pos.pixelRatio);
|
||||
Rect<dimension> rect = allocateImage(sprite->width, sprite->height);
|
||||
if (rect.w == 0) {
|
||||
if (debug::spriteWarnings) {
|
||||
Log::Warning(Event::Sprite, "sprite atlas bitmap overflow");
|
||||
@@ -105,9 +107,8 @@ Rect<SpriteAtlas::dimension> SpriteAtlas::getImage(const std::string& name, cons
|
||||
return rect;
|
||||
}
|
||||
|
||||
images.emplace(name, rect);
|
||||
|
||||
copy(rect, pos, wrap);
|
||||
const Holder& holder = images.emplace(name, Holder{ sprite, rect }).first->second;
|
||||
copy(holder, wrap);
|
||||
|
||||
return rect;
|
||||
}
|
||||
@@ -119,13 +120,14 @@ SpriteAtlasPosition SpriteAtlas::getPosition(const std::string& name, bool repea
|
||||
if (repeating) {
|
||||
// When the image is repeating, get the correct position of the image, rather than the
|
||||
// one rounded up to 4 pixels.
|
||||
const SpritePosition &pos = sprite->getSpritePosition(name);
|
||||
if (!pos.width || !pos.height) {
|
||||
// TODO: Can't we just use originalW/originalH?
|
||||
auto sprite = store.getSprite(name);
|
||||
if (!sprite) {
|
||||
return SpriteAtlasPosition {};
|
||||
}
|
||||
|
||||
rect.w = pos.width / pos.pixelRatio;
|
||||
rect.h = pos.height / pos.pixelRatio;
|
||||
rect.w = sprite->width;
|
||||
rect.h = sprite->height;
|
||||
}
|
||||
|
||||
const float padding = 1;
|
||||
@@ -146,13 +148,12 @@ void SpriteAtlas::allocate() {
|
||||
}
|
||||
}
|
||||
|
||||
void SpriteAtlas::copy(const Rect<dimension>& dst, const SpritePosition& src, const bool wrap) {
|
||||
if (!sprite->raster) return;
|
||||
|
||||
const uint32_t *srcData = reinterpret_cast<const uint32_t *>(sprite->raster->getData());
|
||||
void SpriteAtlas::copy(const Holder& holder, const bool wrap) {
|
||||
const uint32_t *srcData = reinterpret_cast<const uint32_t *>(holder.texture->data.data());
|
||||
if (!srcData) return;
|
||||
const vec2<uint32_t> srcSize { sprite->raster->getWidth(), sprite->raster->getHeight() };
|
||||
const Rect<uint32_t> srcPos { src.x, src.y, src.width, src.height };
|
||||
const vec2<uint32_t> srcSize { holder.texture->pixelWidth, holder.texture->pixelHeight };
|
||||
const Rect<uint32_t> srcPos { 0, 0, srcSize.x, srcSize.y };
|
||||
const auto& dst = holder.pos;
|
||||
|
||||
const int offset = 1;
|
||||
|
||||
@@ -201,34 +202,34 @@ void SpriteAtlas::copy(const Rect<dimension>& dst, const SpritePosition& src, co
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
void SpriteAtlas::setSprite(util::ptr<Sprite> sprite_) {
|
||||
std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
// void SpriteAtlas::setSprite(util::ptr<Sprite> sprite_) {
|
||||
// std::lock_guard<std::recursive_mutex> lock(mtx);
|
||||
|
||||
sprite = sprite_;
|
||||
// sprite = sprite_;
|
||||
|
||||
if (!sprite->isLoaded()) return;
|
||||
// if (!sprite->isLoaded()) return;
|
||||
|
||||
util::erase_if(uninitialized, [this](const std::string &name) {
|
||||
Rect<dimension> dst = getImage(name, false);
|
||||
const SpritePosition& src = sprite->getSpritePosition(name);
|
||||
if (!src) {
|
||||
if (debug::spriteWarnings) {
|
||||
Log::Warning(Event::Sprite, "sprite doesn't have image with name '%s'", name.c_str());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// util::erase_if(uninitialized, [this](const std::string &name) {
|
||||
// Rect<dimension> dst = getImage(name, false);
|
||||
// const SpritePosition& src = sprite->getSpritePosition(name);
|
||||
// if (!src) {
|
||||
// if (debug::spriteWarnings) {
|
||||
// Log::Warning(Event::Sprite, "sprite doesn't have image with name '%s'", name.c_str());
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
|
||||
if (src.width == dst.w * pixelRatio && src.height == dst.h * pixelRatio && src.pixelRatio == pixelRatio) {
|
||||
copy(dst, src, false);
|
||||
return true;
|
||||
} else {
|
||||
if (debug::spriteWarnings) {
|
||||
Log::Warning(Event::Sprite, "sprite icon dimension mismatch");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
// if (src.width == dst.w * pixelRatio && src.height == dst.h * pixelRatio && src.pixelRatio == pixelRatio) {
|
||||
// copy(dst, src, false);
|
||||
// return true;
|
||||
// } else {
|
||||
// if (debug::spriteWarnings) {
|
||||
// Log::Warning(Event::Sprite, "sprite icon dimension mismatch");
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
void SpriteAtlas::upload() {
|
||||
if (dirty) {
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class Sprite;
|
||||
class SpriteStore;
|
||||
class SpriteImage;
|
||||
class SpritePosition;
|
||||
|
||||
struct SpriteAtlasPosition {
|
||||
@@ -33,15 +34,12 @@ public:
|
||||
typedef uint16_t dimension;
|
||||
|
||||
// Add way to construct this from another SpriteAtlas (e.g. with another pixelRatio)
|
||||
SpriteAtlas(dimension width, dimension height);
|
||||
SpriteAtlas(dimension width, dimension height, SpriteStore& store);
|
||||
~SpriteAtlas();
|
||||
|
||||
// Changes the pixel ratio.
|
||||
bool resize(float newRatio);
|
||||
|
||||
// Changes the source sprite.
|
||||
void setSprite(util::ptr<Sprite> sprite);
|
||||
|
||||
// Returns the coordinates of an image that is sourced from the sprite image.
|
||||
// This getter attempts to read the image from the sprite if it is already loaded.
|
||||
// In that case, it copies it into the sprite atlas and returns the dimensions.
|
||||
@@ -69,15 +67,23 @@ public:
|
||||
const dimension height = 0;
|
||||
|
||||
private:
|
||||
struct Holder : private util::noncopyable {
|
||||
Holder(const std::shared_ptr<const SpriteImage>&, const Rect<dimension>&);
|
||||
Holder(Holder&&);
|
||||
std::shared_ptr<const SpriteImage> texture;
|
||||
std::set<uintptr_t> references;
|
||||
const Rect<dimension> pos;
|
||||
};
|
||||
|
||||
void allocate();
|
||||
Rect<SpriteAtlas::dimension> allocateImage(size_t width, size_t height);
|
||||
void copy(const Rect<dimension>& dst, const SpritePosition& src, const bool wrap);
|
||||
void copy(const Holder& holder, const bool wrap);
|
||||
|
||||
std::recursive_mutex mtx;
|
||||
float pixelRatio = 1.0f;
|
||||
BinPack<dimension> bin;
|
||||
util::ptr<Sprite> sprite;
|
||||
std::map<std::string, Rect<dimension>> images;
|
||||
SpriteStore& store;
|
||||
std::map<std::string, Holder> images;
|
||||
std::set<std::string> uninitialized;
|
||||
std::unique_ptr<uint32_t[]> data;
|
||||
std::atomic<bool> dirty;
|
||||
|
||||
@@ -24,7 +24,7 @@ Style::Style(const std::string& data, const std::string&,
|
||||
uv_loop_t* loop)
|
||||
: glyphStore(std::make_unique<GlyphStore>(loop)),
|
||||
glyphAtlas(std::make_unique<GlyphAtlas>(1024, 1024)),
|
||||
spriteAtlas(std::make_unique<SpriteAtlas>(512, 512)),
|
||||
spriteAtlas(std::make_unique<SpriteAtlas>(512, 512, *spriteStore)),
|
||||
lineAtlas(std::make_unique<LineAtlas>(512, 512)),
|
||||
mtx(std::make_unique<uv::rwlock>()),
|
||||
workers(4) {
|
||||
|
||||
Reference in New Issue
Block a user