00001
00002
00003
00004
00005 #include "ps2s/packet.h"
00006 #include "ps2s/math.h"
00007
00008 #include "ps2gl/dlgmanager.h"
00009 #include "ps2gl/immgmanager.h"
00010 #include "ps2gl/glcontext.h"
00011 #include "ps2gl/dlist.h"
00012 #include "ps2gl/texture.h"
00013 #include "ps2gl/lighting.h"
00014 #include "ps2gl/material.h"
00015
00016
00017
00018
00019
00020 CDListGeomManager::CDListGeomManager( CGLContext &context )
00021 : CGeomManager(context),
00022 CurDList(NULL),
00023 Vu1RendererMayHaveChanged(false)
00024 {
00025 }
00026
00027
00028
00029
00030
00031 class CUpdateVu1ContextCmd : public CDListCmd {
00032 GLenum PrimType;
00033 public:
00034 CUpdateVu1ContextCmd( GLenum type ) : PrimType(type) {}
00035 CDListCmd* Play() {
00036 CImmGeomManager &gmanager = pGLContext->GetImmGeomManager();
00037 gmanager.SyncVu1Context(PrimType);
00038 return CDListCmd::GetNextCmd(this);
00039 }
00040 };
00041
00042 void
00043 CDListGeomManager::BeginDListDef()
00044 {
00045 Vu1Prim = GL_INVALID_VALUE;
00046 Geometry.Reset();
00047
00048 CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00049 CurDList = & dlist;
00050 }
00051
00052 class CDrawArraysCmd : public CDListCmd {
00053 CGeometryBlock Geometry;
00054 bool IsCached;
00055 CDList &DList;
00056 CVifSCDmaPacket *RenderPacket;
00057 bool IsTexEnabled, IsLightingEnabled;
00058 public:
00059 CDrawArraysCmd( CGeometryBlock &block, CDList &dlist )
00060 : Geometry(block), IsCached(false), DList(dlist), RenderPacket(NULL)
00061 {}
00062
00063 CDListCmd* Play() {
00064
00065 CImmGeomManager &gmanager = pGLContext->GetImmGeomManager();
00066 gmanager.SyncVu1Context(Geometry.GetPrimType());
00067
00068
00069
00070
00071
00072
00073
00074 bool texEnabled = pGLContext->GetTexManager().GetTexEnabled();
00075 bool lEnabled = pGLContext->GetImmLighting().GetLightingEnabled();
00076
00077
00078 bool dontCache = ( lEnabled && ! Geometry.GetNormalsAreValid() );
00079
00080
00081 if ( ! IsCached
00082 || texEnabled != IsTexEnabled || lEnabled != IsLightingEnabled ) {
00083
00084 if ( ! dontCache ) {
00085
00086
00087 if ( ! RenderPacket ) {
00088
00089 int qwords = Math::Max(Geometry.GetTotalVertices() / 70, 1) * 1000;
00090 RenderPacket = new CVifSCDmaPacket( qwords, DMAC::Channels::vif1,
00091 Packet::kXferTags,
00092 Core::MemMappings::UncachedAccl );
00093 DList.RegisterNewPacket(RenderPacket);
00094 }
00095
00096
00097
00098
00099 if ( IsCached ) {
00100 int qwords = Math::Max(Geometry.GetTotalVertices() / 70, 1) * 1000;
00101 void *newBuf = CDmaPacket::AllocBuffer( qwords,
00102 Core::MemMappings::UncachedAccl );
00103 void *oldBuf = RenderPacket->SwapOutBuffer( newBuf );
00104 gmanager.AddBufferToBeFreed( oldBuf );
00105 }
00106
00107 RenderPacket->Reset();
00108
00109 IsCached = true;
00110 }
00111 else {
00112
00113 RenderPacket = & pGLContext->GetVif1Packet();
00114 }
00115
00116 IsTexEnabled = texEnabled; IsLightingEnabled = lEnabled;
00117
00118 CVsmManager &vsmManager = gmanager.GetVsmManager();
00119 vsmManager.DrawArrays( *RenderPacket, gmanager, Geometry );
00120
00121 if ( ! dontCache ) {
00122 RenderPacket->Ret();
00123 RenderPacket->Pad128();
00124 RenderPacket->CloseTag();
00125 }
00126 }
00127
00128 if ( ! dontCache ) {
00129 pGLContext->GetVif1Packet().Call( *RenderPacket );
00130 pGLContext->GetVif1Packet().Pad128();
00131 pGLContext->GetVif1Packet().CloseTag();
00132 }
00133 else {
00134 RenderPacket = NULL;
00135 }
00136
00137 return CDListCmd::GetNextCmd( this );
00138 }
00139 };
00140
00141 class CUpdatePrimCmd : public CDListCmd {
00142 unsigned char Prim;
00143 public:
00144 CUpdatePrimCmd( unsigned char prim ) : Prim(prim) {}
00145 CDListCmd* Play() {
00146 pGLContext->GetImmGeomManager().GetVsmManager().PrimChanged(Prim);
00147 return CDListCmd::GetNextCmd(this);
00148 }
00149 };
00150
00151 void
00152 CDListGeomManager::PrimChanged( unsigned char prim )
00153 {
00154 GLContext.PrimChanged();
00155 GLContext.GetDListManager().GetOpenDList() += CUpdatePrimCmd(prim);
00156 }
00157
00158 void
00159 CDListGeomManager::BeginGeom( GLenum mode )
00160 {
00161 if ( Vu1Prim != mode ) PrimChanged(mode);
00162
00163 CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00164 CurNormalBuf = & dlist.GetNormalBuf();
00165 CurVertexBuf = & dlist.GetVertexBuf();
00166 CurTexCoordBuf = & dlist.GetTexCoordBuf();
00167 CurColorBuf = & dlist.GetColorBuf();
00168
00169 Geometry.SetPrimType( mode );
00170 Geometry.SetNormals( CurNormalBuf->GetNextPtr() );
00171 Geometry.SetVertices( CurVertexBuf->GetNextPtr() );
00172 Geometry.SetTexCoords( CurTexCoordBuf->GetNextPtr() );
00173 Geometry.SetColors( CurColorBuf->GetNextPtr() );
00174
00175 InsideBeginEnd = true;
00176 }
00177
00178 void
00179 CDListGeomManager::Vertex( cpu_vec_xyzw newVert )
00180 {
00181 *CurVertexBuf += newVert;
00182
00183 Geometry.AddVertices();
00184 }
00185
00186 class CSetNormalCmd : public CDListCmd {
00187 cpu_vec_xyz Normal;
00188 public:
00189 CSetNormalCmd( cpu_vec_xyz normal ) : Normal(normal) {}
00190 CDListCmd* Play() {
00191 pGLContext->GetImmGeomManager().Normal(Normal);
00192 return CDListCmd::GetNextCmd( this );
00193 }
00194 };
00195
00196 void
00197 CDListGeomManager::Normal( cpu_vec_xyz normal )
00198 {
00199 if ( DoNormalize ) normal.normalize();
00200
00201 if ( InsideBeginEnd ) {
00202 CurNormal = normal;
00203
00204 *CurNormalBuf += normal(0);
00205 *CurNormalBuf += normal(1);
00206 *CurNormalBuf += normal(2);
00207
00208 Geometry.AddNormals();
00209 }
00210 else {
00211
00212
00213
00214 Flush();
00215 *CurDList += CSetNormalCmd( normal );
00216 }
00217 }
00218
00219 class CColorCmd : public CDListCmd {
00220 cpu_vec_xyzw CurColor;
00221 public:
00222 CColorCmd( cpu_vec_xyzw color ) : CurColor(color) {}
00223 CDListCmd* Play() {
00224 pGLContext->GetMaterialManager().Color(CurColor);
00225 return CDListCmd::GetNextCmd(this);
00226 }
00227 };
00228
00229 void
00230 CDListGeomManager::Color( cpu_vec_xyzw color )
00231 {
00232 if ( InsideBeginEnd ) {
00233 *CurColorBuf += color;
00234
00235 Geometry.AddColors();
00236 }
00237 else {
00238 CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00239 dlist += CColorCmd( color );
00240 GLContext.CurMaterialChanged();
00241 }
00242 }
00243
00244 class CSetTexCoordCmd : public CDListCmd {
00245 float U, V;
00246 public:
00247 CSetTexCoordCmd( float u, float v ) : U(u), V(v) {}
00248 CDListCmd* Play() {
00249 pGLContext->GetImmGeomManager().TexCoord(U,V);
00250 return CDListCmd::GetNextCmd( this );
00251 }
00252 };
00253
00254 void
00255 CDListGeomManager::TexCoord( float u, float v )
00256 {
00257 if ( InsideBeginEnd ) {
00258 CurTexCoord[0] = u; CurTexCoord[1] = v;
00259
00260 *CurTexCoordBuf += u;
00261 *CurTexCoordBuf += v;
00262
00263 Geometry.AddTexCoords();
00264 }
00265 else {
00266 Flush();
00267 *CurDList += CSetTexCoordCmd( u, v );
00268 }
00269 }
00270
00271 class CUpdateVu1RendererCmd : public CDListCmd {
00272 bool PerVtxColors;
00273 public:
00274 CUpdateVu1RendererCmd( bool pvColors ) : PerVtxColors(pvColors) {}
00275 CDListCmd* Play() {
00276 pGLContext->GetImmGeomManager().SyncColorMaterial(PerVtxColors);
00277 pGLContext->GetImmGeomManager().SyncVu1Renderer();
00278 return CDListCmd::GetNextCmd(this);
00279 }
00280 };
00281
00282 class CUpdateGsContextCmd : public CDListCmd {
00283 public:
00284 CDListCmd* Play() {
00285 pGLContext->GetImmGeomManager().SyncGsContext();
00286 return CDListCmd::GetNextCmd(this);
00287 }
00288 };
00289
00290 void
00291 CDListGeomManager::CommitNewGeom()
00292 {
00293 bool doReset = true;
00294 if ( Geometry.IsPending() ) {
00295
00296
00297 if ( GLContext.GetVu1ContextChanged() == 0
00298 && GLContext.GetGsContextChanged() == 0
00299 && GLContext.GetGeomManagerPropsChanged() == 0
00300 && Geometry.MergeNew() )
00301 doReset = false;
00302
00303 else
00304 DrawBlock( Geometry );
00305 }
00306
00307 if ( doReset ) {
00308 Geometry.MakeNewValuesCurrent();
00309 Geometry.ResetNew();
00310
00311 if ( GLContext.GetGeomManagerPropsChanged() ) {
00312 *CurDList += CUpdateVu1RendererCmd(Geometry.GetColorsAreValid());
00313 GLContext.SetRendererPropsChanged(false);
00314 GLContext.SetVu1ContextChanged(true);
00315 }
00316 if ( GLContext.GetVu1ContextChanged() ) {
00317 *CurDList += CUpdateVu1ContextCmd(Geometry.GetPrimType());
00318 GLContext.SetVu1ContextChanged(false);
00319 Vu1Prim = Geometry.GetPrimType();
00320 }
00321 if ( GLContext.GetGsContextChanged() ) {
00322 *CurDList += CUpdateGsContextCmd();
00323 GLContext.SetGsContextChanged(false);
00324 }
00325 }
00326 }
00327
00328 void
00329 CDListGeomManager::EndGeom()
00330 {
00331 InsideBeginEnd = false;
00332
00333 Geometry.SetWordsPerVertex(4);
00334 Geometry.SetWordsPerNormal(3);
00335 Geometry.SetWordsPerTexCoord(2);
00336 Geometry.SetWordsPerColor(4);
00337
00338 Geometry.SetVerticesAreValid(true);
00339
00340
00341
00342
00343
00344 Geometry.SetNormalsAreValid(false);
00345 if ( Geometry.GetNumNewNormals() > 0 ) {
00346
00347 *CurDList += CSetNormalCmd( CurNormal );
00348
00349 if ( Geometry.GetNumNewNormals() > 1 ) {
00350 mErrorIf( Geometry.GetNumNewVertices() != Geometry.GetNumNewNormals(),
00351 "Sorry, but in display lists you need to specify either one normal, "
00352 "or a normal for each vertex given." );
00353 Geometry.SetNormalsAreValid(true);
00354 }
00355 }
00356
00357
00358 Geometry.SetTexCoordsAreValid(false);
00359 if ( Geometry.GetNumNewTexCoords() > 0 ) {
00360
00361 *CurDList += CSetTexCoordCmd( CurTexCoord[0], CurTexCoord[1] );
00362
00363 mErrorIf( Geometry.GetNumNewVertices() != Geometry.GetNumNewTexCoords(),
00364 "Sorry, but in display lists you need to specify either one "
00365 "texture coord for each vertex given, or zero." );
00366 Geometry.SetTexCoordsAreValid(true);
00367 }
00368
00369
00370 if ( Geometry.GetNumNewColors() > 0 ) {
00371 mErrorIf( Geometry.GetNumNewVertices() != Geometry.GetNumNewColors(),
00372 "Sorry, but in display lists inside glBegin/glEnd you need "
00373 "to specify either one color for each vertex given, or none." );
00374 Geometry.SetColorsAreValid(true);
00375 }
00376 else {
00377 Geometry.SetColorsAreValid(false);
00378 Geometry.SetColors(NULL);
00379 }
00380
00381 CommitNewGeom();
00382 }
00383
00384 void
00385 CDListGeomManager::DrawBlock( CGeometryBlock &block )
00386 {
00387 *CurDList += CDrawArraysCmd( block, *CurDList );
00388 }
00389
00390 void
00391 CDListGeomManager::DrawArrays( GLenum mode, int first, int count )
00392 {
00393 if ( Vu1Prim != mode ) PrimChanged(mode);
00394
00395 Geometry.SetPrimType(mode);
00396
00397 Geometry.SetVertices( VertArray->GetVertices() );
00398 Geometry.SetNormals( VertArray->GetNormals() );
00399 Geometry.SetTexCoords( VertArray->GetTexCoords() );
00400 Geometry.SetColors( VertArray->GetColors() );
00401
00402 Geometry.SetVerticesAreValid( VertArray->GetVerticesAreValid() );
00403 Geometry.SetNormalsAreValid( VertArray->GetNormalsAreValid() );
00404 Geometry.SetTexCoordsAreValid( VertArray->GetTexCoordsAreValid() );
00405 Geometry.SetColorsAreValid( VertArray->GetColorsAreValid() );
00406
00407 Geometry.SetWordsPerVertex( VertArray->GetWordsPerVertex() );
00408 Geometry.SetWordsPerNormal( VertArray->GetWordsPerNormal() );
00409 Geometry.SetWordsPerTexCoord( VertArray->GetWordsPerTexCoord() );
00410 Geometry.SetWordsPerColor( VertArray->GetWordsPerColor() );
00411
00412 Geometry.AddVertices(count);
00413 Geometry.AddNormals(count);
00414 Geometry.AddTexCoords(count);
00415 Geometry.AddColors(count);
00416
00417 Geometry.AdjustNewGeomPtrs( first );
00418
00419 CommitNewGeom();
00420 }
00421
00422 void
00423 CDListGeomManager::Flush()
00424 {
00425 if ( Geometry.IsPending() ) {
00426 DrawBlock( Geometry );
00427 Geometry.Reset();
00428 }
00429 }
00430
00431 void
00432 CDListGeomManager::EndDListDef()
00433 {
00434 Flush();
00435
00436 CurNormalBuf = NULL;
00437 CurVertexBuf = NULL;
00438 CurTexCoordBuf = NULL;
00439 CurColorBuf = NULL;
00440
00441 CurDList = NULL;
00442 }
00443