@@ -76,6 +76,26 @@ typedef struct
76
76
SDL_Texture * texture ;
77
77
} PSP_BlendState ;
78
78
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
+
79
99
typedef struct
80
100
{
81
101
void * frontbuffer ; /**< main screen buffer */
@@ -91,6 +111,7 @@ typedef struct
91
111
PSP_TextureData * most_recent_target ; /**< start of render target LRU double linked list */
92
112
PSP_TextureData * least_recent_target ; /**< end of the LRU list */
93
113
114
+ PSP_DrawstateCache drawstate ;
94
115
SDL_bool vblank_not_reached ; /**< whether vblank wasn't reached */
95
116
} PSP_RenderData ;
96
117
@@ -1034,10 +1055,101 @@ static void PSP_SetBlendState(PSP_RenderData *data, PSP_BlendState *state)
1034
1055
* current = * state ;
1035
1056
}
1036
1057
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_SetViewportOffsetFunk (FunkName , Type ) \
1124
+ static void FunkName(const PSP_DrawstateCache *drawstate, Type *verts, int count, SDL_bool add) \
1125
+ { \
1126
+ size_t i; \
1127
+ float off_x, off_y; \
1128
+ \
1129
+ if (!drawstate->viewport_is_set) { \
1130
+ return; \
1131
+ } \
1132
+ \
1133
+ off_x = add ? drawstate->draw_offset_x : -drawstate->draw_offset_x; \
1134
+ off_y = add ? drawstate->draw_offset_y : -drawstate->draw_offset_y; \
1135
+ \
1136
+ for (i = 0; i < count; ++i) { \
1137
+ verts[i].x += off_x; \
1138
+ verts[i].y += off_y; \
1139
+ } \
1140
+ }
1141
+
1142
+ PSP_SetViewportOffsetFunk (PSP_SetViewportOffset , VertV )
1143
+ PSP_SetViewportOffsetFunk (PSP_SetViewportOffsetT , VertTV )
1144
+ PSP_SetViewportOffsetFunk (PSP_SetViewportOffsetC , VertCV )
1145
+ PSP_SetViewportOffsetFunk (PSP_SetViewportOffsetTC , VertTCV )
1146
+
1037
1147
static int PSP_RunCommandQueue (SDL_Renderer * renderer , SDL_RenderCommand * cmd , void * vertices , size_t vertsize )
1038
1148
{
1039
1149
PSP_RenderData * data = (PSP_RenderData * )renderer -> driverdata ;
1040
1150
Uint8 * gpumem = NULL ;
1151
+ int w = 0 , h = 0 ;
1152
+
1041
1153
StartDrawing (renderer );
1042
1154
1043
1155
/* note that before the renderer interface change, this would do extrememly small
@@ -1052,6 +1164,23 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1052
1164
}
1053
1165
SDL_memcpy (gpumem , vertices , vertsize );
1054
1166
1167
+ data -> drawstate .target = renderer -> target ;
1168
+ if (!data -> drawstate .target ) {
1169
+ SDL_GL_GetDrawableSize (renderer -> window , & w , & h );
1170
+ } else {
1171
+ if (SDL_QueryTexture (renderer -> target , NULL , NULL , & w , & h ) < 0 ) {
1172
+ w = data -> drawstate .drawablew ;
1173
+ h = data -> drawstate .drawableh ;
1174
+ }
1175
+ }
1176
+
1177
+ if ((w != data -> drawstate .drawablew ) || (h != data -> drawstate .drawableh )) {
1178
+ data -> drawstate .viewport_dirty = SDL_TRUE ; /* if the window dimensions changed, invalidate the current viewport, etc. */
1179
+ data -> drawstate .cliprect_dirty = SDL_TRUE ;
1180
+ data -> drawstate .drawablew = w ;
1181
+ data -> drawstate .drawableh = h ;
1182
+ }
1183
+
1055
1184
while (cmd ) {
1056
1185
switch (cmd -> command ) {
1057
1186
case SDL_RENDERCMD_SETDRAWCOLOR :
@@ -1061,22 +1190,42 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1061
1190
1062
1191
case SDL_RENDERCMD_SETVIEWPORT :
1063
1192
{
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 */
1193
+ SDL_Rect * viewport = & data -> drawstate .viewport ;
1194
+ if (SDL_memcmp (viewport , & cmd -> data .viewport .rect , sizeof (cmd -> data .viewport .rect )) != 0 ) {
1195
+ SDL_copyp (viewport , & cmd -> data .viewport .rect );
1196
+ data -> drawstate .viewport_dirty = SDL_TRUE ;
1197
+ data -> drawstate .cliprect_dirty = SDL_TRUE ;
1198
+ data -> drawstate .viewport_is_set = viewport -> x != 0 || viewport -> y != 0 || viewport -> w != data -> drawstate .drawablew || viewport -> h != data -> drawstate .drawableh ;
1199
+ if (!data -> drawstate .cliprect_enabled ) {
1200
+ if (data -> drawstate .viewport_is_set ) {
1201
+ SDL_copyp (& data -> drawstate .cliprect , viewport );
1202
+ data -> drawstate .cliprect .x = 0 ;
1203
+ data -> drawstate .cliprect .y = 0 ;
1204
+ } else {
1205
+ data -> drawstate .cliprect_enabled_dirty = SDL_TRUE ;
1206
+ }
1207
+ }
1208
+ }
1069
1209
break ;
1070
1210
}
1071
1211
1072
1212
case SDL_RENDERCMD_SETCLIPRECT :
1073
1213
{
1074
1214
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 );
1215
+ const SDL_Rect * viewport = & data -> drawstate .viewport ;
1216
+ if (data -> drawstate .cliprect_enabled != cmd -> data .cliprect .enabled ) {
1217
+ data -> drawstate .cliprect_enabled = cmd -> data .cliprect .enabled ;
1218
+ data -> drawstate .cliprect_enabled_dirty = SDL_TRUE ;
1219
+ if (!data -> drawstate .cliprect_enabled && data -> drawstate .viewport_is_set ) {
1220
+ SDL_copyp (& data -> drawstate .cliprect , viewport );
1221
+ data -> drawstate .cliprect .x = 0 ;
1222
+ data -> drawstate .cliprect .y = 0 ;
1223
+ }
1224
+ }
1225
+
1226
+ if (SDL_memcmp (& data -> drawstate .cliprect , rect , sizeof (* rect )) != 0 ) {
1227
+ SDL_copyp (& data -> drawstate .cliprect , rect );
1228
+ data -> drawstate .cliprect_dirty = SDL_TRUE ;
1080
1229
}
1081
1230
break ;
1082
1231
}
@@ -1087,6 +1236,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1087
1236
const Uint8 g = cmd -> data .color .g ;
1088
1237
const Uint8 b = cmd -> data .color .b ;
1089
1238
const Uint8 a = cmd -> data .color .a ;
1239
+ SetDrawState (data );
1090
1240
sceGuClearColor (GU_RGBA (r , g , b , a ));
1091
1241
sceGuClearStencil (a );
1092
1242
sceGuClear (GU_COLOR_BUFFER_BIT | GU_STENCIL_BUFFER_BIT );
@@ -1095,122 +1245,142 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1095
1245
1096
1246
case SDL_RENDERCMD_DRAW_POINTS :
1097
1247
{
1098
- const size_t count = cmd -> data .draw .count ;
1099
- const VertV * verts = (VertV * )(gpumem + cmd -> data .draw .first );
1100
1248
const Uint8 r = cmd -> data .draw .r ;
1101
1249
const Uint8 g = cmd -> data .draw .g ;
1102
1250
const Uint8 b = cmd -> data .draw .b ;
1103
1251
const Uint8 a = cmd -> data .draw .a ;
1252
+ const size_t count = cmd -> data .draw .count ;
1253
+ VertV * verts = (VertV * )(gpumem + cmd -> data .draw .first );
1104
1254
PSP_BlendState state = {
1105
1255
.color = GU_RGBA (r , g , b , a ),
1106
1256
.texture = NULL ,
1107
1257
.mode = cmd -> data .draw .blend ,
1108
1258
.shadeModel = GU_FLAT
1109
1259
};
1260
+ SetDrawState (data );
1261
+ PSP_SetViewportOffset (& data -> drawstate , verts , count , SDL_TRUE );
1110
1262
PSP_SetBlendState (data , & state );
1111
1263
sceGuDrawArray (GU_POINTS , GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
1264
+ PSP_SetViewportOffset (& data -> drawstate , verts , count , SDL_FALSE );
1112
1265
break ;
1113
1266
}
1114
1267
1115
1268
case SDL_RENDERCMD_DRAW_LINES :
1116
1269
{
1117
- const size_t count = cmd -> data .draw .count ;
1118
- const VertV * verts = (VertV * )(gpumem + cmd -> data .draw .first );
1119
1270
const Uint8 r = cmd -> data .draw .r ;
1120
1271
const Uint8 g = cmd -> data .draw .g ;
1121
1272
const Uint8 b = cmd -> data .draw .b ;
1122
1273
const Uint8 a = cmd -> data .draw .a ;
1274
+ const size_t count = cmd -> data .draw .count ;
1275
+ VertV * verts = (VertV * )(gpumem + cmd -> data .draw .first );
1123
1276
PSP_BlendState state = {
1124
1277
.color = GU_RGBA (r , g , b , a ),
1125
1278
.texture = NULL ,
1126
1279
.mode = cmd -> data .draw .blend ,
1127
1280
.shadeModel = GU_FLAT
1128
1281
};
1282
+ SetDrawState (data );
1283
+ PSP_SetViewportOffset (& data -> drawstate , verts , count , SDL_TRUE );
1129
1284
PSP_SetBlendState (data , & state );
1130
1285
sceGuDrawArray (GU_LINE_STRIP , GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
1286
+ PSP_SetViewportOffset (& data -> drawstate , verts , count , SDL_FALSE );
1131
1287
break ;
1132
1288
}
1133
1289
1134
1290
case SDL_RENDERCMD_FILL_RECTS :
1135
1291
{
1136
- const size_t count = cmd -> data .draw .count ;
1137
- const VertV * verts = (VertV * )(gpumem + cmd -> data .draw .first );
1138
1292
const Uint8 r = cmd -> data .draw .r ;
1139
1293
const Uint8 g = cmd -> data .draw .g ;
1140
1294
const Uint8 b = cmd -> data .draw .b ;
1141
1295
const Uint8 a = cmd -> data .draw .a ;
1296
+ const size_t count = cmd -> data .draw .count ;
1297
+ VertV * verts = (VertV * )(gpumem + cmd -> data .draw .first );
1142
1298
PSP_BlendState state = {
1143
1299
.color = GU_RGBA (r , g , b , a ),
1144
1300
.texture = NULL ,
1145
1301
.mode = cmd -> data .draw .blend ,
1146
1302
.shadeModel = GU_FLAT
1147
1303
};
1304
+ SetDrawState (data );
1305
+ PSP_SetViewportOffset (& data -> drawstate , verts , 2 * count , SDL_TRUE );
1148
1306
PSP_SetBlendState (data , & state );
1149
1307
sceGuDrawArray (GU_SPRITES , GU_VERTEX_32BITF | GU_TRANSFORM_2D , 2 * count , 0 , verts );
1308
+ PSP_SetViewportOffset (& data -> drawstate , verts , 2 * count , SDL_FALSE );
1150
1309
break ;
1151
1310
}
1152
1311
1153
1312
case SDL_RENDERCMD_COPY :
1154
1313
{
1155
- const size_t count = cmd -> data .draw .count ;
1156
- const VertTV * verts = (VertTV * )(gpumem + cmd -> data .draw .first );
1157
1314
const Uint8 a = cmd -> data .draw .a ;
1158
1315
const Uint8 r = cmd -> data .draw .r ;
1159
1316
const Uint8 g = cmd -> data .draw .g ;
1160
1317
const Uint8 b = cmd -> data .draw .b ;
1318
+ const size_t count = cmd -> data .draw .count ;
1319
+ VertTV * verts = (VertTV * )(gpumem + cmd -> data .draw .first );
1161
1320
PSP_BlendState state = {
1162
1321
.color = GU_RGBA (r , g , b , a ),
1163
1322
.texture = cmd -> data .draw .texture ,
1164
1323
.mode = cmd -> data .draw .blend ,
1165
1324
.shadeModel = GU_SMOOTH
1166
1325
};
1326
+ SetDrawState (data );
1327
+ PSP_SetViewportOffsetT (& data -> drawstate , verts , 2 * count , SDL_TRUE );
1167
1328
PSP_SetBlendState (data , & state );
1168
1329
sceGuDrawArray (GU_SPRITES , GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D , 2 * count , 0 , verts );
1330
+ PSP_SetViewportOffsetT (& data -> drawstate , verts , 2 * count , SDL_FALSE );
1169
1331
break ;
1170
1332
}
1171
1333
1172
1334
case SDL_RENDERCMD_COPY_EX :
1173
1335
{
1174
- const VertTV * verts = (VertTV * )(gpumem + cmd -> data .draw .first );
1175
1336
const Uint8 a = cmd -> data .draw .a ;
1176
1337
const Uint8 r = cmd -> data .draw .r ;
1177
1338
const Uint8 g = cmd -> data .draw .g ;
1178
1339
const Uint8 b = cmd -> data .draw .b ;
1340
+ VertTV * verts = (VertTV * )(gpumem + cmd -> data .draw .first );
1179
1341
PSP_BlendState state = {
1180
1342
.color = GU_RGBA (r , g , b , a ),
1181
1343
.texture = cmd -> data .draw .texture ,
1182
1344
.mode = cmd -> data .draw .blend ,
1183
1345
.shadeModel = GU_SMOOTH
1184
1346
};
1347
+ SetDrawState (data );
1348
+ PSP_SetViewportOffsetT (& data -> drawstate , verts , 4 , SDL_TRUE );
1185
1349
PSP_SetBlendState (data , & state );
1186
1350
sceGuDrawArray (GU_TRIANGLE_FAN , GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D , 4 , 0 , verts );
1351
+ PSP_SetViewportOffsetT (& data -> drawstate , verts , 4 , SDL_FALSE );
1187
1352
break ;
1188
1353
}
1189
1354
1190
1355
case SDL_RENDERCMD_GEOMETRY :
1191
1356
{
1192
1357
const size_t count = cmd -> data .draw .count ;
1358
+ SetDrawState (data );
1193
1359
if (!cmd -> data .draw .texture ) {
1194
- const VertCV * verts = (VertCV * )(gpumem + cmd -> data .draw .first );
1360
+ VertCV * verts = (VertCV * )(gpumem + cmd -> data .draw .first );
1361
+ PSP_SetViewportOffsetC (& data -> drawstate , verts , count , SDL_TRUE );
1195
1362
sceGuDisable (GU_TEXTURE_2D );
1196
1363
/* In GU_SMOOTH mode */
1197
1364
sceGuDrawArray (GU_TRIANGLES , GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
1198
1365
sceGuEnable (GU_TEXTURE_2D );
1366
+ PSP_SetViewportOffsetC (& data -> drawstate , verts , count , SDL_FALSE );
1199
1367
} else {
1200
- const VertTCV * verts = (VertTCV * )(gpumem + cmd -> data .draw .first );
1201
1368
const Uint8 a = cmd -> data .draw .a ;
1202
1369
const Uint8 r = cmd -> data .draw .r ;
1203
1370
const Uint8 g = cmd -> data .draw .g ;
1204
1371
const Uint8 b = cmd -> data .draw .b ;
1372
+ VertTCV * verts = (VertTCV * )(gpumem + cmd -> data .draw .first );
1205
1373
PSP_BlendState state = {
1206
1374
.color = GU_RGBA (r , g , b , a ),
1207
1375
.texture = NULL ,
1208
1376
.mode = cmd -> data .draw .blend ,
1209
1377
.shadeModel = GU_FLAT
1210
1378
};
1379
+ PSP_SetViewportOffsetTC (& data -> drawstate , verts , count , SDL_TRUE );
1211
1380
TextureActivate (cmd -> data .draw .texture );
1212
1381
PSP_SetBlendState (data , & state );
1213
1382
sceGuDrawArray (GU_TRIANGLES , GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
1383
+ PSP_SetViewportOffsetTC (& data -> drawstate , verts , count , SDL_FALSE );
1214
1384
}
1215
1385
break ;
1216
1386
}
0 commit comments