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 <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
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
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
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
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
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
00322
00323
00324
00325 if ( GLContext.GetRendererContextChanged() == 0
00326 && GLContext.GetGsContextChanged() == 0
00327 && ! UserRenderContextChanged
00328 && ! rendererChanged
00329 && Geometry.MergeNew() ) {
00330 doReset = false;
00331 }
00332 else {
00333
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
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
00391 bool texEnabled = GLContext.GetTexManager().GetTexEnabled();
00392 CVifSCDmaPacket &packet = GLContext.GetVif1Packet();
00393 if ( texEnabled
00394 && changed & GsCtxtFlags::Texture ) {
00395
00396
00397 packet.Cnt();
00398 packet.Flush().Nop();
00399 packet.CloseTag();
00400 GLContext.GetTexManager().UseCurTexture( GLContext.GetVif1Packet() );
00401 }
00402
00403
00404 if ( changed & GsCtxtFlags::DrawEnv ) {
00405
00406 packet.Cnt();
00407 packet.Flush().Nop();
00408 packet.CloseTag();
00409
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
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
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 }