diff --git a/drape/drape_tests/dummy_texture.hpp b/drape/drape_tests/dummy_texture.hpp index 50ab40df2f..445be79869 100644 --- a/drape/drape_tests/dummy_texture.hpp +++ b/drape/drape_tests/dummy_texture.hpp @@ -6,7 +6,7 @@ class DummyTexture : public dp::Texture { public: - virtual dp::RefPointer FindResource(Key const & /*key*/) const + virtual dp::RefPointer FindResource(Key const & /*key*/, bool & /*newResource*/) { return dp::RefPointer(); } diff --git a/drape/drape_tests/font_texture_tests.cpp b/drape/drape_tests/font_texture_tests.cpp index c60f4c502c..e048018fe7 100644 --- a/drape/drape_tests/font_texture_tests.cpp +++ b/drape/drape_tests/font_texture_tests.cpp @@ -76,23 +76,25 @@ UNIT_TEST(UploadingGlyphs) args.m_blacklist = "fonts_blacklist.txt"; GetPlatform().GetFontNames(args.m_fonts); + bool dummy = false; + GlyphManager mng(args); GlyphIndex index(m2::PointU(64, 64), MakeStackRefPointer(&mng)); - index.MapResource(GlyphKey(0x58)); - index.MapResource(GlyphKey(0x59)); - index.MapResource(GlyphKey(0x61)); + index.MapResource(GlyphKey(0x58), dummy); + index.MapResource(GlyphKey(0x59), dummy); + index.MapResource(GlyphKey(0x61), dummy); DummyTexture tex; tex.Create(64, 64, dp::ALPHA, MakeStackRefPointer(nullptr)); EXPECTGL(glTexSubImage2D(_, _, _, _, _, _, _)).WillOnce(Invoke(&r, &UploadedRender::glMemoryToQImage)); index.UploadResources(MakeStackRefPointer(&tex)); - index.MapResource(GlyphKey(0x68)); - index.MapResource(GlyphKey(0x30)); - index.MapResource(GlyphKey(0x62)); - index.MapResource(GlyphKey(0x65)); - index.MapResource(GlyphKey(0x400)); - index.MapResource(GlyphKey(0x401)); + index.MapResource(GlyphKey(0x68), dummy); + index.MapResource(GlyphKey(0x30), dummy); + index.MapResource(GlyphKey(0x62), dummy); + index.MapResource(GlyphKey(0x65), dummy); + index.MapResource(GlyphKey(0x400), dummy); + index.MapResource(GlyphKey(0x401), dummy); EXPECTGL(glTexSubImage2D(_, _, _, _, _, _, _)).WillOnce(Invoke(&r, &UploadedRender::glMemoryToQImage)) .WillOnce(Invoke(&r, &UploadedRender::glMemoryToQImage)); index.UploadResources(MakeStackRefPointer(&tex)); diff --git a/drape/drape_tests/stipple_pen_tests.cpp b/drape/drape_tests/stipple_pen_tests.cpp index ac8b2d4d55..556e9426bd 100644 --- a/drape/drape_tests/stipple_pen_tests.cpp +++ b/drape/drape_tests/stipple_pen_tests.cpp @@ -404,24 +404,25 @@ UNIT_TEST(StippleMappingTest) info.m_pattern.push_back(10); info.m_pattern.push_back(10); - RefPointer r1 = index.MapResource(info); + bool dummy = false; + RefPointer r1 = index.MapResource(info, dummy); TEST(IsRectsEqual(r1->GetTexRect(), m2::RectF(1.0f / width, 1.0f / height, 241.0f / width, 1.0f / height)), ()); - RefPointer r2 = index.MapResource(info); + RefPointer r2 = index.MapResource(info, dummy); TEST(IsRectsEqual(r1->GetTexRect(), r2->GetTexRect()), ()); info.m_pattern.clear(); info.m_pattern.push_back(4); info.m_pattern.push_back(4); - r1 = index.MapResource(info); + r1 = index.MapResource(info, dummy); TEST(IsRectsEqual(r1->GetTexRect(), m2::RectF(1.0f / width, 3.0f / height, 249.0f / width, 3.0f / height)), ()); info.m_pattern.clear(); info.m_pattern.push_back(3); info.m_pattern.push_back(20); - r1 = index.MapResource(info); + r1 = index.MapResource(info, dummy); TEST(IsRectsEqual(r1->GetTexRect(), m2::RectF(1.0f / width, 5.0f / height, 254.0f / width, 5.0f / height)), ()); @@ -445,13 +446,13 @@ UNIT_TEST(StippleMappingTest) StipplePenKey secInfo; secInfo.m_pattern.push_back(20); secInfo.m_pattern.push_back(20); - RefPointer r12 = index.MapResource(secInfo); + RefPointer r12 = index.MapResource(secInfo, dummy); TEST(IsRectsEqual(r12->GetTexRect(), m2::RectF(1.0f / width, 7.0f / height, 241.0f / width, 7.0f / height)), ()); secInfo.m_pattern.push_back(10); secInfo.m_pattern.push_back(10); - r12 = index.MapResource(secInfo); + r12 = index.MapResource(secInfo, dummy); TEST(IsRectsEqual(r12->GetTexRect(), m2::RectF(257.0f / width, 1.0f / height, 497.0f / width, 1.0f / height)), ()); diff --git a/drape/drape_tests/texture_of_colors_tests.cpp b/drape/drape_tests/texture_of_colors_tests.cpp index e784378f02..c4e81da19b 100644 --- a/drape/drape_tests/texture_of_colors_tests.cpp +++ b/drape/drape_tests/texture_of_colors_tests.cpp @@ -48,9 +48,10 @@ UNIT_TEST(ColorPalleteMappingTests) { ColorPalette cp(m2::PointU(32, 16)); - RefPointer info1 = cp.MapResource(dp::Color(0, 0, 0, 0)); - RefPointer info2 = cp.MapResource(dp::Color(1, 1, 1, 1)); - RefPointer info3 = cp.MapResource(dp::Color(0, 0, 0, 0)); + bool dummy = false; + RefPointer info1 = cp.MapResource(dp::Color(0, 0, 0, 0), dummy); + RefPointer info2 = cp.MapResource(dp::Color(1, 1, 1, 1), dummy); + RefPointer info3 = cp.MapResource(dp::Color(0, 0, 0, 0), dummy); TEST_NOT_EQUAL(info1.GetRaw(), info2.GetRaw(), ()); TEST_EQUAL(info1.GetRaw(), info3.GetRaw(), ()); @@ -62,10 +63,10 @@ UNIT_TEST(ColorPalleteMappingTests) 1.0f / 32.0f, 1.0f / 16)); for (int i = 2; i < 100; ++i) - cp.MapResource(dp::Color(i, i, i, i)); + cp.MapResource(dp::Color(i, i, i, i), dummy); - TestRects(cp.MapResource(dp::Color(54, 54, 54, 54))->GetTexRect(), m2::RectF(13.0f / 32.0f, 7.0f / 16.0f, - 13.0f / 32.0f, 7.0f / 16.0f)); + TestRects(cp.MapResource(dp::Color(54, 54, 54, 54), dummy)->GetTexRect(), m2::RectF(13.0f / 32.0f, 7.0f / 16.0f, + 13.0f / 32.0f, 7.0f / 16.0f)); } UNIT_TEST(ColorPalleteUploadingSingleRow) @@ -79,12 +80,14 @@ UNIT_TEST(ColorPalleteUploadingSingleRow) ColorPalette cp(m2::PointU(width, height)); cp.UploadResources(MakeStackRefPointer(&texture)); + bool dummy = false; + { - cp.MapResource(dp::Color(0xFF, 0, 0, 0)); - cp.MapResource(dp::Color(0, 0xFF, 0, 0)); - cp.MapResource(dp::Color(0, 0, 0xFF, 0)); - cp.MapResource(dp::Color(0, 0, 0, 0xFF)); - cp.MapResource(dp::Color(0xAA, 0xBB, 0xCC, 0xDD)); + cp.MapResource(dp::Color(0xFF, 0, 0, 0), dummy); + cp.MapResource(dp::Color(0, 0xFF, 0, 0), dummy); + cp.MapResource(dp::Color(0, 0, 0xFF, 0), dummy); + cp.MapResource(dp::Color(0, 0, 0, 0xFF), dummy); + cp.MapResource(dp::Color(0xAA, 0xBB, 0xCC, 0xDD), dummy); uint8_t memoryEtalon[] = { @@ -106,11 +109,11 @@ UNIT_TEST(ColorPalleteUploadingSingleRow) } { - cp.MapResource(dp::Color(0xFF, 0xAA, 0, 0)); - cp.MapResource(dp::Color(0xAA, 0xFF, 0, 0)); - cp.MapResource(dp::Color(0xAA, 0, 0xFF, 0)); - cp.MapResource(dp::Color(0xAA, 0, 0, 0xFF)); - cp.MapResource(dp::Color(0x00, 0xBB, 0xCC, 0xDD)); + cp.MapResource(dp::Color(0xFF, 0xAA, 0, 0), dummy); + cp.MapResource(dp::Color(0xAA, 0xFF, 0, 0), dummy); + cp.MapResource(dp::Color(0xAA, 0, 0xFF, 0), dummy); + cp.MapResource(dp::Color(0xAA, 0, 0, 0xFF), dummy); + cp.MapResource(dp::Color(0x00, 0xBB, 0xCC, 0xDD), dummy); uint8_t memoryEtalon[] = { @@ -145,13 +148,15 @@ UNIT_TEST(ColorPalleteUploadingPartialyRow) texture.Create(width, height, dp::RGBA8); ColorPalette cp(m2::PointU(width, height)); + bool dummy = false; + { - cp.MapResource(dp::Color(0xFF, 0, 0, 0)); - cp.MapResource(dp::Color(0xFF, 0xFF, 0, 0)); - cp.MapResource(dp::Color(0xFF, 0xFF, 0xFF, 0)); - cp.MapResource(dp::Color(0xFF, 0xFF, 0xFF, 0xFF)); - cp.MapResource(dp::Color(0, 0, 0, 0xFF)); - cp.MapResource(dp::Color(0, 0, 0xFF, 0xFF)); + cp.MapResource(dp::Color(0xFF, 0, 0, 0), dummy); + cp.MapResource(dp::Color(0xFF, 0xFF, 0, 0), dummy); + cp.MapResource(dp::Color(0xFF, 0xFF, 0xFF, 0), dummy); + cp.MapResource(dp::Color(0xFF, 0xFF, 0xFF, 0xFF), dummy); + cp.MapResource(dp::Color(0, 0, 0, 0xFF), dummy); + cp.MapResource(dp::Color(0, 0, 0xFF, 0xFF), dummy); uint8_t memoryEtalon[] = { @@ -173,10 +178,10 @@ UNIT_TEST(ColorPalleteUploadingPartialyRow) } { - cp.MapResource(dp::Color(0xAA, 0, 0, 0)); - cp.MapResource(dp::Color(0xAA, 0xAA, 0, 0)); - cp.MapResource(dp::Color(0xAA, 0xAA, 0xAA, 0)); - cp.MapResource(dp::Color(0xAA, 0xAA, 0xAA, 0xAA)); + cp.MapResource(dp::Color(0xAA, 0, 0, 0), dummy); + cp.MapResource(dp::Color(0xAA, 0xAA, 0, 0), dummy); + cp.MapResource(dp::Color(0xAA, 0xAA, 0xAA, 0), dummy); + cp.MapResource(dp::Color(0xAA, 0xAA, 0xAA, 0xAA), dummy); uint8_t memoryEtalon1[] = { @@ -221,9 +226,11 @@ UNIT_TEST(ColorPalleteUploadingMultipyRow) ColorPalette cp(m2::PointU(width, height)); cp.SetIsDebug(true); + bool dummy = false; + { - cp.MapResource(dp::Color(0xFF, 0, 0, 0)); - cp.MapResource(dp::Color(0xAA, 0, 0, 0)); + cp.MapResource(dp::Color(0xFF, 0, 0, 0), dummy); + cp.MapResource(dp::Color(0xAA, 0, 0, 0), dummy); uint8_t memoryEtalon[] = { @@ -240,13 +247,13 @@ UNIT_TEST(ColorPalleteUploadingMultipyRow) } { - cp.MapResource(dp::Color(0xCC, 0, 0, 0)); - cp.MapResource(dp::Color(0xFF, 0xFF, 0, 0)); - cp.MapResource(dp::Color(0xFF, 0xFF, 0xFF, 0)); - cp.MapResource(dp::Color(0xFF, 0xFF, 0xFF, 0xFF)); - cp.MapResource(dp::Color(0, 0, 0, 0xFF)); - cp.MapResource(dp::Color(0, 0, 0xFF, 0xFF)); - cp.MapResource(dp::Color(0, 0, 0xAA, 0xAA)); + cp.MapResource(dp::Color(0xCC, 0, 0, 0), dummy); + cp.MapResource(dp::Color(0xFF, 0xFF, 0, 0), dummy); + cp.MapResource(dp::Color(0xFF, 0xFF, 0xFF, 0), dummy); + cp.MapResource(dp::Color(0xFF, 0xFF, 0xFF, 0xFF), dummy); + cp.MapResource(dp::Color(0, 0, 0, 0xFF), dummy); + cp.MapResource(dp::Color(0, 0, 0xFF, 0xFF), dummy); + cp.MapResource(dp::Color(0, 0, 0xAA, 0xAA), dummy); uint8_t memoryEtalon1[] = { diff --git a/drape/dynamic_texture.hpp b/drape/dynamic_texture.hpp index c35e84f035..80ba8fe4c8 100644 --- a/drape/dynamic_texture.hpp +++ b/drape/dynamic_texture.hpp @@ -15,19 +15,18 @@ public: ASSERT(m_indexer.IsNull(), ()); } - virtual RefPointer FindResource(Key const & key) const + virtual RefPointer FindResource(Key const & key, bool & newResource) { ASSERT(!m_indexer.IsNull(), ()); if (key.GetType() != TResourceType) return RefPointer(); - return m_indexer->MapResource(static_cast(key)); + return m_indexer->MapResource(static_cast(key), newResource); } virtual void UpdateState() { ASSERT(!m_indexer.IsNull(), ()); - Bind(); m_indexer->UploadResources(MakeStackRefPointer(this)); } @@ -61,7 +60,7 @@ protected: } private: - mutable RefPointer m_indexer; + RefPointer m_indexer; }; } diff --git a/drape/font_texture.cpp b/drape/font_texture.cpp index 793e4ae505..c42f61b8c4 100644 --- a/drape/font_texture.cpp +++ b/drape/font_texture.cpp @@ -82,13 +82,16 @@ GlyphIndex::GlyphIndex(m2::PointU size, RefPointer mng) { } -RefPointer GlyphIndex::MapResource(GlyphKey const & key) +RefPointer GlyphIndex::MapResource(GlyphKey const & key, bool & newResource) { + newResource = false; strings::UniChar uniChar = key.GetUnicodePoint(); auto it = m_index.find(uniChar); if (it != m_index.end()) return MakeStackRefPointer(&it->second); + newResource = true; + GlyphManager::Glyph glyph = m_mng->GetGlyph(uniChar); m2::RectU r; if (!m_packer.PackGlyph(glyph.m_image.m_width, glyph.m_image.m_height, r)) @@ -97,7 +100,10 @@ RefPointer GlyphIndex::MapResource(GlyphKey const & key) return RefPointer(); } - m_pendingNodes.emplace_back(r, glyph); + { + threads::MutexGuard g(m_lock); + m_pendingNodes.emplace_back(r, glyph); + } auto res = m_index.emplace(uniChar, GlyphInfo(m_packer.MapTextureCoords(r), glyph.m_metrics)); ASSERT(res.second, ()); @@ -109,15 +115,21 @@ void GlyphIndex::UploadResources(RefPointer texture) if (m_pendingNodes.empty()) return; + TPendingNodes pendingNodes; + { + threads::MutexGuard g(m_lock); + m_pendingNodes.swap(pendingNodes); + } + buffer_vector ranges; buffer_vector maxHeights; ranges.push_back(0); - uint32_t maxHeight = m_pendingNodes[0].first.SizeY(); - for (size_t i = 1; i < m_pendingNodes.size(); ++i) + uint32_t maxHeight = pendingNodes[0].first.SizeY(); + for (size_t i = 1; i < pendingNodes.size(); ++i) { - TPendingNode const & prevNode = m_pendingNodes[i - 1]; + TPendingNode const & prevNode = pendingNodes[i - 1]; maxHeight = max(maxHeight, prevNode.first.SizeY()); - TPendingNode const & currentNode = m_pendingNodes[i]; + TPendingNode const & currentNode = pendingNodes[i]; if (ranges.size() < 2 && prevNode.first.minY() < currentNode.first.minY()) { ranges.push_back(i); @@ -126,7 +138,7 @@ void GlyphIndex::UploadResources(RefPointer texture) } } maxHeights.push_back(maxHeight); - ranges.push_back(m_pendingNodes.size()); + ranges.push_back(pendingNodes.size()); ASSERT(maxHeights.size() < 3, ()); ASSERT(ranges.size() < 4, ()); @@ -136,17 +148,17 @@ void GlyphIndex::UploadResources(RefPointer texture) size_t startIndex = ranges[i - 1]; size_t endIndex = ranges[i]; uint32_t height = maxHeights[i - 1]; - uint32_t width = m_pendingNodes[endIndex - 1].first.maxX() - m_pendingNodes[startIndex].first.minX(); + uint32_t width = pendingNodes[endIndex - 1].first.maxX() - pendingNodes[startIndex].first.minX(); uint32_t byteCount = my::NextPowOf2(height * width); - m2::PointU zeroPoint = m_pendingNodes[startIndex].first.LeftBottom(); + m2::PointU zeroPoint = pendingNodes[startIndex].first.LeftBottom(); SharedBufferManager::shared_buffer_ptr_t buffer = SharedBufferManager::instance().reserveSharedBuffer(byteCount); uint8_t * dstMemory = SharedBufferManager::GetRawPointer(buffer); view_t dstView = interleaved_view(width, height, (pixel_t *)dstMemory, width); for (size_t node = startIndex; node < endIndex; ++node) { - GlyphManager::Glyph & glyph = m_pendingNodes[node].second; - m2::RectU rect = m_pendingNodes[node].first; + GlyphManager::Glyph & glyph = pendingNodes[node].second; + m2::RectU rect = pendingNodes[node].first; if (rect.SizeX() == 0 || rect.SizeY() == 0) continue; @@ -169,8 +181,6 @@ void GlyphIndex::UploadResources(RefPointer texture) texture->UploadData(zeroPoint.x, zeroPoint.y, width, height, dp::ALPHA, MakeStackRefPointer(dstMemory)); SharedBufferManager::instance().freeSharedBuffer(byteCount, buffer); } - - m_pendingNodes.clear(); } } // namespace dp diff --git a/drape/font_texture.hpp b/drape/font_texture.hpp index 633920c924..e67eedb9b1 100644 --- a/drape/font_texture.hpp +++ b/drape/font_texture.hpp @@ -63,7 +63,7 @@ public: GlyphIndex(m2::PointU size, RefPointer mng); /// can return nullptr - RefPointer MapResource(GlyphKey const & key); + RefPointer MapResource(GlyphKey const & key, bool & newResource); void UploadResources(RefPointer texture); glConst GetMinFilter() const { return gl_const::GLLinear; } @@ -79,6 +79,7 @@ private: TResourceMapping m_index; TPendingNodes m_pendingNodes; + threads::Mutex m_lock; }; class FontTexture : public DynamicTexture diff --git a/drape/stipple_pen_resource.cpp b/drape/stipple_pen_resource.cpp index dd41e0b637..c2540aa084 100644 --- a/drape/stipple_pen_resource.cpp +++ b/drape/stipple_pen_resource.cpp @@ -138,16 +138,22 @@ void StipplePenRasterizator::Rasterize(void * buffer) memcpy(pixels + COLUMN_WIDTH, pixels, COLUMN_WIDTH); } -RefPointer StipplePenIndex::MapResource(StipplePenKey const & key) +RefPointer StipplePenIndex::MapResource(StipplePenKey const & key, bool & newResource) { + newResource = false; StipplePenHandle handle(key); TResourceMapping::iterator it = m_resourceMapping.find(handle); if (it != m_resourceMapping.end()) return MakeStackRefPointer(&it->second); + newResource = true; + StipplePenRasterizator resource(key); m2::RectU pixelRect = m_packer.PackResource(resource.GetSize()); - m_pendingNodes.push_back(make_pair(pixelRect, resource)); + { + threads::MutexGuard g(m_lock); + m_pendingNodes.push_back(make_pair(pixelRect, resource)); + } auto res = m_resourceMapping.emplace(handle, StipplePenResourceInfo(m_packer.MapTextureCoords(pixelRect), resource.GetSize(), @@ -162,18 +168,24 @@ void StipplePenIndex::UploadResources(RefPointer texture) if (m_pendingNodes.empty()) return; + TPendingNodes pendingNodes; + { + threads::MutexGuard g(m_lock); + m_pendingNodes.swap(pendingNodes); + } + buffer_vector ranges; ranges.push_back(0); - uint32_t xOffset = m_pendingNodes[0].first.minX(); - for (size_t i = 1; i < m_pendingNodes.size(); ++i) + uint32_t xOffset = pendingNodes[0].first.minX(); + for (size_t i = 1; i < pendingNodes.size(); ++i) { - m2::RectU & node = m_pendingNodes[i].first; + m2::RectU & node = pendingNodes[i].first; #ifdef DEBUG ASSERT(xOffset <= node.minX(), ()); if (xOffset == node.minX()) { - m2::RectU const & prevNode = m_pendingNodes[i - 1].first; + m2::RectU const & prevNode = pendingNodes[i - 1].first; ASSERT(prevNode.minY() < node.minY(), ()); } #endif @@ -182,7 +194,7 @@ void StipplePenIndex::UploadResources(RefPointer texture) xOffset = node.minX(); } - ranges.push_back(m_pendingNodes.size()); + ranges.push_back(pendingNodes.size()); SharedBufferManager & mng = SharedBufferManager::instance(); for (size_t i = 1; i < ranges.size(); ++i) @@ -199,17 +211,17 @@ void StipplePenIndex::UploadResources(RefPointer texture) uint8_t * rawBuffer = SharedBufferManager::GetRawPointer(ptr); memset(rawBuffer, 0, reserveBufferSize); - m2::RectU const & startNode = m_pendingNodes[rangeStart].first; + m2::RectU const & startNode = pendingNodes[rangeStart].first; uint32_t minX = startNode.minX(); uint32_t minY = startNode.minY(); #ifdef DEBUG - m2::RectU const & endNode = m_pendingNodes[rangeEnd - 1].first; + m2::RectU const & endNode = pendingNodes[rangeEnd - 1].first; ASSERT(endNode.maxY() == (minY + lineCount), ()); #endif for (size_t r = rangeStart; r < rangeEnd; ++r) { - m_pendingNodes[r].second.Rasterize(rawBuffer); + pendingNodes[r].second.Rasterize(rawBuffer); rawBuffer += 2 * COLUMN_WIDTH; } @@ -219,8 +231,6 @@ void StipplePenIndex::UploadResources(RefPointer texture) mng.freeSharedBuffer(reserveBufferSize, ptr); } - - m_pendingNodes.clear(); } glConst StipplePenIndex::GetMinFilter() const diff --git a/drape/stipple_pen_resource.hpp b/drape/stipple_pen_resource.hpp index e976bc0a9e..823b50838e 100644 --- a/drape/stipple_pen_resource.hpp +++ b/drape/stipple_pen_resource.hpp @@ -98,7 +98,7 @@ class StipplePenIndex { public: StipplePenIndex(m2::PointU const & canvasSize) : m_packer(canvasSize) {} - RefPointer MapResource(StipplePenKey const & key); + RefPointer MapResource(StipplePenKey const & key, bool & newResource); void UploadResources(RefPointer texture); glConst GetMinFilter() const; glConst GetMagFilter() const; @@ -111,6 +111,8 @@ private: TResourceMapping m_resourceMapping; TPendingNodes m_pendingNodes; StipplePenPacker m_packer; + + threads::Mutex m_lock; }; string DebugPrint(StipplePenHandle const & key); diff --git a/drape/symbols_texture.cpp b/drape/symbols_texture.cpp index f8f2434c86..4056400781 100644 --- a/drape/symbols_texture.cpp +++ b/drape/symbols_texture.cpp @@ -161,8 +161,9 @@ void SymbolsTexture::Load(string const & skinPathName) stbi_image_free(data); } -RefPointer SymbolsTexture::FindResource(Texture::Key const & key) const +RefPointer SymbolsTexture::FindResource(Texture::Key const & key, bool & newResource) { + newResource = false; if (key.GetType() != Texture::Symbol) return RefPointer(); diff --git a/drape/symbols_texture.hpp b/drape/symbols_texture.hpp index c2c80c06d4..d622861ccc 100644 --- a/drape/symbols_texture.hpp +++ b/drape/symbols_texture.hpp @@ -30,7 +30,7 @@ public: }; void Load(string const & skinPathName); - RefPointer FindResource(Key const & key) const; + RefPointer FindResource(Key const & key, bool & newResource); private: void Fail(); diff --git a/drape/texture.hpp b/drape/texture.hpp index f780902237..25a5f9c43d 100644 --- a/drape/texture.hpp +++ b/drape/texture.hpp @@ -55,7 +55,7 @@ public: void UploadData(uint32_t x, uint32_t y, uint32_t width, uint32_t height, TextureFormat format, RefPointer data); - virtual RefPointer FindResource(Key const & key) const = 0; + virtual RefPointer FindResource(Key const & key, bool & newResource) = 0; virtual void UpdateState() {} TextureFormat GetFormat() const; diff --git a/drape/texture_manager.cpp b/drape/texture_manager.cpp index e30deb3c85..bc5733f67c 100644 --- a/drape/texture_manager.cpp +++ b/drape/texture_manager.cpp @@ -101,6 +101,10 @@ uint32_t TextureManager::StippleRegion::GetPatternPixelLength() const void TextureManager::UpdateDynamicTextures() { + if (!m_hasPendingUpdates) + return; + + m_hasPendingUpdates = false; m_colorTexture->UpdateState(); m_stipplePenTexture->UpdateState(); for_each(m_glyphGroups.begin(), m_glyphGroups.end(), [](GlyphGroup & g) @@ -120,6 +124,15 @@ void TextureManager::AllocateGlyphTexture(TextureManager::GlyphGroup & group) co group.m_texture.Reset(new FontTexture(m2::PointU(m_maxTextureSize, m_maxTextureSize), m_glyphManager.GetRefPointer())); } +void TextureManager::GetRegionBase(RefPointer tex, TextureManager::BaseRegion & region, Texture::Key const & key) +{ + bool dummy = false; + region.SetResourceInfo(tex->FindResource(key, dummy)); + region.SetTexture(tex); + ASSERT(region.IsValid(), ()); + m_hasPendingUpdates |= dummy; +} + void TextureManager::Init(Params const & params) { GLFunctions::glPixelStore(gl_const::GLUnpackAlignment, 1); @@ -131,7 +144,7 @@ void TextureManager::Init(Params const & params) m_colorTexture.Reset(new ColorTexture(m2::PointU(COLOR_TEXTURE_SIZE, COLOR_TEXTURE_SIZE))); m_glyphManager.Reset(new GlyphManager(params.m_glyphMngParams)); - m_maxTextureSize = GLFunctions::glGetInteger(gl_const::GLMaxTextureSize); + m_maxTextureSize = min(2048, GLFunctions::glGetInteger(gl_const::GLMaxTextureSize)); uint32_t const textureSquare = m_maxTextureSize * m_maxTextureSize; uint32_t const baseGlyphHeight = params.m_glyphMngParams.m_baseGlyphHeight; @@ -171,28 +184,22 @@ void TextureManager::Release() DeleteRange(m_hybridGlyphGroups, MasterPointerDeleter()); } -void TextureManager::GetSymbolRegion(string const & symbolName, SymbolRegion & region) const +void TextureManager::GetSymbolRegion(string const & symbolName, SymbolRegion & region) { - region.SetResourceInfo(m_symbolTexture->FindResource(SymbolsTexture::SymbolKey(symbolName))); - region.SetTexture(m_symbolTexture.GetRefPointer()); - ASSERT(region.IsValid(), ()); + GetRegionBase(m_symbolTexture.GetRefPointer(), region, SymbolsTexture::SymbolKey(symbolName)); } -void TextureManager::GetStippleRegion(TStipplePattern const & pen, StippleRegion & region) const +void TextureManager::GetStippleRegion(TStipplePattern const & pen, StippleRegion & region) { - region.SetResourceInfo(m_stipplePenTexture->FindResource(StipplePenKey(pen))); - region.SetTexture(m_stipplePenTexture.GetRefPointer()); - ASSERT(region.IsValid(), ()); + GetRegionBase(m_stipplePenTexture.GetRefPointer(), region, StipplePenKey(pen)); } -void TextureManager::GetColorRegion(Color const & color, ColorRegion & region) const +void TextureManager::GetColorRegion(Color const & color, ColorRegion & region) { - region.SetResourceInfo(m_colorTexture->FindResource(ColorKey(color))); - region.SetTexture(m_colorTexture.GetRefPointer()); - ASSERT(region.IsValid(), ()); + GetRegionBase(m_colorTexture.GetRefPointer(), region, ColorKey(color)); } -void TextureManager::GetGlyphRegions(strings::UniString const & text, TGlyphsBuffer & regions) const +void TextureManager::GetGlyphRegions(strings::UniString const & text, TGlyphsBuffer & regions) { size_t const INVALID_GROUP = static_cast(-1); size_t groupIndex = INVALID_GROUP; @@ -228,8 +235,7 @@ void TextureManager::GetGlyphRegions(strings::UniString const & text, TGlyphsBuf for (strings::UniChar const & c : text) { GlyphRegion reg; - reg.SetResourceInfo(texture->FindResource(GlyphKey(c))); - reg.SetTexture(texture); + GetRegionBase(texture, reg, GlyphKey(c)); regions.push_back(reg); } } diff --git a/drape/texture_manager.hpp b/drape/texture_manager.hpp index 68a41b39f7..798212a9b2 100644 --- a/drape/texture_manager.hpp +++ b/drape/texture_manager.hpp @@ -66,13 +66,18 @@ public: void Init(Params const & params); void Release(); - void GetSymbolRegion(string const & symbolName, SymbolRegion & region) const; + void GetSymbolRegion(string const & symbolName, SymbolRegion & region); + typedef buffer_vector TStipplePattern; - void GetStippleRegion(TStipplePattern const & pen, StippleRegion & region) const; - void GetColorRegion(Color const & color, ColorRegion & region) const; + void GetStippleRegion(TStipplePattern const & pen, StippleRegion & region); + void GetColorRegion(Color const & color, ColorRegion & region); typedef buffer_vector TGlyphsBuffer; - void GetGlyphRegions(strings::UniString const & text, TGlyphsBuffer & regions) const; + void GetGlyphRegions(strings::UniString const & text, TGlyphsBuffer & regions); + + /// On some devices OpenGL driver can't resolve situation when we upload on texture from on thread + /// and use this texture to render on other thread. By this we move UpdateDynamicTextures call into render thread + /// If you implement some kind of dynamic texture, you must synchronyze UploadData and index creation operations void UpdateDynamicTextures(); private: @@ -91,6 +96,7 @@ private: uint32_t m_maxTextureSize; void AllocateGlyphTexture(TextureManager::GlyphGroup & group) const; + void GetRegionBase(RefPointer tex, TextureManager::BaseRegion & region, Texture::Key const & key); private: MasterPointer m_symbolTexture; @@ -99,8 +105,10 @@ private: MasterPointer m_glyphManager; - mutable buffer_vector m_glyphGroups; - mutable buffer_vector, 4> m_hybridGlyphGroups; + buffer_vector m_glyphGroups; + buffer_vector, 4> m_hybridGlyphGroups; + + volatile bool m_hasPendingUpdates = false; }; } // namespace dp diff --git a/drape/texture_of_colors.cpp b/drape/texture_of_colors.cpp index fe290f1668..c1a99077e7 100644 --- a/drape/texture_of_colors.cpp +++ b/drape/texture_of_colors.cpp @@ -20,16 +20,20 @@ ColorPalette::ColorPalette(m2::PointU const & canvasSize) , m_cursor(m2::PointU::Zero()) {} -RefPointer ColorPalette::MapResource(ColorKey const & key) +RefPointer ColorPalette::MapResource(ColorKey const & key, bool & newResource) { TPalette::iterator itm = m_palette.find(key.m_color); - if (itm == m_palette.end()) + newResource = itm == m_palette.end(); + if (newResource) { PendingColor pendingColor; pendingColor.m_color = key.m_color; pendingColor.m_rect = m2::RectU(m_cursor.x, m_cursor.y, m_cursor.x + RESOURCE_SIZE, m_cursor.y + RESOURCE_SIZE); - m_pendingNodes.push_back(pendingColor); + { + threads::MutexGuard g(m_lock); + m_pendingNodes.push_back(pendingColor); + } m_cursor.x += RESOURCE_SIZE; if (m_cursor.x >= m_textureSize.x) @@ -58,13 +62,19 @@ void ColorPalette::UploadResources(RefPointer texture) if (m_pendingNodes.empty()) return; + buffer_vector pendingNodes; + { + threads::MutexGuard g(m_lock); + m_pendingNodes.swap(pendingNodes); + } + buffer_vector ranges; ranges.push_back(0); - uint32_t minX = m_pendingNodes[0].m_rect.minX(); - for (size_t i = 0; i < m_pendingNodes.size(); ++i) + uint32_t minX = pendingNodes[0].m_rect.minX(); + for (size_t i = 0; i < pendingNodes.size(); ++i) { - m2::RectU const & currentRect = m_pendingNodes[i].m_rect; + m2::RectU const & currentRect = pendingNodes[i].m_rect; if (minX > currentRect.minX()) { ranges.push_back(i); @@ -72,15 +82,15 @@ void ColorPalette::UploadResources(RefPointer texture) } } - ranges.push_back(m_pendingNodes.size()); + ranges.push_back(pendingNodes.size()); for (size_t i = 1; i < ranges.size(); ++i) { size_t startRange = ranges[i - 1]; size_t endRange = ranges[i]; - m2::RectU const & startRect = m_pendingNodes[startRange].m_rect; - m2::RectU const & endRect = m_pendingNodes[endRange - 1].m_rect; + m2::RectU const & startRect = pendingNodes[startRange].m_rect; + m2::RectU const & endRect = pendingNodes[endRange - 1].m_rect; m2::RectU uploadRect; if (startRect.minY() == endRect.minY() && @@ -106,7 +116,7 @@ void ColorPalette::UploadResources(RefPointer texture) for (size_t j = startRange; j < endRange; ++j) { ASSERT(pointer < SharedBufferManager::GetRawPointer(buffer) + byteCount, ()); - PendingColor const & c = m_pendingNodes[j]; + PendingColor const & c = pendingNodes[j]; if (c.m_rect.minY() > currentY) { pointer += BYTES_PER_PIXEL * pixelStride; @@ -136,8 +146,6 @@ void ColorPalette::UploadResources(RefPointer texture) texture->UploadData(uploadRect.minX(), uploadRect.minY(), uploadRect.SizeX(), uploadRect.SizeY(), dp::RGBA8, dp::MakeStackRefPointer(pointer)); } - - m_pendingNodes.clear(); } glConst ColorPalette::GetMinFilter() const diff --git a/drape/texture_of_colors.hpp b/drape/texture_of_colors.hpp index e96884add7..7e130bbc1b 100644 --- a/drape/texture_of_colors.hpp +++ b/drape/texture_of_colors.hpp @@ -5,6 +5,7 @@ #include "drape/dynamic_texture.hpp" #include "base/buffer_vector.hpp" +#include "base/mutex.hpp" namespace dp { @@ -30,7 +31,7 @@ class ColorPalette public: ColorPalette(m2::PointU const & canvasSize); - RefPointer MapResource(ColorKey const & key); + RefPointer MapResource(ColorKey const & key, bool & newResource); void UploadResources(RefPointer texture); glConst GetMinFilter() const; glConst GetMagFilter() const; @@ -54,6 +55,7 @@ private: m2::PointU m_textureSize; m2::PointU m_cursor; bool m_isDebug = false; + threads::Mutex m_lock; }; class ColorTexture : public DynamicTexture diff --git a/drape_frontend/backend_renderer.cpp b/drape_frontend/backend_renderer.cpp index 6ccaf37ace..b44cbf3930 100644 --- a/drape_frontend/backend_renderer.cpp +++ b/drape_frontend/backend_renderer.cpp @@ -13,6 +13,8 @@ #include "platform/platform.hpp" +#include "base/logging.hpp" + #include "std/bind.hpp" namespace df @@ -20,12 +22,13 @@ namespace df BackendRenderer::BackendRenderer(dp::RefPointer commutator, dp::RefPointer oglcontextfactory, + dp::RefPointer textureManager, MapDataProvider const & model) : m_model(model) , m_engineContext(commutator) , m_commutator(commutator) , m_contextFactory(oglcontextfactory) - , m_textures(new dp::TextureManager()) + , m_texturesManager(textureManager) { m_commutator->RegisterThread(ThreadsCommutator::ResourceUploadThread, this); m_batchersPool.Reset(new BatchersPool(ReadManager::ReadCount(), bind(&BackendRenderer::FlushGeometry, this, _1))); @@ -71,7 +74,7 @@ void BackendRenderer::AcceptMessage(dp::RefPointer message) MapShapeReadedMessage * msg = df::CastMessage(message); dp::RefPointer batcher = m_batchersPool->GetTileBatcher(msg->GetKey()); dp::MasterPointer shape(msg->GetShape()); - shape->Draw(batcher, m_textures.GetRefPointer()); + shape->Draw(batcher, m_texturesManager); shape.Destroy(); break; @@ -84,7 +87,7 @@ void BackendRenderer::AcceptMessage(dp::RefPointer message) UserMarksProvider const * marksProvider = msg->StartProcess(); if (marksProvider->IsDirty()) - CacheUserMarks(marksProvider, m_batchersPool->GetTileBatcher(key), m_textures.GetRefPointer()); + CacheUserMarks(marksProvider, m_batchersPool->GetTileBatcher(key), m_texturesManager); msg->EndProcess(); m_batchersPool->ReleaseBatcher(key); break; @@ -117,8 +120,7 @@ void BackendRenderer::ReleaseResources() m_readManager.Destroy(); m_batchersPool.Destroy(); - m_textures->Release(); - m_textures.Destroy(); + m_texturesManager->Release(); } BackendRenderer::Routine::Routine(BackendRenderer & renderer) : m_renderer(renderer) {} @@ -143,13 +145,11 @@ void BackendRenderer::InitGLDependentResource() params.m_glyphMngParams.m_blacklist = "fonts_blacklist.txt"; GetPlatform().GetFontNames(params.m_glyphMngParams.m_fonts); - m_textures->Init(params); + m_texturesManager->Init(params); } void BackendRenderer::FlushGeometry(dp::TransferPointer message) { - m_textures->UpdateDynamicTextures(); - GLFunctions::glFlush(); m_commutator->PostMessage(ThreadsCommutator::RenderThread, message); } diff --git a/drape_frontend/backend_renderer.hpp b/drape_frontend/backend_renderer.hpp index 2ec608a8c1..1678c3ec81 100644 --- a/drape_frontend/backend_renderer.hpp +++ b/drape_frontend/backend_renderer.hpp @@ -30,6 +30,7 @@ class BackendRenderer : public MessageAcceptor public: BackendRenderer(dp::RefPointer commutator, dp::RefPointer oglcontextfactory, + dp::RefPointer textureManager, MapDataProvider const & model); ~BackendRenderer() override; @@ -74,7 +75,7 @@ private: dp::RefPointer m_commutator; dp::RefPointer m_contextFactory; - dp::MasterPointer m_textures; + dp::RefPointer m_texturesManager; }; } // namespace df diff --git a/drape_frontend/drape_engine.cpp b/drape_frontend/drape_engine.cpp index 283e714b66..15b2296bf6 100644 --- a/drape_frontend/drape_engine.cpp +++ b/drape_frontend/drape_engine.cpp @@ -18,14 +18,17 @@ DrapeEngine::DrapeEngine(dp::RefPointer contextfactory, { VisualParams::Init(vs, df::CalculateTileSize(m_viewport.GetWidth(), m_viewport.GetHeight())); + m_textureManager = dp::MasterPointer(new dp::TextureManager()); m_threadCommutator = dp::MasterPointer(new ThreadsCommutator()); dp::RefPointer commutatorRef = m_threadCommutator.GetRefPointer(); m_frontend = dp::MasterPointer(new FrontendRenderer(commutatorRef, contextfactory, + m_textureManager.GetRefPointer(), m_viewport)); m_backend = dp::MasterPointer(new BackendRenderer(commutatorRef, contextfactory, + m_textureManager.GetRefPointer(), model)); } @@ -34,6 +37,7 @@ DrapeEngine::~DrapeEngine() m_frontend.Destroy(); m_backend.Destroy(); m_threadCommutator.Destroy(); + m_textureManager.Destroy(); } void DrapeEngine::Resize(int w, int h) diff --git a/drape_frontend/drape_engine.hpp b/drape_frontend/drape_engine.hpp index 0b9d735a1d..9c1d041733 100644 --- a/drape_frontend/drape_engine.hpp +++ b/drape_frontend/drape_engine.hpp @@ -38,6 +38,7 @@ private: dp::MasterPointer m_frontend; dp::MasterPointer m_backend; dp::MasterPointer m_threadCommutator; + dp::MasterPointer m_textureManager; Viewport m_viewport; }; diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 284169ef8b..5c2d77e4e2 100644 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -3,12 +3,14 @@ #include "drape_frontend/visual_params.hpp" #include "drape_frontend/user_mark_shapes.hpp" +#include "drape/utils/gpu_mem_tracker.hpp" #include "drape/utils/projection.hpp" #include "geometry/any_rect2d.hpp" #include "base/timer.hpp" #include "base/assert.hpp" +#include "base/logging.hpp" #include "base/stl_add.hpp" #include "std/bind.hpp" @@ -32,9 +34,11 @@ const double VSyncInterval = 0.014; FrontendRenderer::FrontendRenderer(dp::RefPointer commutator, dp::RefPointer oglcontextfactory, + dp::RefPointer textureManager, Viewport viewport) : m_commutator(commutator) , m_contextFactory(oglcontextfactory) + , m_textureManager(textureManager) , m_gpuProgramManager(new dp::GpuProgramManager()) , m_viewport(viewport) { @@ -78,6 +82,11 @@ void FrontendRenderer::AfterDrawFrame() LOG(LINFO, ("Average Fps : ", m_fps)); LOG(LINFO, ("Average Tpf : ", m_tpf)); + +#if defined(TRACK_GPU_MEM) + string report = dp::GPUMemTracker::Inst().Report(); + LOG(LINFO, (report)); +#endif } } #endif @@ -198,7 +207,6 @@ void FrontendRenderer::AcceptMessage(dp::RefPointer message) group->SetIsVisible(m->IsVisible()); break; } - default: ASSERT(false, ()); } @@ -244,13 +252,6 @@ void FrontendRenderer::RenderScene() m_renderGroups.resize(m_renderGroups.size() - eraseCount); m_viewport.Apply(); - GLFunctions::glEnable(gl_const::GLDepthTest); - - GLFunctions::glClearColor(0.93f, 0.93f, 0.86f, 1.f); - GLFunctions::glClearDepthValue(1.0); - GLFunctions::glDepthFunc(gl_const::GLLessOrEqual); - GLFunctions::glDepthMask(true); - GLFunctions::glClear(); dp::GLState::DepthLayer prevLayer = dp::GLState::GeometryLayer; @@ -387,6 +388,14 @@ void FrontendRenderer::Routine::Do() context->makeCurrent(); GLFunctions::Init(); + GLFunctions::glPixelStore(gl_const::GLUnpackAlignment, 1); + GLFunctions::glEnable(gl_const::GLDepthTest); + + GLFunctions::glClearColor(0.93f, 0.93f, 0.86f, 1.f); + GLFunctions::glClearDepthValue(1.0); + GLFunctions::glDepthFunc(gl_const::GLLessOrEqual); + GLFunctions::glDepthMask(true); + my::Timer timer; //double processingTime = InitAvarageTimePerMessage; // By init we think that one message processed by 1ms @@ -394,6 +403,7 @@ void FrontendRenderer::Routine::Do() while (!IsCancelled()) { context->setDefaultFramebuffer(); + m_textureManager->UpdateDynamicTextures(); m_renderer.RenderScene(); double availableTime = VSyncInterval - (timer.ElapsedSeconds() /*+ avarageMessageTime*/); diff --git a/drape_frontend/frontend_renderer.hpp b/drape_frontend/frontend_renderer.hpp index 0979d1d34c..6c88a2a2bb 100644 --- a/drape_frontend/frontend_renderer.hpp +++ b/drape_frontend/frontend_renderer.hpp @@ -37,6 +37,7 @@ class FrontendRenderer : public MessageAcceptor public: FrontendRenderer(dp::RefPointer commutator, dp::RefPointer oglcontextfactory, + dp::RefPointer textureManager, Viewport viewport); ~FrontendRenderer() override; @@ -93,6 +94,8 @@ private: private: dp::RefPointer m_commutator; dp::RefPointer m_contextFactory; + dp::RefPointer m_textureManager; + dp::MasterPointer m_gpuProgramManager; threads::Thread m_selfThread;