Main Page   Modules   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members  

dlgmanager.cpp

Go to the documentation of this file.
00001 /*           Copyright (C) 2001 Sony Computer Entertainment America
00002                               All Rights Reserved
00003                                SCEA Confidential                                */
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  * CDListGeomManager - the display list gmanager
00018  */
00019 
00020 CDListGeomManager::CDListGeomManager( CGLContext &context )
00021    : CGeomManager(context),
00022      CurDList(NULL),
00023      Vu1RendererMayHaveChanged(false)
00024 {
00025 }
00026 
00027 /********************************************
00028  * display lists and geometry specification
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          // make sure vu1 context is up-to-date
00065          CImmGeomManager &gmanager = pGLContext->GetImmGeomManager();
00066          gmanager.SyncVu1Context(Geometry.GetPrimType());
00067 
00068          // texture and lighting are special cases in that they are the only
00069          // state variables that affect the contents of the geometry packet
00070          // (namely, whether tex coords and/or normals are transferred)
00071          // SO, if they've changed, we need to rebuild the packet..
00072          // FIXME: create separate, uncached command to draw dlists that might
00073          //        depend on the current normal or tex coord
00074          bool texEnabled = pGLContext->GetTexManager().GetTexEnabled();
00075          bool lEnabled = pGLContext->GetImmLighting().GetLightingEnabled();
00076 
00077          // don't cache the packet if it depends on the current normal
00078          bool dontCache = ( lEnabled && ! Geometry.GetNormalsAreValid() );
00079 
00080          // [re]build cached dma packet
00081          if ( ! IsCached
00082               || texEnabled != IsTexEnabled || lEnabled != IsLightingEnabled ) {
00083 
00084             if ( ! dontCache ) {
00085 
00086                // allocate packet
00087                if ( ! RenderPacket ) {
00088                   // change below, too
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                // if this is not the first time creating the packet, we need to
00097                // delete the old packet, but not immediately
00098                // because it may take up to two frames to be dma'ed
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                // don't cache the packet..  use the main dma packet
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       // make sure we don't set this normal before any pending
00212       // geometry that depends on the current normal (the one before
00213       // setting this one)
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(); // see note for Normal
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       // if the context hasn't changed, try to merge the new geometry
00296       // into the current block
00297       if ( GLContext.GetVu1ContextChanged() == 0
00298            && GLContext.GetGsContextChanged() == 0
00299            && GLContext.GetGeomManagerPropsChanged() == 0
00300            && Geometry.MergeNew() )
00301          doReset = false;
00302       // couldn't merge; draw the old geometry so we can reset and start a new block
00303       else
00304          DrawBlock( Geometry );
00305    }
00306 
00307    if ( doReset ) {
00308       Geometry.MakeNewValuesCurrent();
00309       Geometry.ResetNew(); // if we don't do this counts will keep accumulating
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    // if no normals were added use whatever the current normal is at list execution,
00341    // if 1 normal was added, set that as the current normal,
00342    // if more than one normal was added, assume there was one normal per vertex, and
00343    // set the last to be the current normal
00344    Geometry.SetNormalsAreValid(false);
00345    if ( Geometry.GetNumNewNormals() > 0 ) {
00346       // make last normal current
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    // tex coord data
00358    Geometry.SetTexCoordsAreValid(false);
00359    if ( Geometry.GetNumNewTexCoords() > 0 ) {
00360       // make last tex coord current
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    // colors
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 

ps2gl version 0.2