00001
00002
00003
00004
00005 #ifndef ps2gl_dlist_h
00006 #define ps2gl_dlist_h
00007
00008 #include "GL/gl.h"
00009 #include "ps2s/packet.h"
00010 #include "ps2gl/debug.h"
00011
00012
00013
00014
00015
00016 class CDListCmd {
00017 public:
00018 CDListCmd() {}
00019 virtual CDListCmd* Play() = 0;
00020
00021 template <class CmdType>
00022 static inline int SizeOf() {
00023
00024 int size = sizeof(CmdType);
00025
00026
00027 if ( size & 0xf )
00028 size = (size & ~0xf) + 16;
00029 return size;
00030 }
00031
00032 template <class CmdType>
00033 static CDListCmd* GetNextCmd( CmdType *cmd ) {
00034
00035
00036 int size = sizeof(CmdType);
00037
00038
00039 if ( size & 0xf )
00040 size = (size & ~0xf) + 16;
00041
00042 return reinterpret_cast<CDListCmd*>((unsigned int)cmd + size);
00043 }
00044 };
00045
00046 class CEmptyListCmd : public CDListCmd {
00047 public:
00048 CDListCmd* Play() { mError("Trying to play an empty list!"); return NULL; }
00049 };
00050
00051 class CEndListCmd : public CDListCmd {
00052 public:
00053 CDListCmd* Play() { return NULL; }
00054 };
00055
00056 class CDListCmdBlock;
00057 class CNextBlockCmd : public CDListCmd {
00058 CDListCmdBlock *NextBlock;
00059 public:
00060 CNextBlockCmd( CDListCmdBlock* nextBlock ) : NextBlock(nextBlock) {}
00061 CDListCmd* Play();
00062 };
00063
00064 class CEnableCmd : public CDListCmd {
00065 GLenum Property;
00066 public:
00067 CEnableCmd( GLenum prop ) : Property(prop) {}
00068 CDListCmd* Play() { glEnable( Property ); return CDListCmd::GetNextCmd(this); }
00069 };
00070
00071
00072
00073
00074
00075 class CDListCmdBlock {
00076 static const int ByteSize = 1024;
00077 char Memory[ByteSize];
00078 char *MemCursor;
00079 int BytesLeft;
00080 CDListCmdBlock *NextBlock;
00081
00082 public:
00083 CDListCmdBlock()
00084 : MemCursor(Memory), BytesLeft(ByteSize), NextBlock(NULL) {
00085 CEmptyListCmd empty;
00086 memcpy( MemCursor, &empty, CDListCmd::SizeOf<CEmptyListCmd>() );
00087 }
00088 ~CDListCmdBlock() { if (NextBlock) delete NextBlock; }
00089
00090 template <class CmdType>
00091 bool CanFit( CmdType cmd ) {
00092 return ( CDListCmd::SizeOf<CmdType>()
00093 <= BytesLeft - CDListCmd::SizeOf<CNextBlockCmd>() );
00094 }
00095
00096 template <class CmdType>
00097 void operator += ( CmdType cmd ) {
00098 memcpy( MemCursor, &cmd, sizeof(CmdType) );
00099 MemCursor += CDListCmd::SizeOf<CmdType>();
00100 BytesLeft -= CDListCmd::SizeOf<CmdType>();
00101 }
00102
00103 CDListCmd* GetFirstCmd() { return reinterpret_cast<CDListCmd*>(&Memory[0]); }
00104
00105 void SetNextBlock( CDListCmdBlock *next ) { NextBlock = next; }
00106 CDListCmdBlock* GetNextBlock() const { return NextBlock; }
00107 };
00108
00109 inline CDListCmd*
00110 CNextBlockCmd::Play() {
00111 return NextBlock->GetFirstCmd();
00112 }
00113
00114
00115
00116
00117
00118 class CDList {
00119 static const int kBufferMaxQwordLength = 16*1024;
00120 CDmaPacket *VertexBuf, *NormalBuf, *TexCoordBuf, *ColorBuf;
00121 CDListCmdBlock *FirstCmdBlock, *CurCmdBlock;
00122 static const int kMaxNumRenderPackets = 512;
00123 int NumRenderPackets;
00124 CVifSCDmaPacket *RenderPackets[kMaxNumRenderPackets];
00125
00126 public:
00127 CDList();
00128 ~CDList();
00129
00130
00131 template <class CmdType>
00132 CDListCmd* GetNext( CmdType* cmd ) {
00133 return 0;
00134 }
00135
00136 template <class CmdType>
00137 void operator += ( CmdType cmd ) {
00138 if ( ! CurCmdBlock->CanFit(cmd) ) {
00139
00140
00141 CDListCmdBlock *newBlock = new CDListCmdBlock;
00142 CurCmdBlock->SetNextBlock( newBlock );
00143 *CurCmdBlock += CNextBlockCmd(newBlock);
00144 CurCmdBlock = newBlock;
00145 }
00146 *CurCmdBlock += cmd;
00147 }
00148
00149 void Play() {
00150 CDListCmd* nextCmd = FirstCmdBlock->GetFirstCmd();
00151 while ( nextCmd ) nextCmd = nextCmd->Play();
00152 }
00153
00154 void Begin();
00155 void End() { CEndListCmd endList; *this += endList; }
00156
00157 CDmaPacket& GetVertexBuf();
00158 CDmaPacket& GetNormalBuf();
00159 CDmaPacket& GetTexCoordBuf();
00160 CDmaPacket& GetColorBuf();
00161
00162 void RegisterNewPacket( CVifSCDmaPacket *packet ) {
00163 RenderPackets[NumRenderPackets++] = packet;
00164 }
00165 };
00166
00167
00168
00169
00170
00171 class CDListManager {
00172 static const int kMaxListID = 4096;
00173 int NextFreeListID;
00174 CDList *Lists[kMaxListID];
00175 unsigned int OpenListID;
00176 CDList *OpenList;
00177
00178 bool ListsAreFree( int firstListID, int numLists );
00179
00180 static const int kMaxBuffersToBeFreed = 1024;
00181 CDList* ListsToBeFreed[2][kMaxBuffersToBeFreed];
00182 int NumListsToBeFreed[2];
00183 int CurBuffer;
00184
00185 inline void AddListToBeFreed( CDList *dlist ) {
00186 mAssert( NumListsToBeFreed[CurBuffer] < kMaxBuffersToBeFreed );
00187 ListsToBeFreed[CurBuffer][NumListsToBeFreed[CurBuffer]++] = dlist;
00188 }
00189
00190 public:
00191 CDListManager()
00192 : NextFreeListID(1), OpenListID(0), OpenList(NULL), CurBuffer(0)
00193 {
00194 for ( int i = 0; i < kMaxListID; i++ )
00195 Lists[i] = NULL;
00196 NumListsToBeFreed[0] = NumListsToBeFreed[1] = 0;
00197 }
00198 ~CDListManager() {
00199 for ( int i = 0; i < 10; i++ )
00200 if ( Lists[i] ) delete Lists[i];
00201 }
00202
00203 void FrameHasEnded();
00204
00205 unsigned int GenLists( int numLists );
00206 void DeleteLists( unsigned int firstListID, int numLists );
00207 void NewList( unsigned int listID, GLenum mode );
00208 void EndList();
00209 void CallList( unsigned int listID );
00210
00211 CDList& GetOpenDList() const { return *OpenList; }
00212 };
00213
00214 #endif // ps2gl_dlist_h