7#include "ps2s/cpu_matrix.h"
9#include "ps2s/packet.h"
13#include "ps2gl/base_renderer.h"
14#include "ps2gl/drawcontext.h"
15#include "ps2gl/glcontext.h"
16#include "ps2gl/immgmanager.h"
17#include "ps2gl/lighting.h"
18#include "ps2gl/material.h"
19#include "ps2gl/matrix.h"
20#include "ps2gl/metrics.h"
21#include "ps2gl/texture.h"
23#include "vu1_context.h"
25void CBaseRenderer::GetUnpackAttribs(
int numWords,
unsigned int& mode, Vifs::tMask& mask)
29 Vifs::tMask vec3Mask = { 0, 0, 0, 1,
33 mode = Vifs::UnpackModes::v3_32;
35 }
else if (numWords == 4) {
36 Vifs::tMask vec4Mask = { 0, 0, 0, 0,
40 mode = Vifs::UnpackModes::v4_32;
42 }
else if (numWords == 2) {
43 Vifs::tMask vec2Mask = { 0, 0, 1, 1,
47 mode = Vifs::UnpackModes::v2_32;
50 mError(
"shouldn't get here (you're probably calling glDrawArrays"
51 "without setting one of the pointers)");
61 int wordsPerVertex,
int wordsPerNormal,
62 int wordsPerTex,
int wordsPerColor)
66 NormalBuf = &gmanager.GetNormalBuf();
67 TexCoordBuf = &gmanager.GetTexCoordBuf();
69 CurNormal = gmanager.GetCurNormal();
70 const float* texCoord = gmanager.GetCurTexCoord();
71 CurTexCoord[0] = texCoord[0];
72 CurTexCoord[1] = texCoord[1];
76 WordsPerVertex = wordsPerVertex;
77 GetUnpackAttribs(WordsPerVertex, VertexUnpackMode, VertexUnpackMask);
79 WordsPerNormal = (wordsPerNormal > 0) ? wordsPerNormal : 3;
80 GetUnpackAttribs(WordsPerNormal, NormalUnpackMode, NormalUnpackMask);
82 WordsPerTexCoord = (wordsPerTex > 0) ? wordsPerTex : 2;
83 GetUnpackAttribs(WordsPerTexCoord, TexCoordUnpackMode, TexCoordUnpackMask);
85 WordsPerColor = (wordsPerColor > 0) ? wordsPerColor : 3;
86 GetUnpackAttribs(WordsPerColor, ColorUnpackMode, ColorUnpackMask);
95 static const float row[4] = { 0.0f, 0.0f, 1.0f, 256.0f };
115 const void* vertices,
const void* normals,
116 const void* texCoords,
const void* colors,
117 int vu1Offset,
int firstElement,
int numToAdd)
124 mErrorIf(vertices == NULL,
"Tried to render an array with no vertices!");
125 XferVectors(packet, (
unsigned int*)vertices,
126 firstElement, numToAdd,
127 WordsPerVertex, VertexUnpackMask, VertexUnpackMode,
135 int firstNormal = firstElement;
136 if (XferNormals && normals == NULL) {
141 CDmaPacket& normalBuf = *NormalBuf;
142 normals = (
void*)normalBuf.GetNextPtr();
145 for (
int i = 0; i < numToAdd; i++)
146 normalBuf += CurNormal;
150 XferVectors(packet, (
unsigned int*)normals,
151 firstNormal, numToAdd,
152 WordsPerNormal, NormalUnpackMask, NormalUnpackMode,
159 int firstTexCoord = firstElement;
160 if (XferTexCoords && texCoords == NULL) {
163 CDmaPacket& texCoordBuf = *TexCoordBuf;
164 texCoords = (
void*)texCoordBuf.GetNextPtr();
167 for (
int i = 0; i < numToAdd; i++) {
168 texCoordBuf += CurTexCoord[0];
169 texCoordBuf += CurTexCoord[1];
173 XferVectors(packet, (
unsigned int*)texCoords,
174 firstTexCoord, numToAdd,
175 WordsPerTexCoord, TexCoordUnpackMask, TexCoordUnpackMode,
182 int firstColor = firstElement;
183 if (colors != NULL && XferColors) {
184 XferVectors(packet, (
unsigned int*)colors,
185 firstColor, numToAdd,
186 WordsPerColor, ColorUnpackMask, ColorUnpackMode,
191#define kContextStart 0
193void CBaseRenderer::AddVu1RendererContext(CVifSCDmaPacket& packet, GLenum primType,
int vu1Offset)
200 packet.OpenUnpack(Vifs::UnpackModes::v4_32, vu1Offset, Packet::kSingleBuff);
206 nextDir = nextPt = nextSpot = &lightPtrs[0];
207 int numDirs, numPts, numSpots;
208 numDirs = numPts = numSpots = 0;
209 for (
int i = 0; i < 8; i++) {
210 CImmLight& light = lighting.GetImmLight(i);
211 if (light.IsEnabled()) {
212 int lightBase = kLight0Base + vu1Offset;
213 if (light.IsDirectional()) {
214 nextDir->dir = lightBase + i * kLightStructSize;
217 }
else if (light.IsPoint()) {
218 nextPt->point = lightBase + i * kLightStructSize;
221 }
else if (light.IsSpot()) {
222 nextSpot->spot = lightBase + i * kLightStructSize;
229 bool doLighting = glContext.GetImmLighting().GetLightingEnabled();
232 cpu_mat_44 objToWorldXfrmTrans = glContext.GetModelViewStack().GetTop();
234 objToWorldXfrmTrans.set_col3(cpu_vec_xyzw(0, 0, 0, 1));
235 objToWorldXfrmTrans = objToWorldXfrmTrans.transpose();
237 cpu_mat_44 normalRescale;
238 normalRescale.set_identity();
239 float normalScale = 1.0f;
241 if (drawContext.GetRescaleNormals()) {
242 cpu_vec_xyzw fake_normal(1, 0, 0, 0);
243 fake_normal = objToWorldXfrmTrans * fake_normal;
244 normalScale = 1.0f / fake_normal.length();
245 normalRescale.set_scale(cpu_vec_xyz(normalScale, normalScale, normalScale));
247 objToWorldXfrmTrans = normalRescale * objToWorldXfrmTrans;
261 float bfc_mult = (float)drawContext.GetCullFaceDir();
262 unsigned int bfc_word;
266 bool do_culling = drawContext.GetDoCullFace() && (primType > GL_LINE_STRIP);
267 packet += bfc_word | (
unsigned int)do_culling << 5;
270 packet.Add(&lightPtrs[0], 8);
272 float maxColorValue = GetMaxColorValue(glContext.GetTexManager().GetTexEnabled());
275 for (
int i = 0; i < 8; i++) {
276 CImmLight& light = lighting.GetImmLight(i);
277 packet += light.GetAmbient() * maxColorValue;
278 packet += light.GetDiffuse() * maxColorValue;
279 packet += light.GetSpecular() * maxColorValue;
281 if (light.IsDirectional())
282 packet += light.GetPosition();
284 packet += light.GetPosition();
287 packet += light.GetSpotDir();
293 packet += light.GetConstantAtten();
294 packet += light.GetLinearAtten() * 1.0f / normalScale;
295 packet += light.GetQuadAtten() * 1.0f / normalScale;
302 globalAmb = lighting.GetGlobalAmbient() * maxColorValue;
304 globalAmb = cpu_vec_4(0, 0, 0, 0);
305 packet.Add((tU32*)&globalAmb, 3);
308 float depthClipToGs = (float)((1 << drawContext.GetDepthBits()) - 1) / 2.0f;
309 packet += depthClipToGs;
313 CImmMaterial& material = glContext.GetMaterialManager().GetImmMaterial();
318 emission = material.GetEmission() * maxColorValue;
320 emission = glContext.GetMaterialManager().GetCurColor() * maxColorValue;
324 packet += material.GetAmbient();
327 cpu_vec_4 matDiffuse = material.GetDiffuse();
331 matDiffuse[3] = glContext.GetMaterialManager().GetCurColor()[3];
332 packet += matDiffuse;
335 packet += material.GetSpecular();
338 packet += drawContext.GetVertexXform();
341 cpu_vec_xyzw vertToEye(0.0f, 0.0f, 1.0f, 0.0f);
342 packet += objToWorldXfrmTrans * vertToEye;
345 packet += objToWorldXfrmTrans;
348 cpu_mat_44 worldToObjXfrm = glContext.GetModelViewStack().GetInvTop();
349 packet += worldToObjXfrm;
354 GLenum newPrimType = drawContext.GetPolygonMode();
355 if (newPrimType == GL_FILL)
356 newPrimType = primType;
358 tGifTag giftag = BuildGiftag(newPrimType);
363 float xClip = (float)2048.0f / (drawContext.GetFBWidth() * 0.5f * 2.0f);
364 packet += Math::Max(xClip, 1.0f);
365 float yClip = (float)2048.0f / (drawContext.GetFBHeight() * 0.5f * 2.0f);
366 packet += Math::Max(yClip, 1.0f);
367 float depthClip = 2048.0f / depthClipToGs;
372 packet += (drawContext.GetDoClipping()) ? 1 : 0;
374 packet.CloseUnpack();
378CBaseRenderer::BuildGiftag(GLenum primType)
384 bool smoothShading = drawContext.GetDoSmoothShading();
385 bool useTexture = glContext.GetTexManager().GetTexEnabled();
386 bool alpha = drawContext.GetBlendEnabled();
387 unsigned int nreg = OutputQuadsPerVert;
389 GS::tPrim prim = { prim_type : primType, iip : smoothShading, tme : useTexture, fge : 0, abe : alpha, aa1 : 0, fst : 0, ctxt : 0, fix : 0 };
390 tGifTag giftag = { NLOOP : 0, EOP : 1, pad0 : 0, id : 0, PRE : 1, PRIM : *(tU64*)&prim, FLG : 0, NREG : nreg, REGS0 : 2, REGS1 : 1, REGS2 : 4 };
394void CBaseRenderer::CacheRendererState()
396 XferNormals = pGLContext->GetImmLighting().GetLightingEnabled();
397 XferTexCoords = pGLContext->GetTexManager().GetTexEnabled();
398 XferColors = pGLContext->GetMaterialManager().GetColorMaterialEnabled();
403 unsigned int size64 = MicrocodePacketSize / 8;
404 CVifSCDmaPacket& packet = pGLContext->GetVif1Packet();
405 const u64* code = (
const u64*)MicrocodePacket;
406 unsigned int addr64 = 0;
408 mErrorIf((
unsigned int)code & 0xf,
"code not & 0xf");
409 mErrorIf(MicrocodePacketSize & 0xf,
"size not & 0xf");
413 unsigned int sendSize64 = (size64 > 256) ? 256 : size64;
416 packet.Ref(code, sendSize64 / 2);
418 packet.Mpg(sendSize64 & 0xff, addr64);
421 size64 -= sendSize64;
422 addr64 += sendSize64;
429 pglAddToMetric(kMetricsRendererUpload);
432void CBaseRenderer::XferVectors(CVifSCDmaPacket& packet,
unsigned int* dataStart,
433 int startOffset,
int numVectors,
int wordsPerVec,
434 Vifs::tMask unpackMask, tU32 unpackMode,
439 unsigned int* vecDataStart = dataStart + startOffset * wordsPerVec;
440 unsigned int* vecDataEnd = vecDataStart + numVectors * wordsPerVec;
442 mAssert(numVectors > 0);
443 mErrorIf((
unsigned int)vecDataStart & (4 - 1),
444 "XferVectors only works with word-aligned data");
446 int numWordsToPrepend = 0;
447 unsigned int* refXferStart = vecDataStart;
448 while ((
unsigned int)refXferStart & (16 - 1)) {
451 if (refXferStart == vecDataEnd)
454 int numWordsToAppend = 0;
455 unsigned int* refXferEnd = vecDataEnd;
456 while (((
unsigned int)refXferEnd & (16 - 1)) && refXferEnd > refXferStart) {
460 int numQuadsInRefXfer = ((
unsigned int)refXferEnd - (
unsigned int)refXferStart) / 16;
465 packet.Stmask(unpackMask);
468 if (numWordsToPrepend > 1) {
471 if (numWordsToPrepend == 2)
474 packet.OpenUnpack(unpackMode,
478 packet.CloseUnpack(numVectors);
480 if (numWordsToPrepend == 3)
481 packet += *vecDataStart;
489 packet.Ref(Core::MakePtrNormal(refXferStart), numQuadsInRefXfer);
492 if (numWordsToPrepend == 0)
494 if (numWordsToPrepend <= 1) {
495 packet.OpenUnpack(unpackMode,
499 packet.CloseUnpack(numVectors);
501 if (numWordsToPrepend == 1)
502 packet += *vecDataStart;
503 else if (numWordsToPrepend == 2)
504 packet.Add(vecDataStart, 2);
505 else if (numWordsToPrepend == 3)
506 packet.Add(&vecDataStart[1], 2);
510 if (numWordsToAppend > 0) {
513 packet.Add(refXferEnd, numWordsToAppend);
void XferBlock(CVifSCDmaPacket &packet, const void *vertices, const void *normals, const void *texCoords, const void *colors, int vu1Offset, int firstElement, int numToAdd)
virtual void Load()
Load the renderer into vu0/vu1 memory.
void InitXferBlock(CVifSCDmaPacket &packet, int wordsPerVertex, int wordsPerNormal, int wordsPerTex, int wordsPerColor)