From 09fd199487ec43ff646533e8a138708cc94f4aa3 Mon Sep 17 00:00:00 2001 From: TuxSH <1922548+TuxSH@users.noreply.github.com> Date: Fri, 8 May 2020 01:17:46 +0100 Subject: [PATCH] rosalina: Dynamically alloc/free fb cache, exempt rosalina from reslimiting --- sysmodules/pm/source/manager.c | 5 +- sysmodules/rosalina/include/draw.h | 10 +++- sysmodules/rosalina/source/draw.c | 73 +++++++++++++++++++++++------- sysmodules/rosalina/source/main.c | 2 + sysmodules/rosalina/source/menu.c | 23 +++++++--- sysmodules/rosalina/source/menus.c | 4 +- 6 files changed, 89 insertions(+), 28 deletions(-) diff --git a/sysmodules/pm/source/manager.c b/sysmodules/pm/source/manager.c index 8cd07cb..ebcebd2 100644 --- a/sysmodules/pm/source/manager.c +++ b/sysmodules/pm/source/manager.c @@ -38,7 +38,10 @@ void Manager_RegisterKips(void) process->flags = PROCESSFLAG_KIP; process->terminationStatus = TERMSTATUS_RUNNING; - assertSuccess(svcSetProcessResourceLimits(processHandle, g_manager.reslimits[RESLIMIT_CATEGORY_OTHER])); + if (i < 5) { + // Exempt rosalina from being resource-limited at all + assertSuccess(svcSetProcessResourceLimits(processHandle, g_manager.reslimits[RESLIMIT_CATEGORY_OTHER])); + } } ProcessList_Unlock(&g_manager.processList); diff --git a/sysmodules/rosalina/include/draw.h b/sysmodules/rosalina/include/draw.h index d303e78..4a7b0b6 100644 --- a/sysmodules/rosalina/include/draw.h +++ b/sysmodules/rosalina/include/draw.h @@ -57,6 +57,8 @@ #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 SCREEN_BOT_WIDTH 320 #define SCREEN_BOT_HEIGHT 240 @@ -72,6 +74,8 @@ #define DRAW_MAX_FORMATTED_STRING_SIZE 512 +void Draw_Init(void); + void Draw_Lock(void); void Draw_Unlock(void); @@ -81,7 +85,11 @@ u32 Draw_DrawFormattedString(u32 posX, u32 posY, u32 color, const char *fmt, ... void Draw_FillFramebuffer(u32 value); void Draw_ClearFramebuffer(void); -void Draw_SetupFramebuffer(void); +u32 Draw_AllocateFramebufferCache(void); +void Draw_FreeFramebufferCache(void); +void *Draw_GetFramebufferCache(void); +u32 Draw_GetFramebufferCacheSize(void); +u32 Draw_SetupFramebuffer(void); void Draw_RestoreFramebuffer(void); void Draw_FlushFramebuffer(void); u32 Draw_GetCurrentFramebufferAddress(bool top, bool left); diff --git a/sysmodules/rosalina/source/draw.c b/sysmodules/rosalina/source/draw.c index 91bd9e9..67d23db 100644 --- a/sysmodules/rosalina/source/draw.c +++ b/sysmodules/rosalina/source/draw.c @@ -33,21 +33,18 @@ #include "menu.h" #include "utils.h" -u8 framebufferCache[FB_BOTTOM_SIZE]; - static u32 gpuSavedFramebufferAddr1, gpuSavedFramebufferAddr2, gpuSavedFramebufferFormat, gpuSavedFramebufferStride; - +static u32 framebufferCacheSize; +static void *framebufferCache; static RecursiveLock lock; +void Draw_Init(void) +{ + RecursiveLock_Init(&lock); +} + void Draw_Lock(void) { - static bool lockInitialized = false; - if(!lockInitialized) - { - RecursiveLock_Init(&lock); - lockInitialized = true; - } - RecursiveLock_Lock(&lock); } @@ -129,34 +126,78 @@ void Draw_ClearFramebuffer(void) Draw_FillFramebuffer(0); } -void Draw_SetupFramebuffer(void) +u32 Draw_AllocateFramebufferCache(void) +{ + // Try to see how much we can allocate... + // Can't use fbs in FCRAM when Home Menu is active (AXI config related maybe?) + u32 addr = 0x0D000000; + u32 tmp; + u32 minSize = (FB_BOTTOM_SIZE + 0xFFF) & ~0xFFF; + u32 maxSize = (FB_SCREENSHOT_SIZE + 0xFFF) & ~0xFFF; + u32 remaining = (u32)osGetMemRegionFree(MEMREGION_SYSTEM); + u32 size = remaining < maxSize ? remaining : maxSize; + + if (size < minSize || R_FAILED(svcControlMemory(&tmp, addr, 0, size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE))) + { + framebufferCache = NULL; + framebufferCacheSize = 0; + } + else + { + framebufferCache = (u32 *)addr; + framebufferCacheSize = size; + } + + return framebufferCacheSize; +} + +void Draw_FreeFramebufferCache(void) +{ + u32 tmp; + svcControlMemory(&tmp, (u32)framebufferCache, 0, framebufferCacheSize, MEMOP_FREE, 0); + framebufferCacheSize = 0; + framebufferCache = NULL; +} + +void *Draw_GetFramebufferCache(void) +{ + return framebufferCache; +} + +u32 Draw_GetFramebufferSize(void) +{ + return framebufferCacheSize; +} + +u32 Draw_SetupFramebuffer(void) { while((GPU_PSC0_CNT | GPU_PSC1_CNT | GPU_TRANSFER_CNT | GPU_CMDLIST_CNT) & 1); - svcFlushEntireDataCache(); + Draw_FlushFramebuffer(); memcpy(framebufferCache, FB_BOTTOM_VRAM_ADDR, FB_BOTTOM_SIZE); + Draw_ClearFramebuffer(); + Draw_FlushFramebuffer(); gpuSavedFramebufferAddr1 = GPU_FB_BOTTOM_ADDR_1; gpuSavedFramebufferAddr2 = GPU_FB_BOTTOM_ADDR_2; gpuSavedFramebufferFormat = GPU_FB_BOTTOM_FMT; gpuSavedFramebufferStride = GPU_FB_BOTTOM_STRIDE; GPU_FB_BOTTOM_ADDR_1 = GPU_FB_BOTTOM_ADDR_2 = FB_BOTTOM_VRAM_PA; - GPU_FB_BOTTOM_FMT = (GPU_FB_BOTTOM_FMT & ~7) | 2; + GPU_FB_BOTTOM_FMT = (GPU_FB_BOTTOM_FMT & ~7) | GSP_RGB565_OES; GPU_FB_BOTTOM_STRIDE = 240 * 2; - Draw_FlushFramebuffer(); + return framebufferCacheSize; } void Draw_RestoreFramebuffer(void) { memcpy(FB_BOTTOM_VRAM_ADDR, framebufferCache, FB_BOTTOM_SIZE); + Draw_FlushFramebuffer(); GPU_FB_BOTTOM_ADDR_1 = gpuSavedFramebufferAddr1; GPU_FB_BOTTOM_ADDR_2 = gpuSavedFramebufferAddr2; GPU_FB_BOTTOM_FMT = gpuSavedFramebufferFormat; GPU_FB_BOTTOM_STRIDE = gpuSavedFramebufferStride; - - Draw_FlushFramebuffer(); } void Draw_FlushFramebuffer(void) diff --git a/sysmodules/rosalina/source/main.c b/sysmodules/rosalina/source/main.c index 653527f..496005c 100644 --- a/sysmodules/rosalina/source/main.c +++ b/sysmodules/rosalina/source/main.c @@ -41,6 +41,7 @@ #include "menus/sysconfig.h" #include "input_redirection.h" #include "minisoc.h" +#include "draw.h" #include "task_runner.h" @@ -219,6 +220,7 @@ int main(void) if(R_FAILED(svcCreateEvent(&terminationRequestEvent, RESET_STICKY))) svcBreak(USERBREAK_ASSERT); + Draw_Init(); Cheat_SeedRng(svcGetSystemTick()); MyThread *menuThread = menuCreateThread(); diff --git a/sysmodules/rosalina/source/menu.c b/sysmodules/rosalina/source/menu.c index 7f1267e..1191705 100644 --- a/sysmodules/rosalina/source/menu.c +++ b/sysmodules/rosalina/source/menu.c @@ -175,30 +175,39 @@ void menuThreadMain(void) } } -static s32 menuRefCount = 0; +static u32 menuRefCount = 0; void menuEnter(void) { - if(AtomicPostIncrement(&menuRefCount) == 0) + Draw_Lock(); + if(menuRefCount++ == 0) { svcKernelSetState(0x10000, 1); svcSleepThread(5 * 1000 * 100LL); + if (Draw_AllocateFramebufferCache() == 0) + { + // Oops + menuRefCount = 0; + svcKernelSetState(0x10000, 1); + svcSleepThread(5 * 1000 * 100LL); + } + Draw_SetupFramebuffer(); - Draw_ClearFramebuffer(); } + Draw_Unlock(); } void menuLeave(void) { svcSleepThread(50 * 1000 * 1000); - if(AtomicDecrement(&menuRefCount) == 0) + Draw_Lock(); + if(--menuRefCount == 0) { - Draw_Lock(); - Draw_FlushFramebuffer(); Draw_RestoreFramebuffer(); - Draw_Unlock(); + Draw_FreeFramebufferCache(); svcKernelSetState(0x10000, 1); } + Draw_Unlock(); } static void menuDraw(Menu *menu, u32 selected) diff --git a/sysmodules/rosalina/source/menus.c b/sysmodules/rosalina/source/menus.c index 9b245a7..b5496dd 100644 --- a/sysmodules/rosalina/source/menus.c +++ b/sysmodules/rosalina/source/menus.c @@ -151,9 +151,9 @@ void RosalinaMenu_PowerOff(void) // Soft shutdown. while(!terminationRequest); } -extern u8 framebufferCache[FB_BOTTOM_SIZE]; void RosalinaMenu_TakeScreenshot(void) { + u8 *framebufferCache = (u8 *)Draw_GetFramebufferCache(); #define TRY(expr) if(R_FAILED(res = (expr))) goto end; u64 total; @@ -280,8 +280,6 @@ end: IFile_Close(&file); svcFlushEntireDataCache(); Draw_SetupFramebuffer(); - Draw_ClearFramebuffer(); - Draw_FlushFramebuffer(); Draw_Unlock(); do