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 #include "ps2s/packet.h"
00008 #include "ps2s/math.h"
00009
00010 #include "ps2gl/dlgmanager.h"
00011 #include "ps2gl/immgmanager.h"
00012 #include "ps2gl/glcontext.h"
00013 #include "ps2gl/dlist.h"
00014 #include "ps2gl/texture.h"
00015 #include "ps2gl/lighting.h"
00016 #include "ps2gl/material.h"
00017 #include "ps2gl/renderer.h"
00018
00019 using namespace ArrayType;
00020
00021
00022 * methods
00023 */
00024
00025 CDListGeomManager::CDListGeomManager( CGLContext &context )
00026 : CGeomManager(context),
00027 CurDList(NULL),
00028 RendererMayHaveChanged(false)
00029 {
00030 }
00031
00032 void
00033 CDListGeomManager::BeginDListDef()
00034 {
00035 Prim = GL_INVALID_VALUE;
00036 Geometry.Reset();
00037
00038 CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00039 CurDList = & dlist;
00040
00041 LastArrayAccessIsValid = false;
00042 }
00043
00044 void
00045 CDListGeomManager::EndDListDef()
00046 {
00047 Flush();
00048
00049 CurNormalBuf = NULL;
00050 CurVertexBuf = NULL;
00051 CurTexCoordBuf = NULL;
00052 CurColorBuf = NULL;
00053
00054 CurDList = NULL;
00055 }
00056
00057 void
00058 CDListGeomManager::Flush()
00059 {
00060 if ( Geometry.IsPending() ) {
00061 DrawBlock( Geometry );
00062 Geometry.Reset();
00063 }
00064 }
00065
00066
00067 * glBegin/glEnd
00068 */
00069
00070 void
00071 CDListGeomManager::BeginGeom( GLenum mode )
00072 {
00073 if ( Prim != mode ) PrimChanged(mode);
00074
00075 CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00076 CurNormalBuf = & dlist.GetNormalBuf();
00077 CurVertexBuf = & dlist.GetVertexBuf();
00078 CurTexCoordBuf = & dlist.GetTexCoordBuf();
00079 CurColorBuf = & dlist.GetColorBuf();
00080
00081 Geometry.SetPrimType( mode );
00082 Geometry.SetArrayType(kLinear);
00083 Geometry.SetNormals( CurNormalBuf->GetNextPtr() );
00084 Geometry.SetVertices( CurVertexBuf->GetNextPtr() );
00085 Geometry.SetTexCoords( CurTexCoordBuf->GetNextPtr() );
00086 Geometry.SetColors( CurColorBuf->GetNextPtr() );
00087
00088 InsideBeginEnd = true;
00089 }
00090
00091 void
00092 CDListGeomManager::Vertex( cpu_vec_xyzw newVert )
00093 {
00094 *CurVertexBuf += newVert;
00095
00096 Geometry.AddVertices();
00097 }
00098
00099 class CSetNormalCmd : public CDListCmd {
00100 cpu_vec_xyz Normal;
00101 public:
00102 CSetNormalCmd( cpu_vec_xyz normal ) : Normal(normal) {}
00103 CDListCmd* Play() {
00104 pGLContext->GetImmGeomManager().Normal(Normal);
00105 return CDListCmd::GetNextCmd( this );
00106 }
00107 };
00108
00109 void
00110 CDListGeomManager::Normal( cpu_vec_xyz normal )
00111 {
00112 if ( DoNormalize ) normal.normalize();
00113
00114 if ( InsideBeginEnd ) {
00115 CurNormal = normal;
00116
00117 *CurNormalBuf += normal(0);
00118 *CurNormalBuf += normal(1);
00119 *CurNormalBuf += normal(2);
00120
00121 Geometry.AddNormals();
00122 }
00123 else {
00124
00125
00126
00127 Flush();
00128 *CurDList += CSetNormalCmd( normal );
00129 }
00130 }
00131
00132 class CColorCmd : public CDListCmd {
00133 cpu_vec_xyzw CurColor;
00134 public:
00135 CColorCmd( cpu_vec_xyzw color ) : CurColor(color) {}
00136 CDListCmd* Play() {
00137 pGLContext->GetMaterialManager().Color(CurColor);
00138 return CDListCmd::GetNextCmd(this);
00139 }
00140 };
00141
00142 void
00143 CDListGeomManager::Color( cpu_vec_xyzw color )
00144 {
00145 if ( InsideBeginEnd ) {
00146 *CurColorBuf += color;
00147
00148 Geometry.AddColors();
00149 }
00150 else {
00151 CDList &dlist = GLContext.GetDListManager().GetOpenDList();
00152 dlist += CColorCmd( color );
00153 GLContext.CurMaterialChanged();
00154 }
00155 }
00156
00157 class CSetTexCoordCmd : public CDListCmd {
00158 float U, V;
00159 public:
00160 CSetTexCoordCmd( float u, float v ) : U(u), V(v) {}
00161 CDListCmd* Play() {
00162 pGLContext->GetImmGeomManager().TexCoord(U,V);
00163 return CDListCmd::GetNextCmd( this );
00164 }
00165 };
00166
00167 void
00168 CDListGeomManager::TexCoord( float u, float v )
00169 {
00170 if ( InsideBeginEnd ) {
00171 CurTexCoord[0] = u; CurTexCoord[1] = v;
00172
00173 *CurTexCoordBuf += u;
00174 *CurTexCoordBuf += v;
00175
00176 Geometry.AddTexCoords();
00177 }
00178 else {
00179 Flush();
00180 *CurDList += CSetTexCoordCmd( u, v );
00181 }
00182 }
00183
00184 void
00185 CDListGeomManager::EndGeom()
00186 {
00187 InsideBeginEnd = false;
00188
00189 Geometry.SetWordsPerVertex(4);
00190 Geometry.SetWordsPerNormal(3);
00191 Geometry.SetWordsPerTexCoord(2);
00192 Geometry.SetWordsPerColor(4);
00193
00194 Geometry.SetVerticesAreValid(true);
00195
00196
00197
00198
00199
00200 Geometry.SetNormalsAreValid(false);
00201 if ( Geometry.GetNumNewNormals() > 0 ) {
00202
00203 *CurDList += CSetNormalCmd( CurNormal );
00204
00205 if ( Geometry.GetNumNewNormals() > 1 ) {
00206 mErrorIf( Geometry.GetNumNewVertices() != Geometry.GetNumNewNormals(),
00207 "Sorry, but in display lists you need to specify either one normal, "
00208 "or a normal for each vertex given." );
00209 Geometry.SetNormalsAreValid(true);
00210 }
00211 }
00212
00213
00214 Geometry.SetTexCoordsAreValid(false);
00215 if ( Geometry.GetNumNewTexCoords() > 0 ) {
00216
00217 *CurDList += CSetTexCoordCmd( CurTexCoord[0], CurTexCoord[1] );
00218
00219 mErrorIf( Geometry.GetNumNewVertices() != Geometry.GetNumNewTexCoords(),
00220 "Sorry, but in display lists you need to specify either one "
00221 "texture coord for each vertex given, or zero." );
00222 Geometry.SetTexCoordsAreValid(true);
00223 }
00224
00225
00226 if ( Geometry.GetNumNewColors() > 0 ) {
00227 mErrorIf( Geometry.GetNumNewVertices() != Geometry.GetNumNewColors(),
00228 "Sorry, but in display lists inside glBegin/glEnd you need "
00229 "to specify either one color for each vertex given, or none." );
00230 Geometry.SetColorsAreValid(true);
00231 }
00232 else {
00233 Geometry.SetColorsAreValid(false);
00234 Geometry.SetColors(NULL);
00235 }
00236
00237 CommitNewGeom();
00238 }
00239
00240
00241 * DrawArrays
00242 */
00243
00244 void
00245 CDListGeomManager::DrawArrays( GLenum mode, int first, int count )
00246 {
00247 if ( Prim != mode ) PrimChanged(mode);
00248
00249 Geometry.SetPrimType(mode);
00250 Geometry.SetArrayType(kLinear);
00251
00252 Geometry.SetVertices( VertArray->GetVertices() );
00253 Geometry.SetNormals( VertArray->GetNormals() );
00254 Geometry.SetTexCoords( VertArray->GetTexCoords() );
00255 Geometry.SetColors( VertArray->GetColors() );
00256
00257 Geometry.SetVerticesAreValid( VertArray->GetVerticesAreValid() );
00258 Geometry.SetNormalsAreValid( VertArray->GetNormalsAreValid() );
00259 Geometry.SetTexCoordsAreValid( VertArray->GetTexCoordsAreValid() );
00260 Geometry.SetColorsAreValid( VertArray->GetColorsAreValid() );
00261
00262 Geometry.SetWordsPerVertex( VertArray->GetWordsPerVertex() );
00263 Geometry.SetWordsPerNormal( VertArray->GetWordsPerNormal() );
00264 Geometry.SetWordsPerTexCoord( VertArray->GetWordsPerTexCoord() );
00265 Geometry.SetWordsPerColor( VertArray->GetWordsPerColor() );
00266
00267 Geometry.AddVertices(count);
00268 Geometry.AddNormals(count);
00269 Geometry.AddTexCoords(count);
00270 Geometry.AddColors(count);
00271
00272 Geometry.AdjustNewGeomPtrs( first );
00273
00274 CommitNewGeom();
00275 }
00276
00277 void
00278 CDListGeomManager::DrawIndexedArrays( GLenum primType,
00279 int numIndices, const unsigned char* indices,
00280 int numVertices )
00281 {
00282 if ( Prim != primType ) PrimChanged(primType);
00283
00284 Geometry.SetPrimType(primType);
00285 Geometry.SetArrayType(kIndexed);
00286
00287 Geometry.SetVertices( VertArray->GetVertices() );
00288 Geometry.SetNormals( VertArray->GetNormals() );
00289 Geometry.SetTexCoords( VertArray->GetTexCoords() );
00290 Geometry.SetColors( VertArray->GetColors() );
00291
00292 Geometry.SetVerticesAreValid( VertArray->GetVerticesAreValid() );
00293 Geometry.SetNormalsAreValid( VertArray->GetNormalsAreValid() );
00294 Geometry.SetTexCoordsAreValid( VertArray->GetTexCoordsAreValid() );
00295 Geometry.SetColorsAreValid( VertArray->GetColorsAreValid() );
00296
00297 Geometry.SetWordsPerVertex( VertArray->GetWordsPerVertex() );
00298 Geometry.SetWordsPerNormal( VertArray->GetWordsPerNormal() );
00299 Geometry.SetWordsPerTexCoord( VertArray->GetWordsPerTexCoord() );
00300 Geometry.SetWordsPerColor( VertArray->GetWordsPerColor() );
00301
00302 Geometry.AddVertices(numVertices);
00303 Geometry.AddNormals(numVertices);
00304 Geometry.AddTexCoords(numVertices);
00305 Geometry.AddColors(numVertices);
00306
00307 Geometry.SetNumIndices(numIndices);
00308 Geometry.SetIndices(indices);
00309 Geometry.SetIStripLengths(NULL);
00310
00311 CommitNewGeom();
00312 }
00313
00314
00315 * methods / dlist commands that update state
00316 */
00317
00318 class CUpdateRendererContextCmd : public CDListCmd {
00319 GLenum PrimType;
00320 public:
00321 CUpdateRendererContextCmd( GLenum type ) : PrimType(type) {}
00322 CDListCmd* Play() {
00323 CImmGeomManager &gmanager = pGLContext->GetImmGeomManager();
00324 gmanager.SyncRendererContext(PrimType);
00325 return CDListCmd::GetNextCmd(this);
00326 }
00327 };
00328
00329 class CUpdatePrimCmd : public CDListCmd {
00330 unsigned char Prim;
00331 public:
00332 CUpdatePrimCmd( unsigned char prim ) : Prim(prim) {}
00333 CDListCmd* Play() {
00334 pGLContext->GetImmGeomManager().GetRendererManager().PrimChanged(Prim);
00335 return CDListCmd::GetNextCmd(this);
00336 }
00337 };
00338
00339 void
00340 CDListGeomManager::PrimChanged( unsigned char prim )
00341 {
00342 GLContext.PrimChanged();
00343 GLContext.GetDListManager().GetOpenDList() += CUpdatePrimCmd(prim);
00344 }
00345
00346 class CUpdateRendererCmd : public CDListCmd {
00347 bool PerVtxColors;
00348 tArrayType ArrayType;
00349 public:
00350 CUpdateRendererCmd( bool pvColors, tArrayType type )
00351 : PerVtxColors(pvColors), ArrayType(type) {}
00352 CDListCmd* Play() {
00353 CImmGeomManager &gmanager = pGLContext->GetImmGeomManager();
00354 gmanager.SyncColorMaterial(PerVtxColors);
00355 gmanager.SyncArrayType(ArrayType);
00356 gmanager.SyncRenderer();
00357 return CDListCmd::GetNextCmd(this);
00358 }
00359 };
00360
00361 class CUpdateGsContextCmd : public CDListCmd {
00362 public:
00363 CDListCmd* Play() {
00364 pGLContext->GetImmGeomManager().SyncGsContext();
00365 return CDListCmd::GetNextCmd(this);
00366 }
00367 };
00368
00369
00370 * render-related methods/commands
00371 */
00372
00373 void
00374 CDListGeomManager::DrawingLinearArray()
00375 {
00376 if ( ! LastArrayAccessIsValid || LastArrayAccessWasIndexed ) {
00377 GLContext.ArrayAccessChanged();
00378 LastArrayAccessIsValid = true;
00379 }
00380 LastArrayAccessWasIndexed = false;
00381 }
00382
00383 void
00384 CDListGeomManager::DrawingIndexedArray()
00385 {
00386 if ( ! LastArrayAccessIsValid || ! LastArrayAccessWasIndexed ) {
00387 GLContext.ArrayAccessChanged();
00388 LastArrayAccessIsValid = true;
00389 }
00390 LastArrayAccessWasIndexed = true;
00391 }
00392
00393 void
00394 CDListGeomManager::CommitNewGeom()
00395 {
00396
00397 if ( Geometry.GetNewArrayType() == kLinear )
00398 DrawingLinearArray();
00399 else
00400 DrawingIndexedArray();
00401
00402 bool doReset = true;
00403
00404 if ( Geometry.IsPending() ) {
00405
00406
00407 if ( GLContext.GetRendererContextChanged() == 0
00408 && GLContext.GetGsContextChanged() == 0
00409 && ! UserRenderContextChanged
00410 && GLContext.GetRendererPropsChanged() == 0
00411 && Geometry.MergeNew() )
00412 doReset = false;
00413
00414 else {
00415 DrawBlock( Geometry );
00416 }
00417 }
00418
00419 if ( doReset ) {
00420 Geometry.MakeNewValuesCurrent();
00421 Geometry.ResetNew();
00422
00423 if ( GLContext.GetRendererPropsChanged() ) {
00424 *CurDList += CUpdateRendererCmd(Geometry.GetColorsAreValid(), Geometry.GetArrayType());
00425 GLContext.SetRendererPropsChanged(false);
00426 GLContext.SetRendererContextChanged(true);
00427 }
00428 if ( GLContext.GetRendererContextChanged() ) {
00429 *CurDList += CUpdateRendererContextCmd(Geometry.GetPrimType());
00430 GLContext.SetRendererContextChanged(false);
00431 Prim = Geometry.GetPrimType();
00432 }
00433 if ( GLContext.GetGsContextChanged() ) {
00434 *CurDList += CUpdateGsContextCmd();
00435 GLContext.SetGsContextChanged(false);
00436 }
00437 if ( UserRenderContextChanged ) {
00438
00439
00440
00441 UserRenderContextChanged = false;
00442 }
00443
00444 }
00445 }
00446
00447 class CDrawArraysCmd : public CDListCmd {
00448 CGeometryBlock Geometry;
00449 bool IsCached;
00450 CDList &DList;
00451 CVifSCDmaPacket *RenderPacket;
00452 tU64 RenderContextDependencies, RenderContextDepMask;
00453 public:
00454 CDrawArraysCmd( CGeometryBlock &block, CDList &dlist )
00455 : Geometry(block), IsCached(false), DList(dlist), RenderPacket(NULL)
00456 {}
00457
00458 CDListCmd* Play() {
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470 tU64 curRenderContext = (tU64)pGLContext->GetImmGeomManager().GetRendererManager().GetRendererReqs();
00471 tU64 curRenderContextDeps = curRenderContext & RenderContextDepMask;
00472 bool rebuildPacket = ( curRenderContextDeps != RenderContextDependencies );
00473
00474
00475
00476 if ( ! IsCached || rebuildPacket ) {
00477
00478
00479
00480
00481 CImmGeomManager &gmanager = pGLContext->GetImmGeomManager();
00482 CRenderer &renderer = gmanager.GetRendererManager().GetCurRenderer();
00483 bool cachePacket = renderer.GetCachePackets(Geometry);
00484
00485
00486 RenderContextDepMask = renderer.GetRenderContextDeps();
00487 RenderContextDependencies = RenderContextDepMask & curRenderContext;
00488
00489 if ( cachePacket ) {
00490
00491
00492
00493 int qwords = renderer.GetPacketQwordSize(Geometry);
00494
00495 if ( ! RenderPacket ) {
00496 RenderPacket = new CVifSCDmaPacket( qwords, DMAC::Channels::vif1,
00497 Packet::kXferTags,
00498 Core::MemMappings::UncachedAccl );
00499 DList.RegisterNewPacket(RenderPacket);
00500 }
00501
00502
00503
00504
00505 if ( IsCached ) {
00506 void *newBuf = CDmaPacket::AllocBuffer( qwords,
00507 Core::MemMappings::UncachedAccl );
00508 void *oldBuf = RenderPacket->SwapOutBuffer( newBuf );
00509 pGLContext->AddBufferToBeFreed( Core::MakePtrNormal(oldBuf) );
00510 }
00511
00512 RenderPacket->Reset();
00513
00514 IsCached = true;
00515 }
00516 else {
00517
00518 RenderPacket = & pGLContext->GetVif1Packet();
00519 }
00520
00521 pGLContext->PushVif1Packet();
00522 {
00523 pGLContext->SetVif1Packet( *RenderPacket );
00524 renderer.DrawLinearArrays( Geometry );
00525 }
00526 pGLContext->PopVif1Packet();
00527
00528
00529 if ( cachePacket ) {
00530 RenderPacket->Ret();
00531 RenderPacket->Pad128();
00532 RenderPacket->CloseTag();
00533 }
00534 }
00535
00536
00537 if ( IsCached ) {
00538 pGLContext->GetVif1Packet().Call( *RenderPacket );
00539 pGLContext->GetVif1Packet().Pad128();
00540 pGLContext->GetVif1Packet().CloseTag();
00541 }
00542 else {
00543
00544 RenderPacket = NULL;
00545 }
00546
00547 return CDListCmd::GetNextCmd( this );
00548 }
00549 };
00550
00551 class CDrawIndexedArraysCmd : public CDListCmd {
00552 CGeometryBlock Geometry;
00553 bool IsCached;
00554 CDList &DList;
00555 CVifSCDmaPacket *RenderPacket;
00556 bool IsTexEnabled, IsLightingEnabled;
00557 public:
00558 CDrawIndexedArraysCmd( CGeometryBlock &block, CDList &dlist )
00559 : Geometry(block), IsCached(false), DList(dlist), RenderPacket(NULL)
00560 {}
00561
00562 CDListCmd* Play() {
00563
00564
00565
00566
00567 bool texEnabled = pGLContext->GetTexManager().GetTexEnabled();
00568 bool lEnabled = pGLContext->GetImmLighting().GetLightingEnabled();
00569
00570
00571 bool dontCache = ( lEnabled && ! Geometry.GetNormalsAreValid() );
00572
00573
00574 if ( ! IsCached
00575 || texEnabled != IsTexEnabled
00576 || lEnabled != IsLightingEnabled ) {
00577
00578 if ( ! dontCache ) {
00579
00580
00581 if ( ! RenderPacket ) {
00582
00583
00584 int qwords = Math::Max(Geometry.GetNumArrays(), 1) * 100;
00585 RenderPacket = new CVifSCDmaPacket( qwords, DMAC::Channels::vif1,
00586 Packet::kXferTags,
00587 Core::MemMappings::UncachedAccl );
00588 DList.RegisterNewPacket(RenderPacket);
00589 }
00590
00591
00592
00593
00594 if ( IsCached ) {
00595 int qwords = Math::Max(Geometry.GetNumArrays(), 1) * 100;
00596 void *newBuf = CDmaPacket::AllocBuffer( qwords,
00597 Core::MemMappings::UncachedAccl );
00598 void *oldBuf = RenderPacket->SwapOutBuffer( newBuf );
00599 pGLContext->AddBufferToBeFreed( oldBuf );
00600 }
00601
00602 RenderPacket->Reset();
00603
00604 IsCached = true;
00605 }
00606 else {
00607
00608 RenderPacket = & pGLContext->GetVif1Packet();
00609 }
00610
00611 IsTexEnabled = texEnabled; IsLightingEnabled = lEnabled;
00612
00613 pGLContext->PushVif1Packet();
00614 {
00615 pGLContext->SetVif1Packet( *RenderPacket );
00616 CImmGeomManager &gmanager = pGLContext->GetImmGeomManager();
00617 CRenderer &renderer = gmanager.GetRendererManager().GetCurRenderer();
00618 renderer.DrawIndexedArrays( Geometry );
00619 }
00620 pGLContext->PopVif1Packet();
00621
00622 if ( ! dontCache ) {
00623 RenderPacket->Ret();
00624 RenderPacket->Pad128();
00625 RenderPacket->CloseTag();
00626 }
00627 }
00628
00629 if ( ! dontCache ) {
00630 pGLContext->GetVif1Packet().Call( *RenderPacket );
00631 pGLContext->GetVif1Packet().Pad128();
00632 pGLContext->GetVif1Packet().CloseTag();
00633 }
00634 else {
00635 RenderPacket = NULL;
00636 }
00637
00638 return CDListCmd::GetNextCmd( this );
00639 }
00640 };
00641
00642 void
00643 CDListGeomManager::DrawBlock( CGeometryBlock &block )
00644 {
00645 if ( block.GetArrayType() == kLinear )
00646 *CurDList += CDrawArraysCmd( block, *CurDList );
00647 else
00648 *CurDList += CDrawIndexedArraysCmd( block, *CurDList );
00649 }
00650
00651 class CEnableCustomCmd : public CDListCmd {
00652 tU64 Flag;
00653 public:
00654 CEnableCustomCmd( tU64 flag ) : Flag(flag) {}
00655 CDListCmd* Play() {
00656 pGLContext->GetImmGeomManager().GetRendererManager().EnableCustom(Flag);
00657 return CDListCmd::GetNextCmd(this);
00658 }
00659 };
00660
00661 void
00662 CDListGeomManager::EnableCustom( tU64 flag )
00663 {
00664 *CurDList += CEnableCustomCmd(flag);
00665 }
00666
00667 class CDisableCustomCmd : public CDListCmd {
00668 tU64 Flag;
00669 public:
00670 CDisableCustomCmd( tU64 flag ) : Flag(flag) {}
00671 CDListCmd* Play() {
00672 pGLContext->GetImmGeomManager().GetRendererManager().DisableCustom(Flag);
00673 return CDListCmd::GetNextCmd(this);
00674 }
00675 };
00676
00677 void
00678 CDListGeomManager::DisableCustom( tU64 flag )
00679 {
00680 *CurDList += CDisableCustomCmd(flag);
00681 }