3030
3131bool gShowTileLayout = false ;
3232
33+ #if defined(CONSERVE_MEMORY)
34+ bool gConserveMemory = true ;
35+ #else
36+ bool gConserveMemory = false ;
37+ #endif
38+
39+ static DWORD WINAPI RenderCacheThread (LPVOID data);
40+
3341RenderCache::RenderCache () : maxTileSize({GetSystemMetrics (SM_CXSCREEN), GetSystemMetrics (SM_CYSCREEN)}) {
3442 // enable when debugging RenderCache logic
3543 // gEnableDbgLog = true;
@@ -91,11 +99,13 @@ bool RenderCache::Exists(DisplayModel* dm, int pageNo, int rotation, float zoom,
9199}
92100
93101bool RenderCache::DropCacheEntry (BitmapCacheEntry* entry) {
94- ScopedCritSec scope (&cacheAccess);
95102 ReportIf (!entry);
96103 if (!entry) {
97104 return false ;
98105 }
106+
107+ // TODO: make the scope of this lock smaller?
108+ ScopedCritSec scope (&cacheAccess);
99109 int idx = entry->cacheIdx ;
100110 ReportIf (idx < 0 );
101111 ReportIf (idx >= cacheCount);
@@ -109,8 +119,8 @@ bool RenderCache::DropCacheEntry(BitmapCacheEntry* entry) {
109119 }
110120 ReportIf (entry->refs != 0 );
111121 ReportIf (cache[idx] != entry);
112- logf (" RenderCache::DropCacheEntry: pageNo: %d, rotation: %d, zoom: %.2f\n " , entry->pageNo , entry->rotation ,
113- entry->zoom );
122+ logf (" RenderCache::DropCacheEntry: dm: 0x%p pageNo: %d, rotation: %d, zoom: %.2f\n " , entry->dm , entry->pageNo ,
123+ entry->rotation , entry-> zoom );
114124
115125 delete entry;
116126
@@ -242,45 +252,58 @@ static bool IsTileVisible(DisplayModel* dm, int pageNo, TilePosition tile, float
242252 of the given DisplayModel, or even all invisible pages). */
243253void RenderCache::FreePage (DisplayModel* dm, int pageNo, TilePosition* tile) {
244254 logf (" RenderCache::FreePage: dm: 0x%p, pageNo: %d\n " , dm, pageNo);
255+ ReportIf (!dm || pageNo == kInvalidPageNo );
256+ if (!dm || pageNo == kInvalidPageNo ) {
257+ return ;
258+ }
245259 ScopedCritSec scope (&cacheAccess);
246260
247261 // must go from end becaues freeing changes the cache
248262 for (int i = cacheCount - 1 ; i >= 0 ; i--) {
249263 BitmapCacheEntry* entry = cache[i];
250- bool shouldFree;
251- if (dm && pageNo != kInvalidPageNo ) {
252- // a specific page
253- shouldFree = (entry->dm == dm) && (entry->pageNo == pageNo);
254- if (tile) {
255- // a given tile of the page or all tiles not rendered at a given resolution
256- // (and at resolution 0 for quick zoom previews)
257- shouldFree =
258- shouldFree && (entry->tile == *tile ||
259- tile->row == (USHORT)-1 && entry->tile .res > 0 && entry->tile .res != tile->res ||
260- tile->row == (USHORT)-1 && entry->tile .res == 0 && entry->outOfDate );
261- }
262- } else if (dm) {
263- // all pages of this DisplayModel
264- shouldFree = (entry->dm == dm);
265- } else {
266- // all invisible pages resp. page tiles
267- shouldFree = !entry->dm ->PageVisibleNearby (entry->pageNo );
268- if (!shouldFree && entry->tile .res > 1 ) {
269- shouldFree = !IsTileVisible (entry->dm , entry->pageNo , entry->tile , 2.0 );
270- }
264+ bool shouldFree = (entry->dm == dm) && (entry->pageNo == pageNo);
265+ if (!shouldFree && tile) {
266+ // a given tile of the page or all tiles not rendered at a given resolution
267+ // (and at resolution 0 for quick zoom previews)
268+ shouldFree = (entry->tile == *tile ||
269+ tile->row == (USHORT)-1 && entry->tile .res > 0 && entry->tile .res != tile->res ||
270+ tile->row == (USHORT)-1 && entry->tile .res == 0 && entry->outOfDate );
271271 }
272272 if (shouldFree) {
273273 DropCacheEntry (entry);
274274 }
275275 }
276276}
277277
278+ // free all cached pages of this DisplayModel
278279void RenderCache::FreeForDisplayModel (DisplayModel* dm) {
279- FreePage (dm);
280+ logf (" RenderCache::FreeForDisplayModel: dm=0x%p\n " , dm);
281+ ScopedCritSec scope (&cacheAccess);
282+ // must go from end becaues freeing changes the cache
283+ for (int i = cacheCount - 1 ; i >= 0 ; i--) {
284+ BitmapCacheEntry* entry = cache[i];
285+ bool shouldFree = (entry->dm == dm);
286+ if (shouldFree) {
287+ DropCacheEntry (entry);
288+ }
289+ }
280290}
281291
282292void RenderCache::FreeNotVisible () {
283- FreePage ();
293+ // logf("RenderCache::FreeNotVisible\n");
294+ ScopedCritSec scope (&cacheAccess);
295+ // must go from end becaues freeing changes the cache
296+ for (int i = cacheCount - 1 ; i >= 0 ; i--) {
297+ BitmapCacheEntry* entry = cache[i];
298+ // all invisible pages resp. page tiles
299+ bool shouldFree = !entry->dm ->PageVisibleNearby (entry->pageNo );
300+ if (!shouldFree && entry->tile .res > 1 ) {
301+ shouldFree = !IsTileVisible (entry->dm , entry->pageNo , entry->tile , 2.0 );
302+ }
303+ if (shouldFree) {
304+ DropCacheEntry (entry);
305+ }
306+ }
284307}
285308
286309// keep the cached bitmaps for visible pages to avoid flickering during a reload.
@@ -415,12 +438,12 @@ void RenderCache::RequestRendering(DisplayModel* dm, int pageNo) {
415438
416439/* Render a bitmap for page <pageNo> in <dm>. */
417440void RenderCache::RequestRendering (DisplayModel* dm, int pageNo, TilePosition tile, bool clearQueueForPage) {
418- logf (" RenderCache::RequestRendering(): pageNo %d\n " , pageNo);
419- ScopedCritSec scope (&requestAccess);
441+ logf (" RenderCache::RequestRendering: pageNo %d\n " , pageNo);
420442 ReportIf (!dm);
421- if (!dm || dm->dontRenderFlag ) {
443+ if (!dm || dm->pauseRendering ) {
422444 return ;
423445 }
446+ ScopedCritSec scope (&requestAccess);
424447
425448 int rotation = NormalizeRotation (dm->GetRotation ());
426449 float zoom = dm->GetZoomReal (pageNo);
@@ -480,9 +503,10 @@ void RenderCache::Render(DisplayModel* dm, int pageNo, int rotation, float zoom,
480503
481504bool RenderCache::Render (DisplayModel* dm, int pageNo, int rotation, float zoom, TilePosition* tile, RectF* pageRect,
482505 const OnBitmapRendered* renderCb) {
483- logf (" RenderCache::Render() : pageNo %d\n " , pageNo);
506+ logf (" RenderCache::Render: pageNo %d\n " , pageNo);
484507 ReportIf (!dm);
485- if (!dm || dm->dontRenderFlag ) {
508+ if (!dm || dm->pauseRendering ) {
509+ logf (" skipped because dm->pauseRendering\n " );
486510 return false ;
487511 }
488512
@@ -633,7 +657,7 @@ void RenderCache::AbortCurrentRequest() {
633657 curReq->abort = true ;
634658}
635659
636- DWORD WINAPI RenderCache:: RenderCacheThread (LPVOID data) {
660+ static DWORD WINAPI RenderCacheThread (LPVOID data) {
637661 RenderCache* cache = (RenderCache*)data;
638662 PageRenderRequest req;
639663 RenderedBitmap* bmp;
@@ -655,7 +679,7 @@ DWORD WINAPI RenderCache::RenderCacheThread(LPVOID data) {
655679 continue ;
656680 }
657681
658- if (req.dm ->dontRenderFlag ) {
682+ if (req.dm ->pauseRendering ) {
659683 if (req.renderCb ) {
660684 req.renderCb ->Call (nullptr );
661685 }
@@ -674,18 +698,20 @@ DWORD WINAPI RenderCache::RenderCacheThread(LPVOID data) {
674698 RenderPageArgs args (req.pageNo , req.zoom , req.rotation , &req.pageRect , RenderTarget::View, &req.abortCookie );
675699 auto timeStart = TimeGet ();
676700 bmp = engine->RenderPage (args);
701+ auto durMs = TimeSinceInMs (timeStart);
677702 if (req.abort ) {
703+ logf (" RenderCacheThread: aborted rendering page %d in %.2f ms\n " , req.pageNo , (float )durMs);
678704 delete bmp;
679705 if (req.renderCb ) {
680706 req.renderCb ->Call (nullptr );
681707 }
682708 continue ;
683709 }
684- auto durMs = TimeSinceInMs (timeStart);
685710 if (durMs > 100 ) {
686711 auto path = engine->FilePath ();
687712 logfa (" Slow rendering: %.2f ms, page: %d in '%s'\n " , (float )durMs, req.pageNo , path);
688713 }
714+ logf (" RenderCacheThread: rendered page %d in %.2f ms\n " , req.pageNo , (float )durMs);
689715
690716 if (req.renderCb ) {
691717 // the callback must free the RenderedBitmap
@@ -869,18 +895,18 @@ int RenderCache::Paint(HDC hdc, Rect bounds, DisplayModel* dm, int pageNo, PageI
869895 }
870896 }
871897
872- #ifdef CONSERVE_MEMORY
873- if (!neededScaling) {
874- if (renderOutOfDateCue) {
875- *renderOutOfDateCue = false ;
898+ if (gConserveMemory ) {
899+ if (!neededScaling) {
900+ if (renderOutOfDateCue) {
901+ *renderOutOfDateCue = false ;
902+ }
903+ // free tiles with different resolution
904+ TilePosition tile (targetRes, (USHORT)-1 , 0 );
905+ // logf("RenderCache::Paint: calling FreePage() pageNo: %d\n", pageNo);
906+ FreePage (dm, pageNo, &tile);
876907 }
877- // free tiles with different resolution
878- TilePosition tile (targetRes, (USHORT)-1 , 0 );
879- logf (" RenderCache::Paint: calling FreePage() pageNo: %d\n " , pageNo);
880- FreePage (dm, pageNo, &tile);
908+ FreeNotVisible ();
881909 }
882- FreeNotVisible ();
883- #endif
884910
885911 return renderDelayMin;
886912}
0 commit comments