3 Licenced under Academic Free License version 3.0
4 Review OpenUsbLd README & LICENSE files for further details.
10 #include "include/renderman.h"
11 #include "include/ioman.h"
13 // Allocateable space in vram, as indicated in GsKit's code
14 #define __VRAM_SIZE 4194304
19 /** Helper texture list */
20 struct rm_texture_list_t
{
23 struct rm_texture_list_t
*next
;
26 static struct rm_texture_list_t
*uploadedTextures
= NULL
;
30 static enum rm_vmode vmode
;
31 // GSKit side detected vmode...
32 static int defaultVMode
= GS_MODE_PAL
;
34 #define NUM_RM_VMODES 3
35 // RM Vmode -> GS Vmode conversion table
36 static const int rm_mode_table
[NUM_RM_VMODES
] = {
42 // inverse mode conversion table
43 #define MAX_GS_MODE 15
44 static int rm_gsmode_table
[MAX_GS_MODE
+1] = {
45 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
48 static int rm_height_table
[] = {
54 static float aspectWidth
;
55 static float aspectHeight
;
57 // Transposition values - all rendering can be transposed (moved on screen) by these
58 static float transX
= 0;
59 static float transY
= 0;
61 const u64 gColWhite
= GS_SETREG_RGBA(0xFF,0xFF,0xFF,0x00);
62 const u64 gColBlack
= GS_SETREG_RGBA(0x00,0x00,0x00,0x00);
63 const u64 gColDarker
= GS_SETREG_RGBA(0x00,0x00,0x00,0x60);
64 const u64 gColFocus
= GS_SETREG_RGBA(0xFF,0xFF,0xFF,0x50);
66 const u64 gDefaultCol
= GS_SETREG_RGBA(0x80,0x80,0x80,0x80);
67 const u64 gDefaultAlpha
= GS_SETREG_ALPHA(0,1,0,1,0);
69 static float shiftYVal
;
70 static float (*shiftY
)(float posY
);
72 static float shiftYFunc(float posY
) {
73 //return (int) ceil(shiftYVal * posY);
74 return (int) (shiftYVal
* posY
);
77 static float identityFunc(float posY
) {
81 static void rmAppendUploadedTextures(GSTEXTURE
*txt
) {
82 struct rm_texture_list_t
*entry
= (struct rm_texture_list_t
*)malloc(sizeof(struct rm_texture_list_t
));
85 entry
->next
= uploadedTextures
;
86 uploadedTextures
= entry
;
89 static void rmAppendUploadedCLUTs(GSCLUT
*clut
) {
90 struct rm_texture_list_t
*entry
= (struct rm_texture_list_t
*)malloc(sizeof(struct rm_texture_list_t
));
93 entry
->next
= uploadedTextures
;
94 uploadedTextures
= entry
;
97 static int rmClutSize(GSCLUT
*clut
, u32
*size
, u32
*w
, u32
*h
) {
111 switch(clut
->ClutPSM
) {
113 *size
= (*w
) * (*h
) * 4;
116 *size
= (*w
) * (*h
) * 4;
119 *size
= (*w
) * (*h
) * 2;
122 *size
= (*w
) * (*h
) * 2;
131 static int rmUploadClut(GSCLUT
*clut
) {
132 if (clut
->VramClut
&& clut
->VramClut
!= GSKIT_ALLOC_ERROR
) // already uploaded
138 if (!rmClutSize(clut
, &size
, &w
, &h
))
141 size
= (-GS_VRAM_BLOCKSIZE_256
)&(size
+GS_VRAM_BLOCKSIZE_256
-1);
143 // too large to fit VRAM with the currently allocated space?
144 if(gsGlobal
->CurrentPointer
+ size
>= __VRAM_SIZE
)
147 if (size
>= __VRAM_SIZE
) {
148 // Only log this if the allocation is too large itself
149 LOG("RM: CLUT: Requested allocation is bigger than VRAM!\n");
150 // We won't allocate this, it's too large
151 clut
->VramClut
= GSKIT_ALLOC_ERROR
;
158 clut
->VramClut
= gsGlobal
->CurrentPointer
;
159 gsGlobal
->CurrentPointer
+= size
;
161 rmAppendUploadedCLUTs(clut
);
163 gsKit_texture_send(clut
->Clut
, w
, h
, clut
->VramClut
, clut
->ClutPSM
, 1, GS_CLUT_PALLETE
);
167 static int rmUploadTexture(GSTEXTURE
* txt
) {
168 // For clut based textures...
171 if (!rmUploadClut((GSCLUT
*)txt
->Clut
))
174 // copy the new VramClut
175 txt
->VramClut
= ((GSCLUT
*)txt
->Clut
)->VramClut
;
178 u32 size
= gsKit_texture_size(txt
->Width
, txt
->Height
, txt
->PSM
);
179 // alignment of the allocation
180 size
= (-GS_VRAM_BLOCKSIZE_256
)&(size
+GS_VRAM_BLOCKSIZE_256
-1);
182 // too large to fit VRAM with the currently allocated space?
183 if(gsGlobal
->CurrentPointer
+ size
>= __VRAM_SIZE
)
186 if (size
>= __VRAM_SIZE
) {
187 // Only log this if the allocation is too large itself
188 LOG("RM: TXT: Requested allocation is bigger than VRAM!\n");
189 // We won't allocate this, it's too large
190 txt
->Vram
= GSKIT_ALLOC_ERROR
;
196 // Should not flush CLUT away. If this happenned we have to reupload
198 if (!rmUploadClut((GSCLUT
*)txt
->Clut
))
201 txt
->VramClut
= ((GSCLUT
*)txt
->Clut
)->VramClut
;
204 // only could fit CLUT but not the pixmap with it!
205 if(gsGlobal
->CurrentPointer
+ size
>= __VRAM_SIZE
)
209 txt
->Vram
= gsGlobal
->CurrentPointer
;
210 gsGlobal
->CurrentPointer
+= size
;
212 rmAppendUploadedTextures(txt
);
214 // We can't do gsKit_texture_upload since it'd assume txt->Clut is the CLUT table directly
215 // whereas we're using it as a pointer to our structure containg clut data
216 gsKit_setup_tbw(txt
);
217 gsKit_texture_send(txt
->Mem
, txt
->Width
, txt
->Height
, txt
->Vram
, txt
->PSM
, txt
->TBW
, txt
->Clut
? GS_CLUT_TEXTURE
: GS_CLUT_NONE
);
222 int rmPrepareTexture(GSTEXTURE
* txt
) {
223 if (txt
->Vram
&& txt
->Vram
!= GSKIT_ALLOC_ERROR
) // already uploaded
226 return rmUploadTexture(txt
);
229 void rmDispatch(void) {
230 gsKit_queue_exec(gsGlobal
);
237 // release all the uploaded textures
238 gsKit_vram_clear(gsGlobal
);
240 while (uploadedTextures
) {
241 // free clut and txt if those are filled in
242 if (uploadedTextures
->txt
) {
243 uploadedTextures
->txt
->Vram
= 0;
244 uploadedTextures
->txt
->VramClut
= 0;
247 if (uploadedTextures
->clut
)
248 uploadedTextures
->clut
->VramClut
= 0;
250 struct rm_texture_list_t
*entry
= uploadedTextures
;
251 uploadedTextures
= uploadedTextures
->next
;
256 void rmStartFrame(void) {
260 void rmEndFrame(void) {
261 gsKit_set_finish(gsGlobal
);
265 // Wait for draw ops to finish
268 if(!gsGlobal
->FirstFrame
)
273 if(gsGlobal
->DoubleBuffering
== GS_SETTING_ON
)
275 GS_SET_DISPFB2( gsGlobal
->ScreenBuffer
[gsGlobal
->ActiveBuffer
& 1] / 8192,
276 gsGlobal
->Width
/ 64, gsGlobal
->PSM
, 0, 0 );
278 gsGlobal
->ActiveBuffer
^= 1;
279 gsGlobal
->PrimContext
^= 1;
284 gsKit_setactive(gsGlobal
);
287 static int rmOnVSync(void) {
289 iWakeupThread(guiThreadID
);
294 void rmInit(int vsyncon
, enum rm_vmode vmodeset
) {
295 gsGlobal
= gsKit_init_global();
297 defaultVMode
= gsGlobal
->Mode
;
300 for (mde
= 0; mde
< NUM_RM_VMODES
; ++mde
) {
301 int gsmde
= rm_mode_table
[mde
];
302 if (gsmde
>= 0 && gsmde
<= MAX_GS_MODE
)
303 rm_gsmode_table
[rm_mode_table
[mde
]] = mde
;
307 rm_height_table
[RM_VMODE_AUTO
] = rm_height_table
[gsGlobal
->Mode
];
309 dmaKit_init(D_CTRL_RELE_OFF
, D_CTRL_MFD_OFF
, D_CTRL_STS_UNSPEC
,
310 D_CTRL_STD_OFF
, D_CTRL_RCYC_8
, 1 << DMA_CHANNEL_GIF
);
312 // Initialize the DMAC
313 dmaKit_chan_init(DMA_CHANNEL_GIF
);
314 dmaKit_chan_init(DMA_CHANNEL_FROMSPR
);
315 dmaKit_chan_init(DMA_CHANNEL_TOSPR
);
317 rmSetMode(vsyncon
, vmodeset
);
325 shiftY
= &shiftYFunc
;
330 guiThreadID
= GetThreadId();
331 gsKit_add_vsync_handler(&rmOnVSync
);
334 void rmSetMode(int vsyncon
, enum rm_vmode vmodeset
) {
339 if (vmode
!= RM_VMODE_AUTO
) {
340 gsGlobal
->Mode
= rm_mode_table
[vmode
];
342 gsGlobal
->Mode
= defaultVMode
;
345 gsGlobal
->Height
= 512; // whatever...
347 if (gsGlobal
->Mode
<= MAX_GS_MODE
) {
348 // back to rm mode from gs mode
349 int rmmde
= rm_gsmode_table
[gsGlobal
->Mode
];
352 gsGlobal
->Height
= rm_height_table
[rmmde
];
355 gsGlobal
->PSM
= GS_PSM_CT24
;
356 gsGlobal
->PSMZ
= GS_PSMZ_16S
;
357 gsGlobal
->ZBuffering
= GS_SETTING_OFF
;
358 gsGlobal
->PrimAlphaEnable
= GS_SETTING_ON
;
359 gsGlobal
->DoubleBuffering
= GS_SETTING_ON
;
361 gsKit_init_screen(gsGlobal
);
363 gsKit_mode_switch(gsGlobal
, GS_ONESHOT
);
365 gsKit_set_test(gsGlobal
, GS_ZTEST_OFF
);
367 // reset the contents of the screen to avoid garbage being displayed
368 gsKit_clear(gsGlobal
, gColBlack
);
369 gsKit_sync_flip(gsGlobal
);
371 LOG("New vmode: %d x %d\n", gsGlobal
->Width
, gsGlobal
->Height
);
375 void rmGetScreenExtents(int *w
, int *h
) {
376 *w
= gsGlobal
->Width
;
377 *h
= gsGlobal
->Height
;
384 /** If txt is null, don't use DIM_UNDEF size */
385 void rmSetupQuad(GSTEXTURE
* txt
, int x
, int y
, short aligned
, int w
, int h
, short scaled
, u64 color
, rm_quad_t
* q
) {
394 dim
= aspectWidth
* (w
>> 1);
401 dim
= aspectHeight
* (h
>> 1);
404 q
->ul
.y
= shiftY(y
) - dim
;
405 q
->br
.y
= shiftY(y
) + dim
;
414 q
->br
.x
= x
+ aspectWidth
* w
;
420 q
->br
.y
= shiftY(y
) + aspectHeight
* h
;
422 q
->br
.y
= shiftY(y
) + h
;
431 q
->br
.u
= txt
->Width
;
432 q
->br
.v
= txt
->Height
;
436 void rmDrawQuad(rm_quad_t
* q
) { // NO scaling, NO shift, NO alignment
437 if (!rmPrepareTexture(q
->txt
)) // won't render if not ready!
440 if ((q
->txt
->PSM
== GS_PSM_CT32
) || (q
->txt
->Clut
&& q
->txt
->ClutPSM
== GS_PSM_CT32
))
442 gsKit_set_primalpha(gsGlobal
, gDefaultAlpha
, 0);
445 gsKit_prim_sprite_texture(gsGlobal
, q
->txt
,
446 q
->ul
.x
+ transX
, q
->ul
.y
+ transY
,
448 q
->br
.x
+ transX
, q
->br
.y
+ transY
,
449 q
->br
.u
, q
->br
.v
, order
, q
->color
);
452 gsKit_set_primalpha(gsGlobal
, GS_BLEND_BACK2FRONT
, 0);
455 void rmDrawPixmap(GSTEXTURE
* txt
, int x
, int y
, short aligned
, int w
, int h
, short scaled
, u64 color
) {
457 rmSetupQuad(txt
, x
, y
, aligned
, w
, h
, scaled
, color
, &quad
);
461 void rmDrawOverlayPixmap(GSTEXTURE
* overlay
, int x
, int y
, short aligned
, int w
, int h
, short scaled
, u64 color
,
462 GSTEXTURE
* inlay
, int ulx
, int uly
, int urx
, int ury
, int blx
, int bly
, int brx
, int bry
) {
465 rmSetupQuad(overlay
, x
, y
, aligned
, w
, h
, scaled
, color
, &quad
);
467 if (!rmPrepareTexture(inlay
))
470 if (inlay
->PSM
== GS_PSM_CT32
)
471 gsKit_set_primalpha(gsGlobal
, gDefaultAlpha
, 0);
473 gsKit_prim_quad_texture(gsGlobal
, inlay
, quad
.ul
.x
+ transX
+ aspectWidth
* ulx
, quad
.ul
.y
+ transY
+ uly
, 0, 0,
474 quad
.ul
.x
+ transX
+ aspectWidth
* urx
, quad
.ul
.y
+ transY
+ ury
, inlay
->Width
, 0,
475 quad
.ul
.x
+ transX
+ aspectWidth
* blx
, quad
.ul
.y
+ transY
+ bly
, 0, inlay
->Height
,
476 quad
.ul
.x
+ transX
+ aspectWidth
* brx
, quad
.ul
.y
+ transY
+ bry
, inlay
->Width
, inlay
->Height
, order
, gDefaultCol
);
478 gsKit_set_primalpha(gsGlobal
, GS_BLEND_BACK2FRONT
, 0);
483 void rmDrawRect(int x
, int y
, int w
, int h
, u64 color
) {
484 gsKit_set_primalpha(gsGlobal
, GS_SETREG_ALPHA(0,1,0,1,0), 0);
485 gsKit_prim_quad(gsGlobal
, x
+ transX
, shiftY(y
) + transY
, x
+ w
+ transX
, shiftY(y
) + transY
, x
+ transX
, shiftY(y
) + h
+ transY
, x
+ w
+ transX
, shiftY(y
) + h
+ transY
, order
, color
);
487 gsKit_set_primalpha(gsGlobal
, GS_BLEND_BACK2FRONT
, 0);
490 void rmDrawLine(int x
, int y
, int x1
, int y1
, u64 color
) {
491 gsKit_prim_line(gsGlobal
, x
+ transX
, shiftY(y
) + transY
, x1
+ transX
, shiftY(y1
) + transY
, order
, color
);
494 void rmSetAspectRatio(float width
, float height
) {
496 aspectHeight
= height
;
499 void rmResetAspectRatio() {
504 void rmGetAspectRatio(float *w
, float *h
) {
509 void rmApplyAspectRatio(int* w
, int* h
) {
510 *w
= *w
* aspectWidth
;
511 *h
= *h
* aspectHeight
;
514 void rmSetShiftRatio(float shiftYRatio
) {
515 shiftYVal
= shiftYRatio
;
516 shiftY
= &shiftYFunc
;
519 void rmResetShiftRatio() {
520 shiftY
= &identityFunc
;
523 void rmApplyShiftRatio(int* y
) {
527 void rmSetTransposition(float x
, float y
) {