00001
00002
00003
00004
00005 #include "ps2s/packet.h"
00006 #include "ps2s/cpu_matrix.h"
00007 #include "ps2s/math.h"
00008 #include "ps2s/timer.h"
00009
00010 #include "ps2gl/vsmmanager.h"
00011 #include "ps2gl/immgmanager.h"
00012 #include "ps2gl/lighting.h"
00013 #include "ps2gl/glcontext.h"
00014 #include "ps2gl/material.h"
00015 #include "ps2gl/matrix.h"
00016 #include "ps2gl/texture.h"
00017 #include "ps2gl/metrics.h"
00018 #include "ps2gl/drawcontext.h"
00019
00020 #include "vu1common.h"
00021 #include "vu1renderers.h"
00022
00023 using namespace Vu1RendererProps;
00024
00025
00026
00027
00028
00029
00030
00031 const tVu1Renderer CVsmManager::Vu1Renderers[] =
00032 {
00033 {
00034 (void*)vsmSCEI,
00035 {
00036 PrimType: kPtsLinesStripsFans,
00037 Lighting: 1,
00038 LightTypes: k3DirLights,
00039 Texture: 1,
00040 Specular: 0,
00041 PerVtxMaterial: kNone,
00042 CullFace: 0,
00043 TwoSidedLighting: 0
00044 }
00045 , 3, 3
00046 },
00047
00048 {
00049 (void*)vsmGeneralNoSpec,
00050 {
00051 PrimType: kPtsLinesStripsFans,
00052 Lighting: 1,
00053 LightTypes: k3DirLights | k8DirLights | k1PtLight | k2PtLights | k8PtLights,
00054 Texture: 1,
00055 Specular: 0,
00056 PerVtxMaterial: kNone,
00057 CullFace: 1,
00058 TwoSidedLighting: 0
00059 },
00060 3, 3
00061 },
00062 {
00063 (void*)vsmGeneralNoSpecTri,
00064 {
00065 PrimType: kTriangles,
00066 Lighting: 1,
00067 LightTypes: k3DirLights | k8DirLights | k1PtLight | k2PtLights | k8PtLights,
00068 Texture: 1,
00069 Specular: 0,
00070 PerVtxMaterial: kNone,
00071 CullFace: 1,
00072 TwoSidedLighting: 0
00073 },
00074 3, 3
00075 },
00076 {
00077 (void*)vsmGeneralNoSpecQuad,
00078 {
00079 PrimType: kQuads,
00080 Lighting: 1,
00081 LightTypes: k3DirLights | k8DirLights | k1PtLight | k2PtLights | k8PtLights,
00082 Texture: 1,
00083 Specular: 0,
00084 PerVtxMaterial: kNone,
00085 CullFace: 1,
00086 TwoSidedLighting: 0
00087 },
00088 3, 3
00089 },
00090
00091
00092
00093 {
00094 (void*)vsmGeneral,
00095 {
00096 PrimType: kPtsLinesStripsFans,
00097 Lighting: 1,
00098 LightTypes: k3DirLights | k8DirLights | k1PtLight | k2PtLights | k8PtLights,
00099 Texture: 1,
00100 Specular: 1,
00101 PerVtxMaterial: kNone,
00102 CullFace: 1,
00103 TwoSidedLighting: 0
00104 },
00105 3, 3
00106 },
00107 {
00108 (void*)vsmGeneralQuad,
00109 {
00110 PrimType: kQuads,
00111 Lighting: 1,
00112 LightTypes: k3DirLights | k8DirLights | k1PtLight | k2PtLights | k8PtLights,
00113 Texture: 1,
00114 Specular: 1,
00115 PerVtxMaterial: kNone,
00116 CullFace: 1,
00117 TwoSidedLighting: 0
00118 },
00119 3, 3
00120 },
00121 {
00122 (void*)vsmGeneralTri,
00123 {
00124 PrimType: kTriangles,
00125 Lighting: 1,
00126 LightTypes: k3DirLights | k8DirLights | k1PtLight | k2PtLights | k8PtLights,
00127 Texture: 1,
00128 Specular: 1,
00129 PerVtxMaterial: kNone,
00130 CullFace: 1,
00131 TwoSidedLighting: 0
00132 },
00133 3, 3
00134 },
00135
00136
00137
00138
00139 {
00140 (void*)vsmGeneralPVDiff,
00141 {
00142 PrimType: kPtsLinesStripsFans | kTriangles | kQuads,
00143 Lighting: 1,
00144 LightTypes: k3DirLights | k8DirLights | k1PtLight | k2PtLights | k8PtLights,
00145 Texture: 1,
00146 Specular: 1,
00147 PerVtxMaterial: kDiffuse,
00148 CullFace: 1,
00149 TwoSidedLighting: 0
00150 },
00151 4, 3
00152 },
00153 {
00154 (void*)vsmGeneralPVDiffTri,
00155 {
00156 PrimType: kTriangles,
00157 Lighting: 1,
00158 LightTypes: k3DirLights | k8DirLights | k1PtLight | k2PtLights | k8PtLights,
00159 Texture: 1,
00160 Specular: 1,
00161 PerVtxMaterial: kDiffuse,
00162 CullFace: 1,
00163 TwoSidedLighting: 0
00164 },
00165 4, 3
00166 },
00167 {
00168 (void*)vsmGeneralPVDiffQuad,
00169 {
00170 PrimType: kQuads,
00171 Lighting: 1,
00172 LightTypes: k3DirLights | k8DirLights | k1PtLight | k2PtLights | k8PtLights,
00173 Texture: 1,
00174 Specular: 1,
00175 PerVtxMaterial: kDiffuse,
00176 CullFace: 1,
00177 TwoSidedLighting: 0
00178 },
00179 4, 3
00180 },
00181 };
00182
00183 const int CVsmManager::NumVu1Renderers = sizeof(CVsmManager::Vu1Renderers) / sizeof(tVu1Renderer);
00184
00185
00186 CVsmManager::CVsmManager( CGLContext &context)
00187 : GLContext(context),
00188 VsmReqsHaveChanged(false), CurrentVu1Renderer(NULL)
00189 {
00190 VsmRequirements.PrimType = 0;
00191 VsmRequirements.Lighting = 0;
00192 VsmRequirements.LightTypes = 0;
00193 VsmRequirements.Texture = 0;
00194 VsmRequirements.Specular = 0;
00195 VsmRequirements.PerVtxMaterial = kNone;
00196 VsmRequirements.CullFace = 0;
00197 VsmRequirements.TwoSidedLighting = 0;
00198 }
00199
00200
00201
00202 void
00203 CVsmManager::NumLightsChanged( tLightType type, int num )
00204 {
00205 CVu1RendererProps newState = VsmRequirements;
00206
00207 switch (type) {
00208 case kDirectional:
00209 if (0 < num && num <= 3) newState.LightTypes = k3DirLights;
00210 else newState.LightTypes = k8DirLights;
00211
00212 if ( VsmRequirements != newState ) {
00213 VsmRequirements = newState;
00214 VsmReqsHaveChanged = true;
00215 }
00216 break;
00217
00218 case kPoint:
00219 if (num == 1) newState.LightTypes = k1PtLight;
00220 else if (num == 2) newState.LightTypes = k2PtLights;
00221 else newState.LightTypes = k8PtLights;
00222
00223 if ( VsmRequirements != newState ) {
00224 VsmRequirements = newState;
00225 VsmReqsHaveChanged = true;
00226 }
00227 break;
00228
00229 case kSpot:
00230 break;
00231 }
00232 }
00233
00234 void
00235 CVsmManager::PrimChanged( unsigned char prim )
00236 {
00237 CVu1RendererProps newState = VsmRequirements;
00238
00239 if (prim <= GL_LINE_STRIP)
00240 newState.PrimType = kPtsLinesStripsFans;
00241 else if (prim == GL_TRIANGLE_STRIP
00242 || prim == GL_TRIANGLE_FAN
00243 || prim == GL_POLYGON)
00244 newState.PrimType = kPtsLinesStripsFans;
00245 else if (prim == GL_QUAD_STRIP)
00246 newState.PrimType = kPtsLinesStripsFans;
00247 else if (prim == GL_TRIANGLES)
00248 newState.PrimType = kTriangles;
00249 else if (prim == GL_QUADS)
00250 newState.PrimType = kQuads;
00251 else {
00252 mError("shouldn't get here");
00253 }
00254
00255 if ( VsmRequirements != newState ) {
00256 VsmRequirements = newState;
00257 VsmReqsHaveChanged = true;
00258 }
00259 }
00260
00261 void
00262 CVsmManager::TexEnabledChanged( bool enabled )
00263 {
00264 CVu1RendererProps newState = VsmRequirements;
00265
00266 if ( enabled ) newState.Texture = 1;
00267 else newState.Texture = 0;
00268
00269 if ( VsmRequirements != newState ) {
00270 VsmRequirements = newState;
00271 VsmReqsHaveChanged = true;
00272 }
00273 }
00274
00275 void
00276 CVsmManager::LightingEnabledChanged( bool enabled )
00277 {
00278 CVu1RendererProps newState = VsmRequirements;
00279
00280 if (enabled) newState.Lighting = 1;
00281 else newState.Lighting = 0;
00282
00283 if (VsmRequirements != newState) {
00284 VsmRequirements = newState;
00285 VsmReqsHaveChanged = true;
00286 }
00287 }
00288
00289 void
00290 CVsmManager::SpecularEnabledChanged( bool enabled )
00291 {
00292 CVu1RendererProps newState = VsmRequirements;
00293
00294 if (enabled) newState.Specular = 1;
00295 else newState.Specular = 0;
00296
00297 if (VsmRequirements != newState) {
00298 VsmRequirements = newState;
00299 VsmReqsHaveChanged = true;
00300 }
00301 }
00302
00303 void
00304 CVsmManager::PerVtxMaterialChanged( Vu1RendererProps::tPerVtxMaterial matType )
00305 {
00306 if ( VsmRequirements.PerVtxMaterial != (unsigned int)matType ) {
00307 VsmRequirements.PerVtxMaterial = matType;
00308 VsmReqsHaveChanged = true;
00309 }
00310 }
00311
00312 void
00313 CVsmManager::CullFaceEnabledChanged( bool enabled )
00314 {
00315 if ( VsmRequirements.CullFace != enabled ) {
00316 VsmRequirements.CullFace = enabled;
00317 VsmReqsHaveChanged = true;
00318 }
00319 }
00320
00321 bool
00322 CVsmManager::SyncVu1Renderer()
00323 {
00324 bool rendererChanged = false;
00325
00326 if ( VsmReqsHaveChanged ) {
00327 int i;
00328 for ( i = 0; i < NumVu1Renderers; i++ )
00329 if ( VsmRequirements == (VsmRequirements & Vu1Renderers[i].provides) )
00330 break;
00331
00332 mErrorIf( i == NumVu1Renderers,
00333 "Couldn't find a suitable vu1 renderer.. requirements = 0x%08x",
00334 (unsigned int)VsmRequirements );
00335 if (CurrentVu1Renderer != &Vu1Renderers[i]) {
00336 CurrentVu1Renderer = &Vu1Renderers[i];
00337
00338
00339
00340
00341 rendererChanged = true;
00342 }
00343 }
00344
00345 return rendererChanged;
00346 }
00347
00348 void
00349 CVsmManager::XferVu1Renderer( CVifSCDmaPacket &packet )
00350 {
00351 mAssert( CurrentVu1Renderer != NULL );
00352 mErrorIf( *(unsigned short*)CurrentVu1Renderer->packet > 1024,
00353 "This vu1 renderer won't fit into vu1 code memory: 0x%08x",
00354 (unsigned int)CurrentVu1Renderer->provides );
00355
00356 packet.Call( CurrentVu1Renderer->packet );
00357 packet.Pad128();
00358 packet.CloseTag();
00359
00360 pglAddToMetric(kMetricsRendererUpload);
00361 }
00362
00363 void
00364 CVsmManager::TransferSetupInfo( CVifSCDmaPacket &packet,
00365 CImmGeomManager &gmanager, GLenum primType )
00366 {
00367
00368
00369
00370
00371 packet.Cnt();
00372 {
00373 packet.Stcycl(1,1);
00374 packet.Flush();
00375 packet.Pad96();
00376 packet.OpenUnpack( Vifs::UnpackModes::v4_32, kInitInfoStart, Packet::kSingleBuff );
00377 {
00378
00379 CImmLighting &lighting = GLContext.GetImmLighting();
00380 tLightPtrs lightPtrs[8];
00381 tLightPtrs *nextDir, *nextPt, *nextSpot;
00382 nextDir = nextPt = nextSpot = &lightPtrs[0];
00383 int numDirs, numPts, numSpots;
00384 numDirs = numPts = numSpots = 0;
00385 for ( int i = 0; i < 8; i++ ) {
00386 CImmLight& light = lighting.GetImmLight(i);
00387 if ( light.IsEnabled() ) {
00388 if ( light.IsDirectional() ) {
00389 nextDir->dir = kLight0Base + i * kLightStructSize;
00390 nextDir++;
00391 numDirs++;
00392 }
00393 else if ( light.IsPoint() ) {
00394 nextPt->point = kLight0Base + i * kLightStructSize;
00395 nextPt++;
00396 numPts++;
00397 }
00398 else if ( light.IsSpot() ) {
00399 nextSpot->spot = kLight0Base + i * kLightStructSize;
00400 nextSpot++;
00401 numSpots++;
00402 }
00403 }
00404 }
00405
00406 bool doLighting = GLContext.GetImmLighting().GetLightingEnabled();
00407
00408
00409 cpu_mat_44 objToWorldXfrmTrans = GLContext.GetModelViewStack().GetTop();
00410
00411 objToWorldXfrmTrans.set_col3( cpu_vec_xyzw(0, 0, 0, 1) );
00412 objToWorldXfrmTrans = objToWorldXfrmTrans.transpose();
00413
00414 cpu_mat_44 normalRescale;
00415 normalRescale.set_identity();
00416 float normalScale = 1.0f;
00417 CImmDrawContext &drawContext = GLContext.GetImmDrawContext();
00418 if ( drawContext.GetRescaleNormals() ) {
00419 cpu_vec_xyzw fake_normal( 1, 0, 0, 0 );
00420 fake_normal = objToWorldXfrmTrans * fake_normal;
00421 normalScale = 1.0f / fake_normal.length();
00422 normalRescale.set_scale( cpu_vec_xyz(normalScale, normalScale, normalScale) );
00423 }
00424 objToWorldXfrmTrans = normalRescale * objToWorldXfrmTrans;
00425
00426
00427 if ( doLighting ) {
00428 packet += numDirs;
00429 packet += numPts;
00430 packet += numSpots;
00431 }
00432 else {
00433 packet += (tU64)0;
00434 packet += 0;
00435 }
00436
00437
00438
00439 float bfc_mult = (float)drawContext.GetCullFaceDir();
00440 unsigned int bfc_word;
00441 asm( " ## nop ## " : "=r" (bfc_word) : "0" (bfc_mult) );
00442 bool do_culling = drawContext.GetDoCullFace() && (primType > GL_LINE_STRIP);
00443 packet += bfc_word | (unsigned int)do_culling << 5;
00444
00445
00446 packet.Add( &lightPtrs[0], 8 );
00447
00448
00449
00450
00451 float maxColorValue = 255.0f;
00452 if ( GLContext.GetTexManager().GetTexEnabled() )
00453 maxColorValue = 128.0f;
00454
00455
00456 for ( int i = 0; i < 8; i++ ) {
00457 CImmLight& light = lighting.GetImmLight(i);
00458 packet += light.GetAmbient() * maxColorValue;
00459 packet += light.GetDiffuse() * maxColorValue;
00460 packet += light.GetSpecular() * maxColorValue;
00461
00462 if ( light.IsDirectional() )
00463 packet += light.GetPosition();
00464 else {
00465 packet += light.GetPosition();
00466 }
00467
00468 packet += light.GetSpotDir();
00469
00470
00471
00472
00473
00474 packet += light.GetConstantAtten();
00475 packet += light.GetLinearAtten() * 1.0f/normalScale;
00476 packet += light.GetQuadAtten() * 1.0f/normalScale;
00477 packet += 0;
00478
00479 }
00480
00481
00482 tU128 zeroQuad;
00483 asm ( "pxor %0, %0, %0" : "=r" (zeroQuad) );
00484
00485
00486 if ( doLighting )
00487 packet += lighting.GetGlobalAmbient() * maxColorValue;
00488 else
00489 packet += zeroQuad;
00490
00491
00492 CImmMaterial& material = GLContext.GetMaterialManager().GetImmMaterial();
00493 if ( doLighting )
00494 packet += material.GetEmission() * maxColorValue;
00495 else
00496 packet += GLContext.GetMaterialManager().GetCurColor() * maxColorValue;
00497 packet += material.GetAmbient();
00498 packet += material.GetDiffuse();
00499 packet += material.GetSpecular();
00500
00501
00502 packet += drawContext.GetVertexXform();
00503
00504
00505 cpu_vec_xyzw vertToEye( 0.0f, 0.0f, 1.0f, 0.0f );
00506 packet += objToWorldXfrmTrans * vertToEye;
00507
00508
00509 packet += objToWorldXfrmTrans;
00510
00511
00512 cpu_mat_44 worldToObjXfrm = GLContext.GetModelViewStack().GetInvTop();
00513 packet += worldToObjXfrm;
00514
00515
00516
00517
00518 SyncGifTag( gmanager, primType );
00519 packet += GifTag;
00520 }
00521 packet.CloseUnpack();
00522
00523 packet.Mscal(0);
00524 packet.Flushe();
00525
00526 packet.Base( kDoubleBufBase );
00527 packet.Offset( kDoubleBufOffset );
00528 }
00529 packet.CloseTag();
00530
00531 ColorMaterialEnabled = GLContext.GetMaterialManager().GetColorMaterialEnabled();
00532 TexEnabled = GLContext.GetTexManager().GetTexEnabled();
00533 }
00534
00535 void
00536 CVsmManager::SyncGifTag( CImmGeomManager &gmanager, GLenum primType )
00537 {
00538 primType &= 0x7;
00539 CImmDrawContext &drawContext = GLContext.GetImmDrawContext();
00540 bool smoothShading = drawContext.GetDoSmoothShading();
00541 bool useTexture = GLContext.GetTexManager().GetTexEnabled();
00542 bool alpha = drawContext.GetBlendEnabled();
00543 unsigned int nreg = CurrentVu1Renderer->outputQuadsPerVert;
00544
00545 sceGsPrim prim = { PRIM: primType, IIP: smoothShading, TME: useTexture,
00546 FGE: 0, ABE: alpha, AA1: 0, FST: 0, CTXT: 0, FIX: 0 };
00547 sceGifTag giftag = { NLOOP: 0, EOP: 1, pad16: 0, id: 0, PRE: 1,
00548 PRIM: *(tU64*)&prim, FLG: 0, NREG: nreg, REGS0: 2, REGS1: 1,
00549 REGS2: 4 };
00550 GifTag = giftag;
00551 }
00552
00553 void
00554 CVsmManager::XferVectors( CVifSCDmaPacket &packet, unsigned int *dataStart,
00555 int startOffset, int numVectors, int wordsPerVec,
00556 Vifs::tMask unpackMask, tU32 unpackMode,
00557 int vu1MemOffset )
00558 {
00559
00560
00561 unsigned int *vecDataStart = dataStart + startOffset * wordsPerVec;
00562 unsigned int *vecDataEnd = vecDataStart + numVectors * wordsPerVec;
00563
00564 mAssert( numVectors > 0 );
00565 mErrorIf( (unsigned int)vecDataStart & 4-1,
00566 "XferVectors only works with word-aligned data" );
00567
00568 int numWordsToPrepend = 0;
00569 unsigned int *refXferStart = vecDataStart;
00570 while ( (unsigned int)refXferStart & (16-1) ) {
00571 numWordsToPrepend++;
00572 refXferStart++;
00573 if ( refXferStart == vecDataEnd ) break;
00574 }
00575 int numWordsToAppend = 0;
00576 unsigned int *refXferEnd = vecDataEnd;
00577 while ( ((unsigned int)refXferEnd & (16-1)) && refXferEnd > refXferStart ) {
00578 numWordsToAppend++;
00579 refXferEnd--;
00580 }
00581 int numQuadsInRefXfer = ((unsigned int)refXferEnd - (unsigned int)refXferStart) / 16;
00582
00583 packet.Cnt();
00584 {
00585
00586 packet.Stmask( unpackMask );
00587
00588
00589 if ( numWordsToPrepend > 1 ) {
00590
00591 packet.Nop().Nop();
00592 if ( numWordsToPrepend == 2 )
00593 packet.Nop();
00594
00595 packet.OpenUnpack( unpackMode,
00596 vu1MemOffset,
00597 Packet::kDoubleBuff,
00598 Packet::kMasked );
00599 packet.CloseUnpack( numVectors );
00600
00601 if ( numWordsToPrepend == 3 )
00602 packet += *vecDataStart;
00603 }
00604
00605 packet.Pad128();
00606 }
00607 packet.CloseTag();
00608
00609
00610 packet.Ref( Core::MakePtrNormal(refXferStart), numQuadsInRefXfer );
00611 {
00612
00613 if ( numWordsToPrepend == 0 )
00614 packet.Nop();
00615 if ( numWordsToPrepend <= 1 ) {
00616 packet.OpenUnpack( unpackMode,
00617 vu1MemOffset,
00618 Packet::kDoubleBuff,
00619 Packet::kMasked );
00620 packet.CloseUnpack( numVectors );
00621 }
00622 if ( numWordsToPrepend == 1 )
00623 packet += *vecDataStart;
00624 else if ( numWordsToPrepend == 2 )
00625 packet.Add( vecDataStart, 2 );
00626 else if ( numWordsToPrepend == 3 )
00627 packet.Add( &vecDataStart[1], 2 );
00628 }
00629
00630
00631 if ( numWordsToAppend > 0 ) {
00632 packet.Cnt();
00633 {
00634 packet.Add( refXferEnd, numWordsToAppend );
00635 packet.Pad128();
00636 }
00637 packet.CloseTag();
00638 }
00639 }
00640
00641 void
00642 CVsmManager::XferBufferHeader( CVifSCDmaPacket& packet, GLenum primType,
00643 int numVerts,
00644 int numStripsInBuffer, unsigned short *stripOffsets )
00645 {
00646 int vu1InQuadsPerVert = CurrentVu1Renderer->inputQuadsPerVert;
00647 int vu1OutQuadsPerVert = CurrentVu1Renderer->outputQuadsPerVert;
00648
00649 packet.Cnt();
00650 {
00651
00652 packet.Stcycl(4,4);
00653 packet.OpenUnpack( Vifs::UnpackModes::v4_32, 0, Packet::kDoubleBuff );
00654 {
00655
00656 packet += numVerts;
00657 packet += 0; packet += (tU64)0;
00658
00659
00660 if ( primType == GL_QUADS ) {
00661 packet += 1 * vu1InQuadsPerVert;
00662 packet += 2 * vu1InQuadsPerVert;
00663 packet += -1 * vu1InQuadsPerVert;
00664 packet += 2 * vu1InQuadsPerVert;
00665 }
00666 else {
00667 packet += 1 * vu1InQuadsPerVert;
00668 packet += 1 * vu1InQuadsPerVert;
00669 packet += 1 * vu1InQuadsPerVert;
00670 packet += 1 * vu1InQuadsPerVert;
00671 }
00672
00673
00674 if ( primType == GL_QUADS ) {
00675 packet += 0x8000; packet += 0x8000; packet += 0; packet += 0;
00676 }
00677 else {
00678 packet += 0; packet += 0; packet += 0; packet += 0;
00679 }
00680
00681
00682
00683
00684
00685
00686 unsigned int adcBits = 0;
00687 if ( primType == GL_TRIANGLE_STRIP || primType == GL_QUAD_STRIP )
00688 adcBits = 0x800;
00689 float adc;
00690 unsigned int stopBit = 0x400;
00691 for ( int i = 0; i < 16; i++ ) {
00692 if ( i < numStripsInBuffer )
00693 adc = (float)(adcBits |
00694 (unsigned int)stripOffsets[i] * vu1OutQuadsPerVert );
00695 else if ( i == numStripsInBuffer )
00696 adc = (float)stopBit;
00697 else
00698 adc = (float)0;
00699 packet += adc;
00700 }
00701 }
00702 packet.CloseUnpack();
00703 }
00704 packet.CloseTag();
00705 }
00706
00707 void
00708 CVsmManager::GetUnpackAttribs( int numWords, unsigned int &mode, Vifs::tMask &mask )
00709 {
00710
00711 if ( numWords == 3 ) {
00712 Vifs::tMask vec3Mask = { 0, 0, 0, 1,
00713 0, 0, 0, 1,
00714 0, 0, 0, 1,
00715 0, 0, 0, 1 };
00716 mode = Vifs::UnpackModes::v3_32;
00717 mask = vec3Mask;
00718 }
00719 else if ( numWords == 4 ) {
00720 Vifs::tMask vec4Mask = { 0, 0, 0, 0,
00721 0, 0, 0, 0,
00722 0, 0, 0, 0,
00723 0, 0, 0, 0 };
00724 mode = Vifs::UnpackModes::v4_32;
00725 mask = vec4Mask;
00726 }
00727 else if ( numWords == 2 ) {
00728 Vifs::tMask vec2Mask = { 0, 0, 1, 1,
00729 0, 0, 1, 1,
00730 0, 0, 1, 1,
00731 0, 0, 1, 1 };
00732 mode = Vifs::UnpackModes::v2_32;
00733 mask = vec2Mask;
00734 }
00735 else {
00736 mError("shouldn't get here (you're probably calling glDrawArrays"
00737 "without setting one of the pointers)");
00738 }
00739 }
00740
00741 void
00742 CVsmManager::DrawArrays( CVifSCDmaPacket &packet, CImmGeomManager &gmanager,
00743 CGeometryBlock &block )
00744 {
00745 mErrorIf( block.GetWordsPerVertex() == 2, "2 word vertices not supported" );
00746
00747
00748
00749
00750
00751 packet.Cnt();
00752 {
00753 static const float row[4] = { 0.0f, 0.0f, 1.0f, 1.0f };
00754 packet.Strow( row );
00755
00756 packet.Pad128();
00757 }
00758 packet.CloseTag();
00759
00760
00761
00762
00763
00764 WordsPerVertex = block.GetWordsPerVertex();
00765 GetUnpackAttribs( WordsPerVertex, VertexUnpackMode, VertexUnpackMask );
00766
00767 WordsPerNormal = 0;
00768 if ( block.GetNormalsAreValid() )
00769 WordsPerNormal = block.GetWordsPerNormal();
00770 else
00771 WordsPerNormal = 3;
00772 GetUnpackAttribs( WordsPerNormal, NormalUnpackMode, NormalUnpackMask );
00773
00774 WordsPerTexCoord = 0;
00775 if ( block.GetTexCoordsAreValid() )
00776 WordsPerTexCoord = block.GetWordsPerTexCoord();
00777 else
00778 WordsPerTexCoord = 2;
00779 GetUnpackAttribs( WordsPerTexCoord, TexCoordUnpackMode, TexCoordUnpackMask );
00780
00781 WordsPerColor = 0;
00782 if ( block.GetColorsAreValid() )
00783 WordsPerColor = block.GetWordsPerColor();
00784 else
00785 WordsPerColor = 3;
00786 GetUnpackAttribs( WordsPerColor, ColorUnpackMode, ColorUnpackMask );
00787
00788
00789
00790
00791
00792
00793 int maxUnpackVerts = 256;
00794
00795 int vu1QuadsPerVert = CurrentVu1Renderer->inputQuadsPerVert;
00796 int inputBufSize = kInputBufSize - kInputStart;
00797 int maxVu1VertsPerBuffer = inputBufSize / vu1QuadsPerVert;
00798
00799 int maxVertsPerBuffer = Math::Min( maxUnpackVerts, maxVu1VertsPerBuffer );
00800 maxVertsPerBuffer -= 10;
00801
00802 maxVertsPerBuffer -= maxVertsPerBuffer % block.GetNumVertsPerPrim();
00803
00804
00805
00806
00807
00808 DrawStrip( packet, gmanager, block, maxVertsPerBuffer );
00809 }
00810
00811 void
00812 CVsmManager::DrawStrip( CVifSCDmaPacket &packet, CImmGeomManager &gmanager,
00813 CGeometryBlock &block, int maxVertsPerBuffer )
00814 {
00815
00816
00817
00818
00819 int numVertsToRestart = block.GetNumVertsToRestartStrip();
00820 int numVertsXferred = 0;
00821 bool writeModeIsValid = false;
00822 int numStripsInBuffer = 0;
00823 unsigned short stripOffsets[16];
00824 bool haveContinued = false;
00825 void *normals, *vertices, *texCoords, *colors;
00826 normals = vertices = texCoords = colors = NULL;
00827 int vu1BufferOffset = 0, stripIndex = 0, vertsInBlock = 0;
00828 for ( int curStrip = 0; curStrip < block.GetNumStrips(); curStrip++ ) {
00829
00830
00831 int numVertsFirstBuffer, numVertsLastBuffer, numBuffers;
00832 FindNumBuffers( block.GetStripLength(curStrip),
00833 numVertsToRestart, numVertsXferred, maxVertsPerBuffer,
00834 numVertsFirstBuffer, numVertsLastBuffer, numBuffers );
00835
00836
00837
00838
00839
00840 int numVertsThisBuffer;
00841 int indexIntoStrip = 0;
00842 int vu1QuadsPerVert = CurrentVu1Renderer->inputQuadsPerVert;
00843 for ( int curBuffer = 0;
00844 curBuffer < numBuffers;
00845 curBuffer++, indexIntoStrip += numVertsThisBuffer - numVertsToRestart ) {
00846
00847
00848 if ( curBuffer == 0 )
00849 numVertsThisBuffer = numVertsFirstBuffer;
00850 else if ( curBuffer == numBuffers - 1 )
00851 numVertsThisBuffer = numVertsLastBuffer;
00852 else
00853 numVertsThisBuffer = maxVertsPerBuffer;
00854
00855
00856
00857 if ( ! writeModeIsValid ) {
00858
00859
00860
00861 packet.Cnt();
00862 {
00863 packet.Stcycl(1, vu1QuadsPerVert);
00864 packet.Pad128();
00865 }
00866 packet.CloseTag();
00867 }
00868
00869 if ( ! haveContinued ) {
00870 vertices = (block.GetVerticesAreValid()) ? block.GetVertices(curStrip) : NULL;
00871 normals = (block.GetNormalsAreValid()) ? block.GetNormals(curStrip) : NULL;
00872 texCoords = (block.GetTexCoordsAreValid()) ? block.GetTexCoords(curStrip) : NULL;
00873 colors = (block.GetColorsAreValid()) ? block.GetColors(curStrip) : NULL;
00874 vu1BufferOffset = kInputStart + numVertsXferred * vu1QuadsPerVert;
00875 stripIndex = indexIntoStrip;
00876 vertsInBlock = 0;
00877 }
00878
00879
00880
00881
00882
00883 if ( ! block.StripIsContinued(curStrip)
00884 || curBuffer < numBuffers - 1 ) {
00885 XferBlock( packet, gmanager, block.GetPrimType(),
00886 vertices, normals, texCoords, colors,
00887 vu1BufferOffset,
00888 stripIndex, vertsInBlock + numVertsThisBuffer );
00889 haveContinued = false;
00890 }
00891 else {
00892 vertsInBlock += numVertsThisBuffer;
00893 haveContinued = true;
00894 }
00895
00896 stripOffsets[numStripsInBuffer++] = numVertsXferred;
00897 mErrorIf( numStripsInBuffer > 16, "Too many strips in buffer.. this shouldn't happen" );
00898 numVertsXferred += numVertsThisBuffer;
00899
00900
00901 if ( curBuffer < numBuffers - 1 ) {
00902 FinishBuffer( packet, block, numVertsXferred, vu1QuadsPerVert,
00903 numStripsInBuffer, stripOffsets );
00904 writeModeIsValid = false;
00905 numStripsInBuffer = 0;
00906 numVertsXferred = 0;
00907 }
00908
00909 }
00910
00911
00912
00913
00914
00915
00916
00917
00918 if ( ( (maxVertsPerBuffer - numVertsXferred) <= numVertsToRestart + 1 )
00919 || numStripsInBuffer == 16
00920 || (curStrip == block.GetNumStrips() - 1) ) {
00921 if ( haveContinued ) {
00922 XferBlock( packet, gmanager, block.GetPrimType(),
00923 vertices, normals, texCoords, colors,
00924 vu1BufferOffset,
00925 stripIndex, vertsInBlock );
00926 haveContinued = false;
00927 }
00928
00929 FinishBuffer( packet, block, numVertsXferred, vu1QuadsPerVert,
00930 numStripsInBuffer, stripOffsets );
00931 writeModeIsValid = false;
00932 numStripsInBuffer = 0;
00933 numVertsXferred = 0;
00934 }
00935
00936 }
00937 }
00938
00939 void
00940 CVsmManager::FinishBuffer( CVifSCDmaPacket &packet, CGeometryBlock &block,
00941 int numVertsInBuffer, int vu1QuadsPerVert,
00942 int numStripsInBuffer, unsigned short *stripOffsets )
00943 {
00944
00945
00946 XferBufferHeader( packet, block.GetPrimType(),
00947 numVertsInBuffer,
00948 numStripsInBuffer, stripOffsets );
00949
00950
00951 packet.Cnt(); {
00952 packet.Mscnt();
00953 packet.Nop();
00954 }
00955 packet.CloseTag();
00956 }
00957
00958 void
00959 CVsmManager::FindNumBuffers( int numToAdd, int numVertsToRestart,
00960 int numVertsAlreadyInFirstBuffer, int maxVertsPerBuffer,
00961 int &numVertsFirstBuffer, int &numVertsLastBuffer,
00962 int &numBuffers )
00963 {
00964
00965
00966
00967 int numLeftToAdd;
00968 int freeVertsFirstBuffer = maxVertsPerBuffer - numVertsAlreadyInFirstBuffer;
00969 if ( numToAdd <= freeVertsFirstBuffer ) {
00970 numVertsFirstBuffer = numToAdd;
00971 numLeftToAdd = 0;
00972 }
00973 else {
00974
00975
00976
00977 numVertsFirstBuffer = freeVertsFirstBuffer - (int)Math::IsOdd(freeVertsFirstBuffer);
00978 numLeftToAdd = numToAdd - (numVertsFirstBuffer - numVertsToRestart);
00979 }
00980
00981 int adjVertsPerBuffer = maxVertsPerBuffer - numVertsToRestart;
00982 adjVertsPerBuffer -= (int)Math::IsOdd(adjVertsPerBuffer);
00983 numBuffers = 1 + numLeftToAdd / adjVertsPerBuffer;
00984 if ( numLeftToAdd % adjVertsPerBuffer > numVertsToRestart ) numBuffers++;
00985
00986 numVertsLastBuffer =
00987 (numBuffers > 1)
00988 ? numToAdd - ((numVertsFirstBuffer - numVertsToRestart)
00989 + (numBuffers-2) * adjVertsPerBuffer)
00990 : numToAdd;
00991 }
00992
00993
00994
00995
00996
00997 void
00998 CVsmManager::XferBlock( CVifSCDmaPacket &packet, CImmGeomManager &gmanager, GLenum primType,
00999 void *vertices, void *normals, void *texCoords, void *colors,
01000 int vu1Offset, int firstElement, int numToAdd )
01001 {
01002
01003
01004
01005
01006 mErrorIf( vertices == NULL, "Tried to render an array with no vertices!" );
01007 XferVectors( packet, (unsigned int *)vertices,
01008 firstElement, numToAdd,
01009 WordsPerVertex, VertexUnpackMask, VertexUnpackMode,
01010 vu1Offset );
01011
01012
01013
01014
01015
01016 int firstNormal = firstElement;
01017 if ( normals == NULL ) {
01018
01019
01020
01021
01022 CDmaPacket &normalBuf = gmanager.GetNormalBuf();
01023 normals = (void*)normalBuf.GetNextPtr();
01024 firstNormal = 0;
01025
01026 cpu_vec_xyz curNormal = gmanager.GetCurNormal();
01027 for ( int i = 0; i < numToAdd; i++ )
01028 normalBuf += curNormal;
01029 }
01030
01031 XferVectors( packet, (unsigned int*)normals,
01032 firstNormal, numToAdd,
01033 WordsPerNormal, NormalUnpackMask, NormalUnpackMode,
01034 vu1Offset + 1 );
01035
01036
01037
01038
01039
01040 int firstTexCoord = firstElement;
01041 if ( TexEnabled && texCoords == NULL ) {
01042
01043
01044 CDmaPacket &texCoordBuf = gmanager.GetTexCoordBuf();
01045 texCoords = (void*)texCoordBuf.GetNextPtr();
01046 firstTexCoord = 0;
01047
01048 const float* curTexCoord = gmanager.GetCurTexCoord();
01049 for ( int i = 0; i < numToAdd; i++ ) {
01050 texCoordBuf += curTexCoord[0];
01051 texCoordBuf += curTexCoord[1];
01052 }
01053 }
01054 if ( TexEnabled )
01055 XferVectors( packet, (unsigned int*)texCoords,
01056 firstTexCoord, numToAdd,
01057 WordsPerTexCoord, TexCoordUnpackMask, TexCoordUnpackMode,
01058 vu1Offset + 2 );
01059
01060
01061
01062
01063
01064 int firstColor = firstElement;
01065 if ( colors != NULL && ColorMaterialEnabled ) {
01066 XferVectors( packet, (unsigned int*)colors,
01067 firstColor, numToAdd,
01068 WordsPerColor, ColorUnpackMask, ColorUnpackMode,
01069 vu1Offset + 3 );
01070 }
01071
01072 }
01073