Attempt to make render to texture work on PSP
parent
7967c97618
commit
77d874e3c0
|
@ -56,36 +56,13 @@ static unsigned int __attribute__((aligned(16))) DisplayList[262144];
|
||||||
#define COL4444(r,g,b,a) ((r>>4) | ((g>>4)<<4) | ((b>>4)<<8) | ((a>>4)<<12))
|
#define COL4444(r,g,b,a) ((r>>4) | ((g>>4)<<4) | ((b>>4)<<8) | ((a>>4)<<12))
|
||||||
#define COL8888(r,g,b,a) ((r) | ((g)<<8) | ((b)<<16) | ((a)<<24))
|
#define COL8888(r,g,b,a) ((r) | ((g)<<8) | ((b)<<16) | ((a)<<24))
|
||||||
|
|
||||||
typedef struct
|
/**
|
||||||
{
|
* Holds psp specific texture data
|
||||||
SDL_bool viewport_dirty;
|
*
|
||||||
SDL_Rect viewport;
|
* Part of a hot-list of textures that are used as render targets
|
||||||
SDL_bool cliprect_enabled_dirty;
|
* When short of vram we spill Least-Recently-Used render targets to system memory
|
||||||
SDL_bool cliprect_enabled;
|
*/
|
||||||
SDL_bool cliprect_dirty;
|
typedef struct PSP_TextureData
|
||||||
SDL_Rect cliprect;
|
|
||||||
} PSP_DrawStateCache;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
void* frontbuffer ;
|
|
||||||
void* backbuffer ;
|
|
||||||
SDL_bool initialized ;
|
|
||||||
SDL_bool displayListAvail ;
|
|
||||||
unsigned int psm ;
|
|
||||||
unsigned int bpp ;
|
|
||||||
|
|
||||||
SDL_bool vsync;
|
|
||||||
unsigned int currentColor;
|
|
||||||
int currentBlendMode;
|
|
||||||
|
|
||||||
PSP_DrawStateCache drawstate;
|
|
||||||
|
|
||||||
SDL_bool vblank_not_reached; /**< wether vblank wasn't reached */
|
|
||||||
} PSP_RenderData;
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
{
|
||||||
void *data; /**< Image data. */
|
void *data; /**< Image data. */
|
||||||
unsigned int size; /**< Size of data in bytes. */
|
unsigned int size; /**< Size of data in bytes. */
|
||||||
|
@ -97,9 +74,31 @@ typedef struct
|
||||||
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* nexthot; /**< Less recently used render target */
|
||||||
} PSP_TextureData;
|
} PSP_TextureData;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
void* frontbuffer; /**< main screen buffer */
|
||||||
|
void* backbuffer; /**< buffer presented to display */
|
||||||
|
SDL_Texture* boundTarget; /**< currently bound rendertarget */
|
||||||
|
SDL_bool initialized; /**< is driver initialized */
|
||||||
|
SDL_bool displayListAvail; /**< is the display list already initialized for this frame */
|
||||||
|
unsigned int psm; /**< format of the display buffers */
|
||||||
|
unsigned int bpp; /**< bits per pixel of the main display */
|
||||||
|
|
||||||
|
SDL_bool vsync; /**< wether we do vsync */
|
||||||
|
unsigned int currentColor; /**< current drawing color */
|
||||||
|
int currentBlendMode; /**< current blend mode */
|
||||||
|
PSP_TextureData* most_recent_target; /**< start of render target LRU double linked list */
|
||||||
|
PSP_TextureData* least_recent_target; /**< end of the LRU list */
|
||||||
|
|
||||||
|
SDL_bool vblank_not_reached; /**< wether vblank wasn't reached */
|
||||||
|
} PSP_RenderData;
|
||||||
|
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
float x, y, z;
|
float x, y, z;
|
||||||
|
@ -131,7 +130,8 @@ typedef struct
|
||||||
#define radToDeg(x) ((x)*180.f/PI)
|
#define radToDeg(x) ((x)*180.f/PI)
|
||||||
#define degToRad(x) ((x)*PI/180.f)
|
#define degToRad(x) ((x)*PI/180.f)
|
||||||
|
|
||||||
float MathAbs(float x)
|
static float
|
||||||
|
MathAbs(float x)
|
||||||
{
|
{
|
||||||
float result;
|
float result;
|
||||||
|
|
||||||
|
@ -144,7 +144,8 @@ float MathAbs(float x)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MathSincos(float r, float *s, float *c)
|
static void
|
||||||
|
MathSincos(float r, float *s, float *c)
|
||||||
{
|
{
|
||||||
__asm__ volatile (
|
__asm__ volatile (
|
||||||
"mtv %2, S002\n"
|
"mtv %2, S002\n"
|
||||||
|
@ -156,7 +157,8 @@ void MathSincos(float r, float *s, float *c)
|
||||||
: "=r"(*s), "=r"(*c): "r"(r));
|
: "=r"(*s), "=r"(*c): "r"(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Swap(float *a, float *b)
|
static void
|
||||||
|
Swap(float *a, float *b)
|
||||||
{
|
{
|
||||||
float n=*a;
|
float n=*a;
|
||||||
*a = *b;
|
*a = *b;
|
||||||
|
@ -201,19 +203,34 @@ PixelFormatToPSPFMT(Uint32 format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
StartDrawing(SDL_Renderer * renderer)
|
StartDrawing(SDL_Renderer * renderer)
|
||||||
{
|
{
|
||||||
PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
|
PSP_RenderData *data = (PSP_RenderData *) renderer->driverdata;
|
||||||
if(data->displayListAvail)
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
// Check if we need to start GU displaylist
|
||||||
|
if(!data->displayListAvail) {
|
||||||
sceGuStart(GU_DIRECT, DisplayList);
|
sceGuStart(GU_DIRECT, DisplayList);
|
||||||
data->displayListAvail = SDL_TRUE;
|
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 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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int
|
static int
|
||||||
TextureSwizzle(PSP_TextureData *psp_texture)
|
TextureSwizzle(PSP_TextureData *psp_texture)
|
||||||
{
|
{
|
||||||
int bytewidth, height;
|
int bytewidth, height;
|
||||||
|
@ -262,7 +279,9 @@ TextureSwizzle(PSP_TextureData *psp_texture)
|
||||||
sceKernelDcacheWritebackRange(psp_texture->data, psp_texture->size);
|
sceKernelDcacheWritebackRange(psp_texture->data, psp_texture->size);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
int TextureUnswizzle(PSP_TextureData *psp_texture)
|
|
||||||
|
static int
|
||||||
|
TextureUnswizzle(PSP_TextureData *psp_texture)
|
||||||
{
|
{
|
||||||
int bytewidth, height;
|
int bytewidth, height;
|
||||||
int widthblocks, heightblocks;
|
int widthblocks, heightblocks;
|
||||||
|
@ -369,7 +388,11 @@ 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) {
|
||||||
|
psp_texture->data = valloc(psp_texture->size);
|
||||||
|
} else {
|
||||||
psp_texture->data = SDL_calloc(1, psp_texture->size);
|
psp_texture->data = SDL_calloc(1, psp_texture->size);
|
||||||
|
}
|
||||||
|
|
||||||
if(!psp_texture->data)
|
if(!psp_texture->data)
|
||||||
{
|
{
|
||||||
|
@ -381,14 +404,27 @@ PSP_CreateTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static inline int
|
||||||
|
InVram(void* data)
|
||||||
|
{
|
||||||
|
return data < 0x04200000;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
TextureShouldSwizzle(PSP_TextureData* psp_texture, SDL_Texture *texture)
|
||||||
|
{
|
||||||
|
return !((texture->access == SDL_TEXTUREACCESS_TARGET) && InVram(psp_texture->data))
|
||||||
|
&& (texture->w >= 16 || texture->h >= 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
TextureActivate(SDL_Texture * texture)
|
TextureActivate(SDL_Texture * texture)
|
||||||
{
|
{
|
||||||
PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
|
PSP_TextureData *psp_texture = (PSP_TextureData *) texture->driverdata;
|
||||||
int scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GU_NEAREST : GU_LINEAR;
|
int scaleMode = (texture->scaleMode == SDL_ScaleModeNearest) ? GU_NEAREST : GU_LINEAR;
|
||||||
|
|
||||||
/* Swizzling is useless with small textures. */
|
/* Swizzling is useless with small textures. */
|
||||||
if (texture->w >= 16 || texture->h >= 16)
|
if (TextureShouldSwizzle(psp_texture, texture))
|
||||||
{
|
{
|
||||||
TextureSwizzle(psp_texture);
|
TextureSwizzle(psp_texture);
|
||||||
}
|
}
|
||||||
|
@ -837,23 +873,22 @@ PSP_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
|
||||||
}
|
}
|
||||||
|
|
||||||
case SDL_RENDERCMD_SETVIEWPORT: {
|
case SDL_RENDERCMD_SETVIEWPORT: {
|
||||||
SDL_Rect *viewport = &data->drawstate.viewport;
|
SDL_Rect *viewport = &cmd->data.viewport.rect;
|
||||||
if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect)) != 0) {
|
/* Viewport */
|
||||||
SDL_memcpy(viewport, &cmd->data.viewport.rect, sizeof (SDL_Rect));
|
sceGuOffset(2048 - (viewport->w >> 1), 2048 - (viewport->h >> 1));
|
||||||
data->drawstate.viewport_dirty = SDL_TRUE;
|
sceGuViewport(2048, 2048, viewport->w, viewport->h);
|
||||||
}
|
sceGuScissor(viewport->x, viewport->y, viewport->w, viewport->h);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SDL_RENDERCMD_SETCLIPRECT: {
|
case SDL_RENDERCMD_SETCLIPRECT: {
|
||||||
const SDL_Rect *rect = &cmd->data.cliprect.rect;
|
const SDL_Rect *rect = &cmd->data.cliprect.rect;
|
||||||
if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
|
/* Scissoring */
|
||||||
data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
|
if(cmd->data.cliprect.enabled){
|
||||||
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
|
sceGuEnable(GU_SCISSOR_TEST);
|
||||||
}
|
sceGuScissor(rect->x, rect->y, rect->w, rect->h);
|
||||||
if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof (SDL_Rect)) != 0) {
|
} else {
|
||||||
SDL_memcpy(&data->drawstate.cliprect, rect, sizeof (SDL_Rect));
|
sceGuDisable(GU_SCISSOR_TEST);
|
||||||
data->drawstate.cliprect_dirty = SDL_TRUE;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -866,8 +901,7 @@ PSP_RunCommandQueue(SDL_Renderer * renderer, SDL_RenderCommand *cmd, void *verti
|
||||||
const Uint32 color = (((Uint32)a << 24) | (b << 16) | (g << 8) | r);
|
const Uint32 color = (((Uint32)a << 24) | (b << 16) | (g << 8) | r);
|
||||||
/* !!! FIXME: we could cache drawstate like clear color */
|
/* !!! FIXME: we could cache drawstate like clear color */
|
||||||
sceGuClearColor(color);
|
sceGuClearColor(color);
|
||||||
sceGuClearDepth(0);
|
sceGuClear(GU_COLOR_BUFFER_BIT);//|GU_FAST_CLEAR_BIT);
|
||||||
sceGuClear(GU_COLOR_BUFFER_BIT|GU_DEPTH_BUFFER_BIT|GU_FAST_CLEAR_BIT);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1038,7 +1072,11 @@ PSP_DestroyTexture(SDL_Renderer * renderer, SDL_Texture * texture)
|
||||||
if(psp_texture == 0)
|
if(psp_texture == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if(InVram(psp_texture->data)) {
|
||||||
|
vfree(psp_texture->data);
|
||||||
|
} else {
|
||||||
SDL_free(psp_texture->data);
|
SDL_free(psp_texture->data);
|
||||||
|
}
|
||||||
SDL_free(psp_texture);
|
SDL_free(psp_texture);
|
||||||
texture->driverdata = NULL;
|
texture->driverdata = NULL;
|
||||||
}
|
}
|
||||||
|
@ -1058,8 +1096,8 @@ PSP_DestroyRenderer(SDL_Renderer * renderer)
|
||||||
sceDisplayWaitVblankStart();
|
sceDisplayWaitVblankStart();
|
||||||
sceGuDisplay(GU_FALSE);
|
sceGuDisplay(GU_FALSE);
|
||||||
sceGuTerm();
|
sceGuTerm();
|
||||||
/* vfree(data->backbuffer); */
|
vfree(data->backbuffer);
|
||||||
/* vfree(data->frontbuffer); */
|
vfree(data->frontbuffer);
|
||||||
|
|
||||||
data->initialized = SDL_FALSE;
|
data->initialized = SDL_FALSE;
|
||||||
data->displayListAvail = SDL_FALSE;
|
data->displayListAvail = SDL_FALSE;
|
||||||
|
@ -1083,6 +1121,8 @@ PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
SDL_Renderer *renderer;
|
SDL_Renderer *renderer;
|
||||||
PSP_RenderData *data;
|
PSP_RenderData *data;
|
||||||
int pixelformat;
|
int pixelformat;
|
||||||
|
void* doublebuffer = NULL;
|
||||||
|
|
||||||
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
|
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
|
||||||
if (!renderer) {
|
if (!renderer) {
|
||||||
SDL_OutOfMemory();
|
SDL_OutOfMemory();
|
||||||
|
@ -1127,6 +1167,9 @@ PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
return 0;
|
return 0;
|
||||||
data->initialized = SDL_TRUE;
|
data->initialized = SDL_TRUE;
|
||||||
|
|
||||||
|
data->most_recent_target = NULL;
|
||||||
|
data->least_recent_target = NULL;
|
||||||
|
|
||||||
if (flags & SDL_RENDERER_PRESENTVSYNC) {
|
if (flags & SDL_RENDERER_PRESENTVSYNC) {
|
||||||
data->vsync = SDL_TRUE;
|
data->vsync = SDL_TRUE;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1139,31 +1182,35 @@ PSP_CreateRenderer(SDL_Window * window, Uint32 flags)
|
||||||
case GU_PSM_4444:
|
case GU_PSM_4444:
|
||||||
case GU_PSM_5650:
|
case GU_PSM_5650:
|
||||||
case GU_PSM_5551:
|
case GU_PSM_5551:
|
||||||
data->frontbuffer = (unsigned int *)(PSP_FRAME_BUFFER_SIZE<<1);
|
//data->frontbuffer = (unsigned int *)(PSP_FRAME_BUFFER_SIZE<<1);
|
||||||
data->backbuffer = (unsigned int *)(0);
|
//data->backbuffer = (unsigned int *)(0);
|
||||||
data->bpp = 2;
|
data->bpp = 2;
|
||||||
data->psm = pixelformat;
|
data->psm = pixelformat;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
data->frontbuffer = (unsigned int *)(PSP_FRAME_BUFFER_SIZE<<2);
|
//data->frontbuffer = (unsigned int *)(PSP_FRAME_BUFFER_SIZE<<2);
|
||||||
data->backbuffer = (unsigned int *)(0);
|
//data->backbuffer = (unsigned int *)(0);
|
||||||
data->bpp = 4;
|
data->bpp = 4;
|
||||||
data->psm = GU_PSM_8888;
|
data->psm = GU_PSM_8888;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doublebuffer = valloc(PSP_FRAME_BUFFER_SIZE*data->bpp*2);
|
||||||
|
data->backbuffer = doublebuffer;
|
||||||
|
data->frontbuffer = ((uint8_t*)doublebuffer)+PSP_FRAME_BUFFER_SIZE*data->bpp;
|
||||||
|
|
||||||
sceGuInit();
|
sceGuInit();
|
||||||
/* setup GU */
|
/* setup GU */
|
||||||
sceGuStart(GU_DIRECT, DisplayList);
|
sceGuStart(GU_DIRECT, DisplayList);
|
||||||
sceGuDrawBuffer(data->psm, data->frontbuffer, PSP_FRAME_BUFFER_WIDTH);
|
sceGuDrawBuffer(data->psm, vrelptr(data->frontbuffer), PSP_FRAME_BUFFER_WIDTH);
|
||||||
sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, data->backbuffer, PSP_FRAME_BUFFER_WIDTH);
|
sceGuDispBuffer(PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT, vrelptr(data->backbuffer), PSP_FRAME_BUFFER_WIDTH);
|
||||||
|
|
||||||
|
|
||||||
sceGuOffset(2048 - (PSP_SCREEN_WIDTH>>1), 2048 - (PSP_SCREEN_HEIGHT>>1));
|
sceGuOffset(2048 - (PSP_SCREEN_WIDTH>>1), 2048 - (PSP_SCREEN_HEIGHT>>1));
|
||||||
sceGuViewport(2048, 2048, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT);
|
sceGuViewport(2048, 2048, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT);
|
||||||
|
|
||||||
data->frontbuffer = vabsptr(data->frontbuffer);
|
|
||||||
data->backbuffer = vabsptr(data->backbuffer);
|
sceGuDisable(GU_DEPTH_TEST);
|
||||||
|
|
||||||
/* Scissoring */
|
/* Scissoring */
|
||||||
sceGuScissor(0, 0, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT);
|
sceGuScissor(0, 0, PSP_SCREEN_WIDTH, PSP_SCREEN_HEIGHT);
|
||||||
|
|
Loading…
Reference in New Issue