@@ -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+
7999typedef 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,101 @@ 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_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+
10371147static int PSP_RunCommandQueue (SDL_Renderer * renderer , SDL_RenderCommand * cmd , void * vertices , size_t vertsize )
10381148{
10391149 PSP_RenderData * data = (PSP_RenderData * )renderer -> driverdata ;
10401150 Uint8 * gpumem = NULL ;
1151+ int w = 0 , h = 0 ;
1152+
10411153 StartDrawing (renderer );
10421154
10431155 /* 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
10521164 }
10531165 SDL_memcpy (gpumem , vertices , vertsize );
10541166
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+
10551184 while (cmd ) {
10561185 switch (cmd -> command ) {
10571186 case SDL_RENDERCMD_SETDRAWCOLOR :
@@ -1061,22 +1190,42 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
10611190
10621191 case SDL_RENDERCMD_SETVIEWPORT :
10631192 {
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+ }
10691209 break ;
10701210 }
10711211
10721212 case SDL_RENDERCMD_SETCLIPRECT :
10731213 {
10741214 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 ;
10801229 }
10811230 break ;
10821231 }
@@ -1087,6 +1236,7 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
10871236 const Uint8 g = cmd -> data .color .g ;
10881237 const Uint8 b = cmd -> data .color .b ;
10891238 const Uint8 a = cmd -> data .color .a ;
1239+ SetDrawState (data );
10901240 sceGuClearColor (GU_RGBA (r , g , b , a ));
10911241 sceGuClearStencil (a );
10921242 sceGuClear (GU_COLOR_BUFFER_BIT | GU_STENCIL_BUFFER_BIT );
@@ -1095,122 +1245,142 @@ static int PSP_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v
10951245
10961246 case SDL_RENDERCMD_DRAW_POINTS :
10971247 {
1098- const size_t count = cmd -> data .draw .count ;
1099- const VertV * verts = (VertV * )(gpumem + cmd -> data .draw .first );
11001248 const Uint8 r = cmd -> data .draw .r ;
11011249 const Uint8 g = cmd -> data .draw .g ;
11021250 const Uint8 b = cmd -> data .draw .b ;
11031251 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 );
11041254 PSP_BlendState state = {
11051255 .color = GU_RGBA (r , g , b , a ),
11061256 .texture = NULL ,
11071257 .mode = cmd -> data .draw .blend ,
11081258 .shadeModel = GU_FLAT
11091259 };
1260+ SetDrawState (data );
1261+ PSP_SetViewportOffset (& data -> drawstate , verts , count , SDL_TRUE );
11101262 PSP_SetBlendState (data , & state );
11111263 sceGuDrawArray (GU_POINTS , GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
1264+ PSP_SetViewportOffset (& data -> drawstate , verts , count , SDL_FALSE );
11121265 break ;
11131266 }
11141267
11151268 case SDL_RENDERCMD_DRAW_LINES :
11161269 {
1117- const size_t count = cmd -> data .draw .count ;
1118- const VertV * verts = (VertV * )(gpumem + cmd -> data .draw .first );
11191270 const Uint8 r = cmd -> data .draw .r ;
11201271 const Uint8 g = cmd -> data .draw .g ;
11211272 const Uint8 b = cmd -> data .draw .b ;
11221273 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 );
11231276 PSP_BlendState state = {
11241277 .color = GU_RGBA (r , g , b , a ),
11251278 .texture = NULL ,
11261279 .mode = cmd -> data .draw .blend ,
11271280 .shadeModel = GU_FLAT
11281281 };
1282+ SetDrawState (data );
1283+ PSP_SetViewportOffset (& data -> drawstate , verts , count , SDL_TRUE );
11291284 PSP_SetBlendState (data , & state );
11301285 sceGuDrawArray (GU_LINE_STRIP , GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
1286+ PSP_SetViewportOffset (& data -> drawstate , verts , count , SDL_FALSE );
11311287 break ;
11321288 }
11331289
11341290 case SDL_RENDERCMD_FILL_RECTS :
11351291 {
1136- const size_t count = cmd -> data .draw .count ;
1137- const VertV * verts = (VertV * )(gpumem + cmd -> data .draw .first );
11381292 const Uint8 r = cmd -> data .draw .r ;
11391293 const Uint8 g = cmd -> data .draw .g ;
11401294 const Uint8 b = cmd -> data .draw .b ;
11411295 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 );
11421298 PSP_BlendState state = {
11431299 .color = GU_RGBA (r , g , b , a ),
11441300 .texture = NULL ,
11451301 .mode = cmd -> data .draw .blend ,
11461302 .shadeModel = GU_FLAT
11471303 };
1304+ SetDrawState (data );
1305+ PSP_SetViewportOffset (& data -> drawstate , verts , 2 * count , SDL_TRUE );
11481306 PSP_SetBlendState (data , & state );
11491307 sceGuDrawArray (GU_SPRITES , GU_VERTEX_32BITF | GU_TRANSFORM_2D , 2 * count , 0 , verts );
1308+ PSP_SetViewportOffset (& data -> drawstate , verts , 2 * count , SDL_FALSE );
11501309 break ;
11511310 }
11521311
11531312 case SDL_RENDERCMD_COPY :
11541313 {
1155- const size_t count = cmd -> data .draw .count ;
1156- const VertTV * verts = (VertTV * )(gpumem + cmd -> data .draw .first );
11571314 const Uint8 a = cmd -> data .draw .a ;
11581315 const Uint8 r = cmd -> data .draw .r ;
11591316 const Uint8 g = cmd -> data .draw .g ;
11601317 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 );
11611320 PSP_BlendState state = {
11621321 .color = GU_RGBA (r , g , b , a ),
11631322 .texture = cmd -> data .draw .texture ,
11641323 .mode = cmd -> data .draw .blend ,
11651324 .shadeModel = GU_SMOOTH
11661325 };
1326+ SetDrawState (data );
1327+ PSP_SetViewportOffsetT (& data -> drawstate , verts , 2 * count , SDL_TRUE );
11671328 PSP_SetBlendState (data , & state );
11681329 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 );
11691331 break ;
11701332 }
11711333
11721334 case SDL_RENDERCMD_COPY_EX :
11731335 {
1174- const VertTV * verts = (VertTV * )(gpumem + cmd -> data .draw .first );
11751336 const Uint8 a = cmd -> data .draw .a ;
11761337 const Uint8 r = cmd -> data .draw .r ;
11771338 const Uint8 g = cmd -> data .draw .g ;
11781339 const Uint8 b = cmd -> data .draw .b ;
1340+ VertTV * verts = (VertTV * )(gpumem + cmd -> data .draw .first );
11791341 PSP_BlendState state = {
11801342 .color = GU_RGBA (r , g , b , a ),
11811343 .texture = cmd -> data .draw .texture ,
11821344 .mode = cmd -> data .draw .blend ,
11831345 .shadeModel = GU_SMOOTH
11841346 };
1347+ SetDrawState (data );
1348+ PSP_SetViewportOffsetT (& data -> drawstate , verts , 4 , SDL_TRUE );
11851349 PSP_SetBlendState (data , & state );
11861350 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 );
11871352 break ;
11881353 }
11891354
11901355 case SDL_RENDERCMD_GEOMETRY :
11911356 {
11921357 const size_t count = cmd -> data .draw .count ;
1358+ SetDrawState (data );
11931359 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 );
11951362 sceGuDisable (GU_TEXTURE_2D );
11961363 /* In GU_SMOOTH mode */
11971364 sceGuDrawArray (GU_TRIANGLES , GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
11981365 sceGuEnable (GU_TEXTURE_2D );
1366+ PSP_SetViewportOffsetC (& data -> drawstate , verts , count , SDL_FALSE );
11991367 } else {
1200- const VertTCV * verts = (VertTCV * )(gpumem + cmd -> data .draw .first );
12011368 const Uint8 a = cmd -> data .draw .a ;
12021369 const Uint8 r = cmd -> data .draw .r ;
12031370 const Uint8 g = cmd -> data .draw .g ;
12041371 const Uint8 b = cmd -> data .draw .b ;
1372+ VertTCV * verts = (VertTCV * )(gpumem + cmd -> data .draw .first );
12051373 PSP_BlendState state = {
12061374 .color = GU_RGBA (r , g , b , a ),
12071375 .texture = NULL ,
12081376 .mode = cmd -> data .draw .blend ,
12091377 .shadeModel = GU_FLAT
12101378 };
1379+ PSP_SetViewportOffsetTC (& data -> drawstate , verts , count , SDL_TRUE );
12111380 TextureActivate (cmd -> data .draw .texture );
12121381 PSP_SetBlendState (data , & state );
12131382 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 );
12141384 }
12151385 break ;
12161386 }
0 commit comments