Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
194 changes: 178 additions & 16 deletions src/render/psp/SDL_render_psp.c
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,24 @@ typedef struct
SDL_Texture *texture;
} PSP_BlendState;

typedef struct
{
SDL_Rect viewport;
SDL_bool viewport_dirty;
SDL_bool viewport_is_set;

SDL_bool cliprect_enabled_dirty;
SDL_bool cliprect_enabled;
SDL_bool cliprect_dirty;
SDL_Rect cliprect;

float draw_offset_x;
float draw_offset_y;

int drawablew;
int drawableh;
} PSP_DrawstateCache;

typedef struct
{
void *frontbuffer; /**< main screen buffer */
Expand All @@ -91,6 +109,7 @@ typedef struct
PSP_TextureData *most_recent_target; /**< start of render target LRU double linked list */
PSP_TextureData *least_recent_target; /**< end of the LRU list */

PSP_DrawstateCache drawstate;
SDL_bool vblank_not_reached; /**< whether vblank wasn't reached */
} PSP_RenderData;

Expand Down Expand Up @@ -1034,10 +1053,105 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state)
*current = *state;
}

static void ClampCliprectToViewport(SDL_Rect *clip, const SDL_Rect *viewport)
{
int max_x_v, max_y_v, max_x_c, max_y_c;

if (clip->x < 0) {
clip->w += clip->x;
clip->x = 0;
}

if (clip->y < 0) {
clip->h += clip->y;
clip->y = 0;
}

max_x_c = clip->x + clip->w;
max_y_c = clip->y + clip->h;

max_x_v = viewport->x + viewport->w;
max_y_v = viewport->y + viewport->h;

if (max_x_c > max_x_v) {
clip->w -= (max_x_v - max_x_c);
}

if (max_y_c > max_y_v) {
clip->h -= (max_y_v - max_y_c);
}
}

static void SetDrawState(PSP_RenderData *data)
{
if (data->drawstate.viewport_dirty) {
SDL_Rect *viewport = &data->drawstate.viewport;
/* FIXME: Find a genuine way to make viewport work (right now calling these functions here give no effect) */
/*
sceGuOffset(2048 - (480 >> 1) + viewport->x, 2048 - (272 >> 1) + viewport->y);
sceGuViewport(2048, 2048, viewport->w, viewport->h);
*/
data->drawstate.draw_offset_x = viewport->x;
data->drawstate.draw_offset_y = viewport->y;
data->drawstate.viewport_dirty = SDL_FALSE;
}

if (data->drawstate.cliprect_enabled_dirty) {
if (!data->drawstate.cliprect_enabled && !data->drawstate.viewport_is_set) {
sceGuScissor(0, 0, data->drawstate.drawablew, data->drawstate.drawableh);
sceGuEnable(GU_SCISSOR_TEST);
}
data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
}

if ((data->drawstate.cliprect_enabled || data->drawstate.viewport_is_set) && data->drawstate.cliprect_dirty) {
SDL_Rect rect;
SDL_Rect *viewport = &data->drawstate.viewport;
SDL_copyp(&rect, &data->drawstate.cliprect);
if (data->drawstate.viewport_is_set) {
ClampCliprectToViewport(&rect, viewport);
rect.x += viewport->x;
rect.y += viewport->y;
}
sceGuEnable(GU_SCISSOR_TEST);
sceGuScissor(rect.x, rect.y, rect.w, rect.h);
data->drawstate.cliprect_dirty = SDL_FALSE;
}
}

#define PSP_VERTICES_FUNK(FunkName, Type) \
static const Type *FunkName(const PSP_DrawstateCache *drawstate, Uint8 *gpumem, SDL_RenderCommand *cmd, size_t count) \
{ \
size_t i; \
float off_x, off_y; \
Type *verts = (Type *)(gpumem + cmd->data.draw.first); \
\
if (!drawstate->viewport_is_set) { \
return verts; \
} \
\
off_x = drawstate->draw_offset_x; \
off_y = drawstate->draw_offset_y; \
\
for (i = 0; i < count; ++i) { \
verts[i].x += off_x; \
verts[i].y += off_y; \
} \
\
return verts;\
}

PSP_VERTICES_FUNK(PSP_GetVertV, VertV)
PSP_VERTICES_FUNK(PSP_GetVertTV, VertTV)
PSP_VERTICES_FUNK(PSP_GetVertCV, VertCV)
PSP_VERTICES_FUNK(PSP_GetVertTCV, VertTCV)

