@@ -1743,6 +1743,33 @@ bool CodeStreamDecompress::fetchByTile(
17431743 return true ;
17441744}
17451745
1746+ void CodeStreamDecompress::enqueueTileForDecompress (
1747+ uint16_t tileIndex, std::shared_ptr<TPFetchSeq> decompressSeq, uint16_t numTileCols,
1748+ Rect32 unreducedImageBounds,
1749+ std::function<std::function<void ()>(ITileProcessor*)> postGenerator)
1750+ {
1751+ if (compressedChunkCache_)
1752+ compressedChunkCache_->put (tileIndex, decompressSeq);
1753+
1754+ int32_t tileRow = tileIndex / numTileCols;
1755+ int32_t prev = maxFetchedTileRow_.load (std::memory_order_acquire);
1756+ while (prev < tileRow &&
1757+ !maxFetchedTileRow_.compare_exchange_weak (prev, tileRow, std::memory_order_release,
1758+ std::memory_order_acquire))
1759+ {
1760+ }
1761+ decompressQueue_->push (
1762+ [this , tileIndex, decompressSeq, unreducedImageBounds, postGenerator]() {
1763+ const auto tileProcessor = getTileProcessor (tileIndex);
1764+ auto * tp = dynamic_cast <TileProcessor*>(tileProcessor);
1765+ if (tp)
1766+ tp->setSelectiveFetch (true );
1767+ auto decompressTask = genDecompressTileTLMTask (tileProcessor, decompressSeq,
1768+ unreducedImageBounds, postGenerator);
1769+ decompressTask ();
1770+ });
1771+ }
1772+
17461773bool CodeStreamDecompress::fetchByTileSelective (
17471774 std::set<uint16_t >& slated, Rect32 unreducedImageBounds,
17481775 std::function<std::function<void ()>(ITileProcessor*)> postGenerator)
@@ -2039,7 +2066,17 @@ bool CodeStreamDecompress::fetchByTileSelective(
20392066 selectiveFetchTiles->insert (tileIndex);
20402067 }
20412068
2042- // Reuse Phase 1 data for tiles where all needed data fits within the header fetch
2069+ // Phase 1 data reuse: avoid re-fetching data that was already downloaded during the
2070+ // header probe. For small tiles or low target resolutions, the 4 KB header fetch often
2071+ // contains all the packets needed for the reduced decompress. In that case we build the
2072+ // decompression sequence directly from the Phase 1 buffer and skip the Phase 2 HTTP request.
2073+ //
2074+ // Two layouts are handled:
2075+ // - Contiguous (selParts count == tile-part count): each entry maps 1:1 to a tile-part
2076+ // buffer; we copy the prefix of the Phase 1 buffer.
2077+ // - Disjoint (selParts count > tile-part count, single tile-part only): entries reference
2078+ // different sub-ranges of one Phase 1 buffer; we assemble them into a single contiguous
2079+ // buffer identical to the Phase 2 disjoint callback output.
20432080 struct PrefetchedTile
20442081 {
20452082 uint16_t tileIndex;
@@ -2175,29 +2212,8 @@ bool CodeStreamDecompress::fetchByTileSelective(
21752212
21762213 // Queue pre-fetched tiles directly for decompression (reusing Phase 1 data)
21772214 for (auto & pf : prefetchedTiles)
2178- {
2179- if (compressedChunkCache_)
2180- compressedChunkCache_->put (pf.tileIndex , pf.decompressSeq );
2181-
2182- int32_t tileRow = pf.tileIndex / numTileCols;
2183- int32_t prev = maxFetchedTileRow_.load (std::memory_order_acquire);
2184- while (prev < tileRow &&
2185- !maxFetchedTileRow_.compare_exchange_weak (prev, tileRow, std::memory_order_release,
2186- std::memory_order_acquire))
2187- {
2188- }
2189- decompressQueue_->push (
2190- [this , tileIndex = pf.tileIndex , decompressSeq = pf.decompressSeq ,
2191- unreducedImageBounds, postGenerator]() {
2192- const auto tileProcessor = getTileProcessor (tileIndex);
2193- auto * tp = dynamic_cast <TileProcessor*>(tileProcessor);
2194- if (tp)
2195- tp->setSelectiveFetch (true );
2196- auto decompressTask = genDecompressTileTLMTask (tileProcessor, decompressSeq,
2197- unreducedImageBounds, postGenerator);
2198- decompressTask ();
2199- });
2200- }
2215+ enqueueTileForDecompress (pf.tileIndex , pf.decompressSeq , numTileCols, unreducedImageBounds,
2216+ postGenerator);
22012217
22022218 if (!selectiveFetchTiles->empty ())
22032219 {
@@ -2269,26 +2285,8 @@ bool CodeStreamDecompress::fetchByTileSelective(
22692285 decompressSeq = tilePartSeq;
22702286 }
22712287
2272- if (compressedChunkCache_)
2273- compressedChunkCache_->put (tileIndex, decompressSeq);
2274-
2275- int32_t tileRow = tileIndex / numTileCols;
2276- int32_t prev = maxFetchedTileRow_.load (std::memory_order_acquire);
2277- while (prev < tileRow &&
2278- !maxFetchedTileRow_.compare_exchange_weak (prev, tileRow, std::memory_order_release,
2279- std::memory_order_acquire))
2280- {
2281- }
2282- decompressQueue_->push (
2283- [this , tileIndex, decompressSeq, unreducedImageBounds, postGenerator]() {
2284- const auto tileProcessor = getTileProcessor (tileIndex);
2285- auto * tp = dynamic_cast <TileProcessor*>(tileProcessor);
2286- if (tp)
2287- tp->setSelectiveFetch (true );
2288- auto decompressTask = genDecompressTileTLMTask (tileProcessor, decompressSeq,
2289- unreducedImageBounds, postGenerator);
2290- decompressTask ();
2291- });
2288+ enqueueTileForDecompress (tileIndex, decompressSeq, numTileCols, unreducedImageBounds,
2289+ postGenerator);
22922290 }
22932291 }));
22942292 } // if(!selectiveFetchTiles->empty())
0 commit comments