From a479c84b9b749e2eaa9c19d862afc74673697272 Mon Sep 17 00:00:00 2001 From: Tim Sylvester Date: Fri, 5 Jan 2024 11:56:16 -0800 Subject: [PATCH] Stencil clear (#1994) --- src/mbgl/renderer/paint_parameters.cpp | 42 ++++++-------------------- 1 file changed, 10 insertions(+), 32 deletions(-) diff --git a/src/mbgl/renderer/paint_parameters.cpp b/src/mbgl/renderer/paint_parameters.cpp index cd9841da1..0e801a042 100644 --- a/src/mbgl/renderer/paint_parameters.cpp +++ b/src/mbgl/renderer/paint_parameters.cpp @@ -101,37 +101,12 @@ using GetTileIDFunc = const UnwrappedTileID& (*)(const typename TIter::value_typ using TileMaskIDMap = std::map; -// `std::includes` adapted to extract tile IDs from arbitrary collection iterators. -// This is needed because, although it accepts iterators of different types, they must be: -// "...such that an object of type InputIt can be dereferenced and then implicitly converted to both of them.​" -template -bool includes(I1 beg1, const I1 end1, I2 beg2, const I2 end2, const GetTileIDFunc& unwrap) { - for (; beg2 != end2; ++beg1) { - if (beg1 == end1) { - return false; - } - const auto id2 = unwrap(*beg2); - if (id2 < beg1->first) { - return false; - } else if (!(beg1->first < id2)) { - ++beg2; - } - } - return true; -} - -const UnwrappedTileID& unwrap(const RenderTiles::element_type::value_type& iter) { - return iter.get().id; -} - -// Check whether the given set of tile IDs is a subset of the ones already rendered +// Check whether we can reuse a clip mask for a new set of tiles bool tileIDsCovered(const RenderTiles& tiles, const TileMaskIDMap& idMap) { - if (idMap.size() < tiles->size()) { - return false; - } - assert(std::is_sorted( - tiles->begin(), tiles->end(), [=](const auto& a, const auto& b) { return unwrap(a) < unwrap(b); })); - return includes(idMap.cbegin(), idMap.cend(), tiles->cbegin(), tiles->cend(), &unwrap); + return idMap.size() == tiles->size() && + std::equal(idMap.cbegin(), idMap.cend(), tiles->cbegin(), tiles->cend(), [=](const auto& a, const auto& b) { + return a.first == b.get().id; + }); } } // namespace @@ -162,14 +137,17 @@ void PaintParameters::clearStencil() { } void PaintParameters::renderTileClippingMasks(const RenderTiles& renderTiles) { - // If the current stencil mask covers this source already, there's no need to draw another one. + // We can avoid updating the mask if it already contains the same set of tiles. if (!renderTiles || !renderPass || tileIDsCovered(renderTiles, tileClippingMaskIDs)) { return; } + tileClippingMaskIDs.clear(); + + // If the stencil value will overflow, clear the target to ensure ensure that none of the new + // values remain set somewhere in it. Otherwise we can continue to overwrite it incrementally. const auto count = renderTiles->size(); if (nextStencilID + count > maxStencilValue) { - // we'll run out of fresh IDs so we need to clear and start from scratch clearStencil(); }