From bcc6847396aeff5ca0a9fded861d98acb3bd47b8 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Tue, 11 Aug 2015 17:51:11 +0300 Subject: [PATCH] Added patterns caching --- drape/stipple_pen_resource.cpp | 128 ++++++++------------- drape/stipple_pen_resource.hpp | 7 +- drape/texture_manager.cpp | 55 +++++---- iphone/Maps/Maps.xcodeproj/project.pbxproj | 6 + tools/android/update_assets_for_version.sh | 2 +- tools/unix/generate_drules.sh | 2 +- 6 files changed, 90 insertions(+), 110 deletions(-) diff --git a/drape/stipple_pen_resource.cpp b/drape/stipple_pen_resource.cpp index e571c4ac11..3c3e0a5071 100644 --- a/drape/stipple_pen_resource.cpp +++ b/drape/stipple_pen_resource.cpp @@ -11,34 +11,23 @@ namespace dp { -uint32_t const MAX_STIPPLE_PEN_LENGTH = 254; -uint32_t const COLUMN_WIDTH = MAX_STIPPLE_PEN_LENGTH + 2; +uint32_t const MAX_STIPPLE_PEN_LENGTH = 512; +uint32_t const STIPPLE_HEIGHT_DISTANCE = 4; StipplePenPacker::StipplePenPacker(m2::PointU const & canvasSize) : m_canvasSize(canvasSize) - , m_currentColumn(0) + , m_currentRow(0) { - uint32_t columnCount = floor(canvasSize.x / static_cast(COLUMN_WIDTH)); - m_columns.resize(columnCount, 0); + ASSERT(canvasSize.x <= MAX_STIPPLE_PEN_LENGTH, ()); } m2::RectU StipplePenPacker::PackResource(uint32_t width) { - ASSERT(m_currentColumn < m_columns.size(), ()); - uint32_t countInColumn = m_columns[m_currentColumn]; - // 2 pixels height on pattern - uint32_t yOffset = countInColumn * 2; - // ASSERT that ne pattern can be packed in current column - ASSERT(yOffset + 1 <= m_canvasSize.y, ()); - ++m_columns[m_currentColumn]; - // 1 + m_currentColumn = reserve 1 pixel border on left side - uint32_t xOffset = m_currentColumn * COLUMN_WIDTH; - // we check if new pattern can be mapped in this column - // yOffset + 4 = 2 pixels on current pattern and 2 for new pattern - if (yOffset + 4 > m_canvasSize.y) - m_currentColumn++; - - return m2::RectU(xOffset, yOffset, xOffset + width + 2, yOffset + 2); + ASSERT(m_currentRow < m_canvasSize.y, ()); + ASSERT(width <= m_canvasSize.x, ()); + uint32_t yOffset = m_currentRow; + m_currentRow += STIPPLE_HEIGHT_DISTANCE; + return m2::RectU(0, yOffset, width, yOffset + (STIPPLE_HEIGHT_DISTANCE / 2)); } m2::RectF StipplePenPacker::MapTextureCoords(m2::RectU const & pixelRect) const @@ -135,17 +124,18 @@ void StipplePenRasterizator::Rasterize(void * buffer) pixels[0] = pixels[1]; pixels[offset] = pixels[offset - 1]; - memcpy(pixels + COLUMN_WIDTH, pixels, COLUMN_WIDTH); + memcpy(pixels + MAX_STIPPLE_PEN_LENGTH, pixels, MAX_STIPPLE_PEN_LENGTH); } -ref_ptr StipplePenIndex::MapResource(StipplePenKey const & key, bool & newResource) +ref_ptr StipplePenIndex::ReserveResource(bool predefined, StipplePenKey const & key, bool & newResource) { lock_guard g(m_mappingLock); newResource = false; StipplePenHandle handle(key); - TResourceMapping::iterator it = m_resourceMapping.find(handle); - if (it != m_resourceMapping.end()) + TResourceMapping & resourceMapping = predefined ? m_predefinedResourceMapping : m_resourceMapping; + TResourceMapping::iterator it = resourceMapping.find(handle); + if (it != resourceMapping.end()) return make_ref(&it->second); newResource = true; @@ -157,13 +147,26 @@ ref_ptr StipplePenIndex::MapResource(StipplePenKey const m_pendingNodes.push_back(make_pair(pixelRect, resource)); } - auto res = m_resourceMapping.emplace(handle, StipplePenResourceInfo(m_packer.MapTextureCoords(pixelRect), - resource.GetSize(), - resource.GetPatternSize())); + auto res = resourceMapping.emplace(handle, StipplePenResourceInfo(m_packer.MapTextureCoords(pixelRect), + resource.GetSize(), + resource.GetPatternSize())); ASSERT(res.second, ()); return make_ref(&res.first->second); } +ref_ptr StipplePenIndex::MapResource(StipplePenKey const & key, bool & newResource) +{ + StipplePenHandle handle(key); + TResourceMapping::iterator it = m_predefinedResourceMapping.find(handle); + if (it != m_predefinedResourceMapping.end()) + { + newResource = false; + return make_ref(&it->second); + } + + return ReserveResource(false /* predefined */, key, newResource); +} + void StipplePenIndex::UploadResources(ref_ptr texture) { ASSERT(texture->GetFormat() == dp::ALPHA, ()); @@ -176,63 +179,20 @@ void StipplePenIndex::UploadResources(ref_ptr texture) m_pendingNodes.swap(pendingNodes); } - buffer_vector ranges; - ranges.push_back(0); - - uint32_t xOffset = pendingNodes[0].first.minX(); - for (size_t i = 1; i < pendingNodes.size(); ++i) - { - m2::RectU & node = pendingNodes[i].first; -#ifdef DEBUG - ASSERT(xOffset <= node.minX(), ()); - if (xOffset == node.minX()) - { - m2::RectU const & prevNode = pendingNodes[i - 1].first; - ASSERT(prevNode.minY() < node.minY(), ()); - } -#endif - if (node.minX() > xOffset) - ranges.push_back(i); - xOffset = node.minX(); - } - - ranges.push_back(pendingNodes.size()); SharedBufferManager & mng = SharedBufferManager::instance(); + uint32_t const bytesPerNode = MAX_STIPPLE_PEN_LENGTH * STIPPLE_HEIGHT_DISTANCE; + uint32_t reserveBufferSize = my::NextPowOf2(pendingNodes.size() * bytesPerNode); + SharedBufferManager::shared_buffer_ptr_t ptr = mng.reserveSharedBuffer(reserveBufferSize); + uint8_t * rawBuffer = SharedBufferManager::GetRawPointer(ptr); + memset(rawBuffer, 0, reserveBufferSize); + for (size_t i = 0; i < pendingNodes.size(); ++i) + pendingNodes[i].second.Rasterize(rawBuffer + i * bytesPerNode); - for (size_t i = 1; i < ranges.size(); ++i) - { - uint32_t rangeStart = ranges[i - 1]; - uint32_t rangeEnd = ranges[i]; - // rangeEnd - rangeStart give us count of patterns in this package - // 2 * range - count of lines for patterns - uint32_t lineCount = 2 * (rangeEnd - rangeStart); - // MAX_STIPPLE_PEN_LENGTH * lineCount - byte count on all patterns - uint32_t bufferSize = COLUMN_WIDTH * lineCount; - uint32_t reserveBufferSize = my::NextPowOf2(bufferSize); - SharedBufferManager::shared_buffer_ptr_t ptr = mng.reserveSharedBuffer(reserveBufferSize); - uint8_t * rawBuffer = SharedBufferManager::GetRawPointer(ptr); - memset(rawBuffer, 0, reserveBufferSize); + texture->UploadData(0, pendingNodes.front().first.minY(), + MAX_STIPPLE_PEN_LENGTH, pendingNodes.size() * STIPPLE_HEIGHT_DISTANCE, + dp::ALPHA, make_ref(rawBuffer)); - m2::RectU const & startNode = pendingNodes[rangeStart].first; - uint32_t minX = startNode.minX(); - uint32_t minY = startNode.minY(); -#ifdef DEBUG - m2::RectU const & endNode = pendingNodes[rangeEnd - 1].first; - ASSERT(endNode.maxY() == (minY + lineCount), ()); -#endif - - for (size_t r = rangeStart; r < rangeEnd; ++r) - { - pendingNodes[r].second.Rasterize(rawBuffer); - rawBuffer += 2 * COLUMN_WIDTH; - } - - rawBuffer = SharedBufferManager::GetRawPointer(ptr); - texture->UploadData(minX, minY, COLUMN_WIDTH, lineCount, - dp::ALPHA, make_ref(rawBuffer)); - - mng.freeSharedBuffer(reserveBufferSize, ptr); - } + mng.freeSharedBuffer(reserveBufferSize, ptr); } glConst StipplePenIndex::GetMinFilter() const @@ -245,6 +205,12 @@ glConst StipplePenIndex::GetMagFilter() const return gl_const::GLNearest; } +void StipplePenTexture::ReservePattern(buffer_vector const & pattern) +{ + bool newResource = false; + m_indexer->ReserveResource(true /* predefined */, StipplePenKey(pattern), newResource); +} + string DebugPrint(StipplePenHandle const & key) { ostringstream out; diff --git a/drape/stipple_pen_resource.hpp b/drape/stipple_pen_resource.hpp index 57fa1d93b8..4e8744fca7 100644 --- a/drape/stipple_pen_resource.hpp +++ b/drape/stipple_pen_resource.hpp @@ -91,14 +91,14 @@ public: private: m2::PointU m_canvasSize; - buffer_vector m_columns; - uint32_t m_currentColumn; + uint32_t m_currentRow; }; class StipplePenIndex { public: StipplePenIndex(m2::PointU const & canvasSize) : m_packer(canvasSize) {} + ref_ptr ReserveResource(bool predefined, StipplePenKey const & key, bool & newResource); ref_ptr MapResource(StipplePenKey const & key, bool & newResource); void UploadResources(ref_ptr texture); glConst GetMinFilter() const; @@ -109,6 +109,7 @@ private: typedef pair TPendingNode; typedef buffer_vector TPendingNodes; + TResourceMapping m_predefinedResourceMapping; TResourceMapping m_resourceMapping; TPendingNodes m_pendingNodes; StipplePenPacker m_packer; @@ -132,6 +133,8 @@ public: ~StipplePenTexture() { TBase::Reset(); } + void ReservePattern(buffer_vector const & pattern); + private: StipplePenIndex m_index; }; diff --git a/drape/texture_manager.cpp b/drape/texture_manager.cpp index b246cce8b7..c72454ae88 100644 --- a/drape/texture_manager.cpp +++ b/drape/texture_manager.cpp @@ -21,18 +21,18 @@ namespace dp { -uint32_t const STIPPLE_TEXTURE_WIDTH = 512; -uint32_t const MIN_STIPPLE_TEXTURE_HEIGHT = 64; -uint32_t const MIN_COLOR_TEXTURE_SIZE = 64; -size_t const INVALID_GLYPH_GROUP = numeric_limits::max(); +uint32_t const kStippleTextureWidth = 512; +uint32_t const kMinStippleTextureHeight = 64; +uint32_t const kMinColorTextureSize = 64; +size_t const kInvalidGlyphGroup = numeric_limits::max(); -size_t const PIXELS_PER_COLOR = 2; +size_t const kPixelsPerColor = 2; // number of glyphs (since 0) which will be in each texture -size_t const DUPLICATED_GLYPHS_COUNT = 128; +size_t const kDuplicatedGlyphsCount = 128; -size_t const RESERVED_PATTERNS = 10; -size_t const RESERVED_COLORS = 20; +size_t const kReservedPatterns = 10; +size_t const kReservedColors = 20; namespace { @@ -260,45 +260,45 @@ size_t TextureManager::FindGlyphsGroup(strings::UniChar const & c) const }); if (iter == m_glyphGroups.end()) - return INVALID_GLYPH_GROUP; + return kInvalidGlyphGroup; return distance(m_glyphGroups.begin(), iter); } size_t TextureManager::FindGlyphsGroup(strings::UniString const & text) const { - size_t groupIndex = INVALID_GLYPH_GROUP; + size_t groupIndex = kInvalidGlyphGroup; for (strings::UniChar const & c : text) { // skip glyphs which can be duplicated - if (c < DUPLICATED_GLYPHS_COUNT) + if (c < kDuplicatedGlyphsCount) continue; size_t currentIndex = FindGlyphsGroup(c); // an invalid glyph found - if (currentIndex == INVALID_GLYPH_GROUP) + if (currentIndex == kInvalidGlyphGroup) { #if defined(TRACK_GLYPH_USAGE) GlyphUsageTracker::Instance().AddInvalidGlyph(text, c); #endif - return INVALID_GLYPH_GROUP; + return kInvalidGlyphGroup; } // check if each glyph in text id in one group - if (groupIndex == INVALID_GLYPH_GROUP) + if (groupIndex == kInvalidGlyphGroup) groupIndex = currentIndex; else if (groupIndex != currentIndex) { #if defined(TRACK_GLYPH_USAGE) GlyphUsageTracker::Instance().AddUnexpectedGlyph(text, c, currentIndex, groupIndex); #endif - return INVALID_GLYPH_GROUP; + return kInvalidGlyphGroup; } } // all glyphs in duplicated range - if (groupIndex == INVALID_GLYPH_GROUP) + if (groupIndex == kInvalidGlyphGroup) groupIndex = FindGlyphsGroup(text[0]); return groupIndex; @@ -365,6 +365,8 @@ size_t TextureManager::FindHybridGlyphsGroup(TMultilineText const & text) void TextureManager::Init(Params const & params) { + uint32_t const kMaxTextureSize = 2048; + GLFunctions::glPixelStore(gl_const::GLUnpackAlignment, 1); m_symbolTexture = make_unique_dp(params.m_resPostfix); @@ -380,13 +382,14 @@ void TextureManager::Init(Params const & params) patterns.push_back(move(p)); }); - size_t const stippleTextureHeight = max(my::NextPowOf2(patterns.size() + RESERVED_PATTERNS), MIN_STIPPLE_TEXTURE_HEIGHT); - m_stipplePenTexture = make_unique_dp(m2::PointU(STIPPLE_TEXTURE_WIDTH, stippleTextureHeight)); - LOG(LDEBUG, ("Pattens texture size = ", m_stipplePenTexture->GetWidth(), m_stipplePenTexture->GetHeight())); + uint32_t stippleTextureHeight = max(4 * my::NextPowOf2(patterns.size() + kReservedPatterns), kMinStippleTextureHeight); + stippleTextureHeight = min(kMaxTextureSize, stippleTextureHeight); + m_stipplePenTexture = make_unique_dp(m2::PointU(kStippleTextureWidth, stippleTextureHeight)); + LOG(LDEBUG, ("Patterns texture size = ", m_stipplePenTexture->GetWidth(), m_stipplePenTexture->GetHeight())); - ref_ptr stipplePenTextureTex = make_ref(m_stipplePenTexture); - //for (auto it = patterns.begin(); it != patterns.end(); ++it) - // stipplePenTextureTex->ReservePattern(*it); + ref_ptr stipplePenTextureTex = make_ref(m_stipplePenTexture); + for (auto it = patterns.begin(); it != patterns.end(); ++it) + stipplePenTextureTex->ReservePattern(*it); // initialize colors list colors; @@ -395,7 +398,8 @@ void TextureManager::Init(Params const & params) colors.push_back(color); }); - size_t const colorTextureSize = max(my::NextPowOf2(floor(sqrt(colors.size() + RESERVED_COLORS)) * PIXELS_PER_COLOR), MIN_COLOR_TEXTURE_SIZE); + uint32_t colorTextureSize = max(my::NextPowOf2(floor(sqrt(colors.size() + kReservedColors)) * kPixelsPerColor), kMinColorTextureSize); + colorTextureSize = min(kMaxTextureSize, colorTextureSize); m_colorTexture = make_unique_dp(m2::PointU(colorTextureSize, colorTextureSize)); LOG(LDEBUG, ("Colors texture size = ", m_colorTexture->GetWidth(), m_colorTexture->GetHeight())); @@ -403,8 +407,9 @@ void TextureManager::Init(Params const & params) for (auto it = colors.begin(); it != colors.end(); ++it) colorTex->ReserveColor(*it); + // initialize glyphs m_glyphManager = make_unique_dp(params.m_glyphMngParams); - m_maxTextureSize = min(2048, GLFunctions::glGetInteger(gl_const::GLMaxTextureSize)); + m_maxTextureSize = min(kMaxTextureSize, (uint32_t)GLFunctions::glGetInteger(gl_const::GLMaxTextureSize)); uint32_t const textureSquare = m_maxTextureSize * m_maxTextureSize; uint32_t const baseGlyphHeight = params.m_glyphMngParams.m_baseGlyphHeight; @@ -464,7 +469,7 @@ void TextureManager::GetGlyphRegions(strings::UniString const & text, TGlyphsBuf constexpr size_t TextureManager::GetInvalidGlyphGroup() { - return INVALID_GLYPH_GROUP; + return kInvalidGlyphGroup; } } // namespace dp diff --git a/iphone/Maps/Maps.xcodeproj/project.pbxproj b/iphone/Maps/Maps.xcodeproj/project.pbxproj index a9adf32449..1cebdcb343 100644 --- a/iphone/Maps/Maps.xcodeproj/project.pbxproj +++ b/iphone/Maps/Maps.xcodeproj/project.pbxproj @@ -124,6 +124,8 @@ 34F45E901B96E8B100AC93F8 /* MWMSearchTabButtonsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 34F45E8F1B96E8B100AC93F8 /* MWMSearchTabButtonsView.xib */; }; 34F8ADD91B97229A004184CC /* MWMSearchTableView.mm in Sources */ = {isa = PBXBuildFile; fileRef = 34F8ADD81B97229A004184CC /* MWMSearchTableView.mm */; }; 45159BF91B0CA2D5009BFA85 /* resources-6plus in Resources */ = {isa = PBXBuildFile; fileRef = 45159BF81B0CA2D5009BFA85 /* resources-6plus */; }; + 4519503A1B7A3E070085DA05 /* patterns.txt in Resources */ = {isa = PBXBuildFile; fileRef = 451950391B7A3E070085DA05 /* patterns.txt */; }; + 4519503B1B7A3E390085DA05 /* patterns.txt in Resources */ = {isa = PBXBuildFile; fileRef = 451950391B7A3E070085DA05 /* patterns.txt */; }; 452FCA3B1B6A3DF7007019AB /* colors.txt in Resources */ = {isa = PBXBuildFile; fileRef = 452FCA3A1B6A3DF7007019AB /* colors.txt */; }; 452FCA3E1B6A3E83007019AB /* colors.txt in Resources */ = {isa = PBXBuildFile; fileRef = 452FCA3A1B6A3DF7007019AB /* colors.txt */; }; 454040621AD2D75E007A9B12 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46F26C7210F61FD600ECCA39 /* OpenGLES.framework */; }; @@ -1011,6 +1013,7 @@ 34F8ADD81B97229A004184CC /* MWMSearchTableView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MWMSearchTableView.mm; sourceTree = ""; }; 3D443C9C19E421EE0025C2FC /* sv */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sv; path = sv.lproj/Localizable.strings; sourceTree = ""; }; 45159BF81B0CA2D5009BFA85 /* resources-6plus */ = {isa = PBXFileReference; lastKnownFileType = folder; name = "resources-6plus"; path = "../../data/resources-6plus"; sourceTree = ""; }; + 451950391B7A3E070085DA05 /* patterns.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = patterns.txt; path = ../../data/patterns.txt; sourceTree = ""; }; 452FCA3A1B6A3DF7007019AB /* colors.txt */ = {isa = PBXFileReference; lastKnownFileType = text; name = colors.txt; path = ../../data/colors.txt; sourceTree = ""; }; 454040681AD2D8D2007A9B12 /* CoreVideo.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreVideo.framework; path = System/Library/Frameworks/CoreVideo.framework; sourceTree = SDKROOT; }; 4540406E1AD2D9C5007A9B12 /* WatchKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WatchKit.framework; path = System/Library/Frameworks/WatchKit.framework; sourceTree = SDKROOT; }; @@ -2730,6 +2733,7 @@ FAAFD696139D9BE2000AE70C /* categories.txt */, FA64D9A813F975AD00350ECF /* types.txt */, 452FCA3A1B6A3DF7007019AB /* colors.txt */, + 451950391B7A3E070085DA05 /* patterns.txt */, FAF30A94173AB23900818BF6 /* 00_roboto_regular.ttf */, EEA615E5134C4968003A9827 /* 01_dejavusans.ttf */, 9DF04B231B71010E00DACAF1 /* 02_droidsans-fallback.ttf */, @@ -3028,6 +3032,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + 4519503A1B7A3E070085DA05 /* patterns.txt in Resources */, 5605022F1B6211E100169CAD /* sound-strings in Resources */, 452FCA3B1B6A3DF7007019AB /* colors.txt in Resources */, F67BC26F1B254B2000FE1D7B /* MWMPlacePageDescriptionView.xib in Resources */, @@ -3289,6 +3294,7 @@ buildActionMask = 2147483647; files = ( 452FCA3E1B6A3E83007019AB /* colors.txt in Resources */, + 4519503B1B7A3E390085DA05 /* patterns.txt in Resources */, F6C7B7141BA8443C004233F4 /* drules_proto_clear.bin in Resources */, F6C7B7121BA840A4004233F4 /* resources-xhdpi_clear in Resources */, F6C7B7131BA840A4004233F4 /* resources-xhdpi_dark in Resources */, diff --git a/tools/android/update_assets_for_version.sh b/tools/android/update_assets_for_version.sh index ec26032256..4f59119f21 100755 --- a/tools/android/update_assets_for_version.sh +++ b/tools/android/update_assets_for_version.sh @@ -12,7 +12,7 @@ files=(copyright.html faq.html resources-default resources-ldpi resources-mdpi r resources-ldpi_dark resources-mdpi_dark resources-hdpi_dark resources-xhdpi_dark resources-xxhdpi_dark resources-ldpi_clear resources-mdpi_clear resources-hdpi_clear resources-xhdpi_clear resources-xxhdpi_clear types.txt fonts_blacklist.txt fonts_whitelist.txt languages.txt unicode_blocks.txt - drules_proto.bin drules_proto_dark.bin drules_proto_clear.bin external_resources.txt packed_polygons.bin countries.txt sound-strings colors.txt) + drules_proto.bin drules_proto_dark.bin drules_proto_clear.bin external_resources.txt packed_polygons.bin countries.txt sound-strings colors.txt patterns.txt) for item in ${files[*]} do diff --git a/tools/unix/generate_drules.sh b/tools/unix/generate_drules.sh index c6d4277945..85a735af08 100755 --- a/tools/unix/generate_drules.sh +++ b/tools/unix/generate_drules.sh @@ -22,7 +22,7 @@ function BuildDrawingRules() { } # Cleanup -cleanup=(classificator.txt types.txt visibility.txt colors.txt) +cleanup=(classificator.txt types.txt visibility.txt colors.txt patterns.txt) for item in ${cleanup[*]} do rm $DATA_PATH/$item || true