perf: shrink HomeActivity cover cache from 48KB framebuffer to 16KB region (#2035)
On-device repro showed the cover snapshot pinning ~52KB of contiguous heap (cloning the full 48KB framebuffer with malloc overhead). MaxAlloc on Home was 61KB; nothing was leaving headroom for HTTPS, which needs 30-50KB contiguous for the mbedTLS handshake. Add region-aware framebuffer helpers to GfxRenderer that translate a logical rect through rotateCoordinates and copy only the byte range that contains the rotated rect. HomeActivity records the tile rect it passes to drawRecentBookCover and caches only that subregion. Measured on device (X3, Portrait): Idle on Home | Free 102K -> 139K | MaxAlloc 61K -> 115K Mid-EPUB-read | Free 81K -> 134K | MaxAlloc 70K -> 115K Cover cache | ~52K -> ~16K (per allocation) Works in all four orientations because the bounds helper samples the four logical corners through the existing rotation, so the cached byte range always covers the pixels the theme could have drawn into. Savings will vary with theme, but should be significant across all.
This commit is contained in:
@@ -130,37 +130,30 @@ void HomeActivity::onExit() {
|
||||
}
|
||||
|
||||
bool HomeActivity::storeCoverBuffer() {
|
||||
uint8_t* frameBuffer = renderer.getFrameBuffer();
|
||||
if (!frameBuffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Free any existing buffer first
|
||||
// render() must have already set the cover rect; without it we'd be back to
|
||||
// cloning the whole framebuffer.
|
||||
if (coverRectW <= 0 || coverRectH <= 0) return false;
|
||||
freeCoverBuffer();
|
||||
|
||||
const size_t bufferSize = renderer.getBufferSize();
|
||||
coverBuffer = static_cast<uint8_t*>(malloc(bufferSize));
|
||||
const size_t needed = renderer.getRegionByteSize(coverRectX, coverRectY, coverRectW, coverRectH);
|
||||
if (needed == 0) return false;
|
||||
coverBuffer = static_cast<uint8_t*>(malloc(needed));
|
||||
if (!coverBuffer) {
|
||||
LOG_ERR("HOME", "OOM: cover buffer (%u bytes)", (unsigned)needed);
|
||||
return false;
|
||||
}
|
||||
coverBufferSize = needed;
|
||||
if (!renderer.copyRegionToBuffer(coverRectX, coverRectY, coverRectW, coverRectH, coverBuffer, coverBufferSize)) {
|
||||
free(coverBuffer);
|
||||
coverBuffer = nullptr;
|
||||
coverBufferSize = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(coverBuffer, frameBuffer, bufferSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HomeActivity::restoreCoverBuffer() {
|
||||
if (!coverBuffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* frameBuffer = renderer.getFrameBuffer();
|
||||
if (!frameBuffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const size_t bufferSize = renderer.getBufferSize();
|
||||
memcpy(frameBuffer, coverBuffer, bufferSize);
|
||||
return true;
|
||||
if (!coverBuffer || coverRectW <= 0 || coverRectH <= 0) return false;
|
||||
return renderer.copyBufferToRegion(coverRectX, coverRectY, coverRectW, coverRectH, coverBuffer, coverBufferSize);
|
||||
}
|
||||
|
||||
void HomeActivity::freeCoverBuffer() {
|
||||
@@ -168,6 +161,7 @@ void HomeActivity::freeCoverBuffer() {
|
||||
free(coverBuffer);
|
||||
coverBuffer = nullptr;
|
||||
}
|
||||
coverBufferSize = 0;
|
||||
coverBufferStored = false;
|
||||
}
|
||||
|
||||
@@ -221,6 +215,14 @@ void HomeActivity::render(RenderLock&&) {
|
||||
GUI.drawHeader(renderer, Rect{0, metrics.topPadding, pageWidth, metrics.homeTopPadding},
|
||||
metrics.homeContinueReadingInMenu && !recentBooks.empty() ? recentBooks[0].title.c_str() : nullptr);
|
||||
|
||||
// Record the tile rect so storeCoverBuffer (called from the theme) knows
|
||||
// which sub-region of the framebuffer to snapshot. ~16 KB in Portrait
|
||||
// instead of the 48 KB full framebuffer the previous bind captured.
|
||||
coverRectX = 0;
|
||||
coverRectY = metrics.homeTopPadding;
|
||||
coverRectW = pageWidth;
|
||||
coverRectH = metrics.homeCoverTileHeight;
|
||||
|
||||
GUI.drawRecentBookCover(renderer, Rect{0, metrics.homeTopPadding, pageWidth, metrics.homeCoverTileHeight},
|
||||
recentBooks, selectorIndex, coverRendered, coverBufferStored, bufferRestored,
|
||||
std::bind(&HomeActivity::storeCoverBuffer, this));
|
||||
|
||||
Reference in New Issue
Block a user