Skip to content

Commit 67141e5

Browse files
Wohlstandslouken
authored andcommitted
SDL_render_psp.c: Implemented working viewport support
Since it's no known way to use genuine viewport with PSP SDK, I implemented the workaround using manually added/subtracted offsets to vertices passing to the render API. To assign viewport and cliprect in valid way, I copied part of code from the Vita's module and adjusted it to work on PSP.
1 parent 641201a commit 67141e5

File tree

1 file changed

+181
-16
lines changed

1 file changed

+181
-16
lines changed

src/render/psp/SDL_render_psp.c

Lines changed: 181 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,26 @@ typedef struct
7676
SDL_Texture *texture;
7777
} PSP_BlendState;
7878

79+
typedef struct
80+
{
81+
SDL_Rect viewport;
82+
SDL_bool viewport_dirty;
83+
SDL_bool viewport_is_set;
84+
85+
SDL_bool cliprect_enabled_dirty;
86+
SDL_bool cliprect_enabled;
87+
SDL_bool cliprect_dirty;
88+
SDL_Rect cliprect;
89+
90+
SDL_Texture *target;
91+
92+
float draw_offset_x;
93+
float draw_offset_y;
94+
95+
int drawablew;
96+
int drawableh;
97+
} PSP_DrawstateCache;
98+
7999
typedef struct
80100
{
81101
void *frontbuffer; /**< main screen buffer */
@@ -91,6 +111,7 @@ typedef struct
91111
PSP_TextureData *most_recent_target; /**< start of render target LRU double linked list */
92112
PSP_TextureData *least_recent_target; /**< end of the LRU list */
93113

114+
PSP_DrawstateCache drawstate;
94115
SDL_bool vblank_not_reached; /**< whether vblank wasn't reached */
95116
} PSP_RenderData;
96117

@@ -1034,10 +1055,104 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state)
10341055
*current = *state;
10351056
}
10361057

