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