@@ -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,104 @@ 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_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
+
1037
1150
static int PSP_RunCommandQueue (SDL_Renderer * renderer , SDL_RenderCommand * cmd , void * vertices , size_t vertsize )
1038
1151
{
1039
1152
PSP_RenderData * data = (PSP_RenderData * )renderer -> driverdata ;
1040
1153
Uint8 * gpumem = NULL ;
1154
+ int w = 0 , h = 0 ;
1155
+
1041
1156
StartDrawing (renderer );
1042
1157
1043
1158
/* 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
1052
1167
}
1053
1168
SDL_memcpy (gpumem , vertices , vertsize );
1054
1169
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
+
1055
1187
while (cmd ) {
1056
1188
switch (cmd -> command ) {
1057
1189
case SDL_RENDERCMD_SETDRAWCOLOR :
@@ -1061,22 +1193,42 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1061
1193
1062
1194
case SDL_RENDERCMD_SETVIEWPORT :
1063
1195
{
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
+ }
1069
1212
break ;
1070
1213
}
1071
1214
1072
1215
case SDL_RENDERCMD_SETCLIPRECT :
1073
1216
{
1074
1217
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 ;
1080
1232
}
1081
1233
break ;
1082
1234
}
@@ -1087,6 +1239,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1087
1239
const Uint8 g = cmd -> data .color .g ;
1088
1240
const Uint8 b = cmd -> data .color .b ;
1089
1241
const Uint8 a = cmd -> data .color .a ;
1242
+ SetDrawState (data );
1090
1243
sceGuClearColor (GU_RGBA (r , g , b , a ));
1091
1244
sceGuClearStencil (a );
1092
1245
sceGuClear (GU_COLOR_BUFFER_BIT | GU_STENCIL_BUFFER_BIT );
@@ -1096,7 +1249,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1096
1249
case SDL_RENDERCMD_DRAW_POINTS :
1097
1250
{
1098
1251
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);*/
1100
1253
const Uint8 r = cmd -> data .draw .r ;
1101
1254
const Uint8 g = cmd -> data .draw .g ;
1102
1255
const Uint8 b = cmd -> data .draw .b ;
@@ -1107,6 +1260,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1107
1260
.mode = cmd -> data .draw .blend ,
1108
1261
.shadeModel = GU_FLAT
1109
1262
};
1263
+ SetDrawState (data );
1264
+ verts = PSP_GetVertV (& data -> drawstate , gpumem , cmd , count );
1110
1265
PSP_SetBlendState (data , & state );
1111
1266
sceGuDrawArray (GU_POINTS , GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
1112
1267
break ;
@@ -1115,7 +1270,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1115
1270
case SDL_RENDERCMD_DRAW_LINES :
1116
1271
{
1117
1272
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);*/
1119
1274
const Uint8 r = cmd -> data .draw .r ;
1120
1275
const Uint8 g = cmd -> data .draw .g ;
1121
1276
const Uint8 b = cmd -> data .draw .b ;
@@ -1126,6 +1281,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1126
1281
.mode = cmd -> data .draw .blend ,
1127
1282
.shadeModel = GU_FLAT
1128
1283
};
1284
+ SetDrawState (data );
1285
+ verts = PSP_GetVertV (& data -> drawstate , gpumem , cmd , count );
1129
1286
PSP_SetBlendState (data , & state );
1130
1287
sceGuDrawArray (GU_LINE_STRIP , GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
1131
1288
break ;
@@ -1134,7 +1291,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1134
1291
case SDL_RENDERCMD_FILL_RECTS :
1135
1292
{
1136
1293
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);*/
1138
1295
const Uint8 r = cmd -> data .draw .r ;
1139
1296
const Uint8 g = cmd -> data .draw .g ;
1140
1297
const Uint8 b = cmd -> data .draw .b ;
@@ -1145,6 +1302,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1145
1302
.mode = cmd -> data .draw .blend ,
1146
1303
.shadeModel = GU_FLAT
1147
1304
};
1305
+ SetDrawState (data );
1306
+ verts = PSP_GetVertV (& data -> drawstate , gpumem , cmd , 2 * count );
1148
1307
PSP_SetBlendState (data , & state );
1149
1308
sceGuDrawArray (GU_SPRITES , GU_VERTEX_32BITF | GU_TRANSFORM_2D , 2 * count , 0 , verts );
1150
1309
break ;
@@ -1153,7 +1312,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1153
1312
case SDL_RENDERCMD_COPY :
1154
1313
{
1155
1314
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);*/
1157
1316
const Uint8 a = cmd -> data .draw .a ;
1158
1317
const Uint8 r = cmd -> data .draw .r ;
1159
1318
const Uint8 g = cmd -> data .draw .g ;
@@ -1164,6 +1323,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1164
1323
.mode = cmd -> data .draw .blend ,
1165
1324
.shadeModel = GU_SMOOTH
1166
1325
};
1326
+ SetDrawState (data );
1327
+ verts = PSP_GetVertTV (& data -> drawstate , gpumem , cmd , 2 * count );
1167
1328
PSP_SetBlendState (data , & state );
1168
1329
sceGuDrawArray (GU_SPRITES , GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D , 2 * count , 0 , verts );
1169
1330
break ;
@@ -1182,6 +1343,8 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1182
1343
.mode = cmd -> data .draw .blend ,
1183
1344
.shadeModel = GU_SMOOTH
1184
1345
};
1346
+ SetDrawState (data );
1347
+ verts = PSP_GetVertTV (& data -> drawstate , gpumem , cmd , 4 );
1185
1348
PSP_SetBlendState (data , & state );
1186
1349
sceGuDrawArray (GU_TRIANGLE_FAN , GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D , 4 , 0 , verts );
1187
1350
break ;
@@ -1190,14 +1353,15 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1190
1353
case SDL_RENDERCMD_GEOMETRY :
1191
1354
{
1192
1355
const size_t count = cmd -> data .draw .count ;
1356
+ SetDrawState (data );
1193
1357
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 );
1195
1359
sceGuDisable (GU_TEXTURE_2D );
1196
1360
/* In GU_SMOOTH mode */
1197
1361
sceGuDrawArray (GU_TRIANGLES , GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
1198
1362
sceGuEnable (GU_TEXTURE_2D );
1199
1363
} else {
1200
- const VertTCV * verts = (VertTCV * )(gpumem + cmd -> data .draw .first );
1364
+ const VertTCV * verts ; /* = (VertTCV *)(gpumem + cmd->data.draw.first);*/
1201
1365
const Uint8 a = cmd -> data .draw .a ;
1202
1366
const Uint8 r = cmd -> data .draw .r ;
1203
1367
const Uint8 g = cmd -> data .draw .g ;
@@ -1208,6 +1372,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
1208
1372
.mode = cmd -> data .draw .blend ,
1209
1373
.shadeModel = GU_FLAT
1210
1374
};
1375
+ verts = PSP_GetVertTCV (& data -> drawstate , gpumem , cmd , count );
1211
1376
TextureActivate (cmd -> data .draw .texture );
1212
1377
PSP_SetBlendState (data , & state );
1213
1378
sceGuDrawArray (GU_TRIANGLES , GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
0 commit comments