18
int32 dr_dx, dg_dx, db_dx;
22
int32 dr_dy, dg_dy, db_dy;
26
static INLINE int64 MakePolyXFP(int32 x)
28
return ((int64)x << 32) + ((1LL << 32) - (1 << 11));
31
static INLINE int64 MakePolyXFPStep(int32 dx, int32 dy)
34
int64 dx_ex = (int64)dx << 32;
47
static INLINE int32 GetPolyXFP_Int(int64 xfp)
52
//#define CALCIS(x,y) ( A.x * (B.y - C.y) + B.x * (C.y - A.y) + C.x * (A.y - B.y) )
53
#define CALCIS(x,y) (((B.x - A.x) * (C.y - B.y)) - ((C.x - B.x) * (B.y - A.y)))
54
static INLINE bool CalcIDeltas(i_deltas &idl, const tri_vertex &A, const tri_vertex &B, const tri_vertex &C)
56
int64 num = ((int64)COORD_MF_INT(1)) << 32;
57
int64 denom = CALCIS(x, y);
63
//num -= abs(denom) - 1;
64
// num += abs(denom) >> 1;
66
one_div = num / denom;
68
idl.dr_dx = ((one_div * CALCIS(r, y)) + 0x00000000) >> 32;
69
idl.dr_dy = ((one_div * CALCIS(x, r)) + 0x00000000) >> 32;
71
idl.dg_dx = ((one_div * CALCIS(g, y)) + 0x00000000) >> 32;
72
idl.dg_dy = ((one_div * CALCIS(x, g)) + 0x00000000) >> 32;
74
idl.db_dx = ((one_div * CALCIS(b, y)) + 0x00000000) >> 32;
75
idl.db_dy = ((one_div * CALCIS(x, b)) + 0x00000000) >> 32;
77
idl.du_dx = ((one_div * CALCIS(u, y)) + 0x00000000) >> 32;
78
idl.du_dy = ((one_div * CALCIS(x, u)) + 0x00000000) >> 32;
80
idl.dv_dx = ((one_div * CALCIS(v, y)) + 0x00000000) >> 32;
81
idl.dv_dy = ((one_div * CALCIS(x, v)) + 0x00000000) >> 32;
83
// printf(" du_dx=%08x, du_dy=%08x\n", idl.du_dx, idl.du_dy);
89
template<bool goraud, bool textured>
90
static INLINE void AddIDeltas_DX(i_group &ig, const i_deltas &idl)
106
template<bool goraud, bool textured>
107
static INLINE void AddIDeltas_DY(i_group &ig, const i_deltas &idl, int32 count = 1)
111
ig.u += idl.du_dy * count;
112
ig.v += idl.dv_dy * count;
117
ig.r += idl.dr_dy * count;
118
ig.g += idl.dg_dy * count;
119
ig.b += idl.db_dy * count;
123
template<bool goraud, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
124
INLINE void PS_GPU::DrawSpan(int y, uint32 clut_offset, const int32 x_start, const int32 x_bound, const int32 bv_x, i_group ig, const i_deltas &idl)
126
int32 xs = x_start, xb = x_bound;
131
if(xs < xb) // (xs != xb)
136
if(xb > (ClipX1 + 1))
140
DrawTimeAvail -= (xb - xs) * ((BlendMode >= 0) ? 2 : 1);
144
ig.u += (xs - bv_x) * idl.du_dx;
145
ig.v += (xs - bv_x) * idl.dv_dx;
150
ig.r += (xs - bv_x) * idl.dr_dx;
151
ig.g += (xs - bv_x) * idl.dg_dx;
152
ig.b += (xs - bv_x) * idl.db_dx;
155
for(int32 x = xs; x < xb; x++)
161
r = RGB8SAT[COORD_GET_INT(ig.r)];
162
g = RGB8SAT[COORD_GET_INT(ig.g)];
163
b = RGB8SAT[COORD_GET_INT(ig.b)];
167
r = COORD_GET_INT(ig.r);
168
g = COORD_GET_INT(ig.g);
169
b = COORD_GET_INT(ig.b);
174
uint16 fbw = GetTexel<TexMode_TA>(clut_offset, COORD_GET_INT(ig.u), COORD_GET_INT(ig.v));
181
fbw = ModTexel(fbw, r, g, b, x & 3, y & 3);
183
fbw = ModTexel(fbw, r, g, b, 3, 2); //x & 3, y & 3);
185
PlotPixel<BlendMode, MaskEval_TA, true>(x, y, fbw);
194
pix |= DitherLUT[y & 3][x & 3][r] << 0;
195
pix |= DitherLUT[y & 3][x & 3][g] << 5;
196
pix |= DitherLUT[y & 3][x & 3][b] << 10;
200
pix |= (r >> 3) << 0;
201
pix |= (g >> 3) << 5;
202
pix |= (b >> 3) << 10;
205
PlotPixel<BlendMode, MaskEval_TA, false>(x, y, pix);
208
AddIDeltas_DX<goraud, textured>(ig, idl);
209
//AddStep<goraud, textured>(perp_coord, perp_step);
214
template<bool goraud, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
215
void PS_GPU::DrawTriangle(tri_vertex *vertices, uint32 clut)
220
vertices[0].y = COORD_MF_INT(rand());
221
vertices[1].y = COORD_MF_INT(rand());
222
vertices[2].y = COORD_MF_INT(rand());
224
vertices[0].x = COORD_MF_INT(rand());
225
vertices[1].x = COORD_MF_INT(rand());
226
vertices[2].x = COORD_MF_INT(rand());
229
if(vertices[2].y < vertices[1].y)
231
tri_vertex tmp = vertices[1];
232
vertices[1] = vertices[2];
236
if(vertices[1].y < vertices[0].y)
238
tri_vertex tmp = vertices[0];
239
vertices[0] = vertices[1];
243
if(vertices[2].y < vertices[1].y)
245
tri_vertex tmp = vertices[1];
246
vertices[1] = vertices[2];
250
if(vertices[0].y == vertices[2].y)
253
if((vertices[2].y - vertices[0].y) >= 1024)
255
PSX_WARNING("[GPU] Triangle height too large: %d", (vertices[2].y - vertices[0].y));
259
if(abs(vertices[2].x - vertices[0].x) >= 1024 ||
260
abs(vertices[2].x - vertices[1].x) >= 1024 ||
261
abs(vertices[1].x - vertices[0].x) >= 1024)
263
PSX_WARNING("[GPU] Triangle width too large: %d %d %d", abs(vertices[2].x - vertices[0].x), abs(vertices[2].x - vertices[1].x), abs(vertices[1].x - vertices[0].x));
267
if(!CalcIDeltas(idl, vertices[0], vertices[1], vertices[2]))
270
// [0] should be top vertex, [2] should be bottom vertex, [1] should be off to the side vertex.
273
int32 y_start = vertices[0].y;
274
int32 y_middle = vertices[1].y;
275
int32 y_bound = vertices[2].y;
280
int64 bound_coord_ul;
281
int64 bound_coord_us;
283
int64 bound_coord_ll;
284
int64 bound_coord_ls;
290
ig.u = COORD_MF_INT(vertices[0].u) + (1 << (COORD_FBS - 1));
291
ig.v = COORD_MF_INT(vertices[0].v) + (1 << (COORD_FBS - 1));
292
ig.r = COORD_MF_INT(vertices[0].r);
293
ig.g = COORD_MF_INT(vertices[0].g);
294
ig.b = COORD_MF_INT(vertices[0].b);
296
base_coord = MakePolyXFP(vertices[0].x); //COORD_MF_INT(vertices[0].x) + ((1 << COORD_FBS) - 1);
297
base_step = MakePolyXFPStep((vertices[2].x - vertices[0].x), (vertices[2].y - vertices[0].y)); //ROUND_HELPER(COORD_MF_INT(vertices[2].x - vertices[0].x), (vertices[2].y - vertices[0].y));
299
bound_coord_ul = MakePolyXFP(vertices[0].x); // + ((1 << COORD_FBS) - 1);
300
bound_coord_ll = MakePolyXFP(vertices[1].x); // + ((1 << COORD_FBS) - 1);
307
if(vertices[1].y == vertices[0].y)
310
right_facing = (bool)(vertices[1].x > vertices[0].x);
314
bound_coord_us = MakePolyXFPStep((vertices[1].x - vertices[0].x), (vertices[1].y - vertices[0].y));
315
right_facing = (bool)(bound_coord_us > base_step);
318
if(vertices[2].y == vertices[1].y)
321
bound_coord_ls = MakePolyXFPStep((vertices[2].x - vertices[1].x), (vertices[2].y - vertices[1].y));
325
int32 count = ClipY0 - y_start;
328
base_coord += base_step * count;
329
bound_coord_ul += bound_coord_us * count;
331
AddIDeltas_DY<goraud, textured>(ig, idl, count);
333
if(y_middle < ClipY0)
335
int32 count_ls = ClipY0 - y_middle;
338
bound_coord_ll += bound_coord_ls * count_ls;
342
if(y_bound > (ClipY1 + 1))
344
y_bound = ClipY1 + 1;
346
if(y_middle > y_bound)
352
for(int32 y = y_start; y < y_middle; y++)
354
DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(base_coord), GetPolyXFP_Int(bound_coord_ul), vertices[0].x, ig, idl);
355
base_coord += base_step;
356
bound_coord_ul += bound_coord_us;
357
AddIDeltas_DY<goraud, textured>(ig, idl);
360
for(int32 y = y_middle; y < y_bound; y++)
362
DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(base_coord), GetPolyXFP_Int(bound_coord_ll), vertices[0].x, ig, idl);
363
base_coord += base_step;
364
bound_coord_ll += bound_coord_ls;
365
AddIDeltas_DY<goraud, textured>(ig, idl);
370
for(int32 y = y_start; y < y_middle; y++)
372
DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(bound_coord_ul), GetPolyXFP_Int(base_coord), vertices[0].x, ig, idl);
373
base_coord += base_step;
374
bound_coord_ul += bound_coord_us;
375
AddIDeltas_DY<goraud, textured>(ig, idl);
378
for(int32 y = y_middle; y < y_bound; y++)
380
DrawSpan<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(y, clut, GetPolyXFP_Int(bound_coord_ll), GetPolyXFP_Int(base_coord), vertices[0].x, ig, idl);
381
base_coord += base_step;
382
bound_coord_ll += bound_coord_ls;
383
AddIDeltas_DY<goraud, textured>(ig, idl);
388
printf("[GPU] Vertices: %d:%d(r=%d, g=%d, b=%d) -> %d:%d(r=%d, g=%d, b=%d) -> %d:%d(r=%d, g=%d, b=%d)\n\n\n", vertices[0].x, vertices[0].y,
389
vertices[0].r, vertices[0].g, vertices[0].b,
390
vertices[1].x, vertices[1].y,
391
vertices[1].r, vertices[1].g, vertices[1].b,
392
vertices[2].x, vertices[2].y,
393
vertices[2].r, vertices[2].g, vertices[2].b);
398
template<int numvertices, bool goraud, bool textured, int BlendMode, bool TexMult, uint32 TexMode_TA, bool MaskEval_TA>
399
void PS_GPU::Command_DrawPolygon(const uint32 *cb)
401
tri_vertex vertices[4];
402
uint32 raw_colors[4];
407
DrawTimeAvail -= 64; // FIXME, correct time.
409
DrawTimeAvail -= 32; // FIXME, correct time.
411
memset(vertices, 0, sizeof(vertices));
413
raw_colors[0] = (*cb & 0xFFFFFF);
416
vertices[0].x = (int16)(*cb & 0xFFFF);
417
vertices[0].y = (int16)(*cb >> 16);
423
vertices[0].u = (*cb & 0xFF);
424
vertices[0].v = (*cb >> 8) & 0xFF;
425
clut = ((*cb >> 16) & 0xFFFF) << 4;
431
raw_colors[1] = (*cb & 0xFFFFFF);
435
vertices[1].x = (int16)(*cb & 0xFFFF);
436
vertices[1].y = (int16)(*cb >> 16);
441
vertices[1].u = (*cb & 0xFF);
442
vertices[1].v = (*cb >> 8) & 0xFF;
448
raw_colors[2] = (*cb & 0xFFFFFF);
452
vertices[2].x = (int16)(*cb & 0xFFFF);
453
vertices[2].y = (int16)(*cb >> 16);
458
vertices[2].u = (*cb & 0xFF);
459
vertices[2].v = (*cb >> 8) & 0xFF;
467
raw_colors[3] = (*cb & 0xFFFFFF);
471
vertices[3].x = (int16)(*cb & 0xFFFF);
472
vertices[3].y = (int16)(*cb >> 16);
477
vertices[3].u = (*cb & 0xFF);
478
vertices[3].v = (*cb >> 8) & 0xFF;
484
raw_colors[3] = raw_colors[0];
488
raw_colors[1] = raw_colors[2] = raw_colors[3] = raw_colors[0];
490
for(int i = 0; i < numvertices; i++)
492
//raw_colors[i] = rand() & 0xFFFFFF;
494
vertices[i].r = raw_colors[i] & 0xFF;
495
vertices[i].g = (raw_colors[i] >> 8) & 0xFF;
496
vertices[i].b = (raw_colors[i] >> 16) & 0xFF;
499
for(int i = 0; i < numvertices; i++)
501
vertices[i].x += OffsX;
502
vertices[i].y += OffsY;
504
// TODO: Test number of bits on real system.
505
vertices[i].x = sign_x_to_s32(12, vertices[i].x);
506
vertices[i].y = sign_x_to_s32(12, vertices[i].y);
510
printf("Draw polygon %d: ", numvertices);
512
for(int i = 0; i < numvertices; i++)
514
printf("%d:%d ", vertices[i].x, vertices[i].y);
515
//GPURAM[vertices[i].y & 511][vertices[i].x & 1023] = rand();
522
if(textured && !dtd && (raw_colors[0] == raw_colors[1]) && (raw_colors[1] == raw_colors[2]) && (raw_colors[2] == raw_colors[3]) && (raw_colors[0] == 0x808080))
525
DrawTriangle<false, textured, BlendMode, false, TexMode_TA, MaskEval_TA>(vertices, clut);
528
tri_vertex vertices_tmp[3];
530
memcpy(&vertices_tmp[0], &vertices[1], 3 * sizeof(tri_vertex));
532
DrawTriangle<false, textured, BlendMode, false, TexMode_TA, MaskEval_TA>(vertices, clut);
533
DrawTriangle<false, textured, BlendMode, false, TexMode_TA, MaskEval_TA>(vertices_tmp, clut);
539
DrawTriangle<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(vertices, clut);
542
tri_vertex vertices_tmp[3];
544
memcpy(&vertices_tmp[0], &vertices[1], 3 * sizeof(tri_vertex));
546
DrawTriangle<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(vertices, clut);
547
DrawTriangle<goraud, textured, BlendMode, TexMult, TexMode_TA, MaskEval_TA>(vertices_tmp, clut);