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 #include "ps2s/cpu_matrix.h"
00010
00011 #include "ps2gl/linear_renderer.h"
00012 #include "ps2gl/glcontext.h"
00013 #include "ps2gl/metrics.h"
00014 #include "ps2gl/immgmanager.h"
00015 #include "ps2gl/lighting.h"
00016 #include "ps2gl/material.h"
00017 #include "ps2gl/matrix.h"
00018 #include "ps2gl/texture.h"
00019 #include "ps2gl/drawcontext.h"
00020
00021 #include "vu1_mem_linear.h"
00022
00023 void
00024 CLinearRenderer::DrawLinearArrays( CGeometryBlock &block )
00025 {
00026 int wordsPerVert = block.GetWordsPerVertex();
00027 int wordsPerNormal = (block.GetNormalsAreValid()) ? block.GetWordsPerNormal() : 0;
00028 int wordsPerTex = (block.GetTexCoordsAreValid()) ? block.GetWordsPerTexCoord() : 0;
00029 int wordsPerColor = (block.GetColorsAreValid()) ? block.GetWordsPerColor() : 0;
00030
00031 CVifSCDmaPacket &packet = pGLContext->GetVif1Packet();
00032 InitXferBlock( packet, wordsPerVert, wordsPerNormal, wordsPerTex, wordsPerColor );
00033
00034
00035
00036
00037 int maxUnpackVerts = 256;
00038
00039 int vu1QuadsPerVert = InputQuadsPerVert;
00040 int inputBufSize = InputGeomBufSize;
00041 int maxVu1VertsPerBuffer = inputBufSize / vu1QuadsPerVert;
00042
00043 int maxVertsPerBuffer = Math::Min( maxUnpackVerts, maxVu1VertsPerBuffer );
00044 maxVertsPerBuffer -= 3;
00045
00046 maxVertsPerBuffer -= maxVertsPerBuffer % block.GetNumVertsPerPrim();
00047
00048
00049
00050 DrawBlock( packet, block, maxVertsPerBuffer );
00051 }
00052
00053 void
00054 CLinearRenderer::InitContext( GLenum primType, tU32 rcChanges, bool userRcChanged )
00055 {
00056 CGLContext &glContext = *pGLContext;
00057 CVifSCDmaPacket &packet = glContext.GetVif1Packet();
00058
00059 packet.Cnt();
00060 {
00061 AddVu1RendererContext( packet, primType, kContextStart );
00062
00063 packet.Mscal(0);
00064 packet.Flushe();
00065
00066 packet.Base( kDoubleBufBase );
00067 packet.Offset( kDoubleBufOffset );
00068 }
00069 packet.CloseTag();
00070
00071 CacheRendererState();
00072 }
00073
00074 int
00075 CLinearRenderer::GetPacketQwordSize( const CGeometryBlock &geometry )
00076 {
00077
00078 return Math::Max(geometry.GetTotalVertices() / 70, 1) * 1000;
00079 }
00080
00081 CRendererProps
00082 CLinearRenderer::GetRenderContextDeps()
00083 {
00084 CRendererProps deps;
00085 deps = (tU64)0;
00086 deps.Lighting = 1;
00087 deps.Texture = 1;
00088 deps.PerVtxMaterial = 1;
00089
00090 return deps;
00091 }
00092
00093 bool
00094 CLinearRenderer::GetCachePackets( const CGeometryBlock &geometry )
00095 {
00096 return !( pGLContext->GetImmLighting().GetLightingEnabled()
00097 && ! geometry.GetNormalsAreValid() );
00098 }
00099
00100 void
00101 CLinearRenderer::DrawBlock( CVifSCDmaPacket &packet,
00102 CGeometryBlock &block, int maxVertsPerBuffer )
00103 {
00104 mErrorIf( block.GetWordsPerVertex() == 2, "2 word vertices not supported" );
00105
00106
00107
00108
00109 packet.Cnt();
00110 {
00111 packet.Stcycl(1, InputQuadsPerVert);
00112 packet.Pad128();
00113 }
00114 packet.CloseTag();
00115
00116
00117
00118
00119
00120
00121
00122 int numVertsToRestart = block.GetNumVertsToRestartStrip();
00123 bool stripsCanBeMerged = block.GetStripsCanBeMerged();
00124
00125 int numVertsXferred = 0;
00126 int numStripsInBuffer = 0;
00127 unsigned short stripOffsets[16];
00128 bool haveContinued = false;
00129 const void *normals, *vertices, *texCoords, *colors;
00130 normals = vertices = texCoords = colors = NULL;
00131 int vu1BufferOffset = 0, stripIndex = 0, vertsInBlock = 0;
00132
00133
00134 int adjMaxVertsPerBuffer =
00135 maxVertsPerBuffer - (Math::IsOdd(maxVertsPerBuffer - numVertsToRestart));
00136 for ( int curStrip = 0; curStrip < block.GetNumStrips(); curStrip++ ) {
00137
00138
00139 int numVertsFirstBuffer, numVertsLastBuffer, numBuffers;
00140 FindNumBuffers( block.GetStripLength(curStrip),
00141 numVertsToRestart, numVertsXferred, maxVertsPerBuffer,
00142 numVertsFirstBuffer, numVertsLastBuffer, numBuffers );
00143
00144
00145
00146
00147
00148 int numVertsThisBuffer;
00149 int indexIntoStrip = 0;
00150 int vu1QuadsPerVert = InputQuadsPerVert;
00151 for ( int curBuffer = 0;
00152 curBuffer < numBuffers;
00153 curBuffer++, indexIntoStrip += numVertsThisBuffer - numVertsToRestart ) {
00154
00155
00156 if ( curBuffer == 0 )
00157 numVertsThisBuffer = numVertsFirstBuffer;
00158 else if ( curBuffer == numBuffers - 1 )
00159 numVertsThisBuffer = numVertsLastBuffer;
00160 else
00161 numVertsThisBuffer = adjMaxVertsPerBuffer;
00162
00163
00164
00165 if ( ! haveContinued ) {
00166 vertices = (block.GetVerticesAreValid()) ? block.GetVertices(curStrip) : NULL;
00167 normals = (block.GetNormalsAreValid()) ? block.GetNormals(curStrip) : NULL;
00168 texCoords = (block.GetTexCoordsAreValid()) ? block.GetTexCoords(curStrip) : NULL;
00169 colors = (block.GetColorsAreValid()) ? block.GetColors(curStrip) : NULL;
00170 vu1BufferOffset = InputGeomOffset + numVertsXferred * vu1QuadsPerVert;
00171 stripIndex = indexIntoStrip;
00172 vertsInBlock = 0;
00173 }
00174
00175
00176
00177
00178
00179
00180
00181 if ( ! block.StripIsContinued(curStrip)
00182 || curBuffer < numBuffers - 1 ) {
00183 XferBlock( packet,
00184 vertices, normals, texCoords, colors,
00185 vu1BufferOffset,
00186 stripIndex, vertsInBlock + numVertsThisBuffer );
00187 haveContinued = false;
00188 }
00189 else {
00190 vertsInBlock += numVertsThisBuffer;
00191 haveContinued = true;
00192 }
00193
00194 stripOffsets[numStripsInBuffer++] = numVertsXferred;
00195 mErrorIf( numStripsInBuffer > 16, "Too many strips in buffer.. this shouldn't happen" );
00196 numVertsXferred += numVertsThisBuffer;
00197
00198
00199 if ( curBuffer < numBuffers - 1 ) {
00200 FinishBuffer( packet, numVertsToRestart, numVertsXferred, vu1QuadsPerVert,
00201 numStripsInBuffer, stripOffsets );
00202 numStripsInBuffer = 0;
00203 numVertsXferred = 0;
00204 }
00205
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217 if ( ! stripsCanBeMerged
00218 || ( (maxVertsPerBuffer - numVertsXferred) <= numVertsToRestart + 1 )
00219 || numStripsInBuffer == 16
00220 || (curStrip == block.GetNumStrips() - 1) ) {
00221 if ( haveContinued ) {
00222 XferBlock( packet,
00223 vertices, normals, texCoords, colors,
00224 vu1BufferOffset,
00225 stripIndex, vertsInBlock );
00226 haveContinued = false;
00227 }
00228
00229 FinishBuffer( packet, numVertsToRestart, numVertsXferred, vu1QuadsPerVert,
00230 numStripsInBuffer, stripOffsets );
00231 numStripsInBuffer = 0;
00232 numVertsXferred = 0;
00233 }
00234
00235 }
00236 }
00237
00238 void
00239 CLinearRenderer::FinishBuffer( CVifSCDmaPacket &packet, int numVertsToBreakStrip,
00240 int numVertsInBuffer, int vu1QuadsPerVert,
00241 int numStripsInBuffer, unsigned short *stripOffsets )
00242 {
00243 packet.Cnt();
00244 {
00245
00246
00247 XferBufferHeader( packet, numVertsToBreakStrip,
00248 numVertsInBuffer,
00249 numStripsInBuffer, stripOffsets );
00250
00251 packet.Mscnt();
00252 packet.Pad128();
00253 }
00254 packet.CloseTag();
00255 }
00256
00257 void
00258 CLinearRenderer::FindNumBuffers( int numToAdd, int numVertsToRestart,
00259 int numVertsAlreadyInFirstBuffer, int maxVertsPerBuffer,
00260 int &numVertsFirstBuffer, int &numVertsLastBuffer,
00261 int &numBuffers )
00262 {
00263
00264
00265
00266 int numLeftToAdd;
00267 int freeVertsFirstBuffer = maxVertsPerBuffer - numVertsAlreadyInFirstBuffer;
00268 if ( numToAdd <= freeVertsFirstBuffer ) {
00269 numVertsFirstBuffer = numToAdd;
00270 numLeftToAdd = 0;
00271 }
00272 else {
00273
00274
00275
00276 numVertsFirstBuffer = freeVertsFirstBuffer - (int)Math::IsOdd(freeVertsFirstBuffer);
00277 numLeftToAdd = numToAdd - (numVertsFirstBuffer - numVertsToRestart);
00278 }
00279
00280 int adjVertsPerBuffer = maxVertsPerBuffer - numVertsToRestart;
00281 adjVertsPerBuffer -= (int)Math::IsOdd(adjVertsPerBuffer);
00282 numBuffers = 1 + numLeftToAdd / adjVertsPerBuffer;
00283 if ( numLeftToAdd % adjVertsPerBuffer > numVertsToRestart ) numBuffers++;
00284
00285 numVertsLastBuffer =
00286 (numBuffers > 1)
00287 ? numToAdd - ((numVertsFirstBuffer - numVertsToRestart)
00288 + (numBuffers-2) * adjVertsPerBuffer)
00289 : numToAdd;
00290 }
00291
00292 void
00293 CLinearRenderer::XferBufferHeader( CVifSCDmaPacket& packet,
00294 int numVertsToBreakStrip,
00295 int numVerts,
00296 int numStripsInBuffer, unsigned short *stripOffsets )
00297 {
00298 int vu1OutQuadsPerVert = OutputQuadsPerVert;
00299
00300
00301 packet.Stcycl(4,4);
00302 packet.OpenUnpack( Vifs::UnpackModes::v4_32, 0, Packet::kDoubleBuff );
00303 {
00304
00305 packet += numVerts;
00306 packet += 0; packet += (tU64)0;
00307
00308
00309
00310
00311
00312
00313 unsigned int adcBits = 0;
00314 if ( numVertsToBreakStrip == 0 )
00315 numStripsInBuffer = 0;
00316 else if ( numVertsToBreakStrip == 2 )
00317 adcBits = 0x800;
00318
00319 float adc;
00320 unsigned int stopBit = 0x400;
00321 for ( int i = 0; i < 16; i++ ) {
00322 if ( i < numStripsInBuffer )
00323 adc = (float)(adcBits |
00324 (unsigned int)stripOffsets[i] * vu1OutQuadsPerVert );
00325 else if ( i == numStripsInBuffer )
00326 adc = (float)stopBit;
00327 else
00328 adc = (float)0;
00329 packet += adc;
00330 }
00331 }
00332 packet.CloseUnpack();
00333
00334
00335 packet.Stcycl(1, InputQuadsPerVert);
00336 }
00337
00338