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

immgmanager.cpp

Go to the documentation of this file.
00001 /*        Copyright (C) 2000,2001,2002  Sony Computer Entertainment America
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 <stdio.h>
00008 
00009 #include "ps2s/packet.h"
00010 #include "ps2s/cpu_matrix.h"
00011 #include "ps2s/math.h"
00012 #include "ps2s/displayenv.h"
00013 
00014 #include "GL/ps2gl.h"
00015 #include "ps2gl/gmanager.h"
00016 #include "ps2gl/glcontext.h"
00017 #include "ps2gl/dlist.h"
00018 #include "ps2gl/clear.h"
00019 #include "ps2gl/matrix.h"
00020 #include "ps2gl/texture.h"
00021 #include "ps2gl/material.h"
00022 #include "ps2gl/drawcontext.h"
00023 #include "ps2gl/renderer.h"
00024 
00025 using namespace ArrayType;
00026 
00027 /********************************************
00028  * CImmGeomManager
00029  */
00030 
00031 CImmGeomManager::CImmGeomManager( CGLContext &context, int immBufferQwordSize )
00032    : CGeomManager(context),
00033      RendererManager(context),
00034      VertexBuf0( immBufferQwordSize + immBufferQwordSize % 4,
00035                  DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00036      NormalBuf0( immBufferQwordSize * 4 / 3 + 1 + (immBufferQwordSize * 4 / 3 + 1) % 4,
00037                  DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00038      TexCoordBuf0( immBufferQwordSize / 2 + (immBufferQwordSize / 2) % 4,
00039                    DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00040      ColorBuf0( immBufferQwordSize + immBufferQwordSize % 4,
00041                 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00042      VertexBuf1( immBufferQwordSize + immBufferQwordSize % 4,
00043                  DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00044      NormalBuf1( immBufferQwordSize * 4 / 3 + 1 + (immBufferQwordSize * 4 / 3 + 1) % 4,
00045                  DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00046      TexCoordBuf1( immBufferQwordSize / 2 + (immBufferQwordSize / 2) % 4,
00047                    DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00048      ColorBuf1( immBufferQwordSize + immBufferQwordSize % 4,
00049                 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl )
00050 {
00051    CurVertexBuf = &VertexBuf0;
00052    CurNormalBuf = &NormalBuf0;
00053    CurTexCoordBuf = &TexCoordBuf0;
00054    CurColorBuf = &ColorBuf0;
00055 
00056    VertArray = new CVertArray;
00057 
00058    RendererManager.ArrayAccessChanged( RendererProps::kLinear );
00059 }
00060 
00061 CImmGeomManager::~CImmGeomManager()
00062 {
00063    delete VertArray;
00064 }
00065 
00066 void
00067 CImmGeomManager::SwapBuffers()
00068 {
00069    // flip the geometry buffers
00070    if ( CurVertexBuf == &VertexBuf0 ) CurVertexBuf = &VertexBuf1;
00071    else CurVertexBuf = &VertexBuf0;
00072    CurVertexBuf->Reset();
00073    if ( CurNormalBuf == &NormalBuf0 ) CurNormalBuf = &NormalBuf1;
00074    else CurNormalBuf = &NormalBuf0;
00075    CurNormalBuf->Reset();
00076    if ( CurTexCoordBuf == &TexCoordBuf0 ) CurTexCoordBuf = &TexCoordBuf1;
00077    else CurTexCoordBuf = &TexCoordBuf0;
00078    CurTexCoordBuf->Reset();
00079    if ( CurColorBuf == &ColorBuf0 ) CurColorBuf = &ColorBuf1;
00080    else CurColorBuf = &ColorBuf0;
00081    CurColorBuf->Reset();
00082 }
00083 
00084 /********************************************
00085  * glBegin/glEnd and related
00086  */
00087 
00088 void
00089 CImmGeomManager::BeginGeom( GLenum mode )
00090 {
00091    if ( Prim != mode )
00092       PrimChanged(mode);
00093 
00094    Geometry.SetPrimType( mode );
00095    Geometry.SetArrayType(kLinear);
00096 
00097    Geometry.SetNormals( CurNormalBuf->GetNextPtr() );
00098    Geometry.SetVertices( CurVertexBuf->GetNextPtr() );
00099    Geometry.SetTexCoords( CurTexCoordBuf->GetNextPtr() );
00100    Geometry.SetColors( CurColorBuf->GetNextPtr() );
00101 
00102    InsideBeginEnd = true;
00103 }
00104 
00105 void
00106 CImmGeomManager::Vertex( cpu_vec_xyzw newVert )
00107 {
00108    cpu_vec_xyz normal = GetCurNormal();
00109    *CurNormalBuf += normal;
00110 
00111    const float *texCoord = GetCurTexCoord();
00112    *CurTexCoordBuf += texCoord[0];
00113    *CurTexCoordBuf += texCoord[1];
00114 
00115    *CurVertexBuf += newVert;
00116 
00117    Geometry.AddVertices();
00118    Geometry.AddNormals();
00119    Geometry.AddTexCoords();
00120 }
00121 
00122 void
00123 CImmGeomManager::Normal( cpu_vec_xyz normal )
00124 {
00125    if ( DoNormalize ) normal.normalize();
00126    CurNormal = normal;
00127 }
00128 
00129 void
00130 CImmGeomManager::Color( cpu_vec_xyzw color )
00131 {
00132    if ( InsideBeginEnd ) {
00133       *CurColorBuf += color;
00134       Geometry.AddColors();
00135    }
00136    else {
00137       GLContext.GetMaterialManager().Color( color );
00138    }
00139 }
00140 
00141 void
00142 CImmGeomManager::TexCoord( float u, float v )
00143 {
00144    CurTexCoord[0] = u; CurTexCoord[1] = v;
00145 }
00146 
00147 void
00148 CImmGeomManager::EndGeom()
00149 {
00150    InsideBeginEnd = false;
00151 
00152    Geometry.SetVerticesAreValid(true);
00153    Geometry.SetNormalsAreValid(true);
00154    Geometry.SetTexCoordsAreValid(true);
00155 
00156    // check colors
00157    Geometry.SetColorsAreValid(false);
00158    if ( Geometry.GetNumNewColors() > 0 ) {
00159       mErrorIf( Geometry.GetNumNewVertices() != Geometry.GetNumNewColors(),
00160                 "Sorry, but inside glBegin/glEnd you need "
00161                 "to specify either one color for each vertex given, or none." );
00162       Geometry.SetColorsAreValid(true);
00163 
00164       SyncColorMaterial(true);
00165    }
00166    else {
00167       SyncColorMaterial(false);
00168    }
00169 
00170    Geometry.SetWordsPerVertex(4);
00171    Geometry.SetWordsPerNormal(3);
00172    Geometry.SetWordsPerTexCoord(2);
00173    Geometry.SetWordsPerColor(4);
00174 
00175    CommitNewGeom();
00176 }
00177 
00178 /********************************************
00179  * DrawArrays
00180  */
00181 
00182 void
00183 CImmGeomManager::DrawArrays( GLenum mode, int first, int count )
00184 {
00185    if ( Prim != mode )
00186       PrimChanged(mode);
00187 
00188    Geometry.SetPrimType(mode);
00189    Geometry.SetArrayType(kLinear);
00190 
00191    Geometry.SetVertices( VertArray->GetVertices() );
00192    Geometry.SetNormals( VertArray->GetNormals() );
00193    Geometry.SetTexCoords( VertArray->GetTexCoords() );
00194    Geometry.SetColors( VertArray->GetColors() );
00195 
00196    Geometry.SetVerticesAreValid( VertArray->GetVerticesAreValid() );
00197    Geometry.SetNormalsAreValid( VertArray->GetNormalsAreValid() );
00198    Geometry.SetTexCoordsAreValid( VertArray->GetTexCoordsAreValid() );
00199    Geometry.SetColorsAreValid( VertArray->GetColorsAreValid() );
00200 
00201    Geometry.SetWordsPerVertex( VertArray->GetWordsPerVertex() );
00202    Geometry.SetWordsPerNormal( VertArray->GetWordsPerNormal() );
00203    Geometry.SetWordsPerTexCoord( VertArray->GetWordsPerTexCoord() );
00204    Geometry.SetWordsPerColor( VertArray->GetWordsPerColor() );
00205 
00206    Geometry.AddVertices(count);
00207    Geometry.AddNormals(count);
00208    Geometry.AddTexCoords(count);
00209    Geometry.AddColors(count);
00210 
00211    Geometry.AdjustNewGeomPtrs( first );
00212 
00213    // do this before sync'ing the vu1 renderer in CommitNewGeom
00214    SyncColorMaterial(VertArray->GetColors() != NULL);
00215 
00216    CommitNewGeom();
00217 }
00218 
00219 void
00220 CImmGeomManager::DrawingIndexedArray()
00221 {
00222    if ( ! LastArrayAccessIsValid || ! LastArrayAccessWasIndexed ) {
00223       GLContext.ArrayAccessChanged();
00224       RendererManager.ArrayAccessChanged( RendererProps::kIndexed );
00225       LastArrayAccessIsValid = true;
00226    }
00227    LastArrayAccessWasIndexed = true;
00228 }
00229 
00230 void
00231 CImmGeomManager::DrawIndexedArrays( GLenum primType,
00232                                     int numIndices, const unsigned char* indices,
00233                                     int numVertices )
00234 {
00235    /*
00236    // make sure there's no pending geometry
00237    Flush();
00238 
00239    // do these before sync'ing the vu1 renderer
00240    SyncColorMaterial(VertArray->GetColors() != NULL);
00241    DrawingIndexedArray();
00242 
00243    // now update the renderer and render
00244 
00245    bool rendererChanged = RendererManager.UpdateRenderer();
00246 
00247    if ( rendererChanged ) {
00248       RendererManager.LoadRenderer(GLContext.GetVif1Packet());
00249    }
00250    SyncRendererContext(primType);
00251    SyncGsContext();
00252 
00253    RendererManager.GetCurRenderer().DrawIndexedArrays( primType, numIndices, indices,
00254                                                   numVertices, *VertArray );
00255    */
00256    if ( Prim != primType )
00257       PrimChanged(primType);
00258 
00259    Geometry.SetPrimType(primType);
00260    Geometry.SetArrayType(kIndexed);
00261 
00262    Geometry.SetVertices( VertArray->GetVertices() );
00263    Geometry.SetNormals( VertArray->GetNormals() );
00264    Geometry.SetTexCoords( VertArray->GetTexCoords() );
00265    Geometry.SetColors( VertArray->GetColors() );
00266 
00267    Geometry.SetVerticesAreValid( VertArray->GetVerticesAreValid() );
00268    Geometry.SetNormalsAreValid( VertArray->GetNormalsAreValid() );
00269    Geometry.SetTexCoordsAreValid( VertArray->GetTexCoordsAreValid() );
00270    Geometry.SetColorsAreValid( VertArray->GetColorsAreValid() );
00271 
00272    Geometry.SetWordsPerVertex( VertArray->GetWordsPerVertex() );
00273    Geometry.SetWordsPerNormal( VertArray->GetWordsPerNormal() );
00274    Geometry.SetWordsPerTexCoord( VertArray->GetWordsPerTexCoord() );
00275    Geometry.SetWordsPerColor( VertArray->GetWordsPerColor() );
00276 
00277    Geometry.AddVertices(numVertices);
00278    Geometry.AddNormals(numVertices);
00279    Geometry.AddTexCoords(numVertices);
00280    Geometry.AddColors(numVertices);
00281 
00282    Geometry.SetNumIndices(numIndices);
00283    Geometry.SetIndices(indices);
00284    Geometry.SetIStripLengths(NULL);
00285 
00286    // do this before sync'ing the vu1 renderer in CommitNewGeom
00287    SyncColorMaterial(VertArray->GetColors() != NULL);
00288 
00289    CommitNewGeom();
00290 }
00291 
00292 /********************************************
00293  * common and synchronization code
00294  */
00295 
00296 void
00297 CImmGeomManager::DrawingLinearArray()
00298 {
00299    if ( ! LastArrayAccessIsValid || LastArrayAccessWasIndexed ) {
00300       GLContext.ArrayAccessChanged();
00301       RendererManager.ArrayAccessChanged( RendererProps::kLinear );
00302       LastArrayAccessIsValid = true;
00303    }
00304    LastArrayAccessWasIndexed = false;
00305 }
00306 
00307 void
00308 CImmGeomManager::CommitNewGeom()
00309 {
00310    // do this before updating the renderer
00311    if ( Geometry.GetNewArrayType() == kLinear )
00312       DrawingLinearArray();
00313    else
00314       DrawingIndexedArray();
00315 
00316    bool doReset = true;
00317    bool rendererChanged = RendererManager.UpdateNewRenderer();
00318 
00319    if ( Geometry.IsPending() ) {
00320 
00321 // FIXME: need to ask the renderer what context changes it cares about/updates
00322 
00323       // if the context hasn't changed, try to merge the new geometry
00324       // into the current block
00325       if ( GLContext.GetRendererContextChanged() == 0
00326            && GLContext.GetGsContextChanged() == 0
00327            && ! UserRenderContextChanged
00328            && ! rendererChanged
00329            && Geometry.MergeNew() ) {
00330          doReset = false;
00331       }
00332       else {
00333          // couldn't merge; draw the old geometry so we can reset and start a new block
00334          if ( Geometry.GetArrayType() == kLinear )
00335             RendererManager.GetCurRenderer().DrawLinearArrays( Geometry );
00336          else
00337             RendererManager.GetCurRenderer().DrawIndexedArrays( Geometry );
00338       }
00339    }
00340 
00341    if ( doReset ) {
00342       Geometry.MakeNewValuesCurrent();
00343       Geometry.ResetNew();
00344 
00345       if ( rendererChanged ) {
00346          RendererManager.MakeNewRendererCurrent();
00347          RendererManager.LoadRenderer(GLContext.GetVif1Packet());
00348       }
00349       SyncRendererContext(Geometry.GetPrimType());
00350       SyncGsContext();
00351    }
00352 }
00353 
00354 void
00355 CImmGeomManager::PrimChanged( GLenum primType )
00356 {
00357    GLContext.PrimChanged();
00358    RendererManager.PrimChanged(primType);
00359 }
00360 
00361 void
00362 CImmGeomManager::SyncRenderer()
00363 {
00364    if ( RendererManager.UpdateNewRenderer() ) {
00365       RendererManager.MakeNewRendererCurrent();
00366       RendererManager.LoadRenderer( GLContext.GetVif1Packet() );
00367    }
00368 }
00369 
00370 void
00371 CImmGeomManager::SyncRendererContext( GLenum primType )
00372 {
00373    // resend the rendering context if necessary
00374    if ( GLContext.GetRendererContextChanged()
00375         || (RendererManager.IsCurRendererCustom() && UserRenderContextChanged) ) {
00376       RendererManager.GetCurRenderer().InitContext( primType,
00377                                                     GLContext.GetRendererContextChanged(),
00378                                                     UserRenderContextChanged );
00379 
00380       GLContext.SetRendererContextChanged(false);
00381       UserRenderContextChanged = false;
00382       Prim = primType;
00383    }
00384 }
00385 
00386 void
00387 CImmGeomManager::SyncGsContext()
00388 {
00389    if ( tU32 changed = GLContext.GetGsContextChanged() ) {
00390       // has the texture changed?
00391       bool texEnabled = GLContext.GetTexManager().GetTexEnabled();
00392       CVifSCDmaPacket &packet = GLContext.GetVif1Packet();
00393       if ( texEnabled
00394            && changed & GsCtxtFlags::Texture ) {
00395          // we have to wait for all previous buffers to finish, or
00396          // the new texture settings might beat the geometry to the gs..
00397          packet.Cnt();
00398          packet.Flush().Nop();
00399          packet.CloseTag();
00400          GLContext.GetTexManager().UseCurTexture( GLContext.GetVif1Packet() );
00401       }
00402 
00403       // has the draw environment changed?
00404       if ( changed & GsCtxtFlags::DrawEnv ) {
00405          // as with textures..
00406          packet.Cnt();
00407          packet.Flush().Nop();
00408          packet.CloseTag();
00409          // FIXME
00410          GLContext.AddingDrawEnvToPacket( (tU128*)GLContext.GetVif1Packet().GetNextPtr() + 1 );
00411          GLContext.GetImmDrawContext().GetDrawEnv().SendSettings( GLContext.GetVif1Packet() );
00412       }
00413 
00414       GLContext.SetGsContextChanged(false);
00415    }
00416 }
00417 
00418 void
00419 CImmGeomManager::SyncColorMaterial( bool pvColorsArePresent )
00420 {
00421    CMaterialManager &mm = GLContext.GetMaterialManager();
00422    if ( pvColorsArePresent && mm.GetColorMaterialEnabled() ) {
00423       switch ( mm.GetColorMaterialMode() ) {
00424          case GL_EMISSION:
00425             mNotImplemented( "Only GL_DIFFUSE can change per-vertex" );
00426             break;
00427          case GL_AMBIENT:
00428             mNotImplemented( "Only GL_DIFFUSE can change per-vertex" );
00429             break;
00430          case GL_DIFFUSE:
00431             // fix later..
00432             GLContext.PerVtxMaterialChanged();
00433             RendererManager.PerVtxMaterialChanged( RendererProps::kDiffuse );
00434             break;
00435          case GL_AMBIENT_AND_DIFFUSE:
00436             mNotImplemented( "Only GL_DIFFUSE can change per-vertex" );
00437             break;
00438          case GL_SPECULAR:
00439             mNotImplemented( "Only GL_DIFFUSE can change per-vertex" );
00440             // PerVtxMaterialChanged( PerVtxMaterial::kSpecular );
00441             break;
00442       }
00443    }
00444    else {
00445       RendererManager.PerVtxMaterialChanged( RendererProps::kNoMaterial );
00446    }
00447 }
00448 
00449 void
00450 CImmGeomManager::Flush()
00451 {
00452    if ( Geometry.IsPending() ) {
00453          if ( Geometry.GetArrayType() == kLinear )
00454             RendererManager.GetCurRenderer().DrawLinearArrays( Geometry );
00455          else
00456             RendererManager.GetCurRenderer().DrawIndexedArrays( Geometry );
00457       Geometry.Reset();
00458    }
00459 }

ps2gl version cvs