static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
{
PSP_RenderData *data = (PSP_RenderData *)renderer->driverdata;
Uint8 *gpumem = NULL;
int w = 0, h = 0;

StartDrawing(renderer);

/* note that before the renderer interface change, this would do extrememly small
Expand All @@ -1052,6 +1166,21 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
}
SDL_memcpy(gpumem, vertices, vertsize);

if (!data->boundTarget) {
SDL_GL_GetDrawableSize(renderer->window, &w, &h);
} else {
PSP_TextureData *psp_texture = (PSP_TextureData *)data->boundTarget->driverdata;
w = psp_texture->width;
h = psp_texture->height;
}

if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
data->drawstate.viewport_dirty = SDL_TRUE; /* if the window dimensions changed, invalidate the current viewport, etc. */
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.drawablew = w;
data->drawstate.drawableh = h;
}

while (cmd) {
switch (cmd->command) {
case SDL_RENDERCMD_SETDRAWCOLOR:
Expand All @@ -1061,22 +1190,42 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v

case SDL_RENDERCMD_SETVIEWPORT:
{
SDL_Rect *viewport = &cmd->data.viewport.rect;
sceGuOffset(2048 - (viewport->w >> 1), 2048 - (viewport->h >> 1));
sceGuViewport(2048, 2048, viewport->w, viewport->h);
sceGuScissor(viewport->x, viewport->y, viewport->w, viewport->h);
/* FIXME: We need to update the clip rect too, see https://github.com/libsdl-org/SDL/issues/9094 */
SDL_Rect *viewport = &data->drawstate.viewport;
if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(cmd->data.viewport.rect)) != 0) {
SDL_copyp(viewport, &cmd->data.viewport.rect);
data->drawstate.viewport_dirty = SDL_TRUE;
data->drawstate.cliprect_dirty = SDL_TRUE;
data->drawstate.viewport_is_set = viewport->x != 0 || viewport->y != 0 || viewport->w != data->drawstate.drawablew || viewport->h != data->drawstate.drawableh;
if (!data->drawstate.cliprect_enabled) {
if (data->drawstate.viewport_is_set) {
SDL_copyp(&data->drawstate.cliprect, viewport);
data->drawstate.cliprect.x = 0;
data->drawstate.cliprect.y = 0;
} else {
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
}
}
}
break;
}

