mirror of
https://git.planet-casio.com/Lephenixnoir/gint.git
synced 2024-12-29 13:03:36 +01:00
render-cg: allocate VRAM in the heap; default to double buffering
* Create a heap arena over the OS stack, large enough to hold two VRAMs as was previously done, unless GINT_NO_OS_STACK is set at compile time. (This replaces GINT_USER_VRAM.) * Allocate a single VRAM in the heap at startup. * Use double buffering by default as triple buffering is almost entirely useless. dudpate() waits if both VRAMs are identical to prevent corruption, but this can be bypassed with R61524 functions as usual. This adds about 180 kB of heap data to any add-in using default settings.
This commit is contained in:
parent
f219e5c882
commit
7a3604ccbb
5 changed files with 87 additions and 59 deletions
|
@ -6,7 +6,7 @@ project(Gint VERSION 2.7.1 LANGUAGES C ASM)
|
||||||
include(GitVersionNumber)
|
include(GitVersionNumber)
|
||||||
include(Fxconv)
|
include(Fxconv)
|
||||||
|
|
||||||
option(GINT_USER_VRAM "Put all VRAMs into the user stack (fx-CG 50 only)")
|
option(GINT_NO_OS_STACK "Do not use the OS stack as a memory pool (fx-CG only)")
|
||||||
option(GINT_STATIC_GRAY "Use static memory instead of malloc for gray buffers (fx-9860G only)")
|
option(GINT_STATIC_GRAY "Use static memory instead of malloc for gray buffers (fx-9860G only)")
|
||||||
option(GINT_KMALLOC_DEBUG "Enable debug functions for kmalloc")
|
option(GINT_KMALLOC_DEBUG "Enable debug functions for kmalloc")
|
||||||
|
|
||||||
|
|
|
@ -16,10 +16,18 @@
|
||||||
0x03f7c0a0 = Commit 3f7c0a0 */
|
0x03f7c0a0 = Commit 3f7c0a0 */
|
||||||
#define GINT_HASH 0x@GINT_GIT_HASH@
|
#define GINT_HASH 0x@GINT_GIT_HASH@
|
||||||
|
|
||||||
/* GINT_USER_VRAM: Selects whether to store VRAMs in the user stack (occupying
|
/* GINT_NO_OS_STACK: Disables using a chunk of the OS stack as a heap. The top
|
||||||
350k/512k of the area) or in the system stack (the default). (fx-CG 50) */
|
section covering 355/512 ko is otherwise used. (fx-CG 50) */
|
||||||
|
#cmakedefine GINT_NO_OS_STACK
|
||||||
|
|
||||||
|
/* GINT_USER_VRAM: Selects whether to store VRAMs in the user stack or in the
|
||||||
|
OS stack. Deprecated, now controlled by GINT_NO_OS_STACK. (fx-CG 50) */
|
||||||
#cmakedefine GINT_USER_VRAM
|
#cmakedefine GINT_USER_VRAM
|
||||||
|
|
||||||
|
#ifdef GINT_USER_VRAM
|
||||||
|
# define GINT_NO_OS_STACK
|
||||||
|
#endif
|
||||||
|
|
||||||
/* GINT_STATIC_GRAY: Selects whether additional gray VRAMs are allocated
|
/* GINT_STATIC_GRAY: Selects whether additional gray VRAMs are allocated
|
||||||
statically or in the system heap (fx-9860G) */
|
statically or in the system heap (fx-9860G) */
|
||||||
#cmakedefine GINT_STATIC_GRAY
|
#cmakedefine GINT_STATIC_GRAY
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <gint/kmalloc.h>
|
#include <gint/kmalloc.h>
|
||||||
#include <gint/cpu.h>
|
#include <gint/cpu.h>
|
||||||
#include <gint/exc.h>
|
#include <gint/exc.h>
|
||||||
|
#include <gint/config.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -91,15 +92,35 @@ void kinit(void)
|
||||||
static_ram.is_default = isSH4();
|
static_ram.is_default = isSH4();
|
||||||
static_ram.start = mmu_uram() + ((uint32_t)&euram - 0x08100000);
|
static_ram.start = mmu_uram() + ((uint32_t)&euram - 0x08100000);
|
||||||
static_ram.end = (void *)uram_end;
|
static_ram.end = (void *)uram_end;
|
||||||
|
|
||||||
kmalloc_init_arena(&static_ram, true);
|
kmalloc_init_arena(&static_ram, true);
|
||||||
kmalloc_add_arena(&static_ram);
|
kmalloc_add_arena(&static_ram);
|
||||||
|
|
||||||
|
/* Create an arena in the OS stack as well, for VRAM and more data */
|
||||||
|
#if defined(FXCG50) && !defined(GINT_NO_OS_STACK)
|
||||||
|
static kmalloc_arena_t os_stack = { 0 };
|
||||||
|
os_stack.name = "_ostk";
|
||||||
|
os_stack.is_default = true;
|
||||||
|
if(gint[HWCALC] == HWCALC_PRIZM || gint[HWCALC] == HWCALC_FXCG_MANAGER)
|
||||||
|
os_stack.start = (void *)0x880f0000;
|
||||||
|
else
|
||||||
|
os_stack.start = (void *)0x8c0f0000;
|
||||||
|
os_stack.end = os_stack.start + (350 * 1024);
|
||||||
|
kmalloc_init_arena(&os_stack, true);
|
||||||
|
kmalloc_add_arena(&os_stack);
|
||||||
|
#endif /* FXCG50 && !GINT_NO_OS_STACK */
|
||||||
|
|
||||||
/* Allocate world buffers for the OS and for gint */
|
/* Allocate world buffers for the OS and for gint */
|
||||||
gint_world_os = gint_world_alloc();
|
gint_world_os = gint_world_alloc();
|
||||||
gint_world_addin = gint_world_alloc();
|
gint_world_addin = gint_world_alloc();
|
||||||
gint_driver_flags = malloc(gint_driver_count());
|
gint_driver_flags = malloc(gint_driver_count());
|
||||||
|
|
||||||
|
#ifdef FXCG50
|
||||||
|
/* Allocate VRAMs, which is important for panic screens */
|
||||||
|
extern bool dvram_init(void);
|
||||||
|
if(!dvram_init())
|
||||||
|
abort();
|
||||||
|
#endif
|
||||||
|
|
||||||
if(!gint_world_os || !gint_world_addin || !gint_driver_flags)
|
if(!gint_world_os || !gint_world_addin || !gint_driver_flags)
|
||||||
gint_panic(0x1060);
|
gint_panic(0x1060);
|
||||||
|
|
||||||
|
|
|
@ -2,15 +2,19 @@
|
||||||
#include <gint/drivers/r61524.h>
|
#include <gint/drivers/r61524.h>
|
||||||
#include "render-cg.h"
|
#include "render-cg.h"
|
||||||
|
|
||||||
/* dupdate() - Push the video RAM to the display driver */
|
/* dupdate(): Push the video RAM to the display driver */
|
||||||
void dupdate(void)
|
void dupdate(void)
|
||||||
{
|
{
|
||||||
r61524_display(gint_vram, 0, 224, R61524_DMA);
|
/* If triple buffering is enabled, don't wait for the DMA to finish */
|
||||||
|
uint16_t *vram_1, *vram_2;
|
||||||
|
dgetvram(&vram_1, &vram_2);
|
||||||
|
int method = (vram_1 == vram_2) ? R61524_DMA_WAIT : R61524_DMA;
|
||||||
|
|
||||||
|
r61524_display(gint_vram, 0, 224, method);
|
||||||
|
|
||||||
gint_call_t hook = dupdate_get_hook();
|
gint_call_t hook = dupdate_get_hook();
|
||||||
if(hook.function) gint_call(hook);
|
if(hook.function) gint_call(hook);
|
||||||
|
|
||||||
/* The DMA is still running, so we need to switch VRAMs to avoid
|
/* Switch buffers if triple buffering is enabled */
|
||||||
overwriting the data which is about to be sent. */
|
|
||||||
dvram_switch();
|
dvram_switch();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,67 +1,62 @@
|
||||||
#include <gint/display.h>
|
#include <gint/display.h>
|
||||||
#include <gint/hardware.h>
|
#include <stdlib.h>
|
||||||
#include <gint/config.h>
|
|
||||||
|
|
||||||
#ifdef GINT_USER_VRAM
|
/* Up to two VRAM pointers can be set, for triple buffering. */
|
||||||
/* We want to put the VRAM in the user section, however we can't use the
|
static uint16_t *vram_1 = NULL, *vram_2 = NULL;
|
||||||
virtualized P0 address as this will mess up the DMA. As the static RAM is
|
/* Current VRAM pointer, always equal to either vram_1 or vram_2. */
|
||||||
always fully mapped at a fixed place, we can use the target P1 address. We
|
uint16_t *gint_vram = NULL;
|
||||||
just need to allocate the space for the linker. This special section ensures
|
|
||||||
that the first address of the user stack will be used */
|
|
||||||
GALIGNED(4) GSECTION(".bss.vram") int8_t _gint_vram_buffers[396*224*2];
|
|
||||||
|
|
||||||
/* In this case, we can define pointers to our user stack directly, these will
|
bool dvram_init(void)
|
||||||
be the physical address associated with _gint_vram_buffers */
|
|
||||||
static uint16_t *main = (void *)0xac161400;
|
|
||||||
static uint16_t *scnd = (void *)0xac18c900;
|
|
||||||
|
|
||||||
/* Shared VRAM pointer, the one exposed by <gint/display.h> */
|
|
||||||
uint16_t *gint_vram = (void *)0xac161400;
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* Otherwise, just put both VRAMs in the system stack! */
|
|
||||||
static uint16_t *main = (void *)0xac0f0000;
|
|
||||||
static uint16_t *scnd = (void *)0xac11b500;
|
|
||||||
uint16_t *gint_vram = (void *)0xac0f0000;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* On Prizm: should be: 0xa80f0000 and 0xa811b500 */
|
|
||||||
|
|
||||||
__attribute__((constructor))
|
|
||||||
static void init_vram(void)
|
|
||||||
{
|
{
|
||||||
/* On Prizm and fx-CG Manager, move address to 0xa8000000 */
|
int const MARGIN = 32;
|
||||||
/* TODO: Detect base RAM address in BSC rather than hardcoding it */
|
|
||||||
if(gint[HWCALC] == HWCALC_PRIZM || gint[HWCALC] == HWCALC_FXCG_MANAGER)
|
/* Leave MARGIN bytes on each side of the region; this enables some
|
||||||
{
|
important optimisations in the image renderer. We also add another
|
||||||
main = (void *)main - 0x04000000;
|
32 bytes so we can manually 32-align the region */
|
||||||
scnd = (void *)scnd - 0x04000000;
|
uint32_t region = (uint32_t)malloc(DWIDTH * DHEIGHT * 2 + MARGIN + 32);
|
||||||
gint_vram = (void *)gint_vram - 0x04000000;
|
if(region == 0)
|
||||||
}
|
return false;
|
||||||
|
|
||||||
|
/* 32-align the region */
|
||||||
|
region = (region + 31) & -32;
|
||||||
|
/* Skip a MARGIN */
|
||||||
|
region += MARGIN;
|
||||||
|
/* Use an uncached address */
|
||||||
|
region = (region & 0x1fffffff) | 0xa0000000;
|
||||||
|
|
||||||
|
/* Don't enable triple buffering by default */
|
||||||
|
vram_1 = (void *)region;
|
||||||
|
vram_2 = vram_1;
|
||||||
|
gint_vram = vram_1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dsetvram() - Control video RAM address and triple buffering */
|
/* dsetvram(): Control video RAM address and triple buffering */
|
||||||
void dsetvram(uint16_t *new_main, uint16_t *new_secondary)
|
void dsetvram(uint16_t *new_vram_1, uint16_t *new_vram_2)
|
||||||
{
|
{
|
||||||
if(gint_vram == main) gint_vram = new_main;
|
if(!new_vram_1 && !new_vram_2) return;
|
||||||
else if(gint_vram == scnd) gint_vram = new_secondary;
|
if(!new_vram_1) new_vram_1 = new_vram_2;
|
||||||
|
if(!new_vram_2) new_vram_2 = new_vram_1;
|
||||||
|
|
||||||
main = new_main;
|
if(gint_vram == vram_1)
|
||||||
scnd = new_secondary;
|
gint_vram = new_vram_1;
|
||||||
|
else if(gint_vram == vram_2)
|
||||||
|
gint_vram = new_vram_2;
|
||||||
|
|
||||||
|
vram_1 = new_vram_1;
|
||||||
|
vram_2 = new_vram_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dgetvram() - Get VRAM addresses */
|
/* dgetvram(): Get VRAM addresses */
|
||||||
void dgetvram(uint16_t **ptr_main, uint16_t **ptr_scnd)
|
void dgetvram(uint16_t **ptr_vram_1, uint16_t **ptr_vram_2)
|
||||||
{
|
{
|
||||||
if(ptr_main) *ptr_main = main;
|
if(ptr_vram_1) *ptr_vram_1 = vram_1;
|
||||||
if(ptr_scnd) *ptr_scnd = scnd;
|
if(ptr_vram_2) *ptr_vram_2 = vram_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* dvram_switch() - Triple buffering switch
|
/* dvram_switch(): Triple buffering switch
|
||||||
This function is not public, it is used only by dupdate(). */
|
This function is not part of the API; it is used only by dupdate(). */
|
||||||
void dvram_switch(void)
|
void dvram_switch(void)
|
||||||
{
|
{
|
||||||
if(gint_vram == main) gint_vram = scnd;
|
gint_vram = (gint_vram == vram_1) ? vram_2 : vram_1;
|
||||||
else gint_vram = main;
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue