Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/drape
diff options
context:
space:
mode:
authorr.kuznetsov <r.kuznetsov@corp.mail.ru>2019-02-15 11:29:02 +0300
committerDaria Volvenkova <d.volvenkova@corp.mail.ru>2019-03-01 10:45:24 +0300
commit4f47cac04191d2ba98a6bfe450319447f8258d49 (patch)
tree2239939a7e3a11cbfd1facbcc208942863a8a1c5 /drape
parentff589c4b54b190bf8e8dce32b35e7f75715705c8 (diff)
[drape] Optimized font texture memory usage
Diffstat (limited to 'drape')
-rw-r--r--drape/drape_tests/font_texture_tests.cpp5
-rw-r--r--drape/font_texture.cpp23
-rw-r--r--drape/glyph_manager.cpp2
-rw-r--r--drape/texture_manager.cpp91
-rw-r--r--drape/texture_manager.hpp32
5 files changed, 28 insertions, 125 deletions
diff --git a/drape/drape_tests/font_texture_tests.cpp b/drape/drape_tests/font_texture_tests.cpp
index b6f9eca021..6d03cfde8c 100644
--- a/drape/drape_tests/font_texture_tests.cpp
+++ b/drape/drape_tests/font_texture_tests.cpp
@@ -94,9 +94,10 @@ UNIT_TEST(UploadingGlyphs)
args.m_blacklist = "fonts_blacklist.txt";
GetPlatform().GetFontNames(args.m_fonts);
+ uint32_t constexpr kTextureSize = 1024;
GlyphGenerator glyphGenerator(4);
GlyphManager mng(args);
- DummyGlyphIndex index(m2::PointU(128, 128), make_ref(&mng), make_ref(&glyphGenerator));
+ DummyGlyphIndex index(m2::PointU(kTextureSize, kTextureSize), make_ref(&mng), make_ref(&glyphGenerator));
size_t count = 1; // invalid symbol glyph has mapped internally.
count += (index.MapResource(GlyphKey(0x58, GlyphManager::kDynamicGlyphSize)) != nullptr) ? 1 : 0;
count += (index.MapResource(GlyphKey(0x59, GlyphManager::kDynamicGlyphSize)) != nullptr) ? 1 : 0;
@@ -108,7 +109,7 @@ UNIT_TEST(UploadingGlyphs)
Texture::Params p;
p.m_allocator = GetDefaultAllocator(make_ref(&context));
p.m_format = dp::TextureFormat::Alpha;
- p.m_width = p.m_height = 128;
+ p.m_width = p.m_height = kTextureSize;
DummyTexture tex;
tex.Create(make_ref(&context), p);
diff --git a/drape/font_texture.cpp b/drape/font_texture.cpp
index 17a5fb9bf4..b19dd1a45c 100644
--- a/drape/font_texture.cpp
+++ b/drape/font_texture.cpp
@@ -97,11 +97,15 @@ GlyphIndex::GlyphIndex(m2::PointU const & size, ref_ptr<GlyphManager> mng,
ASSERT(m_generator != nullptr, ());
m_generator->RegisterListener(make_ref(this));
- // Cache invalid glyph.
- auto const key = GlyphKey(m_mng->GetInvalidGlyph(GlyphManager::kDynamicGlyphSize).m_code,
- GlyphManager::kDynamicGlyphSize);
+ // Cache predefined glyphs.
bool newResource = false;
- MapResource(key, newResource);
+ uint32_t constexpr kPredefinedGlyphsCount = 128;
+ for (uint32_t i = 0; i < kPredefinedGlyphsCount; ++i)
+ {
+ auto const key = GlyphKey(i, GlyphManager::kDynamicGlyphSize);
+
+ MapResource(key, newResource);
+ }
}
GlyphIndex::~GlyphIndex()
@@ -162,12 +166,15 @@ ref_ptr<Texture::ResourceInfo> GlyphIndex::MapResource(GlyphKey const & key, boo
GlyphManager::Glyph glyph = m_mng->GetGlyph(key.GetUnicodePoint(), key.GetFixedSize());
m2::RectU r;
- if (!m_packer.PackGlyph(glyph.m_image.m_width, glyph.m_image.m_height, r))
+ if (!glyph.m_metrics.m_isValid || !m_packer.PackGlyph(glyph.m_image.m_width, glyph.m_image.m_height, r))
{
glyph.m_image.Destroy();
- LOG(LWARNING, ("Glyphs packer could not pack a glyph", key.GetUnicodePoint(),
- "w =", glyph.m_image.m_width, "h =", glyph.m_image.m_height,
- "packerSize =", m_packer.GetSize()));
+ if (glyph.m_metrics.m_isValid)
+ {
+ LOG(LWARNING, ("Glyphs packer could not pack a glyph", key.GetUnicodePoint(),
+ "w =", glyph.m_image.m_width, "h =", glyph.m_image.m_height,
+ "packerSize =", m_packer.GetSize()));
+ }
auto const invalidGlyph = m_mng->GetInvalidGlyph(key.GetFixedSize());
auto invalidGlyphIndex = m_index.find(GlyphKey(invalidGlyph.m_code, key.GetFixedSize()));
diff --git a/drape/glyph_manager.cpp b/drape/glyph_manager.cpp
index e1d88f6cfd..3144308249 100644
--- a/drape/glyph_manager.cpp
+++ b/drape/glyph_manager.cpp
@@ -649,7 +649,7 @@ bool GlyphManager::AreGlyphsReady(strings::UniString const & str, int fixedSize)
GlyphManager::Glyph GlyphManager::GetInvalidGlyph(int fixedSize) const
{
- strings::UniChar const kInvalidGlyphCode = 0x9;
+ strings::UniChar constexpr kInvalidGlyphCode = 0x9;
int const kFontId = 0;
static bool s_inited = false;
diff --git a/drape/texture_manager.cpp b/drape/texture_manager.cpp
index 2276b9e807..c7c8f22d6c 100644
--- a/drape/texture_manager.cpp
+++ b/drape/texture_manager.cpp
@@ -30,11 +30,9 @@ uint32_t const kMaxTextureSize = 1024;
uint32_t const kStippleTextureWidth = 512;
uint32_t const kMinStippleTextureHeight = 64;
uint32_t const kMinColorTextureSize = 32;
+uint32_t const kGlyphsTextureSize = 1024;
size_t const kInvalidGlyphGroup = std::numeric_limits<size_t>::max();
-// number of glyphs (since 0) which will be in each texture
-size_t const kDuplicatedGlyphsCount = 128;
-
uint32_t const kReservedPatterns = 10;
size_t const kReservedColors = 20;
@@ -237,7 +235,6 @@ uint32_t TextureManager::StippleRegion::GetPatternPixelLength() const
void TextureManager::Release()
{
- m_glyphGroups.clear();
m_hybridGlyphGroups.clear();
m_symbolTextures.clear();
@@ -303,7 +300,7 @@ bool TextureManager::HasAsyncRoutines() const
ref_ptr<Texture> TextureManager::AllocateGlyphTexture()
{
std::lock_guard<std::mutex> lock(m_glyphTexturesMutex);
- m2::PointU size(m_maxTextureSize, m_maxTextureSize);
+ m2::PointU size(kGlyphsTextureSize, kGlyphsTextureSize);
m_glyphTextures.push_back(make_unique_dp<FontTexture>(size, make_ref(m_glyphManager),
m_glyphGenerator,
make_ref(m_textureAllocator)));
@@ -350,67 +347,6 @@ void TextureManager::GetGlyphsRegions(ref_ptr<FontTexture> tex, strings::UniStri
m_nothingToUpload.clear();
}
-size_t TextureManager::FindGlyphsGroup(strings::UniChar const & c) const
-{
- auto const iter = std::lower_bound(m_glyphGroups.begin(), m_glyphGroups.end(), c,
- [](GlyphGroup const & g, strings::UniChar const & c)
- {
- return g.m_endChar < c;
- });
-
- if (iter == m_glyphGroups.end())
- return kInvalidGlyphGroup;
-
- return static_cast<size_t>(std::distance(m_glyphGroups.begin(), iter));
-}
-
-size_t TextureManager::FindGlyphsGroup(strings::UniString const & text) const
-{
- size_t groupIndex = kInvalidGlyphGroup;
- for (auto const & c : text)
- {
- // Skip glyphs which can be duplicated.
- if (c < kDuplicatedGlyphsCount)
- continue;
-
- size_t currentIndex = FindGlyphsGroup(c);
-
- // an invalid glyph found
- if (currentIndex == kInvalidGlyphGroup)
- {
-#if defined(TRACK_GLYPH_USAGE)
- GlyphUsageTracker::Instance().AddInvalidGlyph(text, c);
-#endif
- return kInvalidGlyphGroup;
- }
-
- // Check if each glyph in text id in one group.
- if (groupIndex == kInvalidGlyphGroup)
- groupIndex = currentIndex;
- else if (groupIndex != currentIndex)
- {
-#if defined(TRACK_GLYPH_USAGE)
- GlyphUsageTracker::Instance().AddUnexpectedGlyph(text, c, currentIndex, groupIndex);
-#endif
- return kInvalidGlyphGroup;
- }
- }
-
- // All glyphs in duplicated range.
- if (groupIndex == kInvalidGlyphGroup)
- groupIndex = FindGlyphsGroup(text[0]);
-
- return groupIndex;
-}
-
-size_t TextureManager::FindGlyphsGroup(TMultilineText const & text) const
-{
- strings::UniString combinedString;
- MultilineTextToUniString(text, combinedString);
-
- return FindGlyphsGroup(combinedString);
-}
-
uint32_t TextureManager::GetNumberOfUnfoundCharacters(strings::UniString const & text, int fixedHeight,
HybridGlyphGroup const & group) const
{
@@ -453,8 +389,10 @@ size_t TextureManager::FindHybridGlyphsGroup(strings::UniString const & text, in
// Looking for a hybrid texture which contains text entirely.
for (size_t i = 0; i < m_hybridGlyphGroups.size() - 1; i++)
+ {
if (GetNumberOfUnfoundCharacters(text, fixedHeight, m_hybridGlyphGroups[i]) == 0)
return i;
+ }
// Check if we can contain text in the last hybrid texture.
uint32_t const unfoundChars = GetNumberOfUnfoundCharacters(text, fixedHeight, group);
@@ -539,30 +477,11 @@ void TextureManager::Init(ref_ptr<dp::GraphicsContext> context, Params const & p
// Initialize glyphs.
m_glyphManager = make_unique_dp<GlyphManager>(params.m_glyphMngParams);
-
- uint32_t const textureSquare = m_maxTextureSize * m_maxTextureSize;
+ uint32_t const textureSquare = kGlyphsTextureSize * kGlyphsTextureSize;
uint32_t const baseGlyphHeight =
static_cast<uint32_t>(params.m_glyphMngParams.m_baseGlyphHeight * kGlyphAreaMultiplier);
uint32_t const averageGlyphSquare = baseGlyphHeight * baseGlyphHeight;
-
- m_glyphGroups.push_back(GlyphGroup());
m_maxGlypsCount = static_cast<uint32_t>(ceil(kGlyphAreaCoverage * textureSquare / averageGlyphSquare));
- m_glyphManager->ForEachUnicodeBlock([this](strings::UniChar const & start, strings::UniChar const & end)
- {
- if (m_glyphGroups.empty())
- {
- m_glyphGroups.push_back(GlyphGroup(start, end));
- return;
- }
-
- GlyphGroup & group = m_glyphGroups.back();
- ASSERT_LESS_OR_EQUAL(group.m_endChar, start, ());
-
- if (end - group.m_startChar < m_maxGlypsCount)
- group.m_endChar = end;
- else
- m_glyphGroups.push_back(GlyphGroup(start, end));
- });
m_nothingToUpload.clear();
}
diff --git a/drape/texture_manager.hpp b/drape/texture_manager.hpp
index d4ebe155f7..624f0a980f 100644
--- a/drape/texture_manager.hpp
+++ b/drape/texture_manager.hpp
@@ -150,10 +150,6 @@ private:
void GetGlyphsRegions(ref_ptr<FontTexture> tex, strings::UniString const & text,
int fixedHeight, TGlyphsBuffer & regions);
- size_t FindGlyphsGroup(strings::UniChar const & c) const;
- size_t FindGlyphsGroup(strings::UniString const & text) const;
- size_t FindGlyphsGroup(TMultilineText const & text) const;
-
size_t FindHybridGlyphsGroup(strings::UniString const & text, int fixedHeight);
size_t FindHybridGlyphsGroup(TMultilineText const & text, int fixedHeight);
@@ -198,29 +194,10 @@ private:
template<typename TText, typename TBuffer>
void CalcGlyphRegions(TText const & text, int fixedHeight, TBuffer & buffers)
{
- size_t const groupIndex = FindGlyphsGroup(text);
- bool useHybridGroup = false;
- if (fixedHeight < 0 && groupIndex != GetInvalidGlyphGroup())
- {
- GlyphGroup & group = m_glyphGroups[groupIndex];
- uint32_t const absentGlyphs = GetAbsentGlyphsCount(group.m_texture, text, fixedHeight);
- if (group.m_texture == nullptr || group.m_texture->HasEnoughSpace(absentGlyphs))
- FillResults<GlyphGroup>(text, fixedHeight, buffers, group);
- else
- useHybridGroup = true;
- }
- else
- {
- useHybridGroup = true;
- }
-
- if (useHybridGroup)
- {
- size_t const hybridGroupIndex = FindHybridGlyphsGroup(text, fixedHeight);
- ASSERT(hybridGroupIndex != GetInvalidGlyphGroup(), ());
- HybridGlyphGroup & group = m_hybridGlyphGroups[hybridGroupIndex];
- FillResults<HybridGlyphGroup>(text, fixedHeight, buffers, group);
- }
+ size_t const hybridGroupIndex = FindHybridGlyphsGroup(text, fixedHeight);
+ ASSERT(hybridGroupIndex != GetInvalidGlyphGroup(), ());
+ HybridGlyphGroup & group = m_hybridGlyphGroups[hybridGroupIndex];
+ FillResults<HybridGlyphGroup>(text, fixedHeight, buffers, group);
}
uint32_t GetAbsentGlyphsCount(ref_ptr<Texture> texture, strings::UniString const & text,
@@ -250,7 +227,6 @@ private:
drape_ptr<GlyphManager> m_glyphManager;
drape_ptr<HWTextureAllocator> m_textureAllocator;
- buffer_vector<GlyphGroup, 64> m_glyphGroups;
buffer_vector<HybridGlyphGroup, 4> m_hybridGlyphGroups;
base::Timer m_uploadTimer;