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 #define NH_DEFINE
33 #include "namehack.h"
34 
35 #include "QF/sys.h"
36 
37 #include "d_local.h"
38 #include "r_internal.h"
39 
40 static int  ubasestep, errorterm, erroradjustup, erroradjustdown;
41 
42 // TODO: put in span spilling to shrink list size
43 // !!! if this is changed, it must be changed in d_polysa.s too !!!
44 #define DPS_MAXSPANS		MAXHEIGHT+1		// +1 for spanpackage marking end
45 
46 // !!! if this is changed, it must be changed in asm_draw.h too !!!
47 typedef struct {
48 	int         pdest;
49 	short      *pz;
50 	int         count;
51 	byte       *ptex;
52 	int         sfrac, tfrac, light, zi;
53 } spanpackage_t;
54 
55 typedef struct {
56 	int         isflattop;
57 	int         numleftedges;
58 	int        *pleftedgevert0;
59 	int        *pleftedgevert1;
60 	int        *pleftedgevert2;
61 	int         numrightedges;
62 	int        *prightedgevert0;
63 	int        *prightedgevert1;
64 	int        *prightedgevert2;
65 } edgetable;
66 
67 static int         r_p0[6], r_p1[6], r_p2[6];
68 
69 static int         d_xdenom;
70 
71 static edgetable  *pedgetable;
72 
73 static edgetable   edgetables[12] = {
74 	{0, 1, r_p0, r_p2, NULL, 2, r_p0, r_p1, r_p2},
75 	{0, 2, r_p1, r_p0, r_p2, 1, r_p1, r_p2, NULL},
76 	{1, 1, r_p0, r_p2, NULL, 1, r_p1, r_p2, NULL},
77 	{0, 1, r_p1, r_p0, NULL, 2, r_p1, r_p2, r_p0},
78 	{0, 2, r_p0, r_p2, r_p1, 1, r_p0, r_p1, NULL},
79 	{0, 1, r_p2, r_p1, NULL, 1, r_p2, r_p0, NULL},
80 	{0, 1, r_p2, r_p1, NULL, 2, r_p2, r_p0, r_p1},
81 	{0, 2, r_p2, r_p1, r_p0, 1, r_p2, r_p0, NULL},
82 	{0, 1, r_p1, r_p0, NULL, 1, r_p1, r_p2, NULL},
83 	{1, 1, r_p2, r_p1, NULL, 1, r_p0, r_p1, NULL},
84 	{1, 1, r_p1, r_p0, NULL, 1, r_p2, r_p0, NULL},
85 	{0, 1, r_p0, r_p2, NULL, 1, r_p0, r_p1, NULL},
86 };
87 
88 static int         r_sstepx, r_tstepx, r_lstepx, r_lstepy, r_sstepy, r_tstepy;
89 static int         r_zistepx, r_zistepy;
90 static int         d_aspancount, d_countextrastep;
91 
92 static spanpackage_t *a_spans;
93 static spanpackage_t *d_pedgespanpackage;
94 static int  ystart;
95 static int  d_pdest;
96 static byte       *d_ptex;
97 static short      *d_pz;
98 static int         d_sfrac, d_tfrac, d_light, d_zi;
99 static int         d_ptexextrastep, d_sfracextrastep;
100 static int         d_tfracextrastep, d_lightextrastep, d_pdestextrastep;
101 static int         d_lightbasestep, d_pdestbasestep, d_ptexbasestep;
102 static int         d_sfracbasestep, d_tfracbasestep;
103 static int         d_ziextrastep, d_zibasestep;
104 static 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 
116 void
sw32_D_PolysetSetEdgeTable(void)117 sw32_D_PolysetSetEdgeTable (void)
118 {
119 	int         edgetableindex;
120 
121 	// assume the vertices are already in top to bottom order
122 	edgetableindex = 0;
123 
124 	// determine which edges are right & left, and the order in which
125 	// to rasterize them
126 	if (r_p0[1] >= r_p1[1]) {
127 		if (r_p0[1] == r_p1[1]) {
128 			if (r_p0[1] < r_p2[1])
129 				pedgetable = &edgetables[2];
130 			else
131 				pedgetable = &edgetables[5];
132 
133 			return;
134 		} else {
135 			edgetableindex = 1;
136 		}
137 	}
138 
139 	if (r_p0[1] == r_p2[1]) {
140 		if (edgetableindex)
141 			pedgetable = &edgetables[8];
142 		else
143 			pedgetable = &edgetables[9];
144 
145 		return;
146 	} else if (r_p1[1] == r_p2[1]) {
147 		if (edgetableindex)
148 			pedgetable = &edgetables[10];
149 		else
150 			pedgetable = &edgetables[11];
151 
152 		return;
153 	}
154 
155 	if (r_p0[1] > r_p2[1])
156 		edgetableindex += 2;
157 
158 	if (r_p1[1] > r_p2[1])
159 		edgetableindex += 4;
160 
161 	pedgetable = &edgetables[edgetableindex];
162 }
163 
164 static void
D_DrawNonSubdiv(void)165 D_DrawNonSubdiv (void)
166 {
167 	mtriangle_t *ptri;
168 	finalvert_t *pfv, *index0, *index1, *index2;
169 	int         i;
170 	int         lnumtriangles;
171 
172 	pfv = sw32_r_affinetridesc.pfinalverts;
173 	ptri = sw32_r_affinetridesc.ptriangles;
174 	lnumtriangles = sw32_r_affinetridesc.numtriangles;
175 
176 	for (i = 0; i < lnumtriangles; i++, ptri++) {
177 		index0 = pfv + ptri->vertindex[0];
178 		index1 = pfv + ptri->vertindex[1];
179 		index2 = pfv + ptri->vertindex[2];
180 
181 		d_xdenom =
182 			(index0->v[1] - index1->v[1]) * (index0->v[0] - index2->v[0]) -
183 			(index0->v[0] - index1->v[0]) * (index0->v[1] - index2->v[1]);
184 
185 		if (d_xdenom >= 0)
186 			continue;
187 
188 		r_p0[0] = index0->v[0];			// u
189 		r_p0[1] = index0->v[1];			// v
190 		r_p0[2] = index0->v[2];			// s
191 		r_p0[3] = index0->v[3];			// t
192 		r_p0[4] = index0->v[4];			// light
193 		r_p0[5] = index0->v[5];			// iz
194 
195 		r_p1[0] = index1->v[0];
196 		r_p1[1] = index1->v[1];
197 		r_p1[2] = index1->v[2];
198 		r_p1[3] = index1->v[3];
199 		r_p1[4] = index1->v[4];
200 		r_p1[5] = index1->v[5];
201 
202 		r_p2[0] = index2->v[0];
203 		r_p2[1] = index2->v[1];
204 		r_p2[2] = index2->v[2];
205 		r_p2[3] = index2->v[3];
206 		r_p2[4] = index2->v[4];
207 		r_p2[5] = index2->v[5];
208 
209 		if (!ptri->facesfront) {
210 			if (index0->flags & ALIAS_ONSEAM)
211 				r_p0[2] += sw32_r_affinetridesc.seamfixupX16;
212 			if (index1->flags & ALIAS_ONSEAM)
213 				r_p1[2] += sw32_r_affinetridesc.seamfixupX16;
214 			if (index2->flags & ALIAS_ONSEAM)
215 				r_p2[2] += sw32_r_affinetridesc.seamfixupX16;
216 		}
217 
218 		sw32_D_PolysetSetEdgeTable ();
219 		sw32_D_RasterizeAliasPolySmooth ();
220 	}
221 }
222 
223 void
sw32_D_PolysetDraw(void)224 sw32_D_PolysetDraw (void)
225 {
226 	spanpackage_t spans[DPS_MAXSPANS + 1 +
227 						((CACHE_SIZE - 1) / sizeof (spanpackage_t)) + 1];
228 
229 	// one extra because of cache line pretouching
230 
231 	a_spans = (spanpackage_t *)
232 		(((intptr_t) &spans[0] + CACHE_SIZE - 1) & ~(CACHE_SIZE - 1));
233 
234 	D_DrawNonSubdiv ();
235 }
236 
237 void
sw32_D_PolysetScanLeftEdge(int height)238 sw32_D_PolysetScanLeftEdge (int height)
239 {
240 
241 	do {
242 		d_pedgespanpackage->pdest = d_pdest;
243 		d_pedgespanpackage->pz = d_pz;
244 		d_pedgespanpackage->count = d_aspancount;
245 		d_pedgespanpackage->ptex = d_ptex;
246 
247 		d_pedgespanpackage->sfrac = d_sfrac;
248 		d_pedgespanpackage->tfrac = d_tfrac;
249 
250 		// FIXME: need to clamp l, s, t, at both ends?
251 		d_pedgespanpackage->light = d_light;
252 		d_pedgespanpackage->zi = d_zi;
253 
254 		d_pedgespanpackage++;
255 
256 		errorterm += erroradjustup;
257 		if (errorterm >= 0) {
258 			d_pdest += d_pdestextrastep;
259 			d_pz += d_pzextrastep;
260 			d_aspancount += d_countextrastep;
261 			d_ptex += d_ptexextrastep;
262 			d_sfrac += d_sfracextrastep;
263 			d_ptex += d_sfrac >> 16;
264 
265 			d_sfrac &= 0xFFFF;
266 			d_tfrac += d_tfracextrastep;
267 			if (d_tfrac & 0x10000) {
268 				d_ptex += sw32_r_affinetridesc.skinwidth;
269 				d_tfrac &= 0xFFFF;
270 			}
271 			d_light += d_lightextrastep;
272 			d_zi += d_ziextrastep;
273 			errorterm -= erroradjustdown;
274 		} else {
275 			d_pdest += d_pdestbasestep;
276 			d_pz += d_pzbasestep;
277 			d_aspancount += ubasestep;
278 			d_ptex += d_ptexbasestep;
279 			d_sfrac += d_sfracbasestep;
280 			d_ptex += d_sfrac >> 16;
281 			d_sfrac &= 0xFFFF;
282 			d_tfrac += d_tfracbasestep;
283 			if (d_tfrac & 0x10000) {
284 				d_ptex += sw32_r_affinetridesc.skinwidth;
285 				d_tfrac &= 0xFFFF;
286 			}
287 			d_light += d_lightbasestep;
288 			d_zi += d_zibasestep;
289 		}
290 	} while (--height);
291 }
292 
293 static void
D_PolysetSetUpForLineScan(fixed8_t startvertu,fixed8_t startvertv,fixed8_t endvertu,fixed8_t endvertv)294 D_PolysetSetUpForLineScan (fixed8_t startvertu, fixed8_t startvertv,
295 						   fixed8_t endvertu, fixed8_t endvertv)
296 {
297 	double      dm, dn;
298 	int         tm, tn;
299 	adivtab_t  *ptemp;
300 
301 	// TODO: implement x86 version
302 
303 	errorterm = -1;
304 
305 	tm = endvertu - startvertu;
306 	tn = endvertv - startvertv;
307 
308 	if (((tm <= 16) && (tm >= -15)) && ((tn <= 16) && (tn >= -15))) {
309 		ptemp = &adivtab[((tm + 15) << 5) + (tn + 15)];
310 		ubasestep = ptemp->quotient;
311 		erroradjustup = ptemp->remainder;
312 		erroradjustdown = tn;
313 	} else {
314 		dm = (double) tm;
315 		dn = (double) tn;
316 
317 		FloorDivMod (dm, dn, &ubasestep, &erroradjustup);
318 
319 		erroradjustdown = dn;
320 	}
321 }
322 
323 void
sw32_D_PolysetCalcGradients(int skinwidth)324 sw32_D_PolysetCalcGradients (int skinwidth)
325 {
326 	float       xstepdenominv, ystepdenominv, t0, t1;
327 	float       p01_minus_p21, p11_minus_p21, p00_minus_p20, p10_minus_p20;
328 
329 	p00_minus_p20 = r_p0[0] - r_p2[0];
330 	p01_minus_p21 = r_p0[1] - r_p2[1];
331 	p10_minus_p20 = r_p1[0] - r_p2[0];
332 	p11_minus_p21 = r_p1[1] - r_p2[1];
333 
334 	xstepdenominv = 1.0 / (float) d_xdenom;
335 
336 	ystepdenominv = -xstepdenominv;
337 
338 	// ceil () for light so positive steps are exaggerated, negative steps
339 	// diminished,  pushing us away from underflow toward overflow. Underflow
340 	// is very visible, overflow is very unlikely, because of ambient lighting
341 	t0 = r_p0[4] - r_p2[4];
342 	t1 = r_p1[4] - r_p2[4];
343 	r_lstepx = (int)
344 		ceil ((t1 * p01_minus_p21 - t0 * p11_minus_p21) * xstepdenominv);
345 	r_lstepy = (int)
346 		ceil ((t1 * p00_minus_p20 - t0 * p10_minus_p20) * ystepdenominv);
347 
348 	t0 = r_p0[2] - r_p2[2];
349 	t1 = r_p1[2] - r_p2[2];
350 	r_sstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
351 					  xstepdenominv);
352 	r_sstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
353 					  ystepdenominv);
354 
355 	t0 = r_p0[3] - r_p2[3];
356 	t1 = r_p1[3] - r_p2[3];
357 	r_tstepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
358 					  xstepdenominv);
359 	r_tstepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
360 					  ystepdenominv);
361 
362 	t0 = r_p0[5] - r_p2[5];
363 	t1 = r_p1[5] - r_p2[5];
364 	r_zistepx = (int) ((t1 * p01_minus_p21 - t0 * p11_minus_p21) *
365 					   xstepdenominv);
366 	r_zistepy = (int) ((t1 * p00_minus_p20 - t0 * p10_minus_p20) *
367 					   ystepdenominv);
368 
369 //	a_sstepxfrac = r_sstepx & 0xFFFF;
370 //	a_tstepxfrac = r_tstepx & 0xFFFF;
371 
372 //	a_ststepxwhole = skinwidth * (r_tstepx >> 16) + (r_sstepx >> 16);
373 }
374 
375 
376 static void
D_PolysetDrawSpans(spanpackage_t * pspanpackage)377 D_PolysetDrawSpans (spanpackage_t * pspanpackage)
378 {
379 	int i, j, texscantable[2*MAX_LBM_HEIGHT], *texscan;
380 	// LordHavoc: compute skin row table
381 	for (i = 0, j = -sw32_r_affinetridesc.skinheight * sw32_r_affinetridesc.skinwidth;
382 		 i < sw32_r_affinetridesc.skinheight*2;i++, j += sw32_r_affinetridesc.skinwidth)
383 		texscantable[i] = j;
384 	texscan = texscantable + sw32_r_affinetridesc.skinheight;
385 
386 	switch(sw32_r_pixbytes) {
387 	case 1:
388 	{
389 		int         lcount, count = 0;
390 		byte       *lpdest;
391 		byte       *lptex;
392 		int         lsfrac, ltfrac;
393 		int         llight;
394 		int         lzi;
395 		short      *lpz;
396 
397 		do
398 		{
399 			lcount = d_aspancount - pspanpackage->count;
400 
401 			errorterm += erroradjustup;
402 			if (errorterm >= 0)
403 			{
404 				d_aspancount += d_countextrastep;
405 				errorterm -= erroradjustdown;
406 			}
407 			else
408 				d_aspancount += ubasestep;
409 
410 			if (lcount)
411 			{
412 				lpdest = (byte *) sw32_d_viewbuffer + pspanpackage->pdest;
413 				lptex = pspanpackage->ptex;
414 				lpz = pspanpackage->pz;
415 				lsfrac = pspanpackage->sfrac;
416 				ltfrac = pspanpackage->tfrac;
417 				llight = pspanpackage->light;
418 				lzi = pspanpackage->zi;
419 
420 				// LordHavoc: optimized zbuffer check (switchs between
421 				// loops when state changes, and quickly skips groups
422 				// of hidden pixels)
423 				do
424 				{
425 					if ((lzi >> 16) < *lpz) // hidden
426 					{
427 						count = 0;
428 						goto skiploop8;
429 					}
430 drawloop8:
431 					*lpz++ = lzi >> 16;
432 					*lpdest++ = ((byte *)sw32_acolormap)
433 						[(llight & 0xFF00) | lptex[texscan[ltfrac >> 16] +
434 												   (lsfrac >> 16)]];
435 					lzi += r_zistepx;
436 					lsfrac += r_sstepx;
437 					ltfrac += r_tstepx;
438 					llight += r_lstepx;
439 				}
440 				while (--lcount);
441 				goto done8;
442 
443 				do
444 				{
445 					if ((lzi >> 16) >= *lpz) // draw
446 					{
447 						lsfrac += r_sstepx * count;
448 						ltfrac += r_tstepx * count;
449 						llight += r_lstepx * count;
450 						lpdest += count;
451 						goto drawloop8;
452 					}
453 skiploop8:
454 					count++;
455 					lzi += r_zistepx;
456 					lpz++;
457 				}
458 				while (--lcount);
459 done8:			;
460 			}
461 
462 			pspanpackage++;
463 		}
464 		while (pspanpackage->count != -999999);
465 	}
466 	break;
467 
468 	case 2:
469 	{
470 		int         lcount, count = 0;
471 		short      *lpdest;
472 		byte       *lptex;
473 		int         lsfrac, ltfrac;
474 		int         llight;
475 		int         lzi;
476 		short      *lpz;
477 
478 		do
479 		{
480 			lcount = d_aspancount - pspanpackage->count;
481 
482 			errorterm += erroradjustup;
483 			if (errorterm >= 0)
484 			{
485 				d_aspancount += d_countextrastep;
486 				errorterm -= erroradjustdown;
487 			}
488 			else
489 				d_aspancount += ubasestep;
490 
491 			if (lcount)
492 			{
493 				lpdest = (short *) sw32_d_viewbuffer + pspanpackage->pdest;
494 				lptex = pspanpackage->ptex;
495 				lpz = pspanpackage->pz;
496 				lsfrac = pspanpackage->sfrac;
497 				ltfrac = pspanpackage->tfrac;
498 				llight = pspanpackage->light;
499 				lzi = pspanpackage->zi;
500 
501 				do
502 				{
503 					if ((lzi >> 16) < *lpz) // hidden
504 					{
505 						count = 0;
506 						goto skiploop16;
507 					}
508 drawloop16:
509 					*lpz++ = lzi >> 16;
510 					*lpdest++ = ((short *)sw32_acolormap)[(llight & 0xFF00) | lptex[texscan[ltfrac >> 16] + (lsfrac >> 16)]];
511 					lzi += r_zistepx;
512 					lsfrac += r_sstepx;
513 					ltfrac += r_tstepx;
514 					llight += r_lstepx;
515 				}
516 				while (--lcount);
517 				goto done16;
518 
519 				do
520 				{
521 					if ((lzi >> 16) >= *lpz) // draw
522 					{
523 						lsfrac += r_sstepx * count;
524 						ltfrac += r_tstepx * count;
525 						llight += r_lstepx * count;
526 						lpdest += count;
527 						goto drawloop16;
528 					}
529 skiploop16:
530 					count++;
531 					lzi += r_zistepx;
532 					lpz++;
533 				}
534 				while (--lcount);
535 done16:			;
536 			}
537 
538 			pspanpackage++;
539 		}
540 		while (pspanpackage->count != -999999);
541 	}
542 	break;
543 
544 	case 4:
545 	{
546 		int         lcount, count = 0;
547 		int        *lpdest;
548 		byte       *lptex;
549 		int         lsfrac, ltfrac;
550 		int         llight;
551 		int         lzi;
552 		short      *lpz;
553 
554 		do
555 		{
556 			lcount = d_aspancount - pspanpackage->count;
557 
558 			errorterm += erroradjustup;
559 			if (errorterm >= 0)
560 			{
561 				d_aspancount += d_countextrastep;
562 				errorterm -= erroradjustdown;
563 			}
564 			else
565 				d_aspancount += ubasestep;
566 
567 			if (lcount)
568 			{
569 				lpdest = (int *) sw32_d_viewbuffer + pspanpackage->pdest;
570 				lptex = pspanpackage->ptex;
571 				lpz = pspanpackage->pz;
572 				lsfrac = pspanpackage->sfrac;
573 				ltfrac = pspanpackage->tfrac;
574 				llight = pspanpackage->light;
575 				lzi = pspanpackage->zi;
576 
577 				do
578 				{
579 					if ((lzi >> 16) < *lpz) // hidden
580 					{
581 						count = 0;
582 						goto skiploop32;
583 					}
584 drawloop32:
585 					*lpz++ = lzi >> 16;
586 					*lpdest++ =
587 						vid.colormap32[(llight & 0xFF00) |
588 									   lptex[texscan[ltfrac >> 16] +
589 											 (lsfrac >> 16)]];
590 					lzi += r_zistepx;
591 					lsfrac += r_sstepx;
592 					ltfrac += r_tstepx;
593 					llight += r_lstepx;
594 				}
595 				while (--lcount);
596 				goto done32;
597 
598 				do
599 				{
600 					if ((lzi >> 16) >= *lpz) // draw
601 					{
602 						lsfrac += r_sstepx * count;
603 						ltfrac += r_tstepx * count;
604 						llight += r_lstepx * count;
605 						lpdest += count;
606 						goto drawloop32;
607 					}
608 skiploop32:
609 					count++;
610 					lzi += r_zistepx;
611 					lpz++;
612 				}
613 				while (--lcount);
614 done32:			;
615 			}
616 
617 			pspanpackage++;
618 		}
619 		while (pspanpackage->count != -999999);
620 	}
621 	break;
622 
623 	default:
624 		Sys_Error("D_PolysetDrawSpans: unsupported r_pixbytes %i",
625 				  sw32_r_pixbytes);
626 	}
627 }
628 
629 
630 void
sw32_D_RasterizeAliasPolySmooth(void)631 sw32_D_RasterizeAliasPolySmooth (void)
632 {
633 	int         initialleftheight, initialrightheight;
634 	int        *plefttop, *prighttop, *pleftbottom, *prightbottom;
635 	int         working_lstepx, originalcount;
636 
637 	plefttop = pedgetable->pleftedgevert0;
638 	prighttop = pedgetable->prightedgevert0;
639 
640 	pleftbottom = pedgetable->pleftedgevert1;
641 	prightbottom = pedgetable->prightedgevert1;
642 
643 	initialleftheight = pleftbottom[1] - plefttop[1];
644 	initialrightheight = prightbottom[1] - prighttop[1];
645 
646 	// set the s, t, and light gradients, which are consistent across the
647 	// triangle, because being a triangle, things are affine
648 	sw32_D_PolysetCalcGradients (sw32_r_affinetridesc.skinwidth);
649 
650 // rasterize the polygon
651 
652 	// scan out the top (and possibly only) part of the left edge
653 	D_PolysetSetUpForLineScan (plefttop[0], plefttop[1],
654 							   pleftbottom[0], pleftbottom[1]);
655 
656 	d_pedgespanpackage = a_spans;
657 
658 	ystart = plefttop[1];
659 	d_aspancount = plefttop[0] - prighttop[0];
660 
661 	d_ptex = (byte *) sw32_r_affinetridesc.pskin + (plefttop[2] >> 16) +
662 		(plefttop[3] >> 16) * sw32_r_affinetridesc.skinwidth;
663 	d_sfrac = plefttop[2] & 0xFFFF;
664 	d_tfrac = plefttop[3] & 0xFFFF;
665 	d_pzbasestep = sw32_d_zwidth + ubasestep;
666 	d_pzextrastep = d_pzbasestep + 1;
667 	d_light = plefttop[4];
668 	d_zi = plefttop[5];
669 
670 	d_pdestbasestep = sw32_screenwidth + ubasestep;
671 	d_pdestextrastep = d_pdestbasestep + 1;
672 	// LordHavoc: d_pdest has been changed to pixel offset
673 	d_pdest = ystart * sw32_screenwidth + plefttop[0];
674 	d_pz = sw32_d_pzbuffer + ystart * sw32_d_zwidth + plefttop[0];
675 
676 // TODO: can reuse partial expressions here
677 
678 	// for negative steps in x along left edge, bias toward overflow rather
679 	// than underflow (sort of turning the floor () we did in the gradient
680 	// calcs into ceil (), but plus a little bit)
681 	if (ubasestep < 0)
682 		working_lstepx = r_lstepx - 1;
683 	else
684 		working_lstepx = r_lstepx;
685 
686 	d_countextrastep = ubasestep + 1;
687 	d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
688 		((r_tstepy + r_tstepx * ubasestep) >> 16) * sw32_r_affinetridesc.skinwidth;
689 	d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
690 	d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
691 	d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
692 	d_zibasestep = r_zistepy + r_zistepx * ubasestep;
693 
694 	d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
695 		((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
696 		sw32_r_affinetridesc.skinwidth;
697 	d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF;
698 	d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF;
699 	d_lightextrastep = d_lightbasestep + working_lstepx;
700 	d_ziextrastep = d_zibasestep + r_zistepx;
701 
702 	sw32_D_PolysetScanLeftEdge (initialleftheight);
703 
704 	// scan out the bottom part of the left edge, if it exists
705 	if (pedgetable->numleftedges == 2) {
706 		int         height;
707 
708 		plefttop = pleftbottom;
709 		pleftbottom = pedgetable->pleftedgevert2;
710 
711 		D_PolysetSetUpForLineScan (plefttop[0], plefttop[1],
712 								   pleftbottom[0], pleftbottom[1]);
713 
714 		height = pleftbottom[1] - plefttop[1];
715 
716 // TODO: make this a function; modularize this function in general
717 
718 		ystart = plefttop[1];
719 		d_aspancount = plefttop[0] - prighttop[0];
720 		d_ptex = (byte *) sw32_r_affinetridesc.pskin + (plefttop[2] >> 16) +
721 			(plefttop[3] >> 16) * sw32_r_affinetridesc.skinwidth;
722 		d_sfrac = 0;
723 		d_tfrac = 0;
724 		d_light = plefttop[4];
725 		d_zi = plefttop[5];
726 
727 		d_pdestbasestep = sw32_screenwidth + ubasestep;
728 		d_pdestextrastep = d_pdestbasestep + 1;
729 		// LordHavoc: d_pdest and relatives have been changed to pixel
730 		// offsets into framebuffer
731 		d_pdest = ystart * sw32_screenwidth + plefttop[0];
732 		d_pzbasestep = sw32_d_zwidth + ubasestep;
733 		d_pzextrastep = d_pzbasestep + 1;
734 		d_pz = sw32_d_pzbuffer + ystart * sw32_d_zwidth + plefttop[0];
735 
736 		if (ubasestep < 0)
737 			working_lstepx = r_lstepx - 1;
738 		else
739 			working_lstepx = r_lstepx;
740 
741 		d_countextrastep = ubasestep + 1;
742 		d_ptexbasestep = ((r_sstepy + r_sstepx * ubasestep) >> 16) +
743 			((r_tstepy + r_tstepx * ubasestep) >> 16) *
744 			sw32_r_affinetridesc.skinwidth;
745 		d_sfracbasestep = (r_sstepy + r_sstepx * ubasestep) & 0xFFFF;
746 		d_tfracbasestep = (r_tstepy + r_tstepx * ubasestep) & 0xFFFF;
747 		d_lightbasestep = r_lstepy + working_lstepx * ubasestep;
748 		d_zibasestep = r_zistepy + r_zistepx * ubasestep;
749 
750 		d_ptexextrastep = ((r_sstepy + r_sstepx * d_countextrastep) >> 16) +
751 			((r_tstepy + r_tstepx * d_countextrastep) >> 16) *
752 			sw32_r_affinetridesc.skinwidth;
753 		d_sfracextrastep = (r_sstepy + r_sstepx * d_countextrastep) & 0xFFFF;
754 		d_tfracextrastep = (r_tstepy + r_tstepx * d_countextrastep) & 0xFFFF;
755 		d_lightextrastep = d_lightbasestep + working_lstepx;
756 		d_ziextrastep = d_zibasestep + r_zistepx;
757 
758 		sw32_D_PolysetScanLeftEdge (height);
759 	}
760 	// scan out the top (and possibly only) part of the right edge, updating
761 	// the count field
762 	d_pedgespanpackage = a_spans;
763 
764 	D_PolysetSetUpForLineScan (prighttop[0], prighttop[1],
765 							   prightbottom[0], prightbottom[1]);
766 	d_aspancount = 0;
767 	d_countextrastep = ubasestep + 1;
768 	originalcount = a_spans[initialrightheight].count;
769 	a_spans[initialrightheight].count = -999999;	// mark end of the
770 													// spanpackages
771 	D_PolysetDrawSpans (a_spans);
772 
773 	// scan out the bottom part of the right edge, if it exists
774 	if (pedgetable->numrightedges == 2) {
775 		int         height;
776 		spanpackage_t *pstart;
777 
778 		pstart = a_spans + initialrightheight;
779 		pstart->count = originalcount;
780 
781 		d_aspancount = prightbottom[0] - prighttop[0];
782 
783 		prighttop = prightbottom;
784 		prightbottom = pedgetable->prightedgevert2;
785 
786 		height = prightbottom[1] - prighttop[1];
787 
788 		D_PolysetSetUpForLineScan (prighttop[0], prighttop[1],
789 								   prightbottom[0], prightbottom[1]);
790 
791 		d_countextrastep = ubasestep + 1;
792 		a_spans[initialrightheight + height].count = -999999;
793 		// mark end of the spanpackages
794 		D_PolysetDrawSpans (pstart);
795 	}
796 }
797