Skip to content

Commit e3d6579

Browse files
Wohlstandslouken
authored andcommitted
SDL_render_psp.c: Implemented working viewport support
Backported from the SDL2 branch
1 parent baed512 commit e3d6579

File tree

1 file changed

+180
-27
lines changed

1 file changed

+180
-27
lines changed

src/render/psp/SDL_render_psp.c

Lines changed: 180 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,20 @@ typedef struct
8282

8383
typedef struct
8484
{
85+
SDL_Rect viewport;
86+
bool viewport_dirty;
87+
bool viewport_is_set;
88+
89+
bool cliprect_enabled_dirty;
90+
bool cliprect_enabled;
91+
bool cliprect_dirty;
92+
SDL_Rect cliprect;
93+
94+
float draw_offset_x;
95+
float draw_offset_y;
96+
97+
int drawablew;
98+
int drawableh;
8599
unsigned int color;
86100
} PSP_DrawStateCache;
87101

@@ -100,6 +114,7 @@ typedef struct
100114
PSP_TextureData *most_recent_target; /**< start of render target LRU double linked list */
101115
PSP_TextureData *least_recent_target; /**< end of the LRU list */
102116

117+
PSP_DrawStateCache drawstate;
103118
bool vblank_not_reached; /**< whether vblank wasn't reached */
104119
} PSP_RenderData;
105120

@@ -1074,13 +1089,104 @@ static void PSP_InvalidateCachedState(SDL_Renderer *renderer)
10741089
// currently this doesn't do anything. If this needs to do something (and someone is mixing their own rendering calls in!), update this.
10751090
}
10761091

1092+
static void ClampCliprectToViewport(SDL_Rect *clip, const SDL_Rect *viewport)
1093+
{
1094+
int max_x_v, max_y_v, max_x_c, max_y_c;
1095+
1096+
if (clip->x < 0) {
1097+
clip->w += clip->x;
1098+
clip->x = 0;
1099+
}
1100+
1101+
if (clip->y < 0) {
1102+
clip->h += clip->y;
1103+
clip->y = 0;
1104+
}
1105+
1106+
max_x_c = clip->x + clip->w;
1107+
max_y_c = clip->y + clip->h;
1108+
1109+
max_x_v = viewport->x + viewport->w;
1110+
max_y_v = viewport->y + viewport->h;
1111+
1112+
if (max_x_c > max_x_v) {
1113+
clip->w -= (max_x_v - max_x_c);
1114+
}
1115+
1116+
if (max_y_c > max_y_v) {
1117+
clip->h -= (max_y_v - max_y_c);
1118+
}
1119+
}
1120+
1121+
static void SetDrawState(PSP_RenderData *data)
1122+
{
1123+
if (data->drawstate.viewport_dirty) {
1124+
SDL_Rect *viewport = &data->drawstate.viewport;
1125+
/* FIXME: Find a genuine way to make viewport work (right now calling these functions here give no effect) */
1126+
/*
1127+
sceGuOffset(2048 - (480 >> 1) + viewport->x, 2048 - (272 >> 1) + viewport->y);
1128+
sceGuViewport(2048, 2048, viewport->w, viewport->h);
1129+
*/
1130+
data->drawstate.draw_offset_x = viewport->x;
1131+
data->drawstate.draw_offset_y = viewport->y;
1132+
data->drawstate.viewport_dirty = false;
1133+
}
1134+
1135+
if (data->drawstate.cliprect_enabled_dirty) {
1136+
if (!data->drawstate.cliprect_enabled && !data->drawstate.viewport_is_set) {
1137+
sceGuScissor(0, 0, data->drawstate.drawablew, data->drawstate.drawableh);
1138+
sceGuEnable(GU_SCISSOR_TEST);
1139+
}
1140+
data->drawstate.cliprect_enabled_dirty = false;
1141+
}
1142+
1143+
if ((data->drawstate.cliprect_enabled || data->drawstate.viewport_is_set) && data->drawstate.cliprect_dirty) {
1144+
SDL_Rect rect;
1145+
SDL_Rect *viewport = &data->drawstate.viewport;
1146+
SDL_copyp(&rect, &data->drawstate.cliprect);
1147+
if (data->drawstate.viewport_is_set) {
1148+
ClampCliprectToViewport(&rect, viewport);
1149+
rect.x += viewport->x;
1150+
rect.y += viewport->y;
1151+
}
1152+
sceGuEnable(GU_SCISSOR_TEST);
1153+
sceGuScissor(rect.x, rect.y, rect.w, rect.h);
1154+
data->drawstate.cliprect_dirty = false;
1155+
}
1156+
}
1157+
1158+
#define PSP_VERTICES_FUNK(FunkName, Type) \
1159+
static const Type *FunkName(const PSP_DrawStateCache *drawstate, Uint8 *gpumem, SDL_RenderCommand *cmd, size_t count) \
1160+
{ \
1161+
size_t i; \
1162+
float off_x, off_y; \
1163+
Type *verts = (Type *)(gpumem + cmd->data.draw.first); \
1164+
\
1165+
if (!drawstate->viewport_is_set) { \
1166+
return verts; \
1167+
} \
1168+
\
1169+
off_x = drawstate->draw_offset_x; \
1170+
off_y = drawstate->draw_offset_y; \
1171+
\
1172+
for (i = 0; i < count; ++i) { \
1173+
verts[i].x += off_x; \
1174+
verts[i].y += off_y; \
1175+
} \
1176+
\
1177+
return verts;\
1178+
}
1179+
1180+
PSP_VERTICES_FUNK(PSP_GetVertV, VertV)
1181+
PSP_VERTICES_FUNK(PSP_GetVertTV, VertTV)
1182+
PSP_VERTICES_FUNK(PSP_GetVertCV, VertCV)
1183+
PSP_VERTICES_FUNK(PSP_GetVertTCV, VertTCV)
1184+
10771185
static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, void *vertices, size_t vertsize)
10781186
{
10791187
PSP_RenderData *data = (PSP_RenderData *)renderer->internal;
10801188
Uint8 *gpumem = NULL;
1081-
PSP_DrawStateCache drawstate;
1082-
1083-
drawstate.color = 0;
1189+
int w = 0, h = 0;
10841190

10851191
StartDrawing(renderer);
10861192

@@ -1096,6 +1202,21 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
10961202
}
10971203
SDL_memcpy(gpumem, vertices, vertsize);
10981204

