00001
00002
00003 This file is subject to the terms and conditions of the GNU Lesser
00004 General Public License Version 2.1. See the file "COPYING" in the
00005 main directory of this archive for more details. */
00006
00007 #include <string.h>
00008
00009 #ifndef PS2_LINUX
00010 # include "libgraph.h"
00011 # include "libdma.h"
00012 # include "libdev.h"
00013 #else
00014 # include <sys/mman.h>
00015 # include "ps2stuff_kmodule.h"
00016 # include <ps2gs.h>
00017 #endif
00018
00019 #include "GL/ps2gl.h"
00020
00021 #include "ps2s/ps2stuff.h"
00022 #include "ps2s/types.h"
00023 #include "ps2s/math.h"
00024 #include "ps2s/drawenv.h"
00025 #include "ps2s/displayenv.h"
00026 #include "ps2s/packet.h"
00027 #include "ps2s/gsmem.h"
00028 #include "ps2s/texture.h"
00029
00030 #include "ps2gl/glcontext.h"
00031 #include "ps2gl/matrix.h"
00032 #include "ps2gl/gmanager.h"
00033 #include "ps2gl/dlgmanager.h"
00034 #include "ps2gl/immgmanager.h"
00035 #include "ps2gl/lighting.h"
00036 #include "ps2gl/material.h"
00037 #include "ps2gl/dlist.h"
00038 #include "ps2gl/texture.h"
00039 #include "ps2gl/displaycontext.h"
00040 #include "ps2gl/drawcontext.h"
00041
00042
00043 * globals
00044 */
00045
00046
00047
00048 * CGLContext
00049 */
00050
00051
00052
00053 CVifSCDmaPacket *CGLContext::CurPacket, *CGLContext::LastPacket,
00054 *CGLContext::Vif1Packet = NULL, *CGLContext::SavedVif1Packet = NULL,
00055 *CGLContext::ImmVif1Packet;
00056
00057 int CGLContext::RenderingFinishedSemaId = -1;
00058 int CGLContext::ImmediateRenderingFinishedSemaId = -1;
00059 int CGLContext::VsyncSemaId = -1;
00060
00061 CGLContext::tRenderingFinishedCallback CGLContext::RenderingFinishedCallback = NULL;
00062
00063 CGLContext::CGLContext( int immBufferQwordSize, int immDrawBufferQwordSize )
00064 : StateChangesArePushed(false),
00065 IsCurrentFieldEven(true),
00066 CurrentFrameNumber(0),
00067 CurBuffer(0)
00068 {
00069 CurPacket = new CVifSCDmaPacket( kDmaPacketMaxQwordLength, DMAC::Channels::vif1,
00070 Packet::kXferTags, Core::MemMappings::UncachedAccl );
00071 LastPacket = new CVifSCDmaPacket( kDmaPacketMaxQwordLength, DMAC::Channels::vif1,
00072 Packet::kXferTags, Core::MemMappings::UncachedAccl );
00073 Vif1Packet = CurPacket;
00074
00075 ImmVif1Packet = new CVifSCDmaPacket( immDrawBufferQwordSize, DMAC::Channels::vif1,
00076 Packet::kXferTags, Core::MemMappings::UncachedAccl );
00077
00078 CurDrawEnvPtrs = DrawEnvPtrs0;
00079 LastDrawEnvPtrs = DrawEnvPtrs1;
00080 NumCurDrawEnvPtrs = 0;
00081 NumLastDrawEnvPtrs = 0;
00082
00083 ImmGManager = new CImmGeomManager(*this, immBufferQwordSize);
00084 DListGManager = new CDListGeomManager(*this);
00085 CurGManager = ImmGManager;
00086
00087 ProjectionMatStack = new CImmMatrixStack(*this);
00088 ModelViewMatStack = new CImmMatrixStack(*this);
00089 DListMatStack = new CDListMatrixStack(*this);
00090 CurMatrixStack = ModelViewMatStack;
00091 SavedCurMatStack = NULL;
00092
00093 ImmLighting = new CImmLighting(*this);
00094 DListLighting = new CDListLighting(*this);
00095 CurLighting = ImmLighting;
00096
00097 CLight &light = ImmLighting->GetLight(0);
00098 light.SetDiffuse( cpu_vec_xyzw(1.0f, 1.0f, 1.0f, 1.0f) );
00099 light.SetSpecular( cpu_vec_xyzw(1.0f, 1.0f, 1.0f, 1.0f) );
00100
00101 MaterialManager = new CMaterialManager(*this);
00102 DListManager = new CDListManager;
00103 TexManager = new CTexManager(*this);
00104
00105 ImmDrawContext = new CImmDrawContext(*this);
00106 DListDrawContext = new CDListDrawContext(*this);
00107 CurDrawContext = ImmDrawContext;
00108
00109 DisplayContext = new CDisplayContext(*this);
00110
00111 SetRendererContextChanged(true);
00112 SetGsContextChanged(true);
00113 SetRendererPropsChanged(true);
00114
00115
00116 NumBuffersToBeFreed[0] = NumBuffersToBeFreed[1] = 0;
00117
00118 GS::Init();
00119
00120 #ifndef PS2_LINUX
00121
00122
00123 struct SemaParam newSemaphore = { 0, 1, 0 };
00124 VsyncSemaId = CreateSema( &newSemaphore );
00125 RenderingFinishedSemaId = CreateSema( &newSemaphore );
00126 ImmediateRenderingFinishedSemaId = CreateSema( &newSemaphore );
00127 mErrorIf( VsyncSemaId == -1
00128 || RenderingFinishedSemaId == -1
00129 || ImmediateRenderingFinishedSemaId == -1,
00130 "Failed to create ps2gl semaphores." );
00131
00132
00133
00134
00135 AddIntcHandler( INTC_GS, CGLContext::GsIntHandler, 0 );
00136 EnableIntc( INTC_GS );
00137
00138 *(volatile unsigned int*)GS::ControlRegs::csr = 9;
00139
00140 *(volatile unsigned int*)GS::ControlRegs::imr = 0x7600;
00141 #endif
00142 }
00143
00144 CGLContext::~CGLContext()
00145 {
00146 delete CurPacket;
00147 delete LastPacket;
00148
00149 delete ImmGManager;
00150 delete DListGManager;
00151
00152 delete ProjectionMatStack;
00153 delete ModelViewMatStack;
00154 delete DListMatStack;
00155
00156 delete ImmLighting;
00157 delete DListLighting;
00158
00159 delete MaterialManager;
00160 delete DListManager;
00161 delete TexManager;
00162
00163 delete ImmDrawContext;
00164 delete DListDrawContext;
00165
00166 delete DisplayContext;
00167 }
00168
00169
00170 * display lists
00171 */
00172
00173 void
00174 CGLContext::BeginDListDef( unsigned int listID, GLenum mode )
00175 {
00176 DListManager->NewList( listID, mode );
00177
00178 PushStateChanges();
00179
00180
00181 SetRendererContextChanged(true);
00182 SetGsContextChanged(true);
00183
00184 SetRendererPropsChanged(true);
00185
00186 MaterialManager->BeginDListDef();
00187 TexManager->BeginDListDef();
00188 DListGManager->BeginDListDef();
00189
00190 CurLighting = DListLighting;
00191 CurGManager = DListGManager;
00192 SavedCurMatStack = CurMatrixStack;
00193 CurMatrixStack = DListMatStack;
00194 CurDrawContext = DListDrawContext;
00195 }
00196
00197 void
00198 CGLContext::EndDListDef()
00199 {
00200 DListGManager->EndDListDef();
00201 MaterialManager->EndDListDef();
00202 TexManager->EndDListDef();
00203
00204 CurLighting = ImmLighting;
00205 CurGManager = ImmGManager;
00206 CurMatrixStack = SavedCurMatStack;
00207 CurDrawContext = ImmDrawContext;
00208
00209 PopStateChanges();
00210
00211 DListManager->EndList();
00212 }
00213
00214
00215 * matrix mode
00216 */
00217
00218 class CSetMatrixModeCmd : public CDListCmd {
00219 GLenum Mode;
00220 public:
00221 CSetMatrixModeCmd( GLenum mode ) : Mode(mode) {}
00222 CDListCmd* Play() { glMatrixMode( Mode ); return CDListCmd::GetNextCmd(this); }
00223 };
00224
00225 void
00226 CGLContext::SetMatrixMode( GLenum mode )
00227 {
00228 if ( InDListDef() ) {
00229 DListManager->GetOpenDList() += CSetMatrixModeCmd(mode);
00230 }
00231 else {
00232 switch (mode) {
00233 case GL_MODELVIEW:
00234 CurMatrixStack = ModelViewMatStack;
00235 break;
00236 case GL_PROJECTION:
00237 CurMatrixStack = ProjectionMatStack;
00238 break;
00239 default:
00240 mNotImplemented( );
00241 }
00242 }
00243 }
00244
00245
00246 * immediate geometry
00247 */
00248
00249 void
00250 CGLContext::BeginImmediateGeometry()
00251 {
00252
00253
00254
00255
00256 GetImmGeomManager().Flush();
00257
00258 PushVif1Packet();
00259 SetVif1Packet( *ImmVif1Packet );
00260
00261 ImmVif1Packet->Reset();
00262 }
00263
00264 void
00265 CGLContext::EndImmediateGeometry()
00266 {
00267 mAssert( Vif1Packet == ImmVif1Packet );
00268
00269 EndVif1Packet(2);
00270
00271 PopVif1Packet();
00272 }
00273
00274 void
00275 CGLContext::RenderImmediateGeometry()
00276 {
00277 ImmVif1Packet->End();
00278 ImmVif1Packet->Pad128();
00279 ImmVif1Packet->CloseTag();
00280
00281 ImmVif1Packet->Send();
00282 }
00283
00284 void
00285 CGLContext::FinishRenderingImmediateGeometry( bool forceImmediateStop )
00286 {
00287 mWarnIf( forceImmediateStop, "Interrupting currently rendering dma chain not supported yet" );
00288 mNotImplemented( );
00289 }
00290
00291
00292 * normal geometry
00293 */
00294
00295 void
00296 CGLContext::BeginGeometry()
00297 {
00298
00299
00300 CurPacket->Reset();
00301 }
00302
00303 void
00304 CGLContext::EndGeometry()
00305 {
00306 EndVif1Packet(1);
00307 }
00308
00309 void
00310 CGLContext::EndVif1Packet( unsigned short signalNum )
00311 {
00312
00313 GetImmGeomManager().Flush();
00314
00315
00316
00317
00318
00319 #ifndef PS2_LINUX
00320 tGifTag giftag;
00321 giftag.NLOOP = 1;
00322 giftag.EOP = 1;
00323 giftag.PRE = 0;
00324 giftag.FLG = 0;
00325 giftag.NREG = 1;
00326 giftag.REGS0 = 0xe;
00327
00328 Vif1Packet->End();
00329 Vif1Packet->Flush();
00330 Vif1Packet->OpenDirect();
00331 {
00332 *Vif1Packet += giftag;
00333 *Vif1Packet += Ps2glSignalId | signalNum;
00334 *Vif1Packet += (tU64)0x60;
00335 }
00336 Vif1Packet->CloseDirect();
00337 Vif1Packet->CloseTag();
00338 #else
00339 Vif1Packet->End();
00340 Vif1Packet->Nop().Nop();
00341 Vif1Packet->CloseTag();
00342 #endif
00343 }
00344
00345 void
00346 CGLContext::RenderGeometry()
00347 {
00348 #ifndef PS2_LINUX
00349
00350 while ( PollSema(RenderingFinishedSemaId) != -1 );
00351 #endif
00352
00353 LastPacket->Send();
00354 }
00355
00356 int
00357 CGLContext::GsIntHandler( int cause )
00358 {
00359 int ret = 0;
00360
00361 #ifndef PS2_LINUX
00362 tU32 csr = *(volatile tU32*)GS::ControlRegs::csr;
00363
00364 if ( csr & 1 ) {
00365
00366 tU64 sigLblId = *(volatile tU64*)GS::ControlRegs::siglblid;
00367 if ( (tU16)(sigLblId >> 16) == GetPs2glSignalId() ) {
00368 switch ( sigLblId & 0xffff ) {
00369 case 1:
00370 iSignalSema( RenderingFinishedSemaId );
00371 if ( RenderingFinishedCallback != NULL )
00372 RenderingFinishedCallback();
00373 break;
00374 case 2:
00375 iSignalSema( ImmediateRenderingFinishedSemaId );
00376 break;
00377 default:
00378 mError( "Unknown signal" );
00379 }
00380
00381
00382 sigLblId &= ~0xffffffff;
00383 *(volatile tU64*)GS::ControlRegs::siglblid = sigLblId;
00384
00385 *(volatile unsigned int*)GS::ControlRegs::csr = 1;
00386
00387 ret = -1;
00388 }
00389 }
00390
00391 else if ( csr & 8 ) {
00392 iSignalSema( VsyncSemaId );
00393
00394 *(volatile unsigned int*)GS::ControlRegs::csr = 8;
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 if ( ret == -1 ) {
00406 *(volatile unsigned int*)GS::ControlRegs::imr = 0x7f00;
00407 *(volatile unsigned int*)GS::ControlRegs::imr = 0x7600;
00408 }
00409 #endif
00410
00411 return ret;
00412 }
00413
00414 void
00415 CGLContext::FinishRenderingGeometry( bool forceImmediateStop )
00416 {
00417 #ifndef PS2_LINUX
00418 mWarnIf( forceImmediateStop, "Interrupting currently rendering dma chain not supported yet" );
00419 WaitSema( RenderingFinishedSemaId );
00420 #else
00421 pglWaitForVU1();
00422 #endif
00423 }
00424
00425 void
00426 CGLContext::WaitForVSync()
00427 {
00428
00429 #ifndef PS2_LINUX
00430 WaitSema( VsyncSemaId );
00431
00432
00433
00434
00435 while ( PollSema(VsyncSemaId) != -1 );
00436
00437 tU32 csr = *(volatile tU32*)GS::ControlRegs::csr;
00438 IsCurrentFieldEven = (bool)((csr >> 13) & 1);
00439 #else
00440 IsCurrentFieldEven = Math::IsEven(ps2_gs_sync_v(0));
00441 #endif
00442 }
00443
00444 void
00445 CGLContext::SwapBuffers()
00446 {
00447
00448
00449 CVifSCDmaPacket *tempPkt = CurPacket;
00450 CurPacket = LastPacket;
00451 LastPacket = tempPkt;
00452 Vif1Packet = CurPacket;
00453
00454
00455
00456 void **tempDEPtrs = CurDrawEnvPtrs;
00457 CurDrawEnvPtrs = LastDrawEnvPtrs;
00458 LastDrawEnvPtrs = tempDEPtrs;
00459 NumLastDrawEnvPtrs = NumCurDrawEnvPtrs;
00460 NumCurDrawEnvPtrs = 0;
00461
00462
00463
00464 GetImmGeomManager().SwapBuffers();
00465 GetDListManager().SwapBuffers();
00466 GetDisplayContext().SwapBuffers();
00467 GetImmDrawContext().SwapBuffers( IsCurrentFieldEven );
00468
00469
00470 FreeWaitingBuffersAndSwap();
00471
00472 CurrentFrameNumber++;
00473 }
00474
00475 void
00476 CGLContext::FreeWaitingBuffersAndSwap()
00477 {
00478 CurBuffer = 1 - CurBuffer;
00479
00480 for ( int i = 0; i < NumBuffersToBeFreed[CurBuffer]; i++ ) {
00481 #ifndef PS2_LINUX
00482 free( BuffersToBeFreed[CurBuffer][i] );
00483 #else
00484 munmap(BuffersToBeFreed[CurBuffer][i], 1);
00485 #endif
00486 }
00487
00488 NumBuffersToBeFreed[CurBuffer] = 0;
00489 }
00490
00491
00492 * ps2gl C interface
00493 */
00494
00496 CGLContext *pGLContext = NULL;
00497
00522 int
00523 pglInit( int immBufferVertexSize, int immDrawBufferQwordSize )
00524 {
00525 ps2sInit();
00526 pGLContext = new CGLContext(immBufferVertexSize, immDrawBufferQwordSize);
00527
00528 return true;
00529 }
00530
00535 int
00536 pglHasLibraryBeenInitted(void)
00537 {
00538 return (pGLContext != NULL);
00539 }
00540
00544 void
00545 pglFinish( void )
00546 {
00547 if (pGLContext) delete pGLContext;
00548 ps2sFinish();
00549 }
00550
00551 #ifdef PS2_LINUX
00552
00553
00554 extern int Ps2stuffDeviceFd;
00555 #endif
00556
00564 void
00565 pglWaitForVU1( void )
00566 {
00567 #ifndef PS2_LINUX
00568
00569 *D_PCR = 0x2;
00570
00571 *D_STAT = 2;
00572
00573 asm volatile ("sync.l");
00574
00575 if ( *D1_CHCR & 0x100 ) {
00576
00577 asm volatile (
00578 ".set noreorder \n"
00579
00580 "0: \n"
00581
00582 "nop \n"
00583 "nop \n"
00584
00585 "nop \n"
00586 "nop \n"
00587
00588 "nop \n"
00589 "nop \n"
00590
00591 "nop \n"
00592 "nop \n"
00593
00594 "bc0f 0b \n"
00595 "nop \n"
00596
00597 ".set reorder \n"
00598 );
00599 }
00600 #else
00601 ioctl( Ps2stuffDeviceFd, PS2STUFF_IOCTV1DMAW, 0 );
00602 #endif
00603 }
00604
00609 void
00610 pglWaitForVSync( void )
00611 {
00612 pGLContext->WaitForVSync();
00613 }
00614
00621 void
00622 pglSwapBuffers( void )
00623 {
00624 mErrorIf( pGLContext == NULL, "You need to call pglInit()" );
00625
00626 pGLContext->SwapBuffers();
00627 }
00628
00634 void
00635 pglSetRenderingFinishedCallback( void (*cb)(void) )
00636 {
00637 pGLContext->SetRenderingFinishedCallback(cb);
00638 }
00639
00640
00641 * immediate geometry
00642 */
00643
00644 void
00645 pglBeginImmediateGeometry( void )
00646 {
00647 pGLContext->BeginImmediateGeometry();
00648 }
00649 void
00650 pglEndImmediateGeometry( void )
00651 {
00652 pGLContext->EndImmediateGeometry();
00653 }
00654 void
00655 pglRenderImmediateGeometry( void )
00656 {
00657 pGLContext->RenderImmediateGeometry();
00658 }
00659 void
00660 pglFinishRenderingImmediateGeometry( int forceImmediateStop )
00661 {
00662 pGLContext->FinishRenderingImmediateGeometry( (bool)forceImmediateStop );
00663 }
00664
00665
00666 * normal geometry
00667 */
00668
00669 void
00670 pglBeginGeometry( void )
00671 {
00672 pGLContext->BeginGeometry();
00673 }
00674 void
00675 pglEndGeometry( void )
00676 {
00677 pGLContext->EndGeometry();
00678 }
00679 void
00680 pglRenderGeometry( void )
00681 {
00682 pGLContext->RenderGeometry();
00683 }
00684 void
00685 pglFinishRenderingGeometry( int forceImmediateStop )
00686 {
00687 pGLContext->FinishRenderingGeometry( (bool)forceImmediateStop );
00688 }
00689
00690
00691 * enable / disable
00692 */
00693
00694 void
00695 pglEnable( GLenum cap )
00696 {
00697 switch (cap) {
00698 case PGL_CLIPPING:
00699 pGLContext->GetDrawContext().SetDoClipping(true);
00700 break;
00701 default:
00702 mError( "Unknown option passed to pglEnable()" );
00703 }
00704 }
00705
00706 void
00707 pglDisable( GLenum cap )
00708 {
00709 switch (cap) {
00710 case PGL_CLIPPING:
00711 pGLContext->GetDrawContext().SetDoClipping(false);
00712 break;
00713 default:
00714 mError( "Unknown option passed to pglDisable()" );
00715 }
00716 }
00717
00722
00723 * gl interface
00724 */
00725
00726 void glEnable( GLenum cap )
00727 {
00728 CLighting& lighting = pGLContext->GetLighting();
00729
00730 switch (cap) {
00731 case GL_LIGHT0:
00732 case GL_LIGHT1:
00733 case GL_LIGHT2:
00734 case GL_LIGHT3:
00735 case GL_LIGHT4:
00736 case GL_LIGHT5:
00737 case GL_LIGHT6:
00738 case GL_LIGHT7:
00739 lighting.GetLight(0x7 & cap).SetEnabled(true);
00740 break;
00741 case GL_LIGHTING:
00742 lighting.SetLightingEnabled(true);
00743 break;
00744
00745 case GL_BLEND:
00746 pGLContext->GetDrawContext().SetBlendEnabled(true);
00747 break;
00748
00749 case GL_COLOR_MATERIAL:
00750 pGLContext->GetMaterialManager().SetUseColorMaterial(true);
00751 break;
00752 case GL_RESCALE_NORMAL:
00753 pGLContext->GetDrawContext().SetRescaleNormals(true);
00754 break;
00755
00756 case GL_TEXTURE_2D:
00757 pGLContext->GetTexManager().SetTexEnabled(true);
00758 break;
00759
00760 case GL_NORMALIZE:
00761 pGLContext->GetGeomManager().SetDoNormalize(true);
00762 break;
00763
00764 case GL_CULL_FACE:
00765 pGLContext->GetDrawContext().SetDoCullFace(true);
00766 break;
00767
00768 case GL_ALPHA_TEST:
00769 pGLContext->GetDrawContext().SetAlphaTestEnabled(true);
00770 break;
00771
00772 case GL_DEPTH_TEST:
00773 default:
00774 mNotImplemented( );
00775 break;
00776 }
00777 }
00778
00779 void glDisable( GLenum cap )
00780 {
00781 switch (cap) {
00782 case GL_LIGHT0:
00783 case GL_LIGHT1:
00784 case GL_LIGHT2:
00785 case GL_LIGHT3:
00786 case GL_LIGHT4:
00787 case GL_LIGHT5:
00788 case GL_LIGHT6:
00789 case GL_LIGHT7:
00790 pGLContext->GetLighting().GetLight(0x7 & cap).SetEnabled(false);
00791 break;
00792 case GL_LIGHTING:
00793 pGLContext->GetLighting().SetLightingEnabled(false);
00794 break;
00795
00796 case GL_BLEND:
00797 pGLContext->GetDrawContext().SetBlendEnabled(false);
00798 break;
00799
00800 case GL_COLOR_MATERIAL:
00801 pGLContext->GetMaterialManager().SetUseColorMaterial(false);
00802 break;
00803 case GL_RESCALE_NORMAL:
00804 pGLContext->GetDrawContext().SetRescaleNormals(false);
00805 break;
00806
00807 case GL_TEXTURE_2D:
00808 pGLContext->GetTexManager().SetTexEnabled(false);
00809 break;
00810
00811 case GL_NORMALIZE:
00812 pGLContext->GetGeomManager().SetDoNormalize(false);
00813 break;
00814
00815 case GL_CULL_FACE:
00816 pGLContext->GetDrawContext().SetDoCullFace(false);
00817 break;
00818
00819 case GL_ALPHA_TEST:
00820 pGLContext->GetDrawContext().SetAlphaTestEnabled(false);
00821 break;
00822
00823 case GL_DEPTH_TEST:
00824 default:
00825 mNotImplemented( );
00826 }
00827 }
00828
00829 void glHint( GLenum target, GLenum mode )
00830 {
00831 mNotImplemented( );
00832 }
00833
00834 void glGetFloatv( GLenum pname, GLfloat *params )
00835 {
00836 switch (pname) {
00837 case GL_MODELVIEW_MATRIX:
00838 memcpy( params, & (pGLContext->GetModelViewStack().GetTop()), 16 * 4 );
00839 break;
00840 case GL_PROJECTION_MATRIX:
00841 memcpy( params, & (pGLContext->GetProjectionStack().GetTop()), 16 * 4 );
00842 break;
00843 default:
00844 mNotImplemented( "pname %d", pname );
00845 break;
00846 }
00847 }
00848
00849 const GLubyte *glGetString( GLenum name )
00850 {
00851 mNotImplemented( );
00852 return (GLubyte*)"not implemented";
00853 }