rosalina: fast screenshots (10s -> 0.3s on my end)

This commit is contained in:
TuxSH 2020-05-08 16:03:37 +01:00
parent 09fd199487
commit 00850bf691
3 changed files with 59 additions and 41 deletions

View File

@ -57,7 +57,7 @@
#define FB_BOTTOM_VRAM_ADDR ((void *)0x1F48F000) // cached
#define FB_BOTTOM_VRAM_PA 0x1848F000
#define FB_BOTTOM_SIZE (320 * 240 * 2)
#define FB_SCREENSHOT_SIZE (52 + 400 * 240 * 2)
#define FB_SCREENSHOT_SIZE (52 + 400 * 240 * 3)
#define SCREEN_BOT_WIDTH 320

View File

@ -164,7 +164,7 @@ void *Draw_GetFramebufferCache(void)
return framebufferCache;
}
u32 Draw_GetFramebufferSize(void)
u32 Draw_GetFramebufferCacheSize(void)
{
return framebufferCacheSize;
}

View File

@ -151,14 +151,52 @@ void RosalinaMenu_PowerOff(void) // Soft shutdown.
while(!terminationRequest);
}
void RosalinaMenu_TakeScreenshot(void)
{
u8 *framebufferCache = (u8 *)Draw_GetFramebufferCache();
#define TRY(expr) if(R_FAILED(res = (expr))) goto end;
static s64 timeSpentConvertingScreenshot = 0;
static s64 timeSpentWritingScreenshot = 0;
static Result RosalinaMenu_WriteScreenshot(IFile *file, bool top, bool left)
{
u64 total;
Result res = 0;
u32 dimX = top ? 400 : 320;
u32 lineSize = 3 * dimX;
u32 remaining = lineSize * 240;
u8 *framebufferCache = (u8 *)Draw_GetFramebufferCache();
u8 *framebufferCacheEnd = framebufferCache + Draw_GetFramebufferCacheSize();
u8 *buf = framebufferCache;
Draw_CreateBitmapHeader(framebufferCache, dimX, 240);
buf += 54;
u32 n = 0;
// Our buffer might be smaller than the size of the screenshot...
while (remaining != 0)
{
s64 t0 = svcGetSystemTick();
u32 available = (u32)(framebufferCacheEnd - buf);
u32 size = available < remaining ? available : remaining;
u32 nlines = size / lineSize;
for (u32 y = 0; y < nlines; y++)
Draw_ConvertFrameBufferLine(buf + lineSize * y, top, left, y);
s64 t1 = svcGetSystemTick();
timeSpentConvertingScreenshot += t1 - t0;
TRY(IFile_Write(file, &total, framebufferCache, (n == 0 ? 54 : 0) + lineSize * nlines, 0)); // don't forget to write the header
timeSpentWritingScreenshot += svcGetSystemTick() - t1;
remaining -= lineSize * nlines;
buf = framebufferCache;
}
end: return res;
}
void RosalinaMenu_TakeScreenshot(void)
{
IFile file;
Result res;
Result res = 0;
char filename[64];
@ -167,6 +205,9 @@ void RosalinaMenu_TakeScreenshot(void)
s64 out;
bool isSdMode;
timeSpentConvertingScreenshot = 0;
timeSpentWritingScreenshot = 0;
if(R_FAILED(svcGetSystemInfo(&out, 0x10000, 0x203))) svcBreak(USERBREAK_ASSERT);
isSdMode = (bool)out;
@ -230,49 +271,19 @@ void RosalinaMenu_TakeScreenshot(void)
sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_top.bmp", year, month, days, hours, minutes, seconds, milliseconds);
TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE));
Draw_CreateBitmapHeader(framebufferCache, 400, 240);
for(u32 y = 0; y < 120; y++)
Draw_ConvertFrameBufferLine(framebufferCache + 54 + 3 * 400 * y, true, true, y);
TRY(IFile_Write(&file, &total, framebufferCache, 54 + 3 * 400 * 120, 0));
for(u32 y = 120; y < 240; y++)
Draw_ConvertFrameBufferLine(framebufferCache + 3 * 400 * (y - 120), true, true, y);
TRY(IFile_Write(&file, &total, framebufferCache, 3 * 400 * 120, 0));
TRY(RosalinaMenu_WriteScreenshot(&file, true, true));
TRY(IFile_Close(&file));
sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_bot.bmp", year, month, days, hours, minutes, seconds, milliseconds);
TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE));
Draw_CreateBitmapHeader(framebufferCache, 320, 240);
for(u32 y = 0; y < 120; y++)
Draw_ConvertFrameBufferLine(framebufferCache + 54 + 3 * 320 * y, false, true, y);
TRY(IFile_Write(&file, &total, framebufferCache, 54 + 3 * 320 * 120, 0));
for(u32 y = 120; y < 240; y++)
Draw_ConvertFrameBufferLine(framebufferCache + 3 * 320 * (y - 120), false, true, y);
TRY(IFile_Write(&file, &total, framebufferCache, 3 * 320 * 120, 0));
TRY(RosalinaMenu_WriteScreenshot(&file, false, true));
TRY(IFile_Close(&file));
if((GPU_FB_TOP_FMT & 0x20) && (Draw_GetCurrentFramebufferAddress(true, true) != Draw_GetCurrentFramebufferAddress(true, false)))
if(false && (GPU_FB_TOP_FMT & 0x20) && (Draw_GetCurrentFramebufferAddress(true, true) != Draw_GetCurrentFramebufferAddress(true, false)))
{
sprintf(filename, "/luma/screenshots/%04lu-%02lu-%02lu_%02lu-%02lu-%02lu.%03llu_top_right.bmp", year, month, days, hours, minutes, seconds, milliseconds);
TRY(IFile_Open(&file, archiveId, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, filename), FS_OPEN_CREATE | FS_OPEN_WRITE));
Draw_CreateBitmapHeader(framebufferCache, 400, 240);
for(u32 y = 0; y < 120; y++)
Draw_ConvertFrameBufferLine(framebufferCache + 54 + 3 * 400 * y, true, false, y);
TRY(IFile_Write(&file, &total, framebufferCache, 54 + 3 * 400 * 120, 0));
for(u32 y = 120; y < 240; y++)
Draw_ConvertFrameBufferLine(framebufferCache + 3 * 400 * (y - 120), true, false, y);
TRY(IFile_Write(&file, &total, framebufferCache, 3 * 400 * 120, 0));
TRY(RosalinaMenu_WriteScreenshot(&file, true, false));
TRY(IFile_Close(&file));
}
@ -289,7 +300,14 @@ end:
if(R_FAILED(res))
Draw_DrawFormattedString(10, 30, COLOR_WHITE, "Operation failed (0x%08lx).", (u32)res);
else
Draw_DrawString(10, 30, COLOR_WHITE, "Operation succeeded.");
{
u32 t1 = (u32)(1000 * timeSpentConvertingScreenshot / SYSCLOCK_ARM11);
u32 t2 = (u32)(1000 * timeSpentWritingScreenshot / SYSCLOCK_ARM11);
u32 posY = 30;
posY = Draw_DrawString(10, posY, COLOR_WHITE, "Operation succeeded.\n\n");
posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Time spent converting: %5lums\n", t1);
posY = Draw_DrawFormattedString(10, posY, COLOR_WHITE, "Time spent writing files: %5lums\n", t2);
}
Draw_FlushFramebuffer();
Draw_Unlock();