sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
gsHires.c
1// ____ ___ | / _____ _____
2// | __ | |___/ | |
3// |___| ___| | \ __|__ | gsKit Open Source Project.
4// ----------------------------------------------------------------------
5// Copyright 2017 - Rick "Maximus32" Gaiser <rgaiser@gmail.com>
6// Copyright 2004 - Chris "Neovanglist" Gilbert <Neovanglist@LainOS.org>
7// Licenced under Academic Free License version 2.0
8// Review gsKit README & LICENSE files for further details.
9//
10// gsHires.c - Multi pass high resolution rendering
11//
12
13#include <gsKit.h>
14#include "gsInline.h"
15#include <kernel.h>
16#include <malloc.h>
17
18
19/*
20 * -------------------------------------------------------------------------
21 * 2 pass rendering
22 * Note: GS draw speed must be 60fps == 120 passes/sec
23 * -------------------------------------------------------------------------
24 *
25 * Render Pass1 Render Pass2
26 *
27 * +------------------------------+ +------------------------------+
28 * | Front-Buffer | | CRTC |
29 * +------------------------------+ +------------------------------+
30 * | CRTC | | Front-Buffer |
31 * +------------------------------+ +------------------------------+
32 *
33 * +------------------------------+
34 * | Depth-Buffer |
35 * +------------------------------+
36 * | Textures |
37 * +------------------------------+
38 *
39 *
40 * -------------------------------------------------------------------------
41 * 3 pass rendering
42 * Note: GS draw speed must be 60fps == 180 passes/sec
43 * -------------------------------------------------------------------------
44 *
45 * Render Pass1 Render Pass2 Render Pass3
46 *
47 * +------------------------------+ +------------------------------+ +------------------------------+
48 * | Front-Buffer | | CRTC | | Depth-Buffer |
49 * +------------------------------+ +------------------------------+ +------------------------------+
50 * | Depth-Buffer | | Front-Buffer | | CRTC |
51 * +------------------------------+ +------------------------------+ +------------------------------+
52 * | CRTC | | Depth-Buffer | | Front-Buffer |
53 * +------------------------------+ +------------------------------+ +------------------------------+
54 *
55 * +------------------------------+
56 * | Textures |
57 * +------------------------------+
58 *
59 *
60 * -------------------------------------------------------------------------
61 * 4 pass rendering
62 * Note: GS draw speed must be 60fps == 240 passes/sec
63 * -------------------------------------------------------------------------
64 *
65 * Render Pass1 Render Pass2 Render Pass3 Render Pass4
66 *
67 * +------------------------------+ +------------------------------+ +------------------------------+ +------------------------------+
68 * | Front-Buffer | | CRTC | | Depth-Buffer | | Depth-Buffer |
69 * +------------------------------+ +------------------------------+ +------------------------------+ +------------------------------+
70 * | Textures | | Front-Buffer | | CRTC | | Textures |
71 * +------------------------------+ +------------------------------+ +------------------------------+ +------------------------------+
72 * | Depth-Buffer | | Depth-Buffer | | Front-Buffer | | CRTC |
73 * +------------------------------+ +------------------------------+ +------------------------------+ +------------------------------+
74 * | CRTC | | Textures | | Textures | | Front-Buffer |
75 * +------------------------------+ +------------------------------+ +------------------------------+ +------------------------------+
76 *
77 * +------------------------------+
78 * | Textures |
79 * +------------------------------+
80 *
81 */
82
83
84//#define BG_DEBUG
85
86
87typedef struct {
88 u32 addr;
89
90 u32 bufferline_begin;
91 u32 bufferline_end;
92
93 u32 scanline_begin;
94 u32 scanline_end;
95} SBuffer;
96
97typedef struct {
98 SBuffer * DrawBuffer;
99 SBuffer * DepthBuffer;
100 SBuffer * TextBuffer;
101 SBuffer * CRTCBuffer;
102 GSQUEUE Queue;
103 GSQUEUE QueueIF; // Only for Interlaced Frame mode
104} SPass;
105
106extern void *_gp;
107#define MAX_PASS_COUNT 4
108#define STACK_SIZE (8 * 1024)
109
110GSQUEUE __DrawQueue[2];
111volatile u32 __iCurrentDrawQueue = 0;
112GSTEXTURE * __pTexture = NULL;
113
114u32 __iYStart;
115s32 __hsync_callback_id = -1;
116volatile u32 __vsync_count = 0;
117volatile u32 __hsync_count = 0;
118
119u32 __iPassCount;
120u32 __iCurrentPass = 0;
121u32 __iCurrentRenderField = 0;
122SBuffer __buffer[MAX_PASS_COUNT];
123SPass __pass[MAX_PASS_COUNT];
124
125s32 __sema_vsync_id = 0;
126s32 __sema_hsync_id = 0;
127s32 __sema_queue_id = 0;
128
129u8 __ThreadStack[STACK_SIZE] __attribute__ ((aligned(16)));
130int __ThreadId = -1;
131
132
133static void gsKit_setpass(GSGLOBAL *gsGlobal, const SPass * __pass, int yoff)
134{
135 u64 *p_data;
136 u64 *p_store;
137 int qsize = 8;
138
139 p_data = p_store = (u64*)gsKit_heap_alloc(gsGlobal, qsize, (qsize * 16), GIF_AD);
140
141 *p_data++ = GIF_TAG_AD(qsize);
142 *p_data++ = GIF_AD;
143
144 // Context 1
145 *p_data++ = GS_SETREG_SCISSOR_1(0, gsGlobal->Width - 1, 0, __pass->DrawBuffer->bufferline_end - __pass->DrawBuffer->bufferline_begin);
146 *p_data++ = GS_SCISSOR_1;
147 *p_data++ = GS_SETREG_FRAME_1(__pass->DrawBuffer->addr / 8192, gsGlobal->Width / 64, gsGlobal->PSM, 0);
148 *p_data++ = GS_FRAME_1;
149 *p_data++ = GS_SETREG_ZBUF_1(__pass->DepthBuffer->addr / 8192, gsGlobal->PSMZ, (gsGlobal->ZBuffering == GS_SETTING_ON) ? 0 : 1);
150 *p_data++ = GS_ZBUF_1;
151 *p_data++ = GS_SETREG_XYOFFSET_1(gsGlobal->OffsetX, yoff + gsGlobal->OffsetY + __pass->DrawBuffer->bufferline_begin*16);
152 *p_data++ = GS_XYOFFSET_1;
153
154 // Context 2
155 *p_data++ = GS_SETREG_SCISSOR_1(0, gsGlobal->Width - 1, 0, __pass->DrawBuffer->bufferline_end - __pass->DrawBuffer->bufferline_begin);
156 *p_data++ = GS_SCISSOR_2;
157 *p_data++ = GS_SETREG_FRAME_1(__pass->DrawBuffer->addr / 8192, gsGlobal->Width / 64, gsGlobal->PSM, 0);
158 *p_data++ = GS_FRAME_2;
159 *p_data++ = GS_SETREG_ZBUF_1(__pass->DepthBuffer->addr / 8192, gsGlobal->PSMZ, (gsGlobal->ZBuffering == GS_SETTING_ON) ? 0 : 1);
160 *p_data++ = GS_ZBUF_2;
161 *p_data++ = GS_SETREG_XYOFFSET_1(gsGlobal->OffsetX, yoff + gsGlobal->OffsetY + __pass->DrawBuffer->bufferline_begin*16);
162 *p_data++ = GS_XYOFFSET_2;
163}
164
165static void gsKit_setpass_background(GSGLOBAL *gsGlobal, const SPass * __pass, GSTEXTURE * tex)
166{
167 u16 width = gsGlobal->Width;
168 u16 height = __pass->DrawBuffer->bufferline_end - __pass->DrawBuffer->bufferline_begin + 1;
169 void * mem = &((u16*)tex->Mem)[__pass->DrawBuffer->bufferline_begin*width];
170
171 // Transfer the texture directly into the drawbuffer
172 gsKit_texture_send_inline(gsGlobal, mem, width, height, __pass->DrawBuffer->addr, tex->PSM, tex->TBW, GS_CLUT_NONE);
173}
174
175static void gsKit_create_pass(GSGLOBAL *gsGlobal, const SPass * __pass, GSQUEUE * Queue, int yoff)
176{
177 GSQUEUE * Queue_backup = gsGlobal->CurQueue;
178
179 // Create new queue (if not already created)
180 if (Queue->pool[0] == NULL)
181 gsKit_queue_init(gsGlobal, Queue, GS_PERSISTENT, 8*1024);
183 gsKit_queue_reset(Queue);
184
185 // Set the rendering context
186 gsKit_setpass(gsGlobal, __pass, yoff);
187
188 // Clear depth buffer (and background)
189 if ((gsGlobal->ZBuffering == GS_SETTING_ON) || (__pTexture == NULL))
190 gsKit_clear(gsGlobal, GS_SETREG_RGBAQ(0x00,0x00,0x00,0x00,0x00));
191
192 // Fill with background image
193 if (__pTexture != NULL)
194 gsKit_setpass_background(gsGlobal, __pass, __pTexture);
195
196 // Restore previous queue
197 gsKit_queue_set(gsGlobal, Queue_backup);
198}
199
200void _gsKit_create_passes(GSGLOBAL *gsGlobal)
201{
202 u32 iPass;
203
204 // Create draw queues to setup the rendering for each pass
206 for (iPass = 0; iPass < __iPassCount; iPass++) {
207 // ODD lines
208 gsKit_create_pass(gsGlobal, &__pass[iPass], &__pass[iPass].Queue, 0);
209 // EVEN lines, half a pixel DOWN
210 gsKit_create_pass(gsGlobal, &__pass[iPass], &__pass[iPass].QueueIF, 8);
211 }
212 }
213 else {
214 for (iPass = 0; iPass < __iPassCount; iPass++) {
215 gsKit_create_pass(gsGlobal, &__pass[iPass], &__pass[iPass].Queue, 0);
216 }
217 }
218}
219
221{
222 // Make sure the sema count == 0
223 while (PollSema(__sema_vsync_id) >= 0)
224 ;
225
226 // Wait for vsync
227 WaitSema(__sema_vsync_id);
228}
229
234
235// State tracking for rate limiting
236static u32 __last_flip_vsync_count = 0;
237
239{
240 u32 iY;
241 u32 vsync_end;
242
243 // Handle vsync waiting based on mode
244 switch (mode) {
245 case GSFLIP_DIRECT: vsync_end = __vsync_count; break;
246 case GSFLIP_VSYNC: vsync_end = __vsync_count + 1; break;
247 case GSFLIP_RATE_LIMIT_1: vsync_end = __last_flip_vsync_count + 1; break;
248 case GSFLIP_RATE_LIMIT_2: vsync_end = __last_flip_vsync_count + 2; break;
249 }
250
251 // Wait for required vsyncs
252 while (__vsync_count < vsync_end) {
253 WaitSema(__sema_vsync_id);
254 }
255
256 // Update last flip vsync count
257 __last_flip_vsync_count = __vsync_count;
258
259 // HACK: The start of the first displayed line
260 // this is needed by the hsync interrupt but must be
261 // updated every time StartYOffset changes
264 iY /= 2;
265 __iYStart = iY;
266
267 // Toggle draw queue
268 WaitSema(__sema_queue_id);
270 __iCurrentDrawQueue = (__iCurrentDrawQueue == 0) ? 1 : 0;
271 SignalSema(__sema_queue_id);
272
273 gsKit_queue_reset(&__DrawQueue[__iCurrentDrawQueue]);
274 gsKit_queue_set(gsGlobal, &__DrawQueue[__iCurrentDrawQueue]);
275}
276
277static void gsKit_texture_to_interlaced_frame(GSTEXTURE * tex)
278{
279 int y;
280 int bpp;
281 int size;
282 u16 *tex_new;
283 u16 *tex_old;
284
285 switch (tex->PSM)
286 {
287 case GS_PSM_CT16S: bpp = 2; break;
288 case GS_PSM_CT24: bpp = 3; break;
289 default: return; // not supported
290 };
291
292 size = tex->Width * tex->Height * bpp;
293 tex_new = (u16*)memalign(128, size);
294 tex_old = (u16*)tex->Mem;
295
296 for(y=0; y < tex->Height; y+=2) {
297 // Copy 0,2,4... to 0,1,2...
298 memcpy(&tex_new[(y/2)*tex->Width], &tex_old[y*tex->Width], tex->Width * bpp);
299 // Copy 1,3,5... to (height/2) + 0,1,2...
300 memcpy(&tex_new[((y+tex->Height)/2)*tex->Width], &tex_old[(y+1)*tex->Width], tex->Width * bpp);
301 }
302
303 free(tex->Mem);
304 tex->Mem = (void*)tex_new;
305}
306
307void gsKit_hires_prepare_bg(GSGLOBAL *gsGlobal, GSTEXTURE * tex)
308{
309 // Convert to same color format
310 if (tex->PSM != gsGlobal->PSM) {
311 if (gsGlobal->PSM == GS_PSM_CT16S)
312 gsKit_texture_to_psm16(tex);
313 else
314 return; // not supported
315 }
316
317 // Convert to interlaced (if needed)
319 gsKit_texture_to_interlaced_frame(tex);
320}
321
322int gsKit_hires_set_bg(GSGLOBAL *gsGlobal, GSTEXTURE * tex)
323{
324 // Validate width
325 if (tex->Width != gsGlobal->Width)
326 return -1;
327
328 // Validate height
330 if (tex->Height != gsGlobal->Height*2)
331 return -1;
332 }
333 else {
334 if (tex->Height != gsGlobal->Height)
335 return -1;
336 }
337
338 // Validate PSM
339 if (tex->PSM != gsGlobal->PSM)
340 return -1;
341
342 // Accept background texture
343 __pTexture = tex;
344 // (Re-)create pass queues
346 WaitSema(__sema_queue_id);
348 _gsKit_create_passes(gsGlobal);
349 SignalSema(__sema_queue_id);
350
351 return 0;
352}
353
354static int hsync_callback(int cause)
355{
356 u32 iPass;
357
358 if (*GS_CSR & (1<<2)) {
359 *GS_CSR = (1<<2);
360 __hsync_count++;
361 }
362
363 if (*GS_CSR & (1<<3)) {
364 *GS_CSR = (1<<3);
365 __vsync_count++;
366 __hsync_count=0;
367 }
368
369 for (iPass = 0; iPass < __iPassCount; iPass++) {
370 if (__hsync_count == (__iYStart + __pass[iPass].CRTCBuffer->scanline_begin)) {
371 if (iPass == 0) {
372 // We start rendering the first pass when the CRTC starts
373 // displaying the last pass of the previous field.
374 // So invert to get the current render field.
375 __iCurrentRenderField = (((GSREG*)GS_CSR)->FIELD == 1) ? 0 : 1;
376 }
377
378 __iCurrentPass = iPass;
379 iSignalSema(__sema_hsync_id);
380
381#ifdef BG_DEBUG
382 GS_SET_BGCOLOR((iPass+1)*63, (iPass+1)*63, (iPass+1)*63);
383#endif
384
385 break;
386 }
387 }
388
389 ExitHandler();
390 return 0;
391}
392
393static void gsKit_queue_send(GSGLOBAL *gsGlobal, GSQUEUE *Queue)
394{
395 if(Queue->tag_size == 0)
396 return;
397
398 *(u64 *)Queue->dma_tag = DMA_TAG(Queue->tag_size, 0, DMA_END, 0, 0, 0);
399
400 if(Queue->last_type != GIF_AD)
401 {
402 *(u64 *)Queue->last_tag = ((u64)Queue->same_obj | *(u64 *)Queue->last_tag);
403 }
404
406 dmaKit_send_chain_ucab(DMA_CHANNEL_GIF, Queue->pool[Queue->dbuf]);
407}
408
409static void dma_to_gs_thread(void * data)
410{
411 GSGLOBAL *gsGlobal = (GSGLOBAL *)data;
412 u32 iQueue;
413
414 while(1)
415 {
416 // Make sure the sema count == 0
417 while (PollSema(__sema_hsync_id) >= 0)
418 ;
419
420 // Wait for CRTC
421 WaitSema(__sema_hsync_id);
422
423 WaitSema(__sema_queue_id);
424
425#ifdef BG_DEBUG
426 GS_SET_BGCOLOR(128,0,0);
427#endif
428
429 // Send current pass queue
431 if (__iCurrentRenderField == 1)
432 gsKit_queue_send(gsGlobal, &__pass[__iCurrentPass].Queue); // Odd
433 else
434 gsKit_queue_send(gsGlobal, &__pass[__iCurrentPass].QueueIF); // Even
435 }
436 else {
437 gsKit_queue_send(gsGlobal, &__pass[__iCurrentPass].Queue);
438 }
439
440 // Send current frame queue
441 iQueue = (__iCurrentDrawQueue == 0) ? 1 : 0;
442 gsKit_queue_send(gsGlobal, &__DrawQueue[iQueue]);
443
444#ifdef BG_DEBUG
445 GS_SET_BGCOLOR(0,128,0);
446#endif
447
448 SignalSema(__sema_queue_id);
449
450 // If this was the last pass, send vsync
451 if (__iCurrentPass == (__iPassCount-1))
452 SignalSema(__sema_vsync_id);
453 }
454}
455
456void gsKit_hires_init_screen(GSGLOBAL *gsGlobal, int passCount)
457{
458 u8 ZBuffering_backup;
459 ee_sema_t sema;
460 u32 iPass;
461 u32 iBufferline;
462 u32 iPassHeight;
463 u32 iBpp;
464 u32 iHeightAlign;
465 ee_thread_t thread;
466
467 // Limit __iPassCount between 2 and 4:
468 // 2 Passes: Front buffer split in 2, used as front and back buffer. Separate depth buffer (half the size) needed.
469 // 3 Passes: Front buffer split in 3, used as front, back and depth buffer.
470 // 4 Passes: Front buffer split in 4, used as front, back and depth buffer + some temporary texture space (currently not used).
471 __iPassCount = passCount;
472 __iPassCount = __iPassCount < 2 ? 2 : __iPassCount;
473 __iPassCount = __iPassCount > 4 ? 4 : __iPassCount;
474
475 if (__iPassCount > 2) {
476 // Depth buffer uses the same buffers as the color buffer, so fix PSMZ
477 switch (gsGlobal->PSM) {
478 case GS_PSM_CT32: gsGlobal->PSMZ = GS_PSMZ_32; break;
479 case GS_PSM_CT24: gsGlobal->PSMZ = GS_PSMZ_32; break;
480 case GS_PSM_CT16: gsGlobal->PSMZ = GS_PSMZ_16; break;
481 case GS_PSM_CT16S: gsGlobal->PSMZ = GS_PSMZ_16S; break;
482 default:
483 printf("gsKit_hires: ERROR: invalid PSM\n");
484 return;
485 }
486 }
487
488#ifdef BG_DEBUG
489 if (gsGlobal->Width < 1024)
490 gsGlobal->Width -= 64;
491 else
492 gsGlobal->Width -= 128;
493#endif
494
495 // Bytes per pixel and height align for render buffers
496 if ((gsGlobal->PSM == GS_PSM_CT32) || (gsGlobal->PSM == GS_PSM_CT24)) {
497 iBpp = 4;
498 iHeightAlign = 32;
499 }
500 else {
501 iBpp = 2;
502 iHeightAlign = 64;
503 }
504
505 // The size of a pass must be a multiple of 32 or 64 lines depending on the PSM
506 iPassHeight = (gsGlobal->Height + (__iPassCount-1)) / __iPassCount;
507 iPassHeight = (iPassHeight + (iHeightAlign-1)) & ~(iHeightAlign-1);
508
509 // Double buffering is not used in multi pass rendering
510 // Force double buffering off
512
513 // gsKit_init_screen must only allocate 1 front buffer
514 // so temporarily disable the depth buffer
515 ZBuffering_backup = gsGlobal->ZBuffering;
517
518 // This initialize the display and allocates 1 front buffer
520
521 // We split the front buffer in different passes
522 // Each pass needs to be aligned, so the total alignment requirements become:
523 // - __iPassCount * 32 for 32/24 bit color buffers
524 // - __iPassCount * 64 for 16 bit color buffers
525 if (gsKit_texture_size(gsGlobal->Width, gsGlobal->Height, gsGlobal->PSM) < gsKit_texture_size(gsGlobal->Width, iPassHeight * __iPassCount, gsGlobal->PSM)) {
526 int iAlign = gsKit_texture_size(gsGlobal->Width, iPassHeight * __iPassCount, gsGlobal->PSM) - gsKit_texture_size(gsGlobal->Width, gsGlobal->Height, gsGlobal->PSM);
527 printf("gsKit_hires: Padding front buffer with %dKiB \n", iAlign/1024);
529 }
530
531 // Restore depth buffer setting
532 gsGlobal->ZBuffering = ZBuffering_backup;
535
536 //
537 // The front buffer is split into the number of passes
538 // Fill the buffer array here
539 //
540 iBufferline = 0;
541 for (iPass = 0; iPass < __iPassCount; iPass++) {
542 // Starting address of buffer
543 __buffer[iPass].addr = iBufferline * gsGlobal->Width * iBpp;
544
545 // First and last line of buffer
546 __buffer[iPass].bufferline_begin = iBufferline;
547 iBufferline += iPassHeight;
548 if (iBufferline > gsGlobal->Height)
549 iBufferline = gsGlobal->Height;
550 __buffer[iPass].bufferline_end = iBufferline - 1;
551
552 // First and last line of buffer, measured in CRTC scanlines
553 __buffer[iPass].scanline_begin = __buffer[iPass].bufferline_begin;
554 __buffer[iPass].scanline_end = __buffer[iPass].bufferline_end;
555 if (gsGlobal->MagV > 0)
556 {
557 // Lines in the buffer are magnified (displayed more than once
558 __buffer[iPass].scanline_begin *= (gsGlobal->MagV+1);
559 __buffer[iPass].scanline_end *= (gsGlobal->MagV+1);
560 }
562 {
563 // Only half of the lines in the buffer are read in interlaced field mode
564 __buffer[iPass].scanline_begin /= 2;
565 __buffer[iPass].scanline_end /= 2;
566 }
567 }
568
569 if ((gsGlobal->ZBuffering == GS_SETTING_ON) && (__iPassCount == 2)) {
570 // Depth buffer not inside front buffer, so allocate it
571 // We only need half the height of the depth buffer
573
574 // 3rd buffer is fixed to this depth buffer
575 __buffer[2].addr = gsGlobal->ZBuffer;
576 }
577
578 // first useable address for textures (after any potential Zbuffer allocation)
580
581 //
582 // What buffers need to be used in what pass? That's what the pass array is for.
583 // Fill the pass array
584 //
585 for (iPass = 0; iPass < __iPassCount; iPass++) {
586 int iPrevPass = (iPass == 0) ? (__iPassCount-1) : (iPass-1);
587
588 // We always draw top to bottom
589 __pass[iPass].DrawBuffer = &__buffer[iPass];
590 // The CRTC is right behind the draw buffer
591 __pass[iPass].CRTCBuffer = &__buffer[iPrevPass];
592
593 if (__iPassCount == 2) {
594 // Depth buffer fixed
595 __pass[iPass].DepthBuffer = &__buffer[2];
596 __pass[iPass].TextBuffer = NULL;
597 }
598 else if (__iPassCount == 3) {
599 int iNextPass = (iPass == (__iPassCount-1)) ? 0 : (iPass+1);
600
601 // Depth buffer inside front buffer
602 __pass[iPass].DepthBuffer = &__buffer[iNextPass];
603 __pass[iPass].TextBuffer = NULL;
604 }
605 else {
606 int iNextPass1 = (iPass == (__iPassCount-1)) ? 0 : (iPass+1);
607 int iNextPass2 = (iNextPass1 == (__iPassCount-1)) ? 0 : (iNextPass1+1);
608
609 // Depth and texture buffers inside front buffer
610 //
611 // Toggle the position of the buffers relative to the draw buffer
612 // so the texture buffer can stay in place twice as long
613 __pass[iPass].DepthBuffer = &__buffer[((iPass & 1) == 0) ? iNextPass1 : iNextPass2];
614 __pass[iPass].TextBuffer = &__buffer[((iPass & 1) == 0) ? iNextPass2 : iNextPass1];
615 }
616 }
617
618 // (Re-)create pass queues
619 _gsKit_create_passes(gsGlobal);
620
621 // Re-use the "per" queue from gsKit
622 __DrawQueue[0] = *gsGlobal->Per_Queue;
623 // Create a second identical queue for double buffering
625 // Set active queue
626 gsKit_queue_set(gsGlobal, &__DrawQueue[__iCurrentDrawQueue]);
627
628 // Initialize semaphores
629 sema.init_count = 0;
630 sema.max_count = 1;
631 sema.option = 0;
632 if ((__sema_hsync_id = CreateSema(&sema)) < 0)
633 printf("gsKit_hires: ERROR: creating __sema_hsync_id\n");
634 sema.init_count = 0;
635 sema.max_count = 1;
636 sema.option = 0;
637 if ((__sema_vsync_id = CreateSema(&sema)) < 0)
638 printf("gsKit_hires: ERROR: creating __sema_vsync_id\n");
639 // Initialize mutex (also a semaphore)
640 sema.init_count = 1;
641 sema.max_count = 1;
642 sema.option = 0;
643 if ((__sema_queue_id = CreateSema(&sema)) < 0)
644 printf("gsKit_hires: ERROR: creating __sema_queue_id\n");
645
646 // Create thread for transmitting the draw queues to the GS
647 // This thread must have the highest priority (1).
648 thread.initial_priority = 1;
649 thread.stack_size = STACK_SIZE;
650 thread.gp_reg = &_gp;
651 thread.func = (void *)dma_to_gs_thread;
652 thread.stack = (void *)__ThreadStack;
653 thread.option = 0;
654 thread.attr = 0;
655 if ((__ThreadId = CreateThread(&thread)) < 0)
656 printf("gsKit_hires: ERROR: creating thread\n");
657 StartThread(__ThreadId, gsGlobal);
658
659 // HACK: Change the priority of the caller,
660 // so we can have the highest priority.
661 ChangeThreadPriority(GetThreadId(), 2);
662
663 // Install hsync handler
664 // This will start firing events (using semaphores) to the GS
665 if ((__hsync_callback_id = gsKit_add_hsync_handler(hsync_callback)) < 0)
666 printf("gsKit_hires: ERROR: registering hsync handler\n");
667}
668
670{
671 return gsKit_init_global();
672}
673
675{
676 u32 iPass;
677
678 if (__hsync_callback_id >= 0)
679 gsKit_remove_hsync_handler(__hsync_callback_id);
680
681 WaitSema(__sema_queue_id);
682
683 TerminateThread(__ThreadId);
684 DeleteThread(__ThreadId);
685
686 if (__sema_queue_id >= 0)
687 DeleteSema(__sema_queue_id);
688
689 if (__sema_vsync_id >= 0)
690 DeleteSema(__sema_vsync_id);
691
692 if (__sema_hsync_id >= 0)
693 DeleteSema(__sema_hsync_id);
694
696 gsKit_queue_free(gsGlobal, &__DrawQueue[1]);
697
698 for (iPass = 0; iPass < __iPassCount; iPass++) {
699 gsKit_queue_free(gsGlobal, &__pass[iPass].Queue);
700 gsKit_queue_free(gsGlobal, &__pass[iPass].QueueIF);
701 }
702
703 gsKit_deinit_global(gsGlobal);
704}
void dmaKit_wait_fast(void)
Definition dmaCore.c:45
void dmaKit_send_chain_ucab(u16 channel, void *data)
Definition dmaCore.c:163
void gsKit_queue_reset(GSQUEUE *Queue)
Reset specified drawqueue to it's initial state (Useful for clearing the Persistent Queue).
Definition gsCore.c:553
int gsKit_add_hsync_handler(int(*hsync_callback)(int))
Installs a hsync interrupt handler (hblank_start).
Definition gsCore.c:195
void gsKit_queue_set(GSGLOBAL *gsGlobal, GSQUEUE *Queue)
Set Current Draw Queue.
Definition gsCore.c:652
void gsKit_clear(GSGLOBAL *gsGlobal, u64 Color)
Definition gsCore.c:244
u32 gsKit_vram_alloc(GSGLOBAL *gsGlobal, u32 size, u8 type)
GS VRAM Allocation.
Definition gsCore.c:20
#define GS_ZTEST_ON
Turns on Z Testing.
Definition gsCore.h:60
void gsKit_remove_hsync_handler(int callback_id)
Removes a hsync interrupt handler.
Definition gsCore.c:209
void gsKit_queue_free(GSGLOBAL *gsGlobal, GSQUEUE *Queue)
Free Allocated Memory for Draw Queue.
Definition gsCore.c:634
GSFLIP_MODE
Flip mode for gsKit_hires_flip_ext.
Definition gsCore.h:90
@ GSFLIP_VSYNC
Wait for vsync before flipping.
Definition gsCore.h:92
@ GSFLIP_RATE_LIMIT_2
Limit to 30fps (2 vsyncs per frame).
Definition gsCore.h:94
@ GSFLIP_RATE_LIMIT_1
Limit to 60fps (1 vsync per frame).
Definition gsCore.h:93
@ GSFLIP_DIRECT
Flip immediately, no vsync wait.
Definition gsCore.h:91
void gsKit_set_test(GSGLOBAL *gsGlobal, u8 Preset)
Definition gsCore.c:286
void gsKit_queue_init(GSGLOBAL *gsGlobal, GSQUEUE *Queue, u8 mode, int size)
Initialize a Draw Queue (Allocates memory for the Queue).
Definition gsCore.c:612
#define GSKIT_ALLOC_SYSBUFFER
GS VRAM "System" Allocation (Framebuffer, ZBuffer, etc).
Definition gsCore.h:24
void gsKit_hires_flip_ext(GSGLOBAL *gsGlobal, GSFLIP_MODE mode)
Flips Draw Queue with specified flip mode.
Definition gsHires.c:238
void gsKit_hires_flip(GSGLOBAL *gsGlobal)
Flips Draw Queue.
Definition gsHires.c:230
void gsKit_hires_sync(GSGLOBAL *gsGlobal)
Wait for VSync.
Definition gsHires.c:220
int gsKit_hires_set_bg(GSGLOBAL *gsGlobal, GSTEXTURE *tex)
Set background texture, must be same size and PSM as display.
Definition gsHires.c:322
void gsKit_hires_prepare_bg(GSGLOBAL *gsGlobal, GSTEXTURE *tex)
Converts PSM and interlacing for use as background image.
Definition gsHires.c:307
GSGLOBAL * gsKit_hires_init_global()
Initialize gsGlobal.
Definition gsHires.c:669
void gsKit_hires_deinit_global(GSGLOBAL *gsGlobal)
De-initialize gsGlobal.
Definition gsHires.c:674
void gsKit_hires_init_screen(GSGLOBAL *gsGlobal, int passCount)
Initialize Screen and GS Registers, for multi pass high resolution mode.
Definition gsHires.c:456
#define GS_SETREG_XYOFFSET_1
See GS_SETREG_XYOFFSET.
Definition gsInit.h:738
#define GIF_TAG_AD(NLOOP)
A+D GIFTAG.
Definition gsInit.h:308
#define GS_FRAME_1
GS Frame Buffer (Context 1).
Definition gsInit.h:240
#define GS_PSMZ_16S
RGBA16 ZBuffer ?
Definition gsInit.h:140
#define GS_PSM_CT32
R8 G8 B8 A8 (RGBA32) Texture.
Definition gsInit.h:115
void gsKit_init_screen(GSGLOBAL *gsGlobal)
Initialize Screen and GS Registers.
Definition gsInit.c:238
#define GS_RENDER_QUEUE_PER_POOLSIZE
Size of Persistent drawbuffer (Single Buffered).
Definition gsInit.h:29
#define GS_FRAME_2
GS Frame Buffer (Context 2).
Definition gsInit.h:242
#define GS_PSM_CT16S
RGBA16 Texture ?
Definition gsInit.h:121
#define GS_PSMZ_32
R8 G8 B8 A8 (RGBA32) ZBuffer.
Definition gsInit.h:134
#define GS_FRAME
Frame Mode - Reads Every Line.
Definition gsInit.h:46
#define GS_SETREG_ZBUF_1
See GS_SETREG_ZBUF.
Definition gsInit.h:745
#define GS_SETREG_RGBAQ(r, g, b, a, q)
Object Creation Macro for RGBAQ Color Values.
Definition gsInit.h:579
#define GS_SETTING_OFF
Define a setting to be OFF.
Definition gsInit.h:148
#define GS_XYOFFSET_2
GS Offset Value.
Definition gsInit.h:192
#define GS_PSM_CT24
R8 G8 B8 (RGB24) Texture.
Definition gsInit.h:117
#define GS_SETTING_ON
Define a setting to be ON.
Definition gsInit.h:151
#define GS_ZBUF_1
GS Z Buffer (Context 1).
Definition gsInit.h:244
#define GIF_AD
GIF_TAG Address+Data Setting. (Used after GIF_TAG).
Definition gsInit.h:494
#define GS_PERSISTENT
Persistent Draw Queue.
Definition gsInit.h:24
#define GS_SCISSOR_2
GS Scissoring Area (Context 2).
Definition gsInit.h:218
#define GS_SCISSOR_1
GS Scissoring Area (Context 1).
Definition gsInit.h:216
#define GS_PSMZ_16
RGBA16 ZBuffer.
Definition gsInit.h:138
#define GS_SET_BGCOLOR(R, G, B)
GS Background Color Register Access Macro.
Definition gsInit.h:731
#define GS_SETREG_SCISSOR_1
See GS_SETREG_SCISSOR.
Definition gsInit.h:777
#define GS_XYOFFSET_1
GS Offset Value.
Definition gsInit.h:190
#define GS_ZBUF_2
GS Z Buffer (Context 2).
Definition gsInit.h:246
#define GS_SETREG_FRAME_1
See GS_SETREG_FRAME.
Definition gsInit.h:768
#define GS_INTERLACED
Interlaced Mode.
Definition gsInit.h:41
#define GS_FIELD
Field Mode - Reads Every Other Line.
Definition gsInit.h:44
#define GS_CSR
GS CSR (GS System Status) Register.
Definition gsInit.h:540
#define GS_PSM_CT16
RGBA16 Texture.
Definition gsInit.h:119
u8 ZBuffering
Enable/Disable Z Buffering.
Definition gsInit.h:909
int Width
Framebuffer Width (the mode's DW is a multiple of this value).
Definition gsInit.h:918
u32 CurrentPointer
Current VRAM Pointer.
Definition gsInit.h:904
s16 Field
Field / Frame.
Definition gsInit.h:903
GSQUEUE * CurQueue
Draw Queue (Current).
Definition gsInit.h:934
int PSMZ
ZBuffer Pixel Storage Method.
Definition gsInit.h:941
u32 TexturePointer
Pointer to beginning of Texture Buffer.
Definition gsInit.h:905
u8 DoubleBuffering
Enable/Disable Double Buffering.
Definition gsInit.h:908
int StartYOffset
Y Starting Coordinate (Used for Placement Correction) Additional correction.
Definition gsInit.h:926
int OffsetX
X Window Offset.
Definition gsInit.h:921
int PSM
Pixel Storage Method (Color Mode).
Definition gsInit.h:940
int MagV
Y Magnification Value (MAGV = DH / Height - 1).
Definition gsInit.h:928
int Height
Framebuffer Height (the mode's DH is a multiple of this value).
Definition gsInit.h:919
int OffsetY
Y Window Offset.
Definition gsInit.h:922
u32 ZBuffer
ZBuffer Pointer.
Definition gsInit.h:911
s16 Interlace
Interlace (On/Off).
Definition gsInit.h:902
int StartY
Y Starting Coordinate (Used for Placement Correction) Default value.
Definition gsInit.h:924
GSQUEUE * Per_Queue
Draw Queue (Persistent).
Definition gsInit.h:935
void * dma_tag
Pointer to last DMA_TAG.
Definition gsInit.h:867
int same_obj
Number of times in a row the same REGLIST enabled object has been added (Used for NLOOP fixup later).
Definition gsInit.h:865
void * last_tag
Pointer to the GIF_TAG of the last object in this draw queue.
Definition gsInit.h:863
int dbuf
Which of the pool[2] buffers we are using.
Definition gsInit.h:871
int last_type
Last type of object in this draw queue.
Definition gsInit.h:862
u32 tag_size
Quadwords in current DMA_TAG.
Definition gsInit.h:868
u32 TBW
Texture Base Width.
Definition gsInit.h:960
u32 * Mem
EE Memory Pointer.
Definition gsInit.h:961
u8 PSM
Pixel Storage Method (Color Format).
Definition gsInit.h:958
u32 Height
Height of the Texture.
Definition gsInit.h:957
u32 Width
Width of the Texture.
Definition gsInit.h:956