case SDL_RENDERCMD_SETCLIPRECT:
{
const SDL_Rect *rect = &cmd->data.cliprect.rect;
if (cmd->data.cliprect.enabled) {
sceGuEnable(GU_SCISSOR_TEST);
sceGuScissor(rect->x, rect->y, rect->w, rect->h);
} else {
sceGuDisable(GU_SCISSOR_TEST);
const SDL_Rect *viewport = &data->drawstate.viewport;
if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
if (!data->drawstate.cliprect_enabled && data->drawstate.viewport_is_set) {
SDL_copyp(&data->drawstate.cliprect, viewport);
data->drawstate.cliprect.x = 0;
data->drawstate.cliprect.y = 0;
}
}

if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof(*rect)) != 0) {
SDL_copyp(&data->drawstate.cliprect, rect);
data->drawstate.cliprect_dirty = SDL_TRUE;
}
break;
}
Expand All @@ -1087,6 +1236,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
const Uint8 g = cmd->data.color.g;
const Uint8 b = cmd->data.color.b;
const Uint8 a = cmd->data.color.a;
SetDrawState(data);
sceGuClearColor(GU_RGBA(r, g, b, a));
sceGuClearStencil(a);
sceGuClear(GU_COLOR_BUFFER_BIT | GU_STENCIL_BUFFER_BIT);
Expand All @@ -1096,7 +1246,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
case SDL_RENDERCMD_DRAW_POINTS:
{
const size_t count = cmd->data.draw.count;
const VertV *verts = (VertV *)(gpumem + cmd->data.draw.first);
const VertV *verts; /* = (VertV *)(gpumem + cmd->data.draw.first);*/
const Uint8 r = cmd->data.draw.r;
const Uint8 g = cmd->data.draw.g;
const Uint8 b = cmd->data.draw.b;
Expand All @@ -1107,6 +1257,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
.mode = cmd->data.draw.blend,
.shadeModel = GU_FLAT
};
SetDrawState(data);
verts = PSP_GetVertV(&data->drawstate, gpumem, cmd, count);
PSP_SetBlendState(data, &state);
sceGuDrawArray(GU_POINTS, GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
break;
Expand All @@ -1115,7 +1267,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
case SDL_RENDERCMD_DRAW_LINES:
{
const size_t count = cmd->data.draw.count;
const VertV *verts = (VertV *)(gpumem + cmd->data.draw.first);
const VertV *verts; /* = (VertV *)(gpumem + cmd->data.draw.first);*/
const Uint8 r = cmd->data.draw.r;
const Uint8 g = cmd->data.draw.g;
const Uint8 b = cmd->data.draw.b;
Expand All @@ -1126,6 +1278,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
.mode = cmd->data.draw.blend,
.shadeModel = GU_FLAT
};
SetDrawState(data);
verts = PSP_GetVertV(&data->drawstate, gpumem, cmd, count);
PSP_SetBlendState(data, &state);
sceGuDrawArray(GU_LINE_STRIP, GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
break;
Expand All @@ -1134,7 +1288,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
case SDL_RENDERCMD_FILL_RECTS:
{
const size_t count = cmd->data.draw.count;
const VertV *verts = (VertV *)(gpumem + cmd->data.draw.first);
const VertV *verts; /* = (VertV *)(gpumem + cmd->data.draw.first);*/
const Uint8 r = cmd->data.draw.r;
const Uint8 g = cmd->data.draw.g;
const Uint8 b = cmd->data.draw.b;
Expand All @@ -1145,6 +1299,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
.mode = cmd->data.draw.blend,
.shadeModel = GU_FLAT
};
SetDrawState(data);
verts = PSP_GetVertV(&data->drawstate, gpumem, cmd, 2 * count);
PSP_SetBlendState(data, &state);
sceGuDrawArray(GU_SPRITES, GU_VERTEX_32BITF | GU_TRANSFORM_2D, 2 * count, 0, verts);
break;
Expand All @@ -1153,7 +1309,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
case SDL_RENDERCMD_COPY:
{
const size_t count = cmd->data.draw.count;
const VertTV *verts = (VertTV *)(gpumem + cmd->data.draw.first);
const VertTV *verts; /*= (VertTV *)(gpumem + cmd->data.draw.first);*/
const Uint8 a = cmd->data.draw.a;
const Uint8 r = cmd->data.draw.r;
const Uint8 g = cmd->data.draw.g;
Expand All @@ -1164,6 +1320,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
.mode = cmd->data.draw.blend,
.shadeModel = GU_SMOOTH
};
SetDrawState(data);
verts = PSP_GetVertTV(&data->drawstate, gpumem, cmd, 2 * count);
PSP_SetBlendState(data, &state);
sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 2 * count, 0, verts);
break;
Expand All @@ -1182,6 +1340,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
.mode = cmd->data.draw.blend,
.shadeModel = GU_SMOOTH
};
SetDrawState(data);
verts = PSP_GetVertTV(&data->drawstate, gpumem, cmd, 4);
PSP_SetBlendState(data, &state);
sceGuDrawArray(GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 4, 0, verts);
break;
Expand All @@ -1190,14 +1350,15 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
case SDL_RENDERCMD_GEOMETRY:
{
const size_t count = cmd->data.draw.count;
SetDrawState(data);
if (!cmd->data.draw.texture) {
const VertCV *verts = (VertCV *)(gpumem + cmd->data.draw.first);
const VertCV *verts = PSP_GetVertCV(&data->drawstate, gpumem, cmd, count);
sceGuDisable(GU_TEXTURE_2D);
/* In GU_SMOOTH mode */
sceGuDrawArray(GU_TRIANGLES, GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
sceGuEnable(GU_TEXTURE_2D);
} else {
const VertTCV *verts = (VertTCV *)(gpumem + cmd->data.draw.first);
const VertTCV *verts; /*= (VertTCV *)(gpumem + cmd->data.draw.first);*/
const Uint8 a = cmd->data.draw.a;
const Uint8 r = cmd->data.draw.r;
const Uint8 g = cmd->data.draw.g;
Expand All @@ -1208,6 +1369,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
.mode = cmd->data.draw.blend,
.shadeModel = GU_FLAT
};
verts = PSP_GetVertTCV(&data->drawstate, gpumem, cmd, count);
TextureActivate(cmd->data.draw.texture);
PSP_SetBlendState(data, &state);
sceGuDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
Expand Down
Loading