mirror of
https://github.com/encounter/SDL.git
synced 2025-05-19 22:01:33 +00:00
Spill render targets to ram on PSP
This commit is contained in:
parent
77d874e3c0
commit
c1f152292b
@ -74,8 +74,8 @@ typedef struct PSP_TextureData
|
|||||||
unsigned int format; /**< Image format - one of ::pgePixelFormat. */
|
unsigned int format; /**< Image format - one of ::pgePixelFormat. */
|
||||||
unsigned int pitch;
|
unsigned int pitch;
|
||||||
SDL_bool swizzled; /**< Is image swizzled. */
|
SDL_bool swizzled; /**< Is image swizzled. */
|
||||||
struct PSP_TextureData* prevhot; /**< More recently used render target */
|
struct PSP_TextureData* prevhotw; /**< More recently used render target */
|
||||||
struct PSP_TextureData* nexthot; /**< Less recently used render target */
|
struct PSP_TextureData* nexthotw; /**< Less recently used render target */
|
||||||
} PSP_TextureData;
|
} PSP_TextureData;
|
||||||
|
|
||||||
|
|
||||||
@ -165,6 +165,12 @@ Swap(float *a, float *b)
|
|||||||
*b = n;
|
*b = n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int
|
||||||
|
InVram(void* data)
|
||||||
|
{
|
||||||
|
return data < 0x04200000;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return next power of 2 */
|
/* Return next power of 2 */
|
||||||
static int
|
static int
|
||||||
TextureNextPow2(unsigned int w)
|
TextureNextPow2(unsigned int w)
|
||||||
@ -203,35 +209,70 @@ PixelFormatToPSPFMT(Uint32 format)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///SECTION render target LRU management
|
||||||
static void
|
static void
|
||||||
StartDrawing(SDL_Renderer * renderer)
|
LRUTargetRelink(PSP_TextureData* psp_texture) {
|
||||||
{
|
if(psp_texture->prevhotw) {
|
||||||
PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
|
psp_texture->prevhotw->nexthotw = psp_texture->nexthotw;
|
||||||
|
|
||||||
// Check if we need to start GU displaylist
|
|
||||||
if(!data->displayListAvail) {
|
|
||||||
sceGuStart(GU_DIRECT, DisplayList);
|
|
||||||
data->displayListAvail = SDL_TRUE;
|
|
||||||
}
|
}
|
||||||
|
if(psp_texture->nexthotw) {
|
||||||
// Check if we need a draw buffer change
|
psp_texture->nexthotw->prevhotw = psp_texture->prevhotw;
|
||||||
if(renderer->target != data->boundTarget) {
|
|
||||||
SDL_Texture* texture = renderer->target;
|
|
||||||
if(texture) {
|
|
||||||
PSP_TextureData* psp_texture = (PSP_TextureData*) texture->driverdata;
|
|
||||||
// Set target back to screen
|
|
||||||
sceGuDrawBufferList(psp_texture->format, vrelptr(psp_texture->data), psp_texture->textureWidth);
|
|
||||||
} else {
|
|
||||||
// Set target back to screen
|
|
||||||
sceGuDrawBufferList(data->psm, vrelptr(data->frontbuffer), PSP_FRAME_BUFFER_WIDTH);
|
|
||||||
}
|
|
||||||
data->boundTarget = texture;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
LRUTargetFixTail(PSP_RenderData* data, PSP_TextureData* psp_texture) {
|
||||||
|
if(data->least_recent_target == psp_texture) {
|
||||||
|
data->least_recent_target = psp_texture->prevhotw;
|
||||||
|
} else if(!data->least_recent_target) {
|
||||||
|
data->least_recent_target = psp_texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
LRUTargetPushFront(PSP_RenderData* data, PSP_TextureData* psp_texture) {
|
||||||
|
psp_texture->nexthotw = data->most_recent_target;
|
||||||
|
if(data->most_recent_target) {
|
||||||
|
data->most_recent_target->prevhotw = psp_texture;
|
||||||
|
}
|
||||||
|
LRUTargetFixTail(data, psp_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
LRUTargetBringFront(PSP_RenderData* data, PSP_TextureData* psp_texture) {
|
||||||
|
if(data->most_recent_target == psp_texture) {
|
||||||
|
return; //nothing to do
|
||||||
|
}
|
||||||
|
LRUTargetRelink(psp_texture);
|
||||||
|
psp_texture->prevhotw = NULL;
|
||||||
|
psp_texture->nexthotw = NULL;
|
||||||
|
LRUTargetPushFront(data, psp_texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
LRUTargetRemove(PSP_RenderData* data, PSP_TextureData* psp_texture) {
|
||||||
|
LRUTargetRelink(psp_texture);
|
||||||
|
if(data->most_recent_target == psp_texture) {
|
||||||
|
data->most_recent_target = psp_texture->nexthotw;
|
||||||
|
}
|
||||||
|
if(data->least_recent_target == psp_texture) {
|
||||||
|
data->least_recent_target = psp_texture->prevhotw;
|
||||||
|
}
|
||||||
|
psp_texture->prevhotw = NULL;
|
||||||
|
psp_texture->nexthotw = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
TextureStorageFree(void* storage) {
|
||||||
|
if(InVram(storage)) {
|
||||||
|
vfree(storage);
|
||||||
|
} else {
|
||||||
|
SDL_free(storage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
TextureSwizzle(PSP_TextureData *psp_texture)
|
TextureSwizzle(PSP_TextureData *psp_texture, void* dst)
|
||||||
{
|
{
|
||||||
int bytewidth, height;
|
int bytewidth, height;
|
||||||
int rowblocks, rowblocksadd;
|
int rowblocks, rowblocksadd;
|
||||||
@ -251,7 +292,14 @@ TextureSwizzle(PSP_TextureData *psp_texture)
|
|||||||
|
|
||||||
src = (unsigned int*) psp_texture->data;
|
src = (unsigned int*) psp_texture->data;
|
||||||
|
|
||||||
|
data = dst;
|
||||||
|
if(!data) {
|
||||||
data = SDL_malloc(psp_texture->size);
|
data = SDL_malloc(psp_texture->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!data) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
|
||||||
for(j = 0; j < height; j++, blockaddress += 16)
|
for(j = 0; j < height; j++, blockaddress += 16)
|
||||||
{
|
{
|
||||||
@ -272,7 +320,7 @@ TextureSwizzle(PSP_TextureData *psp_texture)
|
|||||||
blockaddress += rowblocksadd;
|
blockaddress += rowblocksadd;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_free(psp_texture->data);
|
TextureStorageFree(psp_texture->data);
|
||||||
psp_texture->data = data;
|
psp_texture->data = data;
|
||||||
psp_texture->swizzled = SDL_TRUE;
|
psp_texture->swizzled = SDL_TRUE;
|
||||||
|
|
||||||
@ -281,7 +329,7 @@ TextureSwizzle(PSP_TextureData *psp_texture)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
TextureUnswizzle(PSP_TextureData *psp_texture)
|
TextureUnswizzle(PSP_TextureData *psp_texture, void* dst)
|
||||||
{
|
{
|
||||||
int bytewidth, height;
|
int bytewidth, height;
|
||||||
int widthblocks, heightblocks;
|
int widthblocks, heightblocks;
|
||||||
@ -306,10 +354,14 @@ TextureUnswizzle(PSP_TextureData *psp_texture)
|
|||||||
|
|
||||||
src = (unsigned int*) psp_texture->data;
|
src = (unsigned int*) psp_texture->data;
|
||||||
|
|
||||||
|
data = dst;
|
||||||
|
|
||||||
|
if(!data) {
|
||||||
data = SDL_malloc(psp_texture->size);
|
data = SDL_malloc(psp_texture->size);
|
||||||
|
}
|
||||||
|
|
||||||
if(!data)
|
if(!data)
|
||||||
return 0;
|
return SDL_OutOfMemory();
|
||||||
|
|
||||||
ydst = (unsigned char *)data;
|
ydst = (unsigned char *)data;
|
||||||
|
|
||||||
@ -338,7 +390,7 @@ TextureUnswizzle(PSP_TextureData *psp_texture)
|
|||||||
ydst += dstrow;
|
ydst += dstrow;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_free(psp_texture->data);
|
TextureStorageFree(psp_texture->data);
|
||||||
|
|
||||||
psp_texture->data = data;
|
psp_texture->data = data;
|
||||||
|
|
||||||
@ -348,6 +400,80 @@ TextureUnswizzle(PSP_TextureData *psp_texture)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
TextureSpillToSram(PSP_RenderData* data, PSP_TextureData* psp_texture)
|
||||||
|
{
|
||||||
|
// Assumes the texture is in VRAM
|
||||||
|
if(psp_texture->swizzled) {
|
||||||
|
//Texture was swizzled in vram, just copy to system memory
|
||||||
|
void* data = SDL_malloc(psp_texture->size);
|
||||||
|
if(!data) {
|
||||||
|
return SDL_OutOfMemory();
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_memcpy(data, psp_texture->data, psp_texture->size);
|
||||||
|
vfree(psp_texture->data);
|
||||||
|
psp_texture->data = data;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return TextureSwizzle(psp_texture, NULL); //Will realloc in sysram
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
TexturePromoteToVram(PSP_RenderData* data, PSP_TextureData* psp_texture, SDL_bool target)
|
||||||
|
{
|
||||||
|
// Assumes texture in sram and a large enough continuous block in vram
|
||||||
|
void* tdata = valloc(psp_texture->size);
|
||||||
|
if(psp_texture->swizzled && target) {
|
||||||
|
return TextureUnswizzle(psp_texture, tdata);
|
||||||
|
} else {
|
||||||
|
SDL_memcpy(tdata, psp_texture->data, psp_texture->size);
|
||||||
|
SDL_free(psp_texture->data);
|
||||||
|
psp_texture->data = tdata;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
TextureSpillLRU(PSP_RenderData* data) {
|
||||||
|
PSP_TextureData* lru = data->least_recent_target;
|
||||||
|
if(lru) {
|
||||||
|
if(TextureSpillToSram(data, lru) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
LRUTargetRemove(data, lru);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
TextureSpillTargetsForSpace(PSP_RenderData* data, size_t size)
|
||||||
|
{
|
||||||
|
while(vlargestblock() < size) {
|
||||||
|
if(TextureSpillLRU(data) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
TextureBindAsTarget(PSP_RenderData* data, PSP_TextureData* psp_texture) {
|
||||||
|
if(!InVram(psp_texture->data)) {
|
||||||
|
// Bring back the texture in vram
|
||||||
|
if(TextureSpillTargetsForSpace(data, psp_texture->size) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(TexturePromoteToVram(data, psp_texture, SDL_TRUE) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LRUTargetBringFront(data, psp_texture);
|
||||||
|
sceGuDrawBufferList(psp_texture->format, vrelptr(psp_texture->data), psp_texture->textureWidth);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
PSP_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
|
PSP_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
|
||||||
{
|
{
|
||||||
@ -357,7 +483,7 @@ PSP_WindowEvent(SDL_Renderer * renderer, const SDL_WindowEvent *event)
|
|||||||
static int
|
static int
|
||||||
PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
{
|
{
|
||||||
/* PSP_RenderData *renderdata = (PSP_RenderData *) renderer->driverdata; */
|
PSP_RenderData *data = renderer->driverdata;
|
||||||
PSP_TextureData* psp_texture = (PSP_TextureData*) SDL_calloc(1, sizeof(*psp_texture));
|
PSP_TextureData* psp_texture = (PSP_TextureData*) SDL_calloc(1, sizeof(*psp_texture));
|
||||||
|
|
||||||
if(!psp_texture)
|
if(!psp_texture)
|
||||||
@ -389,7 +515,13 @@ PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||||||
psp_texture->pitch = psp_texture->textureWidth * SDL_BYTESPERPIXEL(texture->format);
|
psp_texture->pitch = psp_texture->textureWidth * SDL_BYTESPERPIXEL(texture->format);
|
||||||
psp_texture->size = psp_texture->textureHeight*psp_texture->pitch;
|
psp_texture->size = psp_texture->textureHeight*psp_texture->pitch;
|
||||||
if(texture->access & SDL_TEXTUREACCESS_TARGET) {
|
if(texture->access & SDL_TEXTUREACCESS_TARGET) {
|
||||||
|
if(TextureSpillTargetsForSpace(renderer->driverdata, psp_texture->size) < 0){
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
psp_texture->data = valloc(psp_texture->size);
|
psp_texture->data = valloc(psp_texture->size);
|
||||||
|
if(psp_texture->data) {
|
||||||
|
LRUTargetPushFront(data, psp_texture);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
psp_texture->data = SDL_calloc(1, psp_texture->size);
|
psp_texture->data = SDL_calloc(1, psp_texture->size);
|
||||||
}
|
}
|
||||||
@ -426,7 +558,7 @@ TextureActivate(SDL_Texture * texture)
|
|||||||
/* Swizzling is useless with small textures. */
|
/* Swizzling is useless with small textures. */
|
||||||
if (TextureShouldSwizzle(psp_texture, texture))
|
if (TextureShouldSwizzle(psp_texture, texture))
|
||||||
{
|
{
|
||||||
TextureSwizzle(psp_texture);
|
TextureSwizzle(psp_texture, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
sceGuEnable(GU_TEXTURE_2D);
|
sceGuEnable(GU_TEXTURE_2D);
|
||||||
@ -812,6 +944,34 @@ PSP_QueueCopyEx(SDL_Renderer * renderer, SDL_RenderCommand *cmd, SDL_Texture * t
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
StartDrawing(SDL_Renderer * renderer)
|
||||||
|
{
|
||||||
|
PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
|
||||||
|
|
||||||
|
// Check if we need to start GU displaylist
|
||||||
|
if(!data->displayListAvail) {
|
||||||
|
sceGuStart(GU_DIRECT, DisplayList);
|
||||||
|
data->displayListAvail = SDL_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we need a draw buffer change
|
||||||
|
if(renderer->target != data->boundTarget) {
|
||||||
|
SDL_Texture* texture = renderer->target;
|
||||||
|
if(texture) {
|
||||||
|
PSP_TextureData* psp_texture = (PSP_TextureData*) texture->driverdata;
|
||||||
|
// Set target, registering LRU
|
||||||
|
TextureBindAsTarget(data, psp_texture);
|
||||||
|
} else {
|
||||||
|
// Set target back to screen
|
||||||
|
sceGuDrawBufferList(data->psm, vrelptr(data->frontbuffer), PSP_FRAME_BUFFER_WIDTH);
|
||||||
|
}
|
||||||
|
data->boundTarget = texture;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
PSP_SetBlendMode(SDL_Renderer * renderer, int blendMode)
|
PSP_SetBlendMode(SDL_Renderer * renderer, int blendMode)
|
||||||
{
|
{
|
||||||
@ -1072,11 +1232,7 @@ PSP_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
|||||||
if(psp_texture == 0)
|
if(psp_texture == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(InVram(psp_texture->data)) {
|
TextureStorageFree(psp_texture->data);
|
||||||
vfree(psp_texture->data);
|
|
||||||
} else {
|
|
||||||
SDL_free(psp_texture->data);
|
|
||||||
}
|
|
||||||
SDL_free(psp_texture);
|
SDL_free(psp_texture);
|
||||||
texture->driverdata = NULL;
|
texture->driverdata = NULL;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user