7#include "ps2s/cpu_matrix.h" 
    9#include "ps2s/packet.h" 
   11#include "ps2gl/drawcontext.h" 
   12#include "ps2gl/glcontext.h" 
   13#include "ps2gl/immgmanager.h" 
   14#include "ps2gl/lighting.h" 
   15#include "ps2gl/linear_renderer.h" 
   16#include "ps2gl/material.h" 
   17#include "ps2gl/matrix.h" 
   18#include "ps2gl/metrics.h" 
   19#include "ps2gl/texture.h" 
   21#include "vu1_mem_linear.h" 
   25    int wordsPerVert   = block.GetWordsPerVertex();
 
   26    int wordsPerNormal = (block.GetNormalsAreValid()) ? block.GetWordsPerNormal() : 0;
 
   27    int wordsPerTex    = (block.GetTexCoordsAreValid()) ? block.GetWordsPerTexCoord() : 0;
 
   28    int wordsPerColor  = (block.GetColorsAreValid()) ? block.GetWordsPerColor() : 0;
 
   30    CVifSCDmaPacket& packet = pGLContext->GetVif1Packet();
 
   31    InitXferBlock(packet, wordsPerVert, wordsPerNormal, wordsPerTex, wordsPerColor);
 
   36    int maxUnpackVerts = 256;
 
   38    int vu1QuadsPerVert      = InputQuadsPerVert;
 
   39    int inputBufSize         = InputGeomBufSize;
 
   40    int maxVu1VertsPerBuffer = inputBufSize / vu1QuadsPerVert;
 
   42    int maxVertsPerBuffer = Math::Min(maxUnpackVerts, maxVu1VertsPerBuffer);
 
   43    maxVertsPerBuffer -= 3;
 
   45    maxVertsPerBuffer -= maxVertsPerBuffer % block.GetNumVertsPerPrim();
 
   49    DrawBlock(packet, block, maxVertsPerBuffer);
 
 
   55    CVifSCDmaPacket& packet = glContext.GetVif1Packet();
 
   59        AddVu1RendererContext(packet, primType, kContextStart);
 
   64        packet.Base(kDoubleBufBase);
 
   65        packet.Offset(kDoubleBufOffset);
 
 
   75    return Math::Max(geometry.GetTotalVertices() / 70, 1) * 1000;
 
 
   85    deps.PerVtxMaterial = 1;
 
 
   92    return !(pGLContext->GetImmLighting().GetLightingEnabled()
 
   93        && !geometry.GetNormalsAreValid());
 
 
   96void CLinearRenderer::DrawBlock(CVifSCDmaPacket& packet,
 
   99    mErrorIf(block.GetWordsPerVertex() == 2, 
"2 word vertices not supported");
 
  106        packet.Stcycl(1, InputQuadsPerVert);
 
  118    bool stripsCanBeMerged = block.GetStripsCanBeMerged();
 
  120    int numVertsXferred   = 0;
 
  121    int numStripsInBuffer = 0;
 
  122    unsigned short stripOffsets[16];
 
  123    bool haveContinued = 
false;
 
  124    const void *normals, *vertices, *texCoords, *colors;
 
  125    normals = vertices = texCoords = colors = NULL;
 
  126    int vu1BufferOffset = 0, stripIndex = 0, vertsInBlock = 0;
 
  129    int adjMaxVertsPerBuffer = maxVertsPerBuffer - (Math::IsOdd(maxVertsPerBuffer - numVertsToRestart));
 
  130    for (
int curStrip = 0; curStrip < block.GetNumStrips(); curStrip++) {
 
  133        int numVertsFirstBuffer, numVertsLastBuffer, numBuffers;
 
  134        FindNumBuffers(block.GetStripLength(curStrip),
 
  135            numVertsToRestart, numVertsXferred, maxVertsPerBuffer,
 
  136            numVertsFirstBuffer, numVertsLastBuffer, numBuffers);
 
  142        int numVertsThisBuffer;
 
  143        int indexIntoStrip  = 0;
 
  144        int vu1QuadsPerVert = InputQuadsPerVert;
 
  145        for (
int curBuffer = 0;
 
  146             curBuffer < numBuffers;
 
  147             curBuffer++, indexIntoStrip += numVertsThisBuffer - numVertsToRestart) {
 
  151                numVertsThisBuffer = numVertsFirstBuffer;
 
  152            else if (curBuffer == numBuffers - 1)
 
  153                numVertsThisBuffer = numVertsLastBuffer;
 
  155                numVertsThisBuffer = adjMaxVertsPerBuffer;
 
  159            if (!haveContinued) {
 
  160                vertices        = (block.GetVerticesAreValid()) ? block.GetVertices(curStrip) : NULL;
 
  161                normals         = (block.GetNormalsAreValid()) ? block.GetNormals(curStrip) : NULL;
 
  162                texCoords       = (block.GetTexCoordsAreValid()) ? block.GetTexCoords(curStrip) : NULL;
 
  163                colors          = (block.GetColorsAreValid()) ? block.GetColors(curStrip) : NULL;
 
  164                vu1BufferOffset = InputGeomOffset + numVertsXferred * vu1QuadsPerVert;
 
  165                stripIndex      = indexIntoStrip;
 
  175            if (!block.StripIsContinued(curStrip)
 
  176                || curBuffer < numBuffers - 1) {
 
  178                    vertices, normals, texCoords, colors,
 
  180                    stripIndex, vertsInBlock + numVertsThisBuffer);
 
  181                haveContinued = 
false;
 
  183                vertsInBlock += numVertsThisBuffer;
 
  184                haveContinued = 
true;
 
  187            stripOffsets[numStripsInBuffer++] = numVertsXferred;
 
  188            mErrorIf(numStripsInBuffer > 16, 
"Too many strips in buffer.. this shouldn't happen");
 
  189            numVertsXferred += numVertsThisBuffer;
 
  192            if (curBuffer < numBuffers - 1) {
 
  193                FinishBuffer(packet, numVertsToRestart, numVertsXferred, vu1QuadsPerVert,
 
  194                    numStripsInBuffer, stripOffsets);
 
  195                numStripsInBuffer = 0;
 
  210        if (!stripsCanBeMerged
 
  211            || ((maxVertsPerBuffer - numVertsXferred) <= numVertsToRestart + 1)
 
  212            || numStripsInBuffer == 16
 
  213            || (curStrip == block.GetNumStrips() - 1)) {
 
  216                    vertices, normals, texCoords, colors,
 
  218                    stripIndex, vertsInBlock);
 
  219                haveContinued = 
false;
 
  222            FinishBuffer(packet, numVertsToRestart, numVertsXferred, vu1QuadsPerVert,
 
  223                numStripsInBuffer, stripOffsets);
 
  224            numStripsInBuffer = 0;
 
  231void CLinearRenderer::FinishBuffer(CVifSCDmaPacket& packet, 
int numVertsToBreakStrip,
 
  232    int numVertsInBuffer, 
int vu1QuadsPerVert,
 
  233    int numStripsInBuffer, 
unsigned short* stripOffsets)
 
  239        XferBufferHeader(packet, numVertsToBreakStrip,
 
  241            numStripsInBuffer, stripOffsets);
 
  249void CLinearRenderer::FindNumBuffers(
int numToAdd, 
int numVertsToRestart,
 
  250    int numVertsAlreadyInFirstBuffer, 
int maxVertsPerBuffer,
 
  251    int& numVertsFirstBuffer, 
int& numVertsLastBuffer,
 
  258    int freeVertsFirstBuffer = maxVertsPerBuffer - numVertsAlreadyInFirstBuffer;
 
  259    if (numToAdd <= freeVertsFirstBuffer) {
 
  260        numVertsFirstBuffer = numToAdd;
 
  266        numVertsFirstBuffer = freeVertsFirstBuffer - (int)Math::IsOdd(freeVertsFirstBuffer);
 
  267        numLeftToAdd        = numToAdd - (numVertsFirstBuffer - numVertsToRestart);
 
  270    int adjVertsPerBuffer = maxVertsPerBuffer - numVertsToRestart;
 
  271    adjVertsPerBuffer -= (int)Math::IsOdd(adjVertsPerBuffer);
 
  272    numBuffers = 1 + numLeftToAdd / adjVertsPerBuffer; 
 
  273    if (numLeftToAdd % adjVertsPerBuffer > numVertsToRestart)
 
  276    numVertsLastBuffer = (numBuffers > 1)
 
  277        ? numToAdd - ((numVertsFirstBuffer - numVertsToRestart)
 
  278                         + (numBuffers - 2) * adjVertsPerBuffer)
 
  282void CLinearRenderer::XferBufferHeader(CVifSCDmaPacket& packet,
 
  283    int numVertsToBreakStrip,
 
  285    int numStripsInBuffer, 
unsigned short* stripOffsets)
 
  287    int vu1OutQuadsPerVert = OutputQuadsPerVert;
 
  291    packet.OpenUnpack(Vifs::UnpackModes::v4_32, 0, Packet::kDoubleBuff);
 
  296        packet += (uint64_t)0;
 
  303        unsigned int adcBits = 0;
 
  304        if (numVertsToBreakStrip == 0)
 
  305            numStripsInBuffer = 0;
 
  306        else if (numVertsToBreakStrip == 2)
 
  310        unsigned int stopBit = 0x400;
 
  311        for (
int i = 0; i < 16; i++) {
 
  312            if (i < numStripsInBuffer)
 
  313                adc = (float)(adcBits | (
unsigned int)stripOffsets[i] * vu1OutQuadsPerVert);
 
  314            else if (i == numStripsInBuffer)
 
  315                adc = (float)stopBit;
 
  321    packet.CloseUnpack();
 
  324    packet.Stcycl(1, InputQuadsPerVert);
 
void XferBlock(CVifSCDmaPacket &packet, const void *vertices, const void *normals, const void *texCoords, const void *colors, int vu1Offset, int firstElement, int numToAdd)
void InitXferBlock(CVifSCDmaPacket &packet, int wordsPerVertex, int wordsPerNormal, int wordsPerTex, int wordsPerColor)
int GetNumVertsToRestartStrip()
virtual void InitContext(GLenum primType, uint32_t rcChanges, bool userRcChanged)
virtual int GetPacketQwordSize(const CGeometryBlock &geometry)
virtual CRendererProps GetRenderContextDeps()
virtual bool GetCachePackets(const CGeometryBlock &geometry)
virtual void DrawLinearArrays(CGeometryBlock &block)
Draw arrays of vertices that are accessed linearly (i.e., glDrawArrays)