28
28
29
29
#include <pspdisplay.h>
30
30
#include <pspgu.h>
31
+ #include <pspthreadman.h>
31
32
#include <pspintrman.h>
32
33
#include <psputils.h>
33
34
#include <vram.h>
@@ -57,6 +58,7 @@ typedef struct
57
58
{
58
59
void * data ; /**< Image data. */
59
60
void * swizzledData ; /**< Swizzled image data. */
61
+ uint32_t semaphore ; /**< Semaphore for the texture. */
60
62
uint32_t textureWidth ; /**< Texture width (power of two). */
61
63
uint32_t textureHeight ; /**< Texture height (power of two). */
62
64
uint32_t width ; /**< Image width. */
@@ -128,6 +130,34 @@ static void psp_on_vblank(u32 sub, PSP_RenderData *data)
128
130
}
129
131
}
130
132
133
+ static void psp_on_signal (int id )
134
+ {
135
+ sceKernelSignalSema (id , 1 );
136
+ }
137
+
138
+ static inline uint32_t createSemaphore (SDL_Texture * texture )
139
+ {
140
+ uint32_t semaphore ;
141
+ char semaphoreName [31 ];
142
+ snprintf (semaphoreName , sizeof (semaphoreName ), "PSP_Tex_Sem_%p" , texture );
143
+ semaphore = sceKernelCreateSema (semaphoreName , 0 , 1 , 1 , NULL );
144
+ if (semaphore < 0 ) {
145
+ SDL_SetError ("Failed to create texture semaphore" );
146
+ return -1 ;
147
+ }
148
+ return semaphore ;
149
+ }
150
+
151
+ static inline void destroySemaphore (uint32_t semaphore )
152
+ {
153
+ if (semaphore != -1 ) {
154
+ // Wait for all threads to finish using the semaphore
155
+ sceKernelWaitSema (semaphore , 1 , NULL );
156
+ sceKernelDeleteSema (semaphore );
157
+ semaphore = -1 ;
158
+ }
159
+ }
160
+
131
161
static inline unsigned int getMemorySize (unsigned int width , unsigned int height , unsigned int psm )
132
162
{
133
163
switch (psm ) {
@@ -460,6 +490,10 @@ static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
460
490
return SDL_OutOfMemory ();
461
491
}
462
492
493
+ psp_tex -> semaphore = createSemaphore (texture );
494
+ if (psp_tex -> semaphore == -1 ) {
495
+ return SDL_OutOfMemory ();
496
+ }
463
497
psp_tex -> format = pixelFormatToPSPFMT (texture -> format );
464
498
psp_tex -> textureWidth = calculateNextPow2 (texture -> w );
465
499
psp_tex -> textureHeight = calculateNextPow2 (texture -> h );
@@ -475,12 +509,14 @@ static int PSP_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture)
475
509
if (texture -> access != SDL_TEXTUREACCESS_STATIC ) {
476
510
psp_tex -> data = vramalloc (psp_tex -> size );
477
511
if (!psp_tex -> data ) {
512
+ destroySemaphore (psp_tex -> semaphore );
478
513
vfree (psp_tex );
479
514
return SDL_OutOfMemory ();
480
515
}
481
516
} else {
482
517
psp_tex -> data = SDL_calloc (1 , psp_tex -> size );
483
518
if (!psp_tex -> data ) {
519
+ destroySemaphore (psp_tex -> semaphore );
484
520
SDL_free (psp_tex );
485
521
return SDL_OutOfMemory ();
486
522
}
@@ -500,6 +536,7 @@ static int PSP_LockTexture(SDL_Renderer *renderer, SDL_Texture *texture,
500
536
// How a pointer to the texture data is returned it need to be unswizzled before it can be used
501
537
prepareTextureForDownload (texture );
502
538
539
+ sceKernelWaitSema (psp_tex -> semaphore , 1 , NULL );
503
540
* pixels =
504
541
(void * )((Uint8 * )psp_tex -> data + rect -> y * psp_tex -> pitch +
505
542
rect -> x * SDL_BYTESPERPIXEL (texture -> format ));
@@ -513,6 +550,7 @@ static void PSP_UnlockTexture(SDL_Renderer *renderer, SDL_Texture *texture)
513
550
PSP_Texture * psp_tex = (PSP_Texture * )texture -> driverdata ;
514
551
515
552
sceKernelDcacheWritebackRange (psp_tex -> data , psp_tex -> size );
553
+ sceKernelSignalSema (psp_tex -> semaphore , 1 );
516
554
}
517
555
518
556
static int PSP_UpdateTexture (SDL_Renderer * renderer , SDL_Texture * texture ,
@@ -561,6 +599,7 @@ static int PSP_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
561
599
562
600
if (texture ) {
563
601
PSP_Texture * psp_tex = (PSP_Texture * )texture -> driverdata ;
602
+ sceKernelWaitSema (psp_tex -> semaphore , 1 , NULL );
564
603
sceGuDrawBufferList (psp_tex -> format , vrelptr (psp_tex -> data ), psp_tex -> width );
565
604
data -> currentDrawBufferFormat = psp_tex -> format ;
566
605
@@ -579,6 +618,7 @@ static int PSP_SetRenderTarget(SDL_Renderer *renderer, SDL_Texture *texture)
579
618
sceGuEnable (GU_SCISSOR_TEST );
580
619
sceGuScissor (0 , 0 , psp_tex -> width , psp_tex -> height );
581
620
621
+ sceGuSignal (GU_SIGNAL_WAIT , psp_tex -> semaphore );
582
622
} else {
583
623
sceGuDrawBufferList (data -> drawBufferFormat , vrelptr (data -> backbuffer ), PSP_FRAME_BUFFER_WIDTH );
584
624
data -> currentDrawBufferFormat = data -> drawBufferFormat ;
@@ -830,12 +870,14 @@ static inline int PSP_RenderGeometry(SDL_Renderer *renderer, void *vertices, SDL
830
870
tbw = psp_tex -> swizzled ? psp_tex -> swizzledWidth : psp_tex -> width ;
831
871
twp = psp_tex -> swizzled ? psp_tex -> swizzledData : psp_tex -> data ;
832
872
873
+ sceKernelWaitSema (psp_tex -> semaphore , 1 , NULL );
833
874
sceGuTexMode (psp_tex -> format , 0 , 0 , psp_tex -> swizzled );
834
875
sceGuTexImage (0 , psp_tex -> textureWidth , psp_tex -> textureHeight , tbw , twp );
835
876
sceGuTexFilter (psp_tex -> filter , psp_tex -> filter );
836
877
sceGuEnable (GU_TEXTURE_2D );
837
878
sceGuDrawArray (GU_TRIANGLES , GU_TEXTURE_32BITF | GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
838
879
sceGuDisable (GU_TEXTURE_2D );
880
+ sceGuSignal (GU_SIGNAL_WAIT , psp_tex -> semaphore );
839
881
} else {
840
882
const VertCV * verts = (VertCV * )(vertices + cmd -> data .draw .first );
841
883
sceGuDrawArray (GU_TRIANGLES , GU_COLOR_8888 | GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
@@ -909,6 +951,9 @@ static inline int PSP_RenderCopy(SDL_Renderer *renderer, void *vertices, SDL_Ren
909
951
PSP_SetBlendMode (data , blendInfo );
910
952
911
953
prepareTextureForUpload (texture );
954
+ // We can't use sceKernelWaitSema here because several consecutive SDL_RenderCopy calls
955
+ // could be performed by the user.
956
+ sceKernelPollSema (psp_tex -> semaphore , 1 );
912
957
913
958
tbw = psp_tex -> swizzled ? psp_tex -> textureWidth : psp_tex -> width ;
914
959
twp = psp_tex -> swizzled ? psp_tex -> swizzledData : psp_tex -> data ;
@@ -919,6 +964,7 @@ static inline int PSP_RenderCopy(SDL_Renderer *renderer, void *vertices, SDL_Ren
919
964
sceGuEnable (GU_TEXTURE_2D );
920
965
sceGuDrawArray (GU_SPRITES , GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_2D , count , 0 , verts );
921
966
sceGuDisable (GU_TEXTURE_2D );
967
+ sceGuSignal (GU_SIGNAL_WAIT , psp_tex -> semaphore );
922
968
923
969
return 0 ;
924
970
}
@@ -1053,6 +1099,8 @@ static void PSP_DestroyTexture(SDL_Renderer *renderer, SDL_Texture *texture)
1053
1099
return ;
1054
1100
}
1055
1101
1102
+ destroySemaphore (psp_tex -> semaphore );
1103
+
1056
1104
if (psp_tex -> swizzledData ) {
1057
1105
vfree (psp_tex -> swizzledData );
1058
1106
} else if (texture -> access != SDL_TEXTUREACCESS_STATIC ) {
@@ -1151,6 +1199,9 @@ static int PSP_CreateRenderer(SDL_Renderer *renderer, SDL_Window *window, Uint32
1151
1199
}
1152
1200
data -> vblank_not_reached = SDL_TRUE ;
1153
1201
1202
+ // Set the callback for the texture semaphores
1203
+ sceGuSetCallback (GU_CALLBACK_SIGNAL , psp_on_signal );
1204
+
1154
1205
renderer -> WindowEvent = PSP_WindowEvent ;
1155
1206
renderer -> CreateTexture = PSP_CreateTexture ;
1156
1207
renderer -> UpdateTexture = PSP_UpdateTexture ;
0 commit comments