PS2GL
OpenGL*-like API for the PS2
Loading...
Searching...
No Matches
glcontext.cpp
1/* Copyright (C) 2000,2001,2002 Sony Computer Entertainment America
2
3 This file is subject to the terms and conditions of the GNU Lesser
4 General Public License Version 2.1. See the file "COPYING" in the
5 main directory of this archive for more details. */
6
7#include <string.h>
8
9#include "dma.h"
10#include "graph.h"
11#include "kernel.h"
12
13#include "GL/ps2gl.h"
14
15#include "ps2s/displayenv.h"
16#include "ps2s/drawenv.h"
17#include "ps2s/gsmem.h"
18#include "ps2s/math.h"
19#include "ps2s/packet.h"
20#include "ps2s/ps2stuff.h"
21#include "ps2s/texture.h"
22#include "ps2s/types.h"
23
24#include "ps2gl/displaycontext.h"
25#include "ps2gl/dlgmanager.h"
26#include "ps2gl/dlist.h"
27#include "ps2gl/drawcontext.h"
28#include "ps2gl/glcontext.h"
29#include "ps2gl/gmanager.h"
30#include "ps2gl/immgmanager.h"
31#include "ps2gl/lighting.h"
32#include "ps2gl/material.h"
33#include "ps2gl/matrix.h"
34#include "ps2gl/texture.h"
35
36#include "ee_regs.h"
37
38/********************************************
39 * globals
40 */
41
42/********************************************
43 * CGLContext
44 */
45
46// static members
47
48CVifSCDmaPacket *CGLContext::CurPacket, *CGLContext::LastPacket,
49 *CGLContext::Vif1Packet = NULL, *CGLContext::SavedVif1Packet = NULL,
50 *CGLContext::ImmVif1Packet;
51
53int CGLContext::ImmediateRenderingFinishedSemaId = -1;
54int CGLContext::VsyncSemaId = -1;
55
56CGLContext::tRenderingFinishedCallback CGLContext::RenderingFinishedCallback = NULL;
57
58CGLContext::CGLContext(int immBufferQwordSize, int immDrawBufferQwordSize)
59 : StateChangesArePushed(false)
60 , IsCurrentFieldEven(true)
61 , CurrentFrameNumber(0)
62 , CurBuffer(0)
63{
64 CurPacket = new CVifSCDmaPacket(kDmaPacketMaxQwordLength, DMAC::Channels::vif1,
65 Packet::kXferTags, Core::MemMappings::UncachedAccl);
66 LastPacket = new CVifSCDmaPacket(kDmaPacketMaxQwordLength, DMAC::Channels::vif1,
67 Packet::kXferTags, Core::MemMappings::UncachedAccl);
68 Vif1Packet = CurPacket;
69
70 ImmVif1Packet = new CVifSCDmaPacket(immDrawBufferQwordSize, DMAC::Channels::vif1,
71 Packet::kXferTags, Core::MemMappings::UncachedAccl);
72
73 CurDrawEnvPtrs = DrawEnvPtrs0;
74 LastDrawEnvPtrs = DrawEnvPtrs1;
75 NumCurDrawEnvPtrs = 0;
76 NumLastDrawEnvPtrs = 0;
77
78 ImmGManager = new CImmGeomManager(*this, immBufferQwordSize);
79 DListGManager = new CDListGeomManager(*this);
80 CurGManager = ImmGManager;
81
82 ProjectionMatStack = new CImmMatrixStack(*this);
83 ModelViewMatStack = new CImmMatrixStack(*this);
84 DListMatStack = new CDListMatrixStack(*this);
85 CurMatrixStack = ModelViewMatStack;
86 SavedCurMatStack = NULL;
87
88 ImmLighting = new CImmLighting(*this);
89 DListLighting = new CDListLighting(*this);
90 CurLighting = ImmLighting;
91 // defaults
92 CLight& light = ImmLighting->GetLight(0);
93 light.SetDiffuse(cpu_vec_xyzw(1.0f, 1.0f, 1.0f, 1.0f));
94 light.SetSpecular(cpu_vec_xyzw(1.0f, 1.0f, 1.0f, 1.0f));
95
96 MaterialManager = new CMaterialManager(*this);
97 DListManager = new CDListManager;
98 TexManager = new CTexManager(*this);
99
100 ImmDrawContext = new CImmDrawContext(*this);
101 DListDrawContext = new CDListDrawContext(*this);
102 CurDrawContext = ImmDrawContext;
103
104 DisplayContext = new CDisplayContext(*this);
105
106 SetRendererContextChanged(true);
107 SetGsContextChanged(true);
108 SetRendererPropsChanged(true);
109
110 // util
111 NumBuffersToBeFreed[0] = NumBuffersToBeFreed[1] = 0;
112
113 GS::Init();
114
115 // create a few semaphores
116
117 struct t_ee_sema newSemaphore = { 0, 1, 0 }; // but maxCount doesn't work?
118 VsyncSemaId = CreateSema(&newSemaphore);
119 RenderingFinishedSemaId = CreateSema(&newSemaphore);
120 ImmediateRenderingFinishedSemaId = CreateSema(&newSemaphore);
121 mErrorIf(VsyncSemaId == -1
122 || RenderingFinishedSemaId == -1
123 || ImmediateRenderingFinishedSemaId == -1,
124 "Failed to create ps2gl semaphores.");
125
126 // add an interrupt handler for gs "signal" exceptions
127
128 AddIntcHandler(INTC_GS, CGLContext::GsIntHandler, 0 /*first handler*/);
129 EnableIntc(INTC_GS);
130 // clear any signal/vsync exceptions and wait for the next
131 *(volatile unsigned int*)GS::ControlRegs::csr = 9;
132 // enable signal and vsync exceptions
133 *(volatile unsigned int*)GS::ControlRegs::imr = 0x7600;
134
135 // Mask bugged tag mismatch error
136 WR_EE_VIF1_ERR(2);
137}
138
139CGLContext::~CGLContext()
140{
141 delete CurPacket;
142 delete LastPacket;
143
144 delete ImmGManager;
145 delete DListGManager;
146
147 delete ProjectionMatStack;
148 delete ModelViewMatStack;
149 delete DListMatStack;
150
151 delete ImmLighting;
152 delete DListLighting;
153
154 delete MaterialManager;
155 delete DListManager;
156 delete TexManager;
157
158 delete ImmDrawContext;
159 delete DListDrawContext;
160
161 delete DisplayContext;
162}
163
164/********************************************
165 * display lists
166 */
167
168void CGLContext::BeginDListDef(unsigned int listID, GLenum mode)
169{
170 DListManager->NewList(listID, mode);
171
172 PushStateChanges();
173
174 // not so sure about these two, but let's be cautious
175 SetRendererContextChanged(true);
176 SetGsContextChanged(true);
177 // definately need this to force an update - indexed/linear arrays
178 SetRendererPropsChanged(true);
179
180 MaterialManager->BeginDListDef();
181 TexManager->BeginDListDef();
182 DListGManager->BeginDListDef();
183
184 CurLighting = DListLighting;
185 CurGManager = DListGManager;
186 SavedCurMatStack = CurMatrixStack;
187 CurMatrixStack = DListMatStack;
188 CurDrawContext = DListDrawContext;
189}
190
191void CGLContext::EndDListDef()
192{
193 DListGManager->EndDListDef();
194 MaterialManager->EndDListDef();
195 TexManager->EndDListDef();
196
197 CurLighting = ImmLighting;
198 CurGManager = ImmGManager;
199 CurMatrixStack = SavedCurMatStack;
200 CurDrawContext = ImmDrawContext;
201
202 PopStateChanges();
203
204 DListManager->EndList();
205}
206
207/********************************************
208 * matrix mode
209 */
210
212 GLenum Mode;
213
214public:
215 CSetMatrixModeCmd(GLenum mode)
216 : Mode(mode)
217 {
218 }
219 CDListCmd* Play()
220 {
221 glMatrixMode(Mode);
222 return CDListCmd::GetNextCmd(this);
223 }
224};
225
226void CGLContext::SetMatrixMode(GLenum mode)
227{
228 if (InDListDef()) {
229 DListManager->GetOpenDList() += CSetMatrixModeCmd(mode);
230 } else {
231 switch (mode) {
232 case GL_MODELVIEW:
233 CurMatrixStack = ModelViewMatStack;
234 break;
235 case GL_PROJECTION:
236 CurMatrixStack = ProjectionMatStack;
237 break;
238 default:
239 mNotImplemented();
240 }
241 }
242}
243
244/********************************************
245 * immediate geometry
246 */
247
248void CGLContext::BeginImmediateGeometry()
249{
250 // mErrorIf( InDListDef == true,
251 // "pglBeginImmediateGeom can't be called in a display list definition." );
252
253 // flush any pending geometry
254 GetImmGeomManager().Flush();
255
256 PushVif1Packet();
257 SetVif1Packet(*ImmVif1Packet);
258
259 ImmVif1Packet->Reset();
260}
261
262void CGLContext::EndImmediateGeometry()
263{
264 mAssert(Vif1Packet == ImmVif1Packet);
265
266 EndVif1Packet(2);
267
268 PopVif1Packet();
269}
270
271void CGLContext::RenderImmediateGeometry()
272{
273 ImmVif1Packet->End();
274 ImmVif1Packet->Pad128();
275 ImmVif1Packet->CloseTag();
276
277 ImmVif1Packet->Send();
278}
279
280void CGLContext::FinishRenderingImmediateGeometry(bool forceImmediateStop)
281{
282 mWarnIf(forceImmediateStop, "Interrupting currently rendering dma chain not supported yet");
283 mNotImplemented();
284}
285
286/********************************************
287 * normal geometry
288 */
289
290void CGLContext::BeginGeometry()
291{
292 // reset packets that will be drawn to during this frame
293
294 CurPacket->Reset();
295}
296
297void CGLContext::EndGeometry()
298{
299 EndVif1Packet(1);
300}
301
302void CGLContext::EndVif1Packet(unsigned short signalNum)
303{
304 //printf("%s(%d)\n", __FUNCTION__, signalNum);
305
306 // flush any pending geometry
307 GetImmGeomManager().Flush();
308
309 // end current packet
310 // write our id to the signal register and trigger an
311 // exception on the core when this dma chain reaches the end
312
313 tGifTag giftag;
314 giftag.NLOOP = 1;
315 giftag.EOP = 1;
316 giftag.PRE = 0;
317 giftag.FLG = 0; // packed
318 giftag.NREG = 1;
319 giftag.REGS0 = 0xe; // a+d
320
321 Vif1Packet->End();
322 Vif1Packet->Flush();
323 Vif1Packet->OpenDirect();
324 {
325 *Vif1Packet += giftag;
326 *Vif1Packet += Ps2glSignalId | signalNum;
327 *Vif1Packet += (uint64_t)0x60; // signal
328 }
329 Vif1Packet->CloseDirect();
330 Vif1Packet->CloseTag();
331}
332
333void CGLContext::RenderGeometry()
334{
335 //printf("%s\n", __FUNCTION__);
336
337 // make sure the semaphore we'll signal on completion is zero now
338 while (PollSema(RenderingFinishedSemaId) != -1)
339 ;
340
341 LastPacket->Send();
342}
343
344int CGLContext::GsIntHandler(int cause)
345{
346 uint32_t csr = *(volatile uint32_t*)GS::ControlRegs::csr;
347 // is this a signal interrupt?
348 if (csr & 1) {
349 // is it one of ours?
350 uint64_t sigLblId = *(volatile uint64_t*)GS::ControlRegs::siglblid;
351 if ((uint16_t)(sigLblId >> 16) == GetPs2glSignalId()) {
352 switch (sigLblId & 0xffff) {
353 case 1:
354 iSignalSema(RenderingFinishedSemaId);
355 if (RenderingFinishedCallback != NULL)
356 RenderingFinishedCallback();
357 break;
358 case 2:
359 iSignalSema(ImmediateRenderingFinishedSemaId);
360 break;
361 default:
362 mError("Unknown signal");
363 }
364
365 // clear our signal id
366 sigLblId &= ~0xffffffff;
367 *(volatile uint64_t*)GS::ControlRegs::siglblid = sigLblId;
368 // clear the exception and wait for the next
369 *(volatile unsigned int*)GS::ControlRegs::csr = 1;
370 }
371 }
372 // is this a vsync interrupt?
373 else if (csr & 8) {
374 iSignalSema(VsyncSemaId);
375 // clear the exception and wait for the next
376 *(volatile unsigned int*)GS::ControlRegs::csr = 8;
377 }
378
379 ExitHandler();
380
381 return 0;
382}
383
384void CGLContext::FinishRenderingGeometry(bool forceImmediateStop)
385{
386 //printf("%s(%d)\n", __FUNCTION__, forceImmediateStop);
387
388 mWarnIf(forceImmediateStop, "Interrupting currently rendering dma chain not supported yet");
389 WaitSema(RenderingFinishedSemaId);
390}
391
392void CGLContext::WaitForVSync()
393{
394 //printf("%s\n", __FUNCTION__);
395
396 // wait for beginning of v-sync
397 WaitSema(VsyncSemaId);
398 // sometimes if we miss a frame the semaphore gets incremented
399 // more than once (because maxCount is ignored?) which causes the next
400 // call to WaitForVSync to fall through immediately, which is kinda bad,
401 // so make sure the count is zero after waiting.
402 while (PollSema(VsyncSemaId) != -1)
403 ;
404 // sceGsSyncV(0);
405 uint32_t csr = *(volatile uint32_t*)GS::ControlRegs::csr;
406 IsCurrentFieldEven = (bool)((csr >> 13) & 1);
407}
408
409void CGLContext::SwapBuffers()
410{
411 //printf("%s\n", __FUNCTION__);
412
413 // switch packet ptrs
414
415 CVifSCDmaPacket* tempPkt = CurPacket;
416 CurPacket = LastPacket;
417 LastPacket = tempPkt;
418 Vif1Packet = CurPacket;
419
420 // switch drawenv ptrs
421
422 void** tempDEPtrs = CurDrawEnvPtrs;
423 CurDrawEnvPtrs = LastDrawEnvPtrs;
424 LastDrawEnvPtrs = tempDEPtrs;
425 NumLastDrawEnvPtrs = NumCurDrawEnvPtrs;
426 NumCurDrawEnvPtrs = 0;
427
428 // tell some modules that it's time to flip
429
430 GetImmGeomManager().SwapBuffers();
431 GetDListManager().SwapBuffers();
432 GetDisplayContext().SwapBuffers();
433 GetImmDrawContext().SwapBuffers(IsCurrentFieldEven);
434
435 // free memory that was waiting til end of frame
436 FreeWaitingBuffersAndSwap();
437
438 CurrentFrameNumber++;
439}
440
441void CGLContext::FreeWaitingBuffersAndSwap()
442{
443 //printf("%s\n", __FUNCTION__);
444
445 CurBuffer = 1 - CurBuffer;
446
447 for (int i = 0; i < NumBuffersToBeFreed[CurBuffer]; i++) {
448 free(BuffersToBeFreed[CurBuffer][i]);
449 }
450
451 NumBuffersToBeFreed[CurBuffer] = 0;
452}
453
454/********************************************
455 * ps2gl C interface
456 */
457
459CGLContext* pGLContext = NULL;
460
485int pglInit(int immBufferVertexSize, int immDrawBufferQwordSize)
486{
487 ps2sInit();
488 pGLContext = new CGLContext(immBufferVertexSize, immDrawBufferQwordSize);
489
490 return true;
491}
492
498{
499 return (pGLContext != NULL);
500}
501
505void pglFinish(void)
506{
507 if (pGLContext)
508 delete pGLContext;
509 ps2sFinish();
510}
511
520{
521 dma_channel_wait(DMAC::Channels::vif1, 1000000);
522}
523
529{
530 pGLContext->WaitForVSync();
531}
532
540{
541 mErrorIf(pGLContext == NULL, "You need to call pglInit()");
542
543 pGLContext->SwapBuffers();
544}
545
552{
553 pGLContext->SetRenderingFinishedCallback(cb);
554}
555
556/********************************************
557 * immediate geometry
558 */
559
560void pglBeginImmediateGeometry(void)
561{
562 pGLContext->BeginImmediateGeometry();
563}
564void pglEndImmediateGeometry(void)
565{
566 pGLContext->EndImmediateGeometry();
567}
568void pglRenderImmediateGeometry(void)
569{
570 pGLContext->RenderImmediateGeometry();
571}
572void pglFinishRenderingImmediateGeometry(int forceImmediateStop)
573{
574 pGLContext->FinishRenderingImmediateGeometry((bool)forceImmediateStop);
575}
576
577/********************************************
578 * normal geometry
579 */
580
581void pglBeginGeometry(void)
582{
583 pGLContext->BeginGeometry();
584}
585void pglEndGeometry(void)
586{
587 pGLContext->EndGeometry();
588}
589void pglRenderGeometry(void)
590{
591 pGLContext->RenderGeometry();
592}
593void pglFinishRenderingGeometry(int forceImmediateStop)
594{
595 pGLContext->FinishRenderingGeometry((bool)forceImmediateStop);
596}
597
598/********************************************
599 * enable / disable
600 */
601
602void pglEnable(GLenum cap)
603{
604 switch (cap) {
605 case PGL_CLIPPING:
606 pGLContext->GetDrawContext().SetDoClipping(true);
607 break;
608 default:
609 mError("Unknown option passed to pglEnable()");
610 }
611}
612
613void pglDisable(GLenum cap)
614{
615 switch (cap) {
616 case PGL_CLIPPING:
617 pGLContext->GetDrawContext().SetDoClipping(false);
618 break;
619 default:
620 mError("Unknown option passed to pglDisable()");
621 }
622}
623
628/********************************************
629 * gl interface
630 */
631
632void glEnable(GLenum cap)
633{
634 GL_FUNC_DEBUG("%s(0x%x)\n", __FUNCTION__, cap);
635
636 CLighting& lighting = pGLContext->GetLighting();
637
638 switch (cap) {
639 case GL_LIGHT0:
640 case GL_LIGHT1:
641 case GL_LIGHT2:
642 case GL_LIGHT3:
643 case GL_LIGHT4:
644 case GL_LIGHT5:
645 case GL_LIGHT6:
646 case GL_LIGHT7:
647 lighting.GetLight(0x7 & cap).SetEnabled(true);
648 break;
649 case GL_LIGHTING:
650 lighting.SetLightingEnabled(true);
651 break;
652
653 case GL_BLEND:
654 pGLContext->GetDrawContext().SetBlendEnabled(true);
655 break;
656
657 case GL_COLOR_MATERIAL:
658 pGLContext->GetMaterialManager().SetUseColorMaterial(true);
659 break;
660 case GL_RESCALE_NORMAL:
661 pGLContext->GetDrawContext().SetRescaleNormals(true);
662 break;
663
664 case GL_TEXTURE_2D:
665 pGLContext->GetTexManager().SetTexEnabled(true);
666 break;
667
668 case GL_NORMALIZE:
669 pGLContext->GetGeomManager().SetDoNormalize(true);
670 break;
671
672 case GL_CULL_FACE:
673 pGLContext->GetDrawContext().SetDoCullFace(true);
674 break;
675
676 case GL_ALPHA_TEST:
677 pGLContext->GetDrawContext().SetAlphaTestEnabled(true);
678 break;
679
680 case GL_DEPTH_TEST:
681 pGLContext->GetDrawContext().SetDepthTestEnabled(true);
682 break;
683
684 default:
685 mNotImplemented();
686 break;
687 }
688}
689
690void glDisable(GLenum cap)
691{
692 GL_FUNC_DEBUG("%s(0x%x)\n", __FUNCTION__, cap);
693
694 switch (cap) {
695 case GL_LIGHT0:
696 case GL_LIGHT1:
697 case GL_LIGHT2:
698 case GL_LIGHT3:
699 case GL_LIGHT4:
700 case GL_LIGHT5:
701 case GL_LIGHT6:
702 case GL_LIGHT7:
703 pGLContext->GetLighting().GetLight(0x7 & cap).SetEnabled(false);
704 break;
705 case GL_LIGHTING:
706 pGLContext->GetLighting().SetLightingEnabled(false);
707 break;
708
709 case GL_BLEND:
710 pGLContext->GetDrawContext().SetBlendEnabled(false);
711 break;
712
713 case GL_COLOR_MATERIAL:
714 pGLContext->GetMaterialManager().SetUseColorMaterial(false);
715 break;
716 case GL_RESCALE_NORMAL:
717 pGLContext->GetDrawContext().SetRescaleNormals(false);
718 break;
719
720 case GL_TEXTURE_2D:
721 pGLContext->GetTexManager().SetTexEnabled(false);
722 break;
723
724 case GL_NORMALIZE:
725 pGLContext->GetGeomManager().SetDoNormalize(false);
726 break;
727
728 case GL_CULL_FACE:
729 pGLContext->GetDrawContext().SetDoCullFace(false);
730 break;
731
732 case GL_ALPHA_TEST:
733 pGLContext->GetDrawContext().SetAlphaTestEnabled(false);
734 break;
735
736 case GL_DEPTH_TEST:
737 pGLContext->GetDrawContext().SetDepthTestEnabled(false);
738 break;
739
740 default:
741 mNotImplemented();
742 }
743}
744
745void glHint(GLenum target, GLenum mode)
746{
747 GL_FUNC_DEBUG("%s(0x%x,0x%x)\n", __FUNCTION__, target, mode);
748
749 mNotImplemented();
750}
751
752void glGetFloatv(GLenum pname, GLfloat* params)
753{
754 GL_FUNC_DEBUG("%s(0x%x,...)\n", __FUNCTION__, pname);
755
756 switch (pname) {
757 case GL_MODELVIEW_MATRIX:
758 memcpy(params, &(pGLContext->GetModelViewStack().GetTop()), 16 * 4);
759 break;
760 case GL_PROJECTION_MATRIX:
761 memcpy(params, &(pGLContext->GetProjectionStack().GetTop()), 16 * 4);
762 break;
763 default:
764 mNotImplemented("pname %d", pname);
765 break;
766 }
767}
768
769void glGetIntegerv(GLenum pname, int* params)
770{
771 GL_FUNC_DEBUG("%s(0x%x,...)\n", __FUNCTION__, pname);
772
773 mNotImplemented();
774}
775
776GLenum glGetError(void)
777{
778 GL_FUNC_DEBUG("%s()\n", __FUNCTION__);
779
780 mWarn("glGetError does nothing");
781
782 return 0;
783}
784
785const GLubyte* glGetString(GLenum name)
786{
787 GL_FUNC_DEBUG("%s(0x%x)\n", __FUNCTION__, name);
788
789 mNotImplemented();
790 return (GLubyte*)"not implemented";
791}
static uint16_t GetPs2glSignalId()
Definition glcontext.h:237
static int RenderingFinishedSemaId
Semaphores signaled by the gs int handler.
Definition glcontext.h:168
static const uint64_t Ps2glSignalId
Definition glcontext.h:165
void pglSetRenderingFinishedCallback(void(*cb)(void))
void pglFinish(void)
void pglWaitForVU1(void)
void pglSwapBuffers(void)
int pglHasLibraryBeenInitted(void)
void pglWaitForVSync(void)
int pglInit(int immBufferVertexSize, int immDrawBufferQwordSize)