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