00001
00002
00003
00004
00005 #include <stdio.h>
00006
00007 #include "ps2s/packet.h"
00008 #include "ps2s/cpu_matrix.h"
00009 #include "ps2s/math.h"
00010 #include "ps2s/displayenv.h"
00011
00012 #include "GL/ps2gl.h"
00013 #include "ps2gl/gmanager.h"
00014 #include "ps2gl/glcontext.h"
00015 #include "ps2gl/dlist.h"
00016 #include "ps2gl/clear.h"
00017 #include "ps2gl/matrix.h"
00018 #include "ps2gl/texture.h"
00019 #include "ps2gl/material.h"
00020 #include "ps2gl/drawcontext.h"
00021
00022
00023
00024
00025
00026 CImmGeomManager::CImmGeomManager( CGLContext &context, int immBufferQwordSize )
00027 : CGeomManager(context),
00028 VsmMananger(context),
00029 VertexBuf0( immBufferQwordSize + immBufferQwordSize % 4,
00030 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00031 NormalBuf0( immBufferQwordSize * 4 / 3 + 1 + (immBufferQwordSize * 4 / 3 + 1) % 4,
00032 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00033 TexCoordBuf0( immBufferQwordSize / 2 + (immBufferQwordSize / 2) % 4,
00034 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00035 ColorBuf0( immBufferQwordSize + immBufferQwordSize % 4,
00036 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00037 VertexBuf1( immBufferQwordSize + immBufferQwordSize % 4,
00038 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00039 NormalBuf1( immBufferQwordSize * 4 / 3 + 1 + (immBufferQwordSize * 4 / 3 + 1) % 4,
00040 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00041 TexCoordBuf1( immBufferQwordSize / 2 + (immBufferQwordSize / 2) % 4,
00042 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00043 ColorBuf1( immBufferQwordSize + immBufferQwordSize % 4,
00044 DMAC::Channels::vif1, Core::MemMappings::UncachedAccl ),
00045 CurBuffer(0)
00046 {
00047 CurVertexBuf = &VertexBuf0;
00048 CurNormalBuf = &NormalBuf0;
00049 CurTexCoordBuf = &TexCoordBuf0;
00050 CurColorBuf = &ColorBuf0;
00051
00052 NumBuffersToBeFreed[0] = NumBuffersToBeFreed[1] = 0;
00053
00054 VertArray = new CVertArray;
00055 }
00056
00057 CImmGeomManager::~CImmGeomManager()
00058 {
00059 delete VertArray;
00060 }
00061
00062
00063
00064
00065
00066 void
00067 CImmGeomManager::SwapBuffers()
00068 {
00069
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 FreeWaitingBuffers();
00085 }
00086
00087 void
00088 CImmGeomManager::FreeWaitingBuffers()
00089 {
00090 CurBuffer = 1 - CurBuffer;
00091
00092 for ( int i = 0; i < NumBuffersToBeFreed[CurBuffer]; i++ )
00093 free( BuffersToBeFreed[CurBuffer][i] );
00094 NumBuffersToBeFreed[CurBuffer] = 0;
00095 }
00096
00097
00098
00099
00100
00101 void
00102 CImmGeomManager::BeginDListDef()
00103 {
00104 }
00105
00106 void
00107 CImmGeomManager::BeginGeom( GLenum mode )
00108 {
00109 if ( Vu1Prim != mode ) VsmMananger.PrimChanged(mode);
00110
00111 Geometry.SetPrimType( mode );
00112 Geometry.SetNormals( CurNormalBuf->GetNextPtr() );
00113 Geometry.SetVertices( CurVertexBuf->GetNextPtr() );
00114 Geometry.SetTexCoords( CurTexCoordBuf->GetNextPtr() );
00115 Geometry.SetColors( CurColorBuf->GetNextPtr() );
00116
00117 InsideBeginEnd = true;
00118 }
00119
00120 void
00121 CImmGeomManager::Vertex( cpu_vec_xyzw newVert )
00122 {
00123 cpu_vec_xyz normal = GetCurNormal();
00124 *CurNormalBuf += normal;
00125
00126 const float *texCoord = GetCurTexCoord();
00127 *CurTexCoordBuf += texCoord[0];
00128 *CurTexCoordBuf += texCoord[1];
00129
00130 *CurVertexBuf += newVert;
00131
00132 Geometry.AddVertices();
00133 Geometry.AddNormals();
00134 Geometry.AddTexCoords();
00135 }
00136
00137 void
00138 CImmGeomManager::Normal( cpu_vec_xyz normal )
00139 {
00140 if ( DoNormalize ) normal.normalize();
00141 CurNormal = normal;
00142 }
00143
00144 void
00145 CImmGeomManager::Color( cpu_vec_xyzw color )
00146 {
00147 if ( InsideBeginEnd ) {
00148 *CurColorBuf += color;
00149 Geometry.AddColors();
00150 }
00151 else {
00152 GLContext.GetMaterialManager().Color( color );
00153 }
00154 }
00155
00156 void
00157 CImmGeomManager::TexCoord( float u, float v )
00158 {
00159 CurTexCoord[0] = u; CurTexCoord[1] = v;
00160 }
00161
00162 void
00163 CImmGeomManager::DrawBlock( CGeometryBlock &block )
00164 {
00165 CVifSCDmaPacket &packet = GLContext.GetVif1Packet();;
00166
00167 VsmMananger.DrawArrays( packet, *this, block );
00168 }
00169
00170 void
00171 CImmGeomManager::CommitNewGeom()
00172 {
00173 bool doReset = true;
00174
00175 bool vsmChanged = VsmMananger.SyncVu1Renderer();
00176 if ( Geometry.IsPending() ) {
00177
00178
00179 if ( GLContext.GetVu1ContextChanged() == 0
00180 && GLContext.GetGsContextChanged() == 0
00181 && ! vsmChanged
00182 && Geometry.MergeNew() )
00183 doReset = false;
00184
00185 else
00186 DrawBlock( Geometry );
00187 }
00188
00189 if ( doReset ) {
00190 Geometry.MakeNewValuesCurrent();
00191 Geometry.ResetNew();
00192
00193 if ( vsmChanged ) {
00194 VsmMananger.XferVu1Renderer(GLContext.GetVif1Packet());
00195
00196 }
00197 SyncVu1Context(Geometry.GetPrimType());
00198 SyncGsContext();
00199 }
00200 }
00201
00202 void
00203 CImmGeomManager::EndGeom()
00204 {
00205 InsideBeginEnd = false;
00206
00207 Geometry.SetVerticesAreValid(true);
00208 Geometry.SetNormalsAreValid(true);
00209 Geometry.SetTexCoordsAreValid(true);
00210
00211
00212 Geometry.SetColorsAreValid(false);
00213 if ( Geometry.GetNumNewColors() > 0 ) {
00214 mErrorIf( Geometry.GetNumNewVertices() != Geometry.GetNumNewColors(),
00215 "Sorry, but inside glBegin/glEnd you need "
00216 "to specify either one color for each vertex given, or none." );
00217 Geometry.SetColorsAreValid(true);
00218
00219 SyncColorMaterial(true);
00220 }
00221 else {
00222 SyncColorMaterial(false);
00223 }
00224
00225 Geometry.SetWordsPerVertex(4);
00226 Geometry.SetWordsPerNormal(3);
00227 Geometry.SetWordsPerTexCoord(2);
00228 Geometry.SetWordsPerColor(4);
00229
00230 CommitNewGeom();
00231 }
00232
00233 void
00234 CImmGeomManager::SyncVu1Renderer()
00235 {
00236 if ( VsmMananger.SyncVu1Renderer() )
00237 VsmMananger.XferVu1Renderer( GLContext.GetVif1Packet() );
00238 }
00239
00240 void
00241 CImmGeomManager::SyncVu1Context( GLenum primType )
00242 {
00243
00244 if ( tU32 changed = GLContext.GetVu1ContextChanged() ) {
00245 VsmMananger.TransferSetupInfo( GLContext.GetVif1Packet(), *this, primType );
00246
00247 GLContext.SetVu1ContextChanged(false);
00248 Vu1Prim = primType;
00249 }
00250 }
00251
00252 void
00253 CImmGeomManager::SyncGsContext()
00254 {
00255 if ( tU32 changed = GLContext.GetGsContextChanged() ) {
00256
00257 bool texEnabled = GLContext.GetTexManager().GetTexEnabled();
00258 CVifSCDmaPacket &packet = GLContext.GetVif1Packet();
00259 if ( texEnabled
00260 && changed & GsCtxtFlags::Texture ) {
00261
00262
00263 packet.Cnt();
00264 packet.Flush().Nop();
00265 packet.CloseTag();
00266 GLContext.GetTexManager().UseCurTexture( GLContext.GetVif1Packet() );
00267 }
00268
00269
00270 if ( changed & GsCtxtFlags::DrawEnv ) {
00271
00272 packet.Cnt();
00273 packet.Flush().Nop();
00274 packet.CloseTag();
00275
00276 GLContext.GetImmDrawContext().GetDrawEnv().SendSettings( GLContext.GetVif1Packet() );
00277 }
00278
00279 GLContext.SetGsContextChanged(false);
00280 }
00281 }
00282
00283 void
00284 CImmGeomManager::SyncColorMaterial( bool pvColorsArePresent )
00285 {
00286 CMaterialManager &mm = GLContext.GetMaterialManager();
00287 if ( pvColorsArePresent && mm.GetColorMaterialEnabled() ) {
00288 switch ( mm.GetColorMaterialMode() ) {
00289 case GL_EMISSION:
00290 mNotImplemented( "Only GL_DIFFUSE can change per-vertex" );
00291 break;
00292 case GL_AMBIENT:
00293 mNotImplemented( "Only GL_DIFFUSE can change per-vertex" );
00294 break;
00295 case GL_DIFFUSE:
00296
00297
00298 VsmMananger.PerVtxMaterialChanged( Vu1RendererProps::kDiffuse );
00299 break;
00300 case GL_AMBIENT_AND_DIFFUSE:
00301 mNotImplemented( "Only GL_DIFFUSE can change per-vertex" );
00302 break;
00303 case GL_SPECULAR:
00304 mNotImplemented( "Only GL_DIFFUSE can change per-vertex" );
00305
00306 break;
00307 }
00308 }
00309 else {
00310 VsmMananger.PerVtxMaterialChanged( Vu1RendererProps::kNone );
00311 }
00312 }
00313
00314 void
00315 CImmGeomManager::Flush()
00316 {
00317 if ( Geometry.IsPending() ) {
00318 DrawBlock( Geometry );
00319 Geometry.Reset();
00320 }
00321 }
00322
00323 void
00324 CImmGeomManager::DrawArrays( GLenum mode, int first, int count )
00325 {
00326 if ( Vu1Prim != mode ) VsmMananger.PrimChanged(mode);
00327
00328 Geometry.SetPrimType(mode);
00329
00330 Geometry.SetVertices( VertArray->GetVertices() );
00331 Geometry.SetNormals( VertArray->GetNormals() );
00332 Geometry.SetTexCoords( VertArray->GetTexCoords() );
00333 Geometry.SetColors( VertArray->GetColors() );
00334
00335 Geometry.SetVerticesAreValid( VertArray->GetVerticesAreValid() );
00336 Geometry.SetNormalsAreValid( VertArray->GetNormalsAreValid() );
00337 Geometry.SetTexCoordsAreValid( VertArray->GetTexCoordsAreValid() );
00338 Geometry.SetColorsAreValid( VertArray->GetColorsAreValid() );
00339
00340 Geometry.SetWordsPerVertex( VertArray->GetWordsPerVertex() );
00341 Geometry.SetWordsPerNormal( VertArray->GetWordsPerNormal() );
00342 Geometry.SetWordsPerTexCoord( VertArray->GetWordsPerTexCoord() );
00343 Geometry.SetWordsPerColor( VertArray->GetWordsPerColor() );
00344
00345 Geometry.AddVertices(count);
00346 Geometry.AddNormals(count);
00347 Geometry.AddTexCoords(count);
00348 Geometry.AddColors(count);
00349
00350 Geometry.AdjustNewGeomPtrs( first );
00351
00352
00353 SyncColorMaterial(VertArray->GetColors() != NULL);
00354
00355 CommitNewGeom();
00356 }
00357