1 /*
2 d_polyse.c
3
4 routines for drawing sets of polygons sharing the same texture
5 (used for Alias models)
6
7 Copyright (C) 1996-1997 Id Software, Inc.
8
9 This program is free software; you can redistribute it and/or
10 modify it under the terms of the GNU General Public License
11 as published by the Free Software Foundation; either version 2
12 of the License, or (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17
18 See the GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to:
22
23 Free Software Foundation, Inc.
24 59 Temple Place - Suite 330
25 Boston, MA 02111-1307, USA
26
27 */
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include "QF/render.h"
33
34 #include "d_local.h"
35 #include "r_internal.h"
36
37 int ubasestep, errorterm, erroradjustup, erroradjustdown;
38
39 // TODO: put in span spilling to shrink list size
40 // !!! if this is changed, it must be changed in d_polysa.s too !!!
41 #define DPS_MAXSPANS MAXHEIGHT+1 // +1 for spanpackage marking end
42
43 // !!! if this is changed, it must be changed in asm_draw.h too !!!
44 typedef struct spanpackage_s {
45 void *pdest;
46 short *pz;
47 int count;
48 byte *ptex;
49 int sfrac, tfrac, light, zi;
50 } spanpackage_t;
51
52 typedef struct {
53 int isflattop;
54 int numleftedges;
55 int *pleftedgevert0;
56 int *pleftedgevert1;
57 int *pleftedgevert2;
58 int numrightedges;
59 int *prightedgevert0;
60 int *prightedgevert1;
61 int *prightedgevert2;
62 } edgetable;
63
64 int r_p0[6], r_p1[6], r_p2[6];
65
66 byte *d_pcolormap;
67
68 int d_xdenom;
69
70 static edgetable *pedgetable;
71
72 static edgetable edgetables[12] = {
73 {0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2},
74 {0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL},
75 {1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
76 {0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0},
77 {0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL},
78 {0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
79 {0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1},
80 {0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL},
81 {0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
82 {1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
83 {1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
84 {0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
85 };
86
87 // FIXME: some of these can become statics
88 int a_sstepxfrac, a_tstepxfrac, a_ststepxwhole;
89 int r_sstepx, r_tstepx, r_lstepx, r_lstepy, r_sstepy, r_tstepy;
90 int r_zistepx, r_zistepy;
91 int d_aspancount, d_countextrastep;
92
93 spanpackage_t *a_spans;
94 spanpackage_t *d_pedgespanpackage;
95 static int ystart;
96 byte *d_pdest, *d_ptex;
97 short *d_pz;
98 int d_sfrac, d_tfrac, d_light, d_zi;
99 int d_ptexextrastep, d_sfracextrastep;
100 int d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
101 int d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
102 int d_sfracbasestep, d_tfracbasestep;
103 int d_ziextrastep, d_zibasestep;
104 int d_pzextrastep, d_pzbasestep;
105
106 typedef struct {
107 int quotient;
108 int remainder;
109 } adivtab_t;
110
111 static adivtab_t adivtab[32 * 32] = {
112 #include "adivtab.h"
113 };
114
115 byte *skintable[MAX_LBM_HEIGHT];
116 int skinwidth;
117 byte *skinstart;
118
119 #ifdef PIC
120 #undef USE_INTEL_ASM //XXX asm pic hack
121 #endif
122
123
124 void
D_PolysetSetEdgeTable(void)125 D_PolysetSetEdgeTable (void)
126 {
127 int edgetableindex;
128
129 // assume the vertices are already in top to bottom order
130 edgetableindex = 0;
131
132 // determine which edges are right & left, and the order in which
133 // to rasterize them
134 if (r_p0[1] >= r_p1[1]) {
135 if (r_p0[1] == r_p1[1]) {
136 if (r_p0[1] < r_p2[1])
137 pedgetable = &edgetables[2];
138 else
139 pedgetable = &edgetables[5];
140
141 return;
142 } else {
143 edgetableindex = 1;
144 }
145 }
146
147 if (r_p0[1] == r_p2[1]) {
148 if (edgetableindex)
149 pedgetable = &edgetables[8];
150 else
151 pedgetable = &edgetables[9];
152
153 return;
154 } else if (r_p1[1] == r_p2[1]) {
155 if (edgetableindex)
156 pedgetable = &edgetables[10];
157 else
158 pedgetable = &edgetables[11];
159
160 return;
161 }
162
163 if (r_p0[1] > r_p2[1])
164 edgetableindex += 2;
165
166 if (r_p1[1] > r_p2[1])
167 edgetableindex += 4;
168
169 pedgetable = &edgetables[edgetableindex];
170 }
171
172 #ifndef USE_INTEL_ASM
173
174 static void
D_PolysetRecursiveTriangle(int * lp1,int * lp2,int * lp3)175 D_PolysetRecursiveTriangle (int *lp1, int *lp2, int *lp3)
176 {
177 int *temp;
178 int d;
179 int new[6];
180 int z;
181 short *zbuf;
182
183 d = lp2[0] - lp1[0];
184 if (d < -1 || d > 1)
185 goto split;
186 d = lp2[1] - lp1[1];
187 if (d < -1 || d > 1)
188 goto split;
189
190 d = lp3[0] - lp2[0];
191 if (d < -1 || d > 1)
192 goto split2;
193 d = lp3[1] - lp2[1];
194 if (d < -1 || d > 1)
195 goto split2;
196
197 d = lp1[0] - lp3[0];
198 if (d < -1 || d > 1)
199 goto split3;
200 d = lp1[1] - lp3[1];
201 if (d < -1 || d > 1) {
202 split3:
203 temp = lp1;
204 lp1 = lp3;
205 lp3 = lp2;
206 lp2 = temp;
207
208 goto split;
209 }
210
211 return; // entire tri is filled
212
213 split2:
214 temp = lp1;
215 lp1 = lp2;
216 lp2 = lp3;
217 lp3 = temp;
218
219 split:
220 // split this edge
221 new[0] = (lp1[0] + lp2[0]) >> 1;
222 new[1] = (lp1[1] + lp2[1]) >> 1;
223 new[2] = (lp1[2] + lp2[2]) >> 1;
224 new[3] = (lp1[3] + lp2[3]) >> 1;
225 new[5] = (lp1[5] + lp2[5]) >> 1;
226
227 // draw the point if splitting a leading edge
228 if (lp2[1] > lp1[1])
229 goto nodraw;
230 if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
231 goto nodraw;
232
233
234 z = new[5] >> 16;
235 zbuf = zspantable[new[1]] + new[0];
236 if (z >= *zbuf) {
237 int pix;
238
239 *zbuf = z;
240 pix = d_pcolormap[skintable[new[3] >> 16][new[2] >> 16]];
241 d_viewbuffer[d_scantable[new[1]] + new[0]] = pix;
242 }
243
244 nodraw:
245 // recursively continue
246 D_PolysetRecursiveTriangle (lp3, lp1, new);
247 D_PolysetRecursiveTriangle (lp3, new, lp2);
248 }
249
250
251 static void
D_DrawSubdiv(void)252 D_DrawSubdiv (void)
253 {
254 mtriangle_t *ptri;
255 finalvert_t *pfv, *index0, *index1, *index2;
256 int i;
257 int lnumtriangles;
258
259 pfv = r_affinetridesc.pfinalverts;
260 ptri = r_affinetridesc.ptriangles;
261 lnumtriangles = r_affinetridesc.numtriangles;
262
263 for (i = 0; i < lnumtriangles; i++) {
264 index0 = pfv + ptri[i].vertindex[0];
265 index1 = pfv + ptri[i].vertindex[1];
266 index2 = pfv + ptri[i].vertindex[2];
267
268 if (((index0->v[1] - index1->v[1]) *
269 (index0->v[0] - index2->v[0]) -
270 (index0->v[0] - index1->v[0]) *
271 (index0->v[1] - index2->v[1])) >= 0) {
272 continue;
273 }
274
275 d_pcolormap = &((byte *) acolormap)[index0->v[4] & 0xFF00];
276
277 if (ptri[i].facesfront) {
278 D_PolysetRecursiveTriangle (index0->v, index1->v, index2->v);
279 } else {
280 int s0, s1, s2;
281
282 s0 = index0->v[2];
283 s1 = index1->v[2];
284 s2 = index2->v[2];
285
286 if (index0->flags & ALIAS_ONSEAM)
287 index0->v[2] += r_affinetridesc.seamfixupX16;
288 if (index1->flags & ALIAS_ONSEAM)
289 index1->v[2] += r_affinetridesc.seamfixupX16;
290 if (index2->flags & ALIAS_ONSEAM)
291 index2->v[2] += r_affinetridesc.seamfixupX16;
292
293 D_PolysetRecursiveTriangle (index0->v, index1->v, index2->v);
294
295 index0->v[2] = s0;
296 index1->v[2] = s1;
297 index2->v[2] = s2;
298 }
299 }
300 }
301
302
303 static void
D_DrawNonSubdiv(void)304 D_DrawNonSubdiv (void)
305 {
306 mtriangle_t *ptri;
307 finalvert_t *pfv, *index0, *index1, *index2;
308 int i;
309 int lnumtriangles;
310
311 pfv = r_affinetridesc.pfinalverts;
312 ptri = r_affinetridesc.ptriangles;
313 lnumtriangles = r_affinetridesc.numtriangles;
314
315 for (i = 0; i < lnumtriangles; i++, ptri++) {
316 index0 = pfv + ptri->vertindex[0];
317 index1 = pfv + ptri->vertindex[1];
318 index2 = pfv + ptri->vertindex[2];
319
320 d_xdenom =
321 (index0->v[1] - index1->v[1]) * (index0->v[0] - index2->v[0]) -
322 (index0->v[0] - index1->v[0]) * (index0->v[1] - index2->v[1]);
323
324 if (d_xdenom >= 0)
325 continue;
326
327 r_p0[0] = index0->v[0]; // u
328 r_p0[1] = index0->v[1]; // v
329 r_p0[2] = index0->v[2]; // s
330 r_p0[3] = index0->v[3]; // t
331 r_p0[4] = index0->v[4]; // light
332 r_p0[5] = index0->v[5]; // iz
333
334 r_p1[0] = index1->v[0];
335 r_p1[1] = index1->v[1];
336 r_p1[2] = index1->v[2];
337 r_p1[3] = index1->v[3];
338 r_p1[4] = index1->v[4];
339 r_p1[5] = index1->v[5];
340
341 r_p2[0] = index2->v[0];
342 r_p2[1] = index2->v[1];
343 r_p2[2] = index2->v[2];
344 r_p2[3] = index2->v[3];
345 r_p2[4] = index2->v[4];
346 r_p2[5] = index2->v[5];
347
348 if (!ptri->facesfront) {
349 if (index0->flags & ALIAS_ONSEAM)
350 r_p0[2] += r_affinetridesc.seamfixupX16;
351 if (index1->flags & ALIAS_ONSEAM)
352 r_p1[2] += r_affinetridesc.seamfixupX16;
353 if (index2->flags & ALIAS_ONSEAM)
354 r_p2[2] += r_affinetridesc.seamfixupX16;
355 }
356
357 D_PolysetSetEdgeTable ();
358 D_RasterizeAliasPolySmooth ();
359 }
360 }
361
362
363 void
D_PolysetDraw(void)364 D_PolysetDraw (void)
365 {
366 spanpackage_t spans[DPS_MAXSPANS + 1 +
367 ((CACHE_SIZE - 1) / sizeof (spanpackage_t)) + 1];
368
369 // one extra because of cache line pretouching
370
371 a_spans = (spanpackage_t *)
372 (((intptr_t) &spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
373
374 if (r_affinetridesc.drawtype) {
375 D_DrawSubdiv ();
376 } else {
377 D_DrawNonSubdiv ();
378 }
379 }
380
381
382 void
D_PolysetDrawFinalVerts(finalvert_t * fv,int numverts)383 D_PolysetDrawFinalVerts (finalvert_t *fv, int numverts)
384 {
385 int i, z;
386 short *zbuf;
387
388 for (i = 0; i < numverts; i++, fv++) {
389 // valid triangle coordinates for filling can include the bottom and
390 // right clip edges, due to the fill rule; these shouldn't be drawn
391 if ((fv->v[0] < r_refdef.vrectright) &&
392 (fv->v[1] < r_refdef.vrectbottom)) {
393 z = fv->v[5] >> 16;
394 zbuf = zspantable[fv->v[1]] + fv->v[0];
395 if (z >= *zbuf) {
396 int pix;
397
398 *zbuf = z;
399 pix = skintable[fv->v[3] >> 16][fv->v[2] >> 16];
400 pix = ((byte *) acolormap)[pix + (fv->v[4] & 0xFF00)];
401 d_viewbuffer[d_scantable[fv->v[1]] + fv->v[0]] = pix;
402 }
403 }
404 }
405 }
406
407 #endif // !USE_INTEL_ASM
408
409
410 void
D_PolysetUpdateTables(void)411 D_PolysetUpdateTables (void)
412 {
413 int i;
414 byte *s;
415
416 if (r_affinetridesc.skinwidth != skinwidth ||
417 r_affinetridesc.pskin != skinstart) {
418 skinwidth = r_affinetridesc.skinwidth;
419 skinstart = r_affinetridesc.pskin;
420 s = skinstart;
421 for (i = 0; i < MAX_LBM_HEIGHT; i++, s += skinwidth)
422 skintable[i] = s;
423 }
424 }
425
426
427 #ifndef USE_INTEL_ASM
428 void
D_PolysetScanLeftEdge(int height)429 D_PolysetScanLeftEdge (int height)
430 {
431
432 do {
433 d_pedgespanpackage->pdest = d_pdest;
434 d_pedgespanpackage->pz = d_pz;
435 d_pedgespanpackage->count = d_aspancount;
436 d_pedgespanpackage->ptex = d_ptex;
437
438 d_pedgespanpackage->sfrac = d_sfrac;
439 d_pedgespanpackage->tfrac = d_tfrac;
440
441 // FIXME: need to clamp l, s, t, at both ends?
442 d_pedgespanpackage->light = d_light;
443 d_pedgespanpackage->zi = d_zi;
444
445 d_pedgespanpackage++;
446
447 errorterm += erroradjustup;
448 if (errorterm >= 0) {
449 d_pdest += d_pdestextrastep;
450 d_pz += d_pzextrastep;
451 d_aspancount += d_countextrastep;
452 d_ptex += d_ptexextrastep;
453 d_sfrac += d_sfracextrastep;
454 d_ptex += d_sfrac >> 16;
455
456 d_sfrac &= 0xFFFF;
457 d_tfrac += d_tfracextrastep;
458 if (d_tfrac & 0x10000) {
459 d_ptex += r_affinetridesc.skinwidth;
460 d_tfrac &= 0xFFFF;
461 }
462 d_light += d_lightextrastep;
463 d_zi += d_ziextrastep;
464 errorterm -= erroradjustdown;
465 } else {
466 d_pdest += d_pdestbasestep;
467 d_pz += d_pzbasestep;
468 d_aspancount += ubasestep;
469 d_ptex += d_ptexbasestep;
470 d_sfrac += d_sfracbasestep;
471 d_ptex += d_sfrac >> 16;
472 d_sfrac &= 0xFFFF;
473 d_tfrac += d_tfracbasestep;
474 if (d_tfrac & 0x10000) {
475 d_ptex += r_affinetridesc.skinwidth;
476 d_tfrac &= 0xFFFF;
477 }
478 d_light += d_lightbasestep;
479 d_zi += d_zibasestep;
480 }
481 } while (--height);
482 }
483 #endif // !USE_INTEL_ASM
484
485
486 static void
D_PolysetSetUpForLineScan(fixed8_t startvertu,fixed8_t startvertv,fixed8_t endvertu,fixed8_t endvertv)487 D_PolysetSetUpForLineScan (fixed8_t startvertu, fixed8_t startvertv,
488 fixed8_t endvertu, fixed8_t endvertv)
489 {
490 double dm, dn;
491 int tm, tn;
492 adivtab_t *ptemp;
493
494 // TODO: implement x86 version
495
496 errorterm = -1;
497
498 tm = endvertu - startvertu;
499 tn = endvertv - startvertv;
500
501 if (((tm <= 16) && (tm >= -15)) && ((tn <= 16) && (tn >= -15))) {
502 ptemp = &adivtab[((tm + 15) << 5) + (tn + 15)];
503 ubasestep = ptemp->quotient;
504 erroradjustup = ptemp->remainder;
505 erroradjustdown = tn;
506 } else {
507 dm = (double) tm;
508 dn = (double) tn;
509
510 FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
511
512 erroradjustdown = dn;
513 }
514 }
515
516
517 #ifndef USE_INTEL_ASM
518 void
D_PolysetCalcGradients(int skinwidth)519 D_PolysetCalcGradients (int skinwidth)
520 {
521 float xstepdenominv, ystepdenominv, t0, t1;
522 float p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
523
524 p00_minus_p20 = r_p0[0] - r_p2[0];
525 p01_minus_p21 = r_p0[1] - r_p2[1];
526 p10_minus_p20 = r_p1[0] - r_p2[0];
527 p11_minus_p21 = r_p1[1] - r_p2[1];
528
529 xstepdenominv = 1.0 / (float) d_xdenom;
530
531 ystepdenominv = -xstepdenominv;
532
533 // ceil () for light so positive steps are exaggerated, negative steps
534 // diminished, pushing us away from underflow toward overflow. Underflow
535 // is very visible, overflow is very unlikely, because of ambient lighting
536 t0 = r_p0[4] - r_p2[4];
537 t1 = r_p1[4] - r_p2[4];
538 r_lstepx = (int)
539 ceil ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
540 r_lstepy = (int)
541 ceil ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
542
543 t0 = r_p0[2] - r_p2[2];
544 t1 = r_p1[2] - r_p2[2];
545 r_sstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
546 xstepdenominv);
547 r_sstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
548 ystepdenominv);
549
550 t0 = r_p0[3] - r_p2[3];
551 t1 = r_p1[3] - r_p2[3];
552 r_tstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
553 xstepdenominv);
554 r_tstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
555 ystepdenominv);
556
557 t0 = r_p0[5] - r_p2[5];
558 t1 = r_p1[5] - r_p2[5];
559 r_zistepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
560 xstepdenominv);
561 r_zistepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
562 ystepdenominv);
563
564 #ifdef USE_INTEL_ASM
565 a_sstepxfrac = r_sstepx << 16;
566 a_tstepxfrac = r_tstepx << 16;
567 #else
568 a_sstepxfrac = r_sstepx & 0xFFFF;
569 a_tstepxfrac = r_tstepx & 0xFFFF;
570 #endif
571
572 a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
573 }
574 #endif // !USE_INTEL_ASM
575
576 #if 0 //XXX eh?
577 byte gelmap[256];
578
579 static void
580 InitGel (byte * palette)
581 {
582 int i;
583 int r;
584
585 for (i = 0; i < 256; i++) {
586 // r = (palette[i*3]>>4);
587 r =
588 (palette[i * 3] + palette[i * 3 + 1] +
589 palette[i * 3 + 2]) / (16 * 3);
590 gelmap[i] = /* 64 */ 0 + r;
591 }
592 }
593 #endif
594
595 #ifndef USE_INTEL_ASM
596 void
D_PolysetDrawSpans8(spanpackage_t * pspanpackage)597 D_PolysetDrawSpans8 (spanpackage_t * pspanpackage)
598 {
599 int lcount;
600 byte *lpdest;
601 byte *lptex;
602 int lsfrac, ltfrac;
603 int llight;
604 int lzi;
605 short *lpz;
606
607 do {
608 lcount = d_aspancount - pspanpackage->count;
609
610 errorterm += erroradjustup;
611 if (errorterm >= 0) {
612 d_aspancount += d_countextrastep;
613 errorterm -= erroradjustdown;
614 } else {
615 d_aspancount += ubasestep;
616 }
617
618 if (lcount) {
619 lpdest = pspanpackage->pdest;
620 lptex = pspanpackage->ptex;
621 lpz = pspanpackage->pz;
622 lsfrac = pspanpackage->sfrac;
623 ltfrac = pspanpackage->tfrac;
624 llight = pspanpackage->light;
625 lzi = pspanpackage->zi;
626
627 do {
628 if ((lzi >> 16) >= *lpz) {
629 *lpdest = ((byte *) acolormap)[*lptex + (llight & 0xFF00)];
630 // gel mapping *lpdest = gelmap[*lpdest];
631 *lpz = lzi >> 16;
632 }
633 lpdest++;
634 lzi += r_zistepx;
635 lpz++;
636 llight += r_lstepx;
637 lptex += a_ststepxwhole;
638 lsfrac += a_sstepxfrac;
639 lptex += lsfrac >> 16;
640 lsfrac &= 0xFFFF;
641 ltfrac += a_tstepxfrac;
642 if (ltfrac & 0x10000) {
643 lptex += r_affinetridesc.skinwidth;
644 ltfrac &= 0xFFFF;
645 }
646 } while (--lcount);
647 }
648
649 pspanpackage++;
650 } while (pspanpackage->count != -999999);
651 }
652 #endif // !USE_INTEL_ASM
653
654
655 void
D_RasterizeAliasPolySmooth(void)656 D_RasterizeAliasPolySmooth (void)
657 {
658 int initialleftheight, initialrightheight;
659 int *plefttop, *prighttop, *pleftbottom, *prightbottom;
660 int working_lstepx, originalcount;
661
662 plefttop = pedgetable->pleftedgevert0;
663 prighttop = pedgetable->prightedgevert0;
664
665 pleftbottom = pedgetable->pleftedgevert1;
666 prightbottom = pedgetable->prightedgevert1;
667
668 initialleftheight = pleftbottom[1] - plefttop[1];
669 initialrightheight = prightbottom[1] - prighttop[1];
670
671 // set the s, t, and light gradients, which are consistent across the
672 // triangle, because being a triangle, things are affine
673 D_PolysetCalcGradients (r_affinetridesc.skinwidth);
674
675 // rasterize the polygon
676
677 // scan out the top (and possibly only) part of the left edge
678 D_PolysetSetUpForLineScan (plefttop[0], plefttop[1],
679 pleftbottom[0], pleftbottom[1]);
680
681 d_pedgespanpackage = a_spans;
682
683 ystart = plefttop[1];
684 d_aspancount = plefttop[0] - prighttop[0];
685
686 d_ptex = (byte *) r_affinetridesc.pskin + (plefttop[2] >> 16) +
687 (plefttop[3] >> 16) * r_affinetridesc.skinwidth;
688 #ifdef USE_INTEL_ASM
689 d_sfrac = (plefttop[2] & 0xFFFF) << 16;
690 d_tfrac = (plefttop[3] & 0xFFFF) << 16;
691 d_pzbasestep = (d_zwidth + ubasestep) << 1;
692 d_pzextrastep = d_pzbasestep + 2;
693 #else
694 d_sfrac = plefttop[2] & 0xFFFF;
695 d_tfrac = plefttop[3] & 0xFFFF;
696 d_pzbasestep = d_zwidth + ubasestep;
697 d_pzextrastep = d_pzbasestep + 1;
698 #endif
699 d_light = plefttop[4];
700 d_zi = plefttop[5];
701
702 d_pdestbasestep = screenwidth + ubasestep;
703 d_pdestextrastep = d_pdestbasestep + 1;
704 d_pdest = (byte *) d_viewbuffer + ystart * screenwidth + plefttop[0];
705 d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
706
707 // TODO: can reuse partial expressions here
708
709 // for negative steps in x along left edge, bias toward overflow rather
710 // than underflow (sort of turning the floor () we did in the gradient
711 // calcs into ceil (), but plus a little bit)
712 if (ubasestep < 0)
713 working_lstepx = r_lstepx - 1;
714 else
715 working_lstepx = r_lstepx;
716
717 d_countextrastep = ubasestep + 1;
718 d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
719 ((r_tstepy + r_tstepx * ubasestep) >> 16) * r_affinetridesc.skinwidth;
720 #ifdef USE_INTEL_ASM
721 d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
722 d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
723 #else
724 d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
725 d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
726 #endif
727 d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
728 d_zibasestep = r_zistepy + r_zistepx * ubasestep;
729
730 d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
731 ((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
732 r_affinetridesc.skinwidth;
733 #ifdef USE_INTEL_ASM
734 d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) << 16;
735 d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) << 16;
736 #else
737 d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF;
738 d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF;
739 #endif
740 d_lightextrastep = d_lightbasestep + working_lstepx;
741 d_ziextrastep = d_zibasestep + r_zistepx;
742
743 D_PolysetScanLeftEdge (initialleftheight);
744
745 // scan out the bottom part of the left edge, if it exists
746 if (pedgetable->numleftedges == 2) {
747 int height;
748
749 plefttop = pleftbottom;
750 pleftbottom = pedgetable->pleftedgevert2;
751
752 D_PolysetSetUpForLineScan (plefttop[0], plefttop[1],
753 pleftbottom[0], pleftbottom[1]);
754
755 height = pleftbottom[1] - plefttop[1];
756
757 // TODO: make this a function; modularize this function in general
758
759 ystart = plefttop[1];
760 d_aspancount = plefttop[0] - prighttop[0];
761 d_ptex = (byte *) r_affinetridesc.pskin + (plefttop[2] >> 16) +
762 (plefttop[3] >> 16) * r_affinetridesc.skinwidth;
763 d_sfrac = 0;
764 d_tfrac = 0;
765 d_light = plefttop[4];
766 d_zi = plefttop[5];
767
768 d_pdestbasestep = screenwidth + ubasestep;
769 d_pdestextrastep = d_pdestbasestep + 1;
770 d_pdest = (byte *) d_viewbuffer + ystart * screenwidth + plefttop[0];
771 #ifdef USE_INTEL_ASM
772 d_pzbasestep = (d_zwidth + ubasestep) << 1;
773 d_pzextrastep = d_pzbasestep + 2;
774 #else
775 d_pzbasestep = d_zwidth + ubasestep;
776 d_pzextrastep = d_pzbasestep + 1;
777 #endif
778 d_pz = d_pzbuffer + ystart * d_zwidth + plefttop[0];
779
780 if (ubasestep < 0)
781 working_lstepx = r_lstepx - 1;
782 else
783 working_lstepx = r_lstepx;
784
785 d_countextrastep = ubasestep + 1;
786 d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
787 ((r_tstepy + r_tstepx * ubasestep) >> 16) *
788 r_affinetridesc.skinwidth;
789 #ifdef USE_INTEL_ASM
790 d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) << 16;
791 d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) << 16;
792 #else
793 d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
794 d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
795 #endif
796 d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
797 d_zibasestep = r_zistepy + r_zistepx * ubasestep;
798
799 d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
800 ((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
801 r_affinetridesc.skinwidth;
802 #ifdef USE_INTEL_ASM
803 d_sfracextrastep =
804 ((r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF) << 16;
805 d_tfracextrastep =
806 ((r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF) << 16;
807 #else
808 d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF;
809 d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF;
810 #endif
811 d_lightextrastep = d_lightbasestep + working_lstepx;
812 d_ziextrastep = d_zibasestep + r_zistepx;
813
814 D_PolysetScanLeftEdge (height);
815 }
816 // scan out the top (and possibly only) part of the right edge, updating
817 // the count field
818 d_pedgespanpackage = a_spans;
819
820 D_PolysetSetUpForLineScan (prighttop[0], prighttop[1],
821 prightbottom[0], prightbottom[1]);
822 d_aspancount = 0;
823 d_countextrastep = ubasestep + 1;
824 originalcount = a_spans[initialrightheight].count;
825 a_spans[initialrightheight].count = -999999; // mark end of the
826 // spanpackages
827 D_PolysetDrawSpans8 (a_spans);
828
829 // scan out the bottom part of the right edge, if it exists
830 if (pedgetable->numrightedges == 2) {
831 int height;
832 spanpackage_t *pstart;
833
834 pstart = a_spans + initialrightheight;
835 pstart->count = originalcount;
836
837 d_aspancount = prightbottom[0] - prighttop[0];
838
839 prighttop = prightbottom;
840 prightbottom = pedgetable->prightedgevert2;
841
842 height = prightbottom[1] - prighttop[1];
843
844 D_PolysetSetUpForLineScan (prighttop[0], prighttop[1],
845 prightbottom[0], prightbottom[1]);
846
847 d_countextrastep = ubasestep + 1;
848 a_spans[initialrightheight + height].count = -999999;
849 // mark end of the spanpackages
850 D_PolysetDrawSpans8 (pstart);
851 }
852 }
853
854
855 #if 0
856
857 void
858 D_PolysetRecursiveDrawLine (int *lp1, int *lp2)
859 {
860 int d;
861 int new[6];
862 int ofs;
863
864 d = lp2[0] - lp1[0];
865 if (d < -1 || d > 1)
866 goto split;
867 d = lp2[1] - lp1[1];
868 if (d < -1 || d > 1)
869 goto split;
870
871 return; // line is completed
872
873 split:
874 // split this edge
875 new[0] = (lp1[0] + lp2[0]) >> 1;
876 new[1] = (lp1[1] + lp2[1]) >> 1;
877 new[5] = (lp1[5] + lp2[5]) >> 1;
878 new[2] = (lp1[2] + lp2[2]) >> 1;
879 new[3] = (lp1[3] + lp2[3]) >> 1;
880 new[4] = (lp1[4] + lp2[4]) >> 1;
881
882 // draw the point
883 ofs = d_scantable[new[1]] + new[0];
884 if (new[5] > d_pzbuffer[ofs]) {
885 int pix;
886
887 d_pzbuffer[ofs] = new[5];
888 pix = skintable[new[3] >> 16][new[2] >> 16];
889 // pix = ((byte *)acolormap)[pix + (new[4] & 0xFF00)];
890 d_viewbuffer[ofs] = pix;
891 }
892 // recursively continue
893 D_PolysetRecursiveDrawLine (lp1, new);
894 D_PolysetRecursiveDrawLine (new, lp2);
895 }
896
897
898 void
899 D_PolysetRecursiveTriangle2 (int *lp1, int *lp2, int *lp3)
900 {
901 int d;
902 int new[4];
903
904 d = lp2[0] - lp1[0];
905 if (d < -1 || d > 1)
906 goto split;
907 d = lp2[1] - lp1[1];
908 if (d < -1 || d > 1)
909 goto split;
910 return;
911
912 split:
913 // split this edge
914 new[0] = (lp1[0] + lp2[0]) >> 1;
915 new[1] = (lp1[1] + lp2[1]) >> 1;
916 new[5] = (lp1[5] + lp2[5]) >> 1;
917 new[2] = (lp1[2] + lp2[2]) >> 1;
918 new[3] = (lp1[3] + lp2[3]) >> 1;
919 new[4] = (lp1[4] + lp2[4]) >> 1;
920
921 D_PolysetRecursiveDrawLine (new, lp3);
922
923 // recursively continue
924 D_PolysetRecursiveTriangle (lp1, new, lp3);
925 D_PolysetRecursiveTriangle (new, lp2, lp3);
926 }
927
928 #endif
929