Grok 20.3.2
TileCache.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016-2026 Grok Image Compression Inc.
3 *
4 * This source code is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Affero General Public License, version 3,
6 * as published by the Free Software Foundation.
7 *
8 * This source code is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU Affero General Public License for more details.
12 *
13 * You should have received a copy of the GNU Affero General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 */
17
18#pragma once
19
20#include <vector>
21#include <list>
22#include <algorithm>
23
24namespace grk
25{
26
48{
49 explicit TileCacheEntry(ITileProcessor* p) : processor(p), dirty_(true) {}
52 {
53 delete processor;
54 }
55
58 bool dirty_;
59};
60
108{
109public:
111
113 {
114 for(auto* entry : cache_)
115 {
116 delete entry;
117 }
118 }
119
120 void init(uint16_t numTiles)
121 {
122 if(initialized_)
123 {
124 return; // Prevent reinitialization
125 }
126 initialized_ = true;
127
128 // Initialize cache array with nullptrs
129 cache_.resize(numTiles, nullptr);
130 }
131
132 bool empty() const
133 {
134 return cache_.empty();
135 }
136
137 void setStrategy(uint32_t strategy)
138 {
139 strategy_ = strategy;
140 }
141
142 uint32_t getStrategy() const
143 {
144 return strategy_;
145 }
146
151 void setMaxActiveTiles(uint16_t maxActive)
152 {
153 maxActiveTiles_ = maxActive;
154 }
155
156 uint16_t getMaxActiveTiles() const
157 {
158 return maxActiveTiles_;
159 }
160
161 void setTruncated(void)
162 {
163 for(auto* entry : cache_)
164 {
165 if(!entry || !entry->processor)
166 continue;
167 entry->processor->setTruncated();
168 }
169 }
170
171 void setDirty(bool dirty)
172 {
173 for(auto* entry : cache_)
174 {
175 if(!entry)
176 continue;
177 entry->dirty_ = dirty;
178 }
179 }
180
181 void setDirty(uint16_t tileIndex, bool dirty)
182 {
183 if(tileIndex >= cache_.size())
184 return;
185 if(cache_[tileIndex])
186 {
187 cache_[tileIndex]->dirty_ = dirty;
188 }
189 }
190
191 bool isDirty(uint16_t tileIndex)
192 {
193 if(tileIndex >= cache_.size())
194 return false;
195 return cache_[tileIndex] ? cache_[tileIndex]->dirty_ : false;
196 }
197
198 TileCacheEntry* put(uint16_t tile_index, ITileProcessor* processor)
199 {
200 if(tile_index >= cache_.size())
201 {
202 delete processor;
203 grklog.warn("Failed to put tile processor for tile %d because tile index is out of bounds",
204 tile_index);
205 return nullptr;
206 }
207 if(!cache_[tile_index])
208 {
209 cache_[tile_index] = new TileCacheEntry(processor);
210 }
211 else
212 {
213 if(cache_[tile_index]->processor)
214 delete cache_[tile_index]->processor;
215 cache_[tile_index]->processor = processor;
216 }
217
218 // LRU: promote this tile and evict if over limit
219 promoteLRU(tile_index);
220 evictLRU();
221
222 return cache_[tile_index];
223 }
224
225 TileCacheEntry* get(uint16_t tile_index)
226 {
227 if(tile_index >= cache_.size())
228 return nullptr;
229
230 // LRU: promote on access
231 if(cache_[tile_index] && cache_[tile_index]->processor)
232 promoteLRU(tile_index);
233
234 return cache_[tile_index];
235 }
236
237 void release(uint16_t tileIndex)
238 {
239 if(cache_[tileIndex] && cache_[tileIndex]->processor)
240 cache_[tileIndex]->processor->release(strategy_);
241 }
242
250 void releaseForSwath(uint16_t tileIndex)
251 {
252 if(tileIndex >= cache_.size())
253 return;
254 if(cache_[tileIndex] && cache_[tileIndex]->processor)
255 cache_[tileIndex]->processor->releaseForSwath();
256 }
257
259 {
260 for(auto* entry : cache_)
261 {
262 if(!entry || !entry->processor)
263 continue;
264 // Skip tiles that are already decompressed or have cached SOT info
265 if(entry->processor->isBestEffortDecompressed() || entry->processor->getImage())
266 continue;
267 entry->processor->resetSOTParsing();
268 }
269 }
270
271 bool allSlatedSOTMarkersParsed(const std::set<uint16_t>& tilesSlatedForDecompression)
272 {
273 return std::all_of(tilesSlatedForDecompression.begin(), tilesSlatedForDecompression.end(),
274 [this](uint16_t tileId) {
275 if(tileId >= cache_.size())
276 return false;
277 auto* entry = cache_[tileId];
278 return entry && entry->processor &&
279 entry->processor->allSOTMarkersParsed();
280 });
281 }
282
284 {
285 if(!state.single_tile)
286 return false;
287
288 auto cached = get(state.tile_index);
289 if(!cached || !cached->processor)
290 return false;
291
292 uint16_t maxlayer = 0;
293 for(uint8_t r = 0; r < state.num_resolutions; ++r)
294 {
295 maxlayer = std::max(maxlayer, state.layers_per_resolution[r]);
296 }
297 if(maxlayer != cached->processor->getTCP()->layersToDecompress_)
298 {
299 cached->dirty_ = true;
300 cached->processor->getTCP()->layersToDecompress_ = maxlayer;
301 }
302
303 return true;
304 }
305
307 {
308 auto cached = get(tileIndex);
309 if(!cached)
310 return {};
311
312 return cached->processor->getProgressionState();
313 }
314
315private:
319 void promoteLRU(uint16_t tileIndex)
320 {
321 if(maxActiveTiles_ == 0)
322 return; // LRU disabled
323
324 // Remove existing entry if present
325 lruList_.remove(tileIndex);
326 lruList_.push_front(tileIndex);
327 }
328
335 void evictLRU()
336 {
337 if(maxActiveTiles_ == 0)
338 return; // LRU disabled
339
340 while(lruList_.size() > maxActiveTiles_)
341 {
342 uint16_t victim = lruList_.back();
343 lruList_.pop_back();
344
345 if(victim < cache_.size() && cache_[victim] && cache_[victim]->processor)
346 {
347 cache_[victim]->processor->release(GRK_TILE_CACHE_LRU);
348 }
349 }
350 }
351
352 std::vector<TileCacheEntry*> cache_; // Array of cache entries
353 std::list<uint16_t> lruList_; // Front = MRU, back = LRU (tile indices with active data)
354 uint32_t strategy_; // Cache strategy
355 bool initialized_; // Flag to prevent reinitialization
356 uint16_t maxActiveTiles_; // Max tiles with decompressed data (0 = unlimited)
357};
358
359} // namespace grk
TileCacheEntry * put(uint16_t tile_index, ITileProcessor *processor)
Definition TileCache.h:198
void setTruncated(void)
Definition TileCache.h:161
std::vector< TileCacheEntry * > cache_
Definition TileCache.h:352
void evictLRU()
Evict least-recently-used tiles when over the active limit.
Definition TileCache.h:335
grk_progression_state getProgressionState(uint16_t tileIndex)
Definition TileCache.h:306
void setMaxActiveTiles(uint16_t maxActive)
Set the maximum number of tiles that can hold decompressed data simultaneously.
Definition TileCache.h:151
TileCache()
Definition TileCache.h:110
bool setProgressionState(grk_progression_state state)
Definition TileCache.h:283
uint32_t getStrategy() const
Definition TileCache.h:142
void setStrategy(uint32_t strategy)
Definition TileCache.h:137
bool allSlatedSOTMarkersParsed(const std::set< uint16_t > &tilesSlatedForDecompression)
Definition TileCache.h:271
bool isDirty(uint16_t tileIndex)
Definition TileCache.h:191
std::list< uint16_t > lruList_
Definition TileCache.h:353
void resetSOTParsing()
Definition TileCache.h:258
bool empty() const
Definition TileCache.h:132
~TileCache()
Definition TileCache.h:112
void init(uint16_t numTiles)
Definition TileCache.h:120
void setDirty(uint16_t tileIndex, bool dirty)
Definition TileCache.h:181
void releaseForSwath(uint16_t tileIndex)
Release tile data unconditionally (swath consumer path).
Definition TileCache.h:250
bool initialized_
Definition TileCache.h:355
void setDirty(bool dirty)
Definition TileCache.h:171
void release(uint16_t tileIndex)
Definition TileCache.h:237
uint16_t getMaxActiveTiles() const
Definition TileCache.h:156
uint16_t maxActiveTiles_
Definition TileCache.h:356
uint32_t strategy_
Definition TileCache.h:354
TileCacheEntry * get(uint16_t tile_index)
Definition TileCache.h:225
void promoteLRU(uint16_t tileIndex)
Move a tile to the front of the LRU list (most recently used).
Definition TileCache.h:319
#define GRK_TILE_CACHE_NONE
Grok tile cache strategy.
Definition grok.h:632
#define GRK_TILE_CACHE_LRU
Definition grok.h:635
ResWindow.
Definition CompressedChunkCache.h:36
ILogger & grklog
Definition Logger.cpp:24
Interface for managing tile compression/decompression.
Definition ITileProcessor.h:37
Stores a tile processor together with its cache state.
Definition TileCache.h:48
ITileProcessor * processor
Definition TileCache.h:56
TileCacheEntry(ITileProcessor *p)
Definition TileCache.h:49
~TileCacheEntry()
Definition TileCache.h:51
TileCacheEntry()
Definition TileCache.h:50
bool dirty_
True when the entry's decompressed image is stale or absent.
Definition TileCache.h:58
Stores progression state information Note: limited to 256 components.