1205+
if (!data->boundTarget) {
1206+
SDL_GetWindowSizeInPixels(renderer->window, &w, &h);
1207+
} else {
1208+
PSP_TextureData *psp_texture = (PSP_TextureData *)data->boundTarget->internal;
1209+
w = psp_texture->width;
1210+
h = psp_texture->height;
1211+
}
1212+
1213+
if ((w != data->drawstate.drawablew) || (h != data->drawstate.drawableh)) {
1214+
data->drawstate.viewport_dirty = true; // if the window dimensions changed, invalidate the current viewport, etc.
1215+
data->drawstate.cliprect_dirty = true;
1216+
data->drawstate.drawablew = w;
1217+
data->drawstate.drawableh = h;
1218+
}
1219+
10991220
while (cmd) {
11001221
switch (cmd->command) {
11011222
case SDL_RENDERCMD_SETDRAWCOLOR:
@@ -1104,28 +1225,48 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
11041225
const Uint8 g = (Uint8)SDL_roundf(SDL_clamp(cmd->data.color.color.g * cmd->data.color.color_scale, 0.0f, 1.0f) * 255.0f);
11051226
const Uint8 b = (Uint8)SDL_roundf(SDL_clamp(cmd->data.color.color.b * cmd->data.color.color_scale, 0.0f, 1.0f) * 255.0f);
11061227
const Uint8 a = (Uint8)SDL_roundf(SDL_clamp(cmd->data.color.color.a, 0.0f, 1.0f) * 255.0f);
1107-
drawstate.color = GU_RGBA(r, g, b, a);
1228+
data->drawstate.color = GU_RGBA(r, g, b, a);
11081229
break;
11091230
}
11101231

11111232
case SDL_RENDERCMD_SETVIEWPORT:
11121233
{
1113-
SDL_Rect *viewport = &cmd->data.viewport.rect;
1114-
sceGuOffset(2048 - (viewport->w >> 1), 2048 - (viewport->h >> 1));
1115-
sceGuViewport(2048, 2048, viewport->w, viewport->h);
1116-
sceGuScissor(viewport->x, viewport->y, viewport->w, viewport->h);
1117-
// FIXME: We need to update the clip rect too, see https://github.com/libsdl-org/SDL/issues/9094
1234+
SDL_Rect *viewport = &data->drawstate.viewport;
1235+
if (SDL_memcmp(viewport, &cmd->data.viewport.rect, sizeof(cmd->data.viewport.rect)) != 0) {
1236+
SDL_copyp(viewport, &cmd->data.viewport.rect);
1237+
data->drawstate.viewport_dirty = true;
1238+
data->drawstate.cliprect_dirty = true;
1239+
data->drawstate.viewport_is_set = viewport->x != 0 || viewport->y != 0 || viewport->w != data->drawstate.drawablew || viewport->h != data->drawstate.drawableh;
1240+
if (!data->drawstate.cliprect_enabled) {
1241+
if (data->drawstate.viewport_is_set) {
1242+
SDL_copyp(&data->drawstate.cliprect, viewport);
1243+
data->drawstate.cliprect.x = 0;
1244+
data->drawstate.cliprect.y = 0;
1245+
} else {
1246+
data->drawstate.cliprect_enabled_dirty = true;
1247+
}
1248+
}
1249+
}
11181250
break;
11191251
}
11201252

11211253
case SDL_RENDERCMD_SETCLIPRECT:
11221254
{
11231255
const SDL_Rect *rect = &cmd->data.cliprect.rect;
1124-
if (cmd->data.cliprect.enabled) {
1125-
sceGuEnable(GU_SCISSOR_TEST);
1126-
sceGuScissor(rect->x, rect->y, rect->w, rect->h);
1127-
} else {
1128-
sceGuDisable(GU_SCISSOR_TEST);
1256+
const SDL_Rect *viewport = &data->drawstate.viewport;
1257+
if (data->drawstate.cliprect_enabled != cmd->data.cliprect.enabled) {
1258+
data->drawstate.cliprect_enabled = cmd->data.cliprect.enabled;
1259+
data->drawstate.cliprect_enabled_dirty = true;
1260+
if (!data->drawstate.cliprect_enabled && data->drawstate.viewport_is_set) {
1261+
SDL_copyp(&data->drawstate.cliprect, viewport);
1262+
data->drawstate.cliprect.x = 0;
1263+
data->drawstate.cliprect.y = 0;
1264+
}
1265+
}
1266+
1267+
if (SDL_memcmp(&data->drawstate.cliprect, rect, sizeof(*rect)) != 0) {
1268+
SDL_copyp(&data->drawstate.cliprect, rect);
1269+
data->drawstate.cliprect_dirty = true;
11291270
}
11301271
break;
11311272
}
@@ -1145,16 +1286,18 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
11451286
case SDL_RENDERCMD_DRAW_POINTS:
11461287
{
11471288
const size_t count = cmd->data.draw.count;
1148-
const VertV *verts = (VertV *)(gpumem + cmd->data.draw.first);
1289+
const VertV *verts; // = (VertV *)(gpumem + cmd->data.draw.first);
11491290
PSP_BlendState state = {
1150-
.color = drawstate.color,
1291+
.color = data->drawstate.color,
11511292
.texture = NULL,
11521293
.texture_scale_mode = SDL_SCALEMODE_INVALID,
11531294
.texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID,
11541295
.texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID,
11551296
.mode = cmd->data.draw.blend,
11561297
.shadeModel = GU_FLAT
11571298
};
1299+
SetDrawState(data);
1300+
verts = PSP_GetVertV(&data->drawstate, gpumem, cmd, count);
11581301
PSP_SetBlendState(data, &state);
11591302
sceGuDrawArray(GU_POINTS, GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
11601303
break;
@@ -1163,16 +1306,18 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
11631306
case SDL_RENDERCMD_DRAW_LINES:
11641307
{
11651308
const size_t count = cmd->data.draw.count;
1166-
const VertV *verts = (VertV *)(gpumem + cmd->data.draw.first);
1309+
const VertV *verts; // = (VertV *)(gpumem + cmd->data.draw.first);
11671310
PSP_BlendState state = {
1168-
.color = drawstate.color,
1311+
.color = data->drawstate.color,
11691312
.texture = NULL,
11701313
.texture_scale_mode = SDL_SCALEMODE_INVALID,
11711314
.texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID,
11721315
.texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID,
11731316
.mode = cmd->data.draw.blend,
11741317
.shadeModel = GU_FLAT
11751318
};
1319+
SetDrawState(data);
1320+
verts = PSP_GetVertV(&data->drawstate, gpumem, cmd, count);
11761321
PSP_SetBlendState(data, &state);
11771322
sceGuDrawArray(GU_LINE_STRIP, GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
11781323
break;
@@ -1181,16 +1326,18 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
11811326
case SDL_RENDERCMD_FILL_RECTS:
11821327
{
11831328
const size_t count = cmd->data.draw.count;
1184-
const VertV *verts = (VertV *)(gpumem + cmd->data.draw.first);
1329+
const VertV *verts; // = (VertV *)(gpumem + cmd->data.draw.first);
11851330
PSP_BlendState state = {
1186-
.color = drawstate.color,
1331+
.color = data->drawstate.color,
11871332
.texture = NULL,
11881333
.texture_scale_mode = SDL_SCALEMODE_INVALID,
11891334
.texture_address_mode_u = SDL_TEXTURE_ADDRESS_INVALID,
11901335
.texture_address_mode_v = SDL_TEXTURE_ADDRESS_INVALID,
11911336
.mode = cmd->data.draw.blend,
11921337
.shadeModel = GU_FLAT
11931338
};
1339+
SetDrawState(data);
1340+
verts = PSP_GetVertV(&data->drawstate, gpumem, cmd, 2 * count);
11941341
PSP_SetBlendState(data, &state);
11951342
sceGuDrawArray(GU_SPRITES, GU_VERTEX_32BITF | GU_TRANSFORM_2D, 2 * count, 0, verts);
11961343
break;
@@ -1199,33 +1346,37 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
11991346
case SDL_RENDERCMD_COPY:
12001347
{
12011348
const size_t count = cmd->data.draw.count;
1202-
const VertTV *verts = (VertTV *)(gpumem + cmd->data.draw.first);
1349+
const VertTV *verts; // = (VertTV *)(gpumem + cmd->data.draw.first);
12031350
PSP_BlendState state = {
1204-
.color = drawstate.color,
1351+
.color = data->drawstate.color,
12051352
.texture = cmd->data.draw.texture,
12061353
.texture_scale_mode = cmd->data.draw.texture_scale_mode,
12071354
.texture_address_mode_u = cmd->data.draw.texture_address_mode_u,
12081355
.texture_address_mode_v = cmd->data.draw.texture_address_mode_v,
12091356
.mode = cmd->data.draw.blend,
12101357
.shadeModel = GU_SMOOTH
12111358
};
1359+
SetDrawState(data);
1360+
verts = PSP_GetVertTV(&data->drawstate, gpumem, cmd, 2 * count);
12121361
PSP_SetBlendState(data, &state);
12131362
sceGuDrawArray(GU_SPRITES, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 2 * count, 0, verts);
12141363
break;
12151364
}
12161365

12171366
case SDL_RENDERCMD_COPY_EX:
12181367
{
1219-
const VertTV *verts = (VertTV *)(gpumem + cmd->data.draw.first);
1368+
const VertTV *verts; // = (VertTV *)(gpumem + cmd->data.draw.first);
12201369
PSP_BlendState state = {
1221-
.color = drawstate.color,
1370+
.color = data->drawstate.color,
12221371
.texture = cmd->data.draw.texture,
12231372
.texture_scale_mode = cmd->data.draw.texture_scale_mode,
12241373
.texture_address_mode_u = cmd->data.draw.texture_address_mode_u,
12251374
.texture_address_mode_v = cmd->data.draw.texture_address_mode_v,
12261375
.mode = cmd->data.draw.blend,
12271376
.shadeModel = GU_SMOOTH
12281377
};
1378+
SetDrawState(data);
1379+
verts = PSP_GetVertTV(&data->drawstate, gpumem, cmd, 4);
12291380
PSP_SetBlendState(data, &state);
12301381
sceGuDrawArray(GU_TRIANGLE_FAN, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D, 4, 0, verts);
12311382
break;
@@ -1234,23 +1385,25 @@ static bool PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd,
12341385
case SDL_RENDERCMD_GEOMETRY:
12351386
{
12361387
const size_t count = cmd->data.draw.count;
1388+
SetDrawState(data);
12371389
if (!cmd->data.draw.texture) {
1238-
const VertCV *verts = (VertCV *)(gpumem + cmd->data.draw.first);
1390+
const VertCV *verts = PSP_GetVertCV(&data->drawstate, gpumem, cmd, count);
12391391
sceGuDisable(GU_TEXTURE_2D);
12401392
// In GU_SMOOTH mode
12411393
sceGuDrawArray(GU_TRIANGLES, GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
12421394
sceGuEnable(GU_TEXTURE_2D);
12431395
} else {
1244-
const VertTCV *verts = (VertTCV *)(gpumem + cmd->data.draw.first);
1396+
const VertTCV *verts; // = (VertTCV *)(gpumem + cmd->data.draw.first);
12451397
PSP_BlendState state = {
1246-
.color = drawstate.color,
1398+
.color = data->drawstate.color,
12471399
.texture = cmd->data.draw.texture,
12481400
.texture_scale_mode = cmd->data.draw.texture_scale_mode,
12491401
.texture_address_mode_u = cmd->data.draw.texture_address_mode_u,
12501402
.texture_address_mode_v = cmd->data.draw.texture_address_mode_v,
12511403
.mode = cmd->data.draw.blend,
12521404
.shadeModel = GU_SMOOTH
12531405
};
1406+
verts = PSP_GetVertTCV(&data->drawstate, gpumem, cmd, count);
12541407
PSP_SetBlendState(data, &state);
12551408
sceGuDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D, count, 0, verts);
12561409
}

0 commit comments

Comments
 (0)