1058+
static void ClampCliprectToViewport(SDL_Rect *clip, const SDL_Rect *viewport)
1059+
{
1060+
int max_x_v, max_y_v, max_x_c, max_y_c;
1061+
1062+
if (clip->x < 0) {
1063+
clip->w += clip->x;
1064+
clip->x = 0;
1065+
}
1066+
1067+
if (clip->y < 0) {
1068+
clip->h += clip->y;
1069+
clip->y = 0;
1070+
}
1071+
1072+
max_x_c = clip->x + clip->w;
1073+
max_y_c = clip->y + clip->h;
1074+
1075+
max_x_v = viewport->x + viewport->w;
1076+
max_y_v = viewport->y + viewport->h;
1077+
1078+
if (max_x_c > max_x_v) {
1079+
clip->w -= (max_x_v - max_x_c);
1080+
}
1081+
1082+
if (max_y_c > max_y_v) {
1083+
clip->h -= (max_y_v - max_y_c);
1084+
}
1085+
}
1086+
1087+
static void SetDrawState(PSP_RenderData *data)
1088+
{
1089+
if (data->drawstate.viewport_dirty) {
1090+
SDL_Rect *viewport = &data->drawstate.viewport;
1091+
/* FIXME: Find a genuine way to make viewport work (right now calling these functions here give no effect) */
1092+
/*
1093+
sceGuOffset(2048 - (480 >> 1) + viewport->x, 2048 - (272 >> 1) + viewport->y);
1094+
sceGuViewport(2048, 2048, viewport->w, viewport->h);
1095+
*/
1096+
data->drawstate.draw_offset_x = viewport->x;
1097+
data->drawstate.draw_offset_y = viewport->y;
1098+
data->drawstate.viewport_dirty = SDL_FALSE;
1099+
}
1100+
1101+
if (data->drawstate.cliprect_enabled_dirty) {
1102+
if (!data->drawstate.cliprect_enabled && !data->drawstate.viewport_is_set) {
1103+
sceGuDisable(GU_SCISSOR_TEST);
1104+
}
1105+
data->drawstate.cliprect_enabled_dirty = SDL_FALSE;
1106+
}
1107+
1108+
if ((data->drawstate.cliprect_enabled || data->drawstate.viewport_is_set) && data->drawstate.cliprect_dirty) {
1109+
SDL_Rect rect;
1110+
SDL_Rect *viewport = &data->drawstate.viewport;
1111+
SDL_copyp(&rect, &data->drawstate.cliprect);
1112+
if (data->drawstate.viewport_is_set) {
1113+
ClampCliprectToViewport(&rect, viewport);
1114+
rect.x += viewport->x;
1115+
rect.y += viewport->y;
1116+
}
1117+
sceGuEnable(GU_SCISSOR_TEST);
1118+
sceGuScissor(rect.x, rect.y, rect.w, rect.h);
1119+
data->drawstate.cliprect_dirty = SDL_FALSE;
1120+
}
1121+
}
1122+
1123+
#define PSP_VERTICES_FUNK(FunkName, Type) \
1124+
static const Type *FunkName(const PSP_DrawstateCache *drawstate, Uint8 *gpumem, SDL_RenderCommand *cmd, size_t count) \
1125+
{ \
1126+
size_t i; \
1127+
float off_x, off_y; \
1128+
Type *verts = (Type *)(gpumem + cmd->data.draw.first); \
1129+
\
1130+
if (!drawstate->viewport_is_set) { \
1131+
return verts; \
1132+
} \
1133+
\
1134+
off_x = drawstate->draw_offset_x; \
1135+
off_y = drawstate->draw_offset_y; \
1136+
\
1137+
for (i = 0; i < count; ++i) { \
1138+
verts[i].x += off_x; \
1139+
verts[i].y += off_y; \
1140+
} \
1141+
\
1142+
return verts;\
1143+
}
1144+
1145+
PSP_VERTICES_FUNK(PSP_GetVertV, VertV)
1146+
PSP_VERTICES_FUNK(PSP_GetVertTV, VertTV)
1147+
PSP_VERTICES_FUNK(PSP_GetVertCV, VertCV)
1148+
PSP_VERTICES_FUNK(PSP_GetVertTCV, VertTCV)
1149+
10371150
static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
10381151
{
10391152
PSP_RenderData *data = (PSP_RenderData *)renderer->driverdata;
10401153
Uint8 *gpumem = NULL;
1154+
int w = 0, h = 0;
1155+
10411156
StartDrawing(renderer);
10421157

10431158
/* note that before the renderer interface change, this would do extrememly small
@@ -1052,6 +1167,23 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
10521167
}
10531168
SDL_memcpy(gpumem, vertices, vertsize);
10541169

1170+
data->drawstate.target = renderer->target;
1171+
if (!data->drawstate.target) {
1172+
SDL_GL_GetDrawableSize(renderer->window, &w, &h);
1173+
} else {
1174+
if (SDL_QueryTexture(renderer->target, NULL, NULL, &w, &h) < 0) {
1175+
w = data->drawstate.drawablew;
1176+
h = data->drawstate.drawableh;
1177+
}
1178+
}
1179+
1180+
if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
1181+
data->drawstate.viewport_dirty = SDL_TRUE; /* if the window dimensions changed, invalidate the current viewport, etc. */
1182+
data->drawstate.cliprect_dirty = SDL_TRUE;
1183+
data->drawstate.drawablew = w;
1184+
data->drawstate.drawableh = h;
1185+
}
1186+
10551187
while (cmd) {
10561188
switch (cmd->command) {
10571189
case SDL_RENDERCMD_SETDRAWCOLOR:
@@ -1061,22 +1193,42 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
10611193

10621194
case SDL_RENDERCMD_SETVIEWPORT:
10631195
{
1064-
SDL_Rect *viewport = &cmd->data.viewport.rect;
1065-
sceGuOffset(2048 - (viewport->w >> 1), 2048 - (viewport->h >> 1));
1066-
sceGuViewport(2048, 2048, viewport->w, viewport->h);
1067-
sceGuScissor(viewport->x, viewport->y, viewport->w, viewport->h);
1068-
/* FIXME: We need to update the clip rect too, see https://github.com/libsdl-org/SDL/issues/9094 */
1196+
SDL_Rect *viewport = &data->drawstate.viewport;
1197+
if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(cmd->data.viewport.rect)) != 0) {
1198+
SDL_copyp(viewport, &cmd->data.viewport.rect);
1199+
data->drawstate.viewport_dirty = SDL_TRUE;
1200+
data->drawstate.cliprect_dirty = SDL_TRUE;
1201+
data->drawstate.viewport_is_set = viewport->x != 0 || viewport->y != 0 || viewport->w != data->drawstate.drawablew || viewport->h != data->drawstate.drawableh;
1202+
if (!data->drawstate.cliprect_enabled) {
1203+
if (data->drawstate.viewport_is_set) {
1204+
SDL_copyp(&data->drawstate.cliprect, viewport);
1205+
data->drawstate.cliprect.x = 0;
1206+
data->drawstate.cliprect.y = 0;
1207+
} else {
1208+
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
1209+
}
1210+
}
1211+
}
10691212
break;
10701213
}
10711214

10721215
case SDL_RENDERCMD_SETCLIPRECT:
10731216
{
10741217
const SDL_Rect *rect = &cmd->data.cliprect.rect;
1075-
if (cmd->data.cliprect.enabled) {
1076-
sceGuEnable(GU_SCISSOR_TEST);
1077-
sceGuScissor(rect->x, rect->y, rect->w, rect->h);
1078-
} else {
1079-
sceGuDisable(GU_SCISSOR_TEST);
1218+
const SDL_Rect *viewport = &data->drawstate.viewport;
1219+
if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
1220+
data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
1221+
data->drawstate.cliprect_enabled_dirty = SDL_TRUE;
1222+
if (!data->drawstate.cliprect_enabled && data->drawstate.viewport_is_set) {
1223+
SDL_copyp(&data->drawstate.cliprect, viewport);
1224+
data->drawstate.cliprect.x = 0;
1225+
data->drawstate.cliprect.y = 0;
1226+
}
1227+
}
1228+
1229+
if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof(*rect)) != 0) {
1230+
SDL_copyp(&data->drawstate.cliprect, rect);
1231+
data->drawstate.cliprect_dirty = SDL_TRUE;
10801232
}
10811233
break;
10821234
}
@@ -1087,6 +1239,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
10871239
const Uint8 g = cmd->data.color.g;
10881240
const Uint8 b = cmd->data.color.b;
10891241
const Uint8 a = cmd->data.color.a;
1242+
SetDrawState(data);
10901243
sceGuClearColor(GU_RGBA(r, g, b, a));
10911244
sceGuClearStencil(a);
10921245
sceGuClear(GU_COLOR_BUFFER_BIT | GU_STENCIL_BUFFER_BIT);
@@ -1096,7 +1249,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
10961249
case SDL_RENDERCMD_DRAW_POINTS:
10971250
{
10981251
const size_t count = cmd->data.draw.count;
1099-
const VertV *verts = (VertV *)(gpumem + cmd->data.draw.first);
1252+
const VertV *verts; /* = (VertV *)(gpumem + cmd->data.draw.first);*/
11001253
const Uint8 r = cmd->data.draw.r;
11011254
const Uint8 g = cmd->data.draw.g;
11021255
const Uint8 b = cmd->data.draw.b;
@@ -1107,6 +1260,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
11071260
.mode = cmd->data.draw.blend,
11081261
.shadeModel = GU_FLAT
11091262
};
1263+
SetDrawState(data);
1264+
verts = PSP_GetVertV(&data->drawstate, gpumem, cmd, count);
11101265
PSP_SetBlendState(data, &state);
11111266
sceGuDrawArray(GU_POINTS, GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
11121267
break;
@@ -1115,7 +1270,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
11151270
case SDL_RENDERCMD_DRAW_LINES:
11161271
{
11171272
const size_t count = cmd->data.draw.count;
1118-
const VertV *verts = (VertV *)(gpumem + cmd->data.draw.first);
1273+
const VertV *verts; /* = (VertV *)(gpumem + cmd->data.draw.first);*/
11191274
const Uint8 r = cmd->data.draw.r;
11201275
const Uint8 g = cmd->data.draw.g;
11211276
const Uint8 b = cmd->data.draw.b;
@@ -1126,6 +1281,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
11261281
.mode = cmd->data.draw.blend,
11271282
.shadeModel = GU_FLAT
11281283
};
1284+
SetDrawState(data);
1285+
verts = PSP_GetVertV(&data->drawstate, gpumem, cmd, count);
11291286
PSP_SetBlendState(data, &state);
11301287
sceGuDrawArray(GU_LINE_STRIP, GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
11311288
break;
@@ -1134,7 +1291,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
11341291
case SDL_RENDERCMD_FILL_RECTS:
11351292
{
11361293
const size_t count = cmd->data.draw.count;
1137-
const VertV *verts = (VertV *)(gpumem + cmd->data.draw.first);
1294+
const VertV *verts; /* = (VertV *)(gpumem + cmd->data.draw.first);*/
11381295
const Uint8 r = cmd->data.draw.r;
11391296
const Uint8 g = cmd->data.draw.g;
11401297
const Uint8 b = cmd->data.draw.b;
@@ -1145,6 +1302,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
11451302
.mode = cmd->data.draw.blend,
11461303
.shadeModel = GU_FLAT
11471304
};
1305+
SetDrawState(data);
1306+
verts = PSP_GetVertV(&data->drawstate, gpumem, cmd, 2 * count);
11481307
PSP_SetBlendState(data, &state);
11491308
sceGuDrawArray(GU_SPRITES, GU_VERTEX_32BITF | GU_TRANSFORM_2D, 2 * count, 0, verts);
11501309
break;
@@ -1153,7 +1312,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
11531312
case SDL_RENDERCMD_COPY:
11541313
{
11551314
const size_t count = cmd->data.draw.count;
1156-
const VertTV *verts = (VertTV *)(gpumem + cmd->data.draw.first);
1315+
const VertTV *verts; /*= (VertTV *)(gpumem + cmd->data.draw.first);*/
11571316
const Uint8 a = cmd->data.draw.a;
11581317
const Uint8 r = cmd->data.draw.r;
11591318
const Uint8 g = cmd->data.draw.g;
@@ -1164,6 +1323,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
11641323
.mode = cmd->data.draw.blend,
11651324
.shadeModel = GU_SMOOTH
11661325
};
1326+
SetDrawState(data);
1327+
verts = PSP_GetVertTV(&data->drawstate, gpumem, cmd, 2 * count);
11671328
PSP_SetBlendState(data, &state);
11681329
sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 2 * count, 0, verts);
11691330
break;
@@ -1182,6 +1343,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
11821343
.mode = cmd->data.draw.blend,
11831344
.shadeModel = GU_SMOOTH
11841345
};
1346+
SetDrawState(data);
1347+
verts = PSP_GetVertTV(&data->drawstate, gpumem, cmd, 4);
11851348
PSP_SetBlendState(data, &state);
11861349
sceGuDrawArray(GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 4, 0, verts);
11871350
break;
@@ -1190,14 +1353,15 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
11901353
case SDL_RENDERCMD_GEOMETRY:
11911354
{
11921355
const size_t count = cmd->data.draw.count;
1356+
SetDrawState(data);
11931357
if (!cmd->data.draw.texture) {
1194-
const VertCV *verts = (VertCV *)(gpumem + cmd->data.draw.first);
1358+
const VertCV *verts = PSP_GetVertCV(&data->drawstate, gpumem, cmd, count);
11951359
sceGuDisable(GU_TEXTURE_2D);
11961360
/* In GU_SMOOTH mode */
11971361
sceGuDrawArray(GU_TRIANGLES, GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
11981362
sceGuEnable(GU_TEXTURE_2D);
11991363
} else {
1200-
const VertTCV *verts = (VertTCV *)(gpumem + cmd->data.draw.first);
1364+
const VertTCV *verts; /*= (VertTCV *)(gpumem + cmd->data.draw.first);*/
12011365
const Uint8 a = cmd->data.draw.a;
12021366
const Uint8 r = cmd->data.draw.r;
12031367
const Uint8 g = cmd->data.draw.g;
@@ -1208,6 +1372,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
12081372
.mode = cmd->data.draw.blend,
12091373
.shadeModel = GU_FLAT
12101374
};
1375+
verts = PSP_GetVertTCV(&data->drawstate, gpumem, cmd, count);
12111376
TextureActivate(cmd->data.draw.texture);
12121377
PSP_SetBlendState(data, &state);
12131378
sceGuDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);

0 commit comments

Comments
 (0)