1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      The 3d polygon rasteriser.
12  *
13  *      By Shawn Hargreaves.
14  *
15  *      Hicolor support added by Przemek Podsiadly. Complete support for
16  *      all drawing modes in every color depth MMX optimisations and z-buffer
17  *      added by Calin Andrian. Subpixel and subtexel accuracy, triangle
18  *      functions and speed enhancements added by Bertrand Coconnier.
19  *      Functions adapted to handle two coincident vertices by Ben Davis.
20  *
21  *      See readme.txt for copyright information.
22  */
23 
24 
25 #include <limits.h>
26 #include <float.h>
27 
28 #include "allegro.h"
29 #include "allegro/internal/aintern.h"
30 
31 #if defined ALLEGRO_ASMCAPA_HEADER && !defined ALLEGRO_NO_ASM
32    #include ALLEGRO_ASMCAPA_HEADER
33 #endif
34 
35 #ifdef ALLEGRO_MMX
36 
37 /* for use by iscan.s */
38 uint32_t _mask_mmx_15[] = { 0x03E0001F, 0x007C };
39 uint32_t _mask_mmx_16[] = { 0x07E0001F, 0x00F8 };
40 
41 #endif
42 
43 
_poly_scanline_dummy(uintptr_t addr,int w,POLYGON_SEGMENT * info)44 void _poly_scanline_dummy(uintptr_t addr, int w, POLYGON_SEGMENT *info) { }
45 
46 ZBUFFER *_zbuffer = NULL;
47 
48 SCANLINE_FILLER _optim_alternative_drawer;
49 
50 
51 /* _fill_3d_edge_structure:
52  *  Polygon helper function: initialises an edge structure for the 3d
53  *  rasterising code, using fixed point vertex structures. Returns 1 on
54  *  success, or 0 if the edge is horizontal or clipped out of existence.
55  */
_fill_3d_edge_structure(POLYGON_EDGE * edge,AL_CONST V3D * v1,AL_CONST V3D * v2,int flags,BITMAP * bmp)56 int _fill_3d_edge_structure(POLYGON_EDGE *edge, AL_CONST V3D *v1, AL_CONST V3D *v2, int flags, BITMAP *bmp)
57 {
58    int r1, r2, g1, g2, b1, b2;
59    fixed h, step;
60 
61    /* swap vertices if they are the wrong way up */
62    if (v2->y < v1->y) {
63       AL_CONST V3D *vt;
64 
65       vt = v1;
66       v1 = v2;
67       v2 = vt;
68    }
69 
70    /* set up screen rasterising parameters */
71    edge->top = fixceil(v1->y);
72    edge->bottom = fixceil(v2->y) - 1;
73 
74    if (edge->bottom < edge->top) return 0;
75 
76    h = v2->y - v1->y;
77    step = (edge->top << 16) - v1->y;
78 
79    edge->dx = fixdiv(v2->x - v1->x, h);
80    edge->x = v1->x + fixmul(step, edge->dx);
81 
82    edge->prev = NULL;
83    edge->next = NULL;
84    edge->w = 0;
85 
86    if (flags & INTERP_Z) {
87       float h1 = 65536. / h;
88       float step_f = fixtof(step);
89 
90       /* Z (depth) interpolation */
91       float z1 = 65536. / v1->z;
92       float z2 = 65536. / v2->z;
93 
94       edge->dat.dz = (z2 - z1) * h1;
95       edge->dat.z = z1 + edge->dat.dz * step_f;
96 
97       if (flags & INTERP_FLOAT_UV) {
98 	 /* floating point (perspective correct) texture interpolation */
99 	 float fu1 = v1->u * z1;
100 	 float fv1 = v1->v * z1;
101 	 float fu2 = v2->u * z2;
102 	 float fv2 = v2->v * z2;
103 
104 	 edge->dat.dfu = (fu2 - fu1) * h1;
105 	 edge->dat.dfv = (fv2 - fv1) * h1;
106 	 edge->dat.fu = fu1 + edge->dat.dfu * step_f;
107 	 edge->dat.fv = fv1 + edge->dat.dfv * step_f;
108       }
109    }
110 
111    if (flags & INTERP_FLAT) {
112       /* if clipping is enabled then clip edge */
113       if (bmp->clip) {
114          if (edge->top < bmp->ct) {
115             edge->x += (bmp->ct - edge->top) * edge->dx;
116 	    edge->top = bmp->ct;
117          }
118 
119          if (edge->bottom >= bmp->cb)
120 	    edge->bottom = bmp->cb - 1;
121       }
122 
123       return (edge->bottom >= edge->top);
124    }
125 
126    if (flags & INTERP_1COL) {
127       /* single color shading interpolation */
128       edge->dat.dc = fixdiv(itofix(v2->c - v1->c), h);
129       edge->dat.c = itofix(v1->c) + fixmul(step, edge->dat.dc);
130    }
131 
132    if (flags & INTERP_3COL) {
133       /* RGB shading interpolation */
134       if (flags & COLOR_TO_RGB) {
135          AL_CONST int coldepth = bitmap_color_depth(bmp);
136 	 r1 = getr_depth(coldepth, v1->c);
137 	 r2 = getr_depth(coldepth, v2->c);
138 	 g1 = getg_depth(coldepth, v1->c);
139 	 g2 = getg_depth(coldepth, v2->c);
140 	 b1 = getb_depth(coldepth, v1->c);
141 	 b2 = getb_depth(coldepth, v2->c);
142       }
143       else {
144 	 r1 = (v1->c >> 16) & 0xFF;
145 	 r2 = (v2->c >> 16) & 0xFF;
146 	 g1 = (v1->c >> 8) & 0xFF;
147 	 g2 = (v2->c >> 8) & 0xFF;
148 	 b1 = v1->c & 0xFF;
149 	 b2 = v2->c & 0xFF;
150       }
151 
152       edge->dat.dr = fixdiv(itofix(r2 - r1), h);
153       edge->dat.dg = fixdiv(itofix(g2 - g1), h);
154       edge->dat.db = fixdiv(itofix(b2 - b1), h);
155       edge->dat.r = itofix(r1) + fixmul(step, edge->dat.dr);
156       edge->dat.g = itofix(g1) + fixmul(step, edge->dat.dg);
157       edge->dat.b = itofix(b1) + fixmul(step, edge->dat.db);
158    }
159 
160    if (flags & INTERP_FIX_UV) {
161       /* fixed point (affine) texture interpolation */
162       edge->dat.du = fixdiv(v2->u - v1->u, h);
163       edge->dat.dv = fixdiv(v2->v - v1->v, h);
164       edge->dat.u = v1->u + fixmul(step, edge->dat.du);
165       edge->dat.v = v1->v + fixmul(step, edge->dat.dv);
166    }
167 
168    /* if clipping is enabled then clip edge */
169    if (bmp->clip) {
170       if (edge->top < bmp->ct) {
171          int gap = bmp->ct - edge->top;
172          edge->top = bmp->ct;
173          edge->x += gap * edge->dx;
174          _clip_polygon_segment(&(edge->dat), itofix(gap), flags);
175       }
176 
177       if (edge->bottom >= bmp->cb)
178          edge->bottom = bmp->cb - 1;
179    }
180 
181    return (edge->bottom >= edge->top);
182 }
183 
184 
185 
186 /* _fill_3d_edge_structure_f:
187  *  Polygon helper function: initialises an edge structure for the 3d
188  *  rasterising code, using floating point vertex structures. Returns 1 on
189  *  success, or 0 if the edge is horizontal or clipped out of existence.
190  */
_fill_3d_edge_structure_f(POLYGON_EDGE * edge,AL_CONST V3D_f * v1,AL_CONST V3D_f * v2,int flags,BITMAP * bmp)191 int _fill_3d_edge_structure_f(POLYGON_EDGE *edge, AL_CONST V3D_f *v1, AL_CONST V3D_f *v2, int flags, BITMAP *bmp)
192 {
193    int r1, r2, g1, g2, b1, b2;
194    fixed h, step;
195    float h1;
196 
197    /* swap vertices if they are the wrong way up */
198    if (v2->y < v1->y) {
199       AL_CONST V3D_f *vt;
200 
201       vt = v1;
202       v1 = v2;
203       v2 = vt;
204    }
205 
206    /* set up screen rasterising parameters */
207    edge->top = fixceil(ftofix(v1->y));
208    edge->bottom = fixceil(ftofix(v2->y)) - 1;
209 
210    if (edge->bottom < edge->top) return 0;
211 
212    h1 = 1.0 / (v2->y - v1->y);
213    h = ftofix(v2->y - v1->y);
214    step = (edge->top << 16) - ftofix(v1->y);
215 
216    edge->dx = ftofix((v2->x - v1->x)  * h1);
217    edge->x = ftofix(v1->x) + fixmul(step, edge->dx);
218 
219    edge->prev = NULL;
220    edge->next = NULL;
221    edge->w = 0;
222 
223    if (flags & INTERP_Z) {
224       float step_f = fixtof(step);
225 
226       /* Z (depth) interpolation */
227       float z1 = 1. / v1->z;
228       float z2 = 1. / v2->z;
229 
230       edge->dat.dz = (z2 - z1) * h1;
231       edge->dat.z = z1 + edge->dat.dz * step_f;
232 
233       if (flags & INTERP_FLOAT_UV) {
234 	 /* floating point (perspective correct) texture interpolation */
235 	 float fu1 = v1->u * z1 * 65536.;
236 	 float fv1 = v1->v * z1 * 65536.;
237 	 float fu2 = v2->u * z2 * 65536.;
238 	 float fv2 = v2->v * z2 * 65536.;
239 
240 	 edge->dat.dfu = (fu2 - fu1) * h1;
241 	 edge->dat.dfv = (fv2 - fv1) * h1;
242 	 edge->dat.fu = fu1 + edge->dat.dfu * step_f;
243 	 edge->dat.fv = fv1 + edge->dat.dfv * step_f;
244       }
245    }
246 
247    if (flags & INTERP_FLAT) {
248       /* if clipping is enabled then clip edge */
249       if (bmp->clip) {
250          if (edge->top < bmp->ct) {
251 	    edge->x += (bmp->ct - edge->top) * edge->dx;
252 	    edge->top = bmp->ct;
253          }
254 
255          if (edge->bottom >= bmp->cb)
256 	    edge->bottom = bmp->cb - 1;
257       }
258 
259       return (edge->bottom >= edge->top);
260    }
261 
262    if (flags & INTERP_1COL) {
263       /* single color shading interpolation */
264       edge->dat.dc = fixdiv(itofix(v2->c - v1->c), h);
265       edge->dat.c = itofix(v1->c) + fixmul(step, edge->dat.dc);
266    }
267 
268    if (flags & INTERP_3COL) {
269       /* RGB shading interpolation */
270       if (flags & COLOR_TO_RGB) {
271          AL_CONST int coldepth = bitmap_color_depth(bmp);
272 	 r1 = getr_depth(coldepth, v1->c);
273 	 r2 = getr_depth(coldepth, v2->c);
274 	 g1 = getg_depth(coldepth, v1->c);
275 	 g2 = getg_depth(coldepth, v2->c);
276 	 b1 = getb_depth(coldepth, v1->c);
277 	 b2 = getb_depth(coldepth, v2->c);
278       }
279       else {
280 	 r1 = (v1->c >> 16) & 0xFF;
281 	 r2 = (v2->c >> 16) & 0xFF;
282 	 g1 = (v1->c >> 8) & 0xFF;
283 	 g2 = (v2->c >> 8) & 0xFF;
284 	 b1 = v1->c & 0xFF;
285 	 b2 = v2->c & 0xFF;
286       }
287 
288       edge->dat.dr = fixdiv(itofix(r2 - r1), h);
289       edge->dat.dg = fixdiv(itofix(g2 - g1), h);
290       edge->dat.db = fixdiv(itofix(b2 - b1), h);
291       edge->dat.r = itofix(r1) + fixmul(step, edge->dat.dr);
292       edge->dat.g = itofix(g1) + fixmul(step, edge->dat.dg);
293       edge->dat.b = itofix(b1) + fixmul(step, edge->dat.db);
294    }
295 
296    if (flags & INTERP_FIX_UV) {
297       /* fixed point (affine) texture interpolation */
298       edge->dat.du = ftofix((v2->u - v1->u) * h1);
299       edge->dat.dv = ftofix((v2->v - v1->v) * h1);
300       edge->dat.u = ftofix(v1->u) + fixmul(step, edge->dat.du);
301       edge->dat.v = ftofix(v1->v) + fixmul(step, edge->dat.dv);
302    }
303 
304    /* if clipping is enabled then clip edge */
305    if (bmp->clip) {
306       if (edge->top < bmp->ct) {
307          int gap = bmp->ct - edge->top;
308          edge->top = bmp->ct;
309          edge->x += gap * edge->dx;
310          _clip_polygon_segment_f(&(edge->dat), gap, flags);
311       }
312 
313       if (edge->bottom >= bmp->cb)
314          edge->bottom = bmp->cb - 1;
315    }
316 
317    return (edge->bottom >= edge->top);
318 }
319 
320 
321 
322 /* _get_scanline_filler:
323  *  Helper function for deciding which rasterisation function and
324  *  interpolation flags we should use for a specific polygon type.
325  */
_get_scanline_filler(int type,int * flags,POLYGON_SEGMENT * info,BITMAP * texture,BITMAP * bmp)326 SCANLINE_FILLER _get_scanline_filler(int type, int *flags, POLYGON_SEGMENT *info, BITMAP *texture, BITMAP *bmp)
327 {
328    typedef struct POLYTYPE_INFO
329    {
330       SCANLINE_FILLER filler;
331       SCANLINE_FILLER alternative;
332    } POLYTYPE_INFO;
333 
334    static int polytype_interp_pal[] =
335    {
336       INTERP_FLAT,
337       INTERP_1COL,
338       INTERP_3COL,
339       INTERP_FIX_UV,
340       INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX,
341       INTERP_FIX_UV,
342       INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX,
343       INTERP_FIX_UV | INTERP_1COL,
344       INTERP_Z | INTERP_FLOAT_UV | INTERP_1COL | OPT_FLOAT_UV_TO_FIX,
345       INTERP_FIX_UV | INTERP_1COL,
346       INTERP_Z | INTERP_FLOAT_UV | INTERP_1COL | OPT_FLOAT_UV_TO_FIX,
347       INTERP_FIX_UV,
348       INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX,
349       INTERP_FIX_UV,
350       INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX
351    };
352 
353    static int polytype_interp_tc[] =
354    {
355       INTERP_FLAT,
356       INTERP_3COL | COLOR_TO_RGB,
357       INTERP_3COL,
358       INTERP_FIX_UV,
359       INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX,
360       INTERP_FIX_UV,
361       INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX,
362       INTERP_FIX_UV | INTERP_1COL,
363       INTERP_Z | INTERP_FLOAT_UV | INTERP_1COL | OPT_FLOAT_UV_TO_FIX,
364       INTERP_FIX_UV | INTERP_1COL,
365       INTERP_Z | INTERP_FLOAT_UV | INTERP_1COL | OPT_FLOAT_UV_TO_FIX,
366       INTERP_FIX_UV,
367       INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX,
368       INTERP_FIX_UV,
369       INTERP_Z | INTERP_FLOAT_UV | OPT_FLOAT_UV_TO_FIX
370    };
371 
372    #ifdef ALLEGRO_COLOR8
373    static POLYTYPE_INFO polytype_info8[] =
374    {
375       {  _poly_scanline_dummy,            NULL },
376       {  _poly_scanline_gcol8,            NULL },
377       {  _poly_scanline_grgb8,            NULL },
378       {  _poly_scanline_atex8,            NULL },
379       {  _poly_scanline_ptex8,            _poly_scanline_atex8 },
380       {  _poly_scanline_atex_mask8,       NULL },
381       {  _poly_scanline_ptex_mask8,       _poly_scanline_atex_mask8 },
382       {  _poly_scanline_atex_lit8,        NULL },
383       {  _poly_scanline_ptex_lit8,        _poly_scanline_atex_lit8 },
384       {  _poly_scanline_atex_mask_lit8,   NULL },
385       {  _poly_scanline_ptex_mask_lit8,   _poly_scanline_atex_mask_lit8 },
386       {  _poly_scanline_atex_trans8,      NULL },
387       {  _poly_scanline_ptex_trans8,      _poly_scanline_atex_trans8 },
388       {  _poly_scanline_atex_mask_trans8, NULL },
389       {  _poly_scanline_ptex_mask_trans8, _poly_scanline_atex_mask_trans8 }
390    };
391 
392    #ifdef ALLEGRO_MMX
393    static POLYTYPE_INFO polytype_info8x[] =
394    {
395       {  NULL,                    NULL },
396       {  NULL,                    NULL },
397       {  _poly_scanline_grgb8x,   NULL },
398       {  NULL,                    NULL },
399       {  NULL,                    NULL },
400       {  NULL,                    NULL },
401       {  NULL,                    NULL },
402       {  NULL,                    NULL },
403       {  NULL,                    NULL },
404       {  NULL,                    NULL },
405       {  NULL,                    NULL },
406       {  NULL,                    NULL },
407       {  NULL,                    NULL },
408       {  NULL,                    NULL },
409       {  NULL,                    NULL }
410    };
411 
412    static POLYTYPE_INFO polytype_info8d[] =
413    {
414       {  NULL,                           NULL },
415       {  NULL,                           NULL },
416       {  NULL,                           NULL },
417       {  NULL,                           NULL },
418       {  NULL,                           NULL },
419       {  NULL,                           NULL },
420       {  NULL,                           NULL },
421       {  NULL,                           NULL },
422       {  NULL,                           NULL },
423       {  NULL,                           NULL },
424       {  NULL,                           NULL },
425       {  NULL,                           NULL },
426       {  NULL,                           NULL },
427       {  NULL,                           NULL },
428       {  NULL,                           NULL }
429    };
430    #endif
431    #endif
432 
433    #ifdef ALLEGRO_COLOR16
434    static POLYTYPE_INFO polytype_info15[] =
435    {
436       {  _poly_scanline_dummy,             NULL },
437       {  _poly_scanline_grgb15,            NULL },
438       {  _poly_scanline_grgb15,            NULL },
439       {  _poly_scanline_atex16,            NULL },
440       {  _poly_scanline_ptex16,            _poly_scanline_atex16 },
441       {  _poly_scanline_atex_mask15,       NULL },
442       {  _poly_scanline_ptex_mask15,       _poly_scanline_atex_mask15 },
443       {  _poly_scanline_atex_lit15,        NULL },
444       {  _poly_scanline_ptex_lit15,        _poly_scanline_atex_lit15 },
445       {  _poly_scanline_atex_mask_lit15,   NULL },
446       {  _poly_scanline_ptex_mask_lit15,   _poly_scanline_atex_mask_lit15 },
447       {  _poly_scanline_atex_trans15,      NULL },
448       {  _poly_scanline_ptex_trans15,      _poly_scanline_atex_trans15 },
449       {  _poly_scanline_atex_mask_trans15, NULL },
450       {  _poly_scanline_ptex_mask_trans15, _poly_scanline_atex_mask_trans15 }
451    };
452 
453    #ifdef ALLEGRO_MMX
454    static POLYTYPE_INFO polytype_info15x[] =
455    {
456       {  NULL,                            NULL },
457       {  _poly_scanline_grgb15x,          NULL },
458       {  _poly_scanline_grgb15x,          NULL },
459       {  NULL,                            NULL },
460       {  NULL,                            NULL },
461       {  NULL,                            NULL },
462       {  NULL,                            NULL },
463       {  _poly_scanline_atex_lit15x,      NULL },
464       {  _poly_scanline_ptex_lit15x,      _poly_scanline_atex_lit15x },
465       {  _poly_scanline_atex_mask_lit15x, NULL },
466       {  _poly_scanline_ptex_mask_lit15x, _poly_scanline_atex_mask_lit15x },
467       {  NULL,                            NULL },
468       {  NULL,                            NULL },
469       {  NULL,                            NULL },
470       {  NULL,                            NULL }
471    };
472 
473    static POLYTYPE_INFO polytype_info15d[] =
474    {
475       {  NULL,                            NULL },
476       {  NULL,                            NULL },
477       {  NULL,                            NULL },
478       {  NULL,                            NULL },
479       {  NULL,                            NULL },
480       {  NULL,                            NULL },
481       {  NULL,                            NULL },
482       {  NULL,                            NULL },
483       {  _poly_scanline_ptex_lit15d,      _poly_scanline_atex_lit15x },
484       {  NULL,                            NULL },
485       {  _poly_scanline_ptex_mask_lit15d, _poly_scanline_atex_mask_lit15x },
486       {  NULL,                            NULL },
487       {  NULL,                            NULL },
488       {  NULL,                            NULL },
489       {  NULL,                            NULL }
490    };
491    #endif
492 
493    static POLYTYPE_INFO polytype_info16[] =
494    {
495       {  _poly_scanline_dummy,             NULL },
496       {  _poly_scanline_grgb16,            NULL },
497       {  _poly_scanline_grgb16,            NULL },
498       {  _poly_scanline_atex16,            NULL },
499       {  _poly_scanline_ptex16,            _poly_scanline_atex16 },
500       {  _poly_scanline_atex_mask16,       NULL },
501       {  _poly_scanline_ptex_mask16,       _poly_scanline_atex_mask16 },
502       {  _poly_scanline_atex_lit16,        NULL },
503       {  _poly_scanline_ptex_lit16,        _poly_scanline_atex_lit16 },
504       {  _poly_scanline_atex_mask_lit16,   NULL },
505       {  _poly_scanline_ptex_mask_lit16,   _poly_scanline_atex_mask_lit16 },
506       {  _poly_scanline_atex_trans16,      NULL },
507       {  _poly_scanline_ptex_trans16,      _poly_scanline_atex_trans16 },
508       {  _poly_scanline_atex_mask_trans16, NULL },
509       {  _poly_scanline_ptex_mask_trans16, _poly_scanline_atex_mask_trans16 }
510    };
511 
512    #ifdef ALLEGRO_MMX
513    static POLYTYPE_INFO polytype_info16x[] =
514    {
515       {  NULL,                            NULL },
516       {  _poly_scanline_grgb16x,          NULL },
517       {  _poly_scanline_grgb16x,          NULL },
518       {  NULL,                            NULL },
519       {  NULL,                            NULL },
520       {  NULL,                            NULL },
521       {  NULL,                            NULL },
522       {  _poly_scanline_atex_lit16x,      NULL },
523       {  _poly_scanline_ptex_lit16x,      _poly_scanline_atex_lit16x },
524       {  _poly_scanline_atex_mask_lit16x, NULL },
525       {  _poly_scanline_ptex_mask_lit16x, _poly_scanline_atex_mask_lit16x },
526       {  NULL,                            NULL },
527       {  NULL,                            NULL },
528       {  NULL,                            NULL },
529       {  NULL,                            NULL }
530    };
531 
532    static POLYTYPE_INFO polytype_info16d[] =
533    {
534       {  NULL,                            NULL },
535       {  NULL,                            NULL },
536       {  NULL,                            NULL },
537       {  NULL,                            NULL },
538       {  NULL,                            NULL },
539       {  NULL,                            NULL },
540       {  NULL,                            NULL },
541       {  NULL,                            NULL },
542       {  _poly_scanline_ptex_lit16d,      _poly_scanline_atex_lit16x },
543       {  NULL,                            NULL },
544       {  _poly_scanline_ptex_mask_lit16d, _poly_scanline_atex_mask_lit16x },
545       {  NULL,                            NULL },
546       {  NULL,                            NULL },
547       {  NULL,                            NULL },
548       {  NULL,                            NULL }
549    };
550    #endif
551    #endif
552 
553    #ifdef ALLEGRO_COLOR24
554    static POLYTYPE_INFO polytype_info24[] =
555    {
556       {  _poly_scanline_dummy,             NULL },
557       {  _poly_scanline_grgb24,            NULL },
558       {  _poly_scanline_grgb24,            NULL },
559       {  _poly_scanline_atex24,            NULL },
560       {  _poly_scanline_ptex24,            _poly_scanline_atex24 },
561       {  _poly_scanline_atex_mask24,       NULL },
562       {  _poly_scanline_ptex_mask24,       _poly_scanline_atex_mask24 },
563       {  _poly_scanline_atex_lit24,        NULL },
564       {  _poly_scanline_ptex_lit24,        _poly_scanline_atex_lit24 },
565       {  _poly_scanline_atex_mask_lit24,   NULL },
566       {  _poly_scanline_ptex_mask_lit24,   _poly_scanline_atex_mask_lit24 },
567       {  _poly_scanline_atex_trans24,      NULL },
568       {  _poly_scanline_ptex_trans24,      _poly_scanline_atex_trans24 },
569       {  _poly_scanline_atex_mask_trans24, NULL },
570       {  _poly_scanline_ptex_mask_trans24, _poly_scanline_atex_mask_trans24 }
571    };
572 
573    #ifdef ALLEGRO_MMX
574    static POLYTYPE_INFO polytype_info24x[] =
575    {
576       {  NULL,                            NULL },
577       {  _poly_scanline_grgb24x,          NULL },
578       {  _poly_scanline_grgb24x,          NULL },
579       {  NULL,                            NULL },
580       {  NULL,                            NULL },
581       {  NULL,                            NULL },
582       {  NULL,                            NULL },
583       {  _poly_scanline_atex_lit24x,      NULL },
584       {  _poly_scanline_ptex_lit24x,      _poly_scanline_atex_lit24x },
585       {  _poly_scanline_atex_mask_lit24x, NULL },
586       {  _poly_scanline_ptex_mask_lit24x, _poly_scanline_atex_mask_lit24x },
587       {  NULL,                            NULL },
588       {  NULL,                            NULL },
589       {  NULL,                            NULL },
590       {  NULL,                            NULL }
591    };
592 
593    static POLYTYPE_INFO polytype_info24d[] =
594    {
595       {  NULL,                            NULL },
596       {  NULL,                            NULL },
597       {  NULL,                            NULL },
598       {  NULL,                            NULL },
599       {  NULL,                            NULL },
600       {  NULL,                            NULL },
601       {  NULL,                            NULL },
602       {  NULL,                            NULL },
603       {  _poly_scanline_ptex_lit24d,      _poly_scanline_atex_lit24x },
604       {  NULL,                            NULL },
605       {  _poly_scanline_ptex_mask_lit24d, _poly_scanline_atex_mask_lit24x },
606       {  NULL,                            NULL },
607       {  NULL,                            NULL },
608       {  NULL,                            NULL },
609       {  NULL,                            NULL }
610    };
611    #endif
612    #endif
613 
614    #ifdef ALLEGRO_COLOR32
615    static POLYTYPE_INFO polytype_info32[] =
616    {
617       {  _poly_scanline_dummy,             NULL },
618       {  _poly_scanline_grgb32,            NULL },
619       {  _poly_scanline_grgb32,            NULL },
620       {  _poly_scanline_atex32,            NULL },
621       {  _poly_scanline_ptex32,            _poly_scanline_atex32 },
622       {  _poly_scanline_atex_mask32,       NULL },
623       {  _poly_scanline_ptex_mask32,       _poly_scanline_atex_mask32 },
624       {  _poly_scanline_atex_lit32,        NULL },
625       {  _poly_scanline_ptex_lit32,        _poly_scanline_atex_lit32 },
626       {  _poly_scanline_atex_mask_lit32,   NULL },
627       {  _poly_scanline_ptex_mask_lit32,   _poly_scanline_atex_mask_lit32 },
628       {  _poly_scanline_atex_trans32,      NULL },
629       {  _poly_scanline_ptex_trans32,      _poly_scanline_atex_trans32 },
630       {  _poly_scanline_atex_mask_trans32, NULL },
631       {  _poly_scanline_ptex_mask_trans32, _poly_scanline_atex_mask_trans32 }
632    };
633 
634    #ifdef ALLEGRO_MMX
635    static POLYTYPE_INFO polytype_info32x[] =
636    {
637       {  NULL,                            NULL },
638       {  _poly_scanline_grgb32x,          NULL },
639       {  _poly_scanline_grgb32x,          NULL },
640       {  NULL,                            NULL },
641       {  NULL,                            NULL },
642       {  NULL,                            NULL },
643       {  NULL,                            NULL },
644       {  _poly_scanline_atex_lit32x,      NULL },
645       {  _poly_scanline_ptex_lit32x,      _poly_scanline_atex_lit32x },
646       {  _poly_scanline_atex_mask_lit32x, NULL },
647       {  _poly_scanline_ptex_mask_lit32x, _poly_scanline_atex_mask_lit32x },
648       {  NULL,                            NULL },
649       {  NULL,                            NULL },
650       {  NULL,                            NULL },
651       {  NULL,                            NULL }
652    };
653 
654    static POLYTYPE_INFO polytype_info32d[] =
655    {
656       {  NULL,                            NULL },
657       {  NULL,                            NULL },
658       {  NULL,                            NULL },
659       {  NULL,                            NULL },
660       {  NULL,                            NULL },
661       {  NULL,                            NULL },
662       {  NULL,                            NULL },
663       {  NULL,                            NULL },
664       {  _poly_scanline_ptex_lit32d,      _poly_scanline_atex_lit32x },
665       {  NULL,                            NULL },
666       {  _poly_scanline_ptex_mask_lit32d, _poly_scanline_atex_mask_lit32x },
667       {  NULL,                            NULL },
668       {  NULL,                            NULL },
669       {  NULL,                            NULL },
670       {  NULL,                            NULL }
671    };
672    #endif
673    #endif
674 
675    #ifdef ALLEGRO_COLOR8
676    static POLYTYPE_INFO polytype_info8z[] =
677    {
678       {  _poly_zbuf_flat8,            NULL },
679       {  _poly_zbuf_gcol8,            NULL },
680       {  _poly_zbuf_grgb8,            NULL },
681       {  _poly_zbuf_atex8,            NULL },
682       {  _poly_zbuf_ptex8,            _poly_zbuf_atex8 },
683       {  _poly_zbuf_atex_mask8,       NULL },
684       {  _poly_zbuf_ptex_mask8,       _poly_zbuf_atex_mask8 },
685       {  _poly_zbuf_atex_lit8,        NULL },
686       {  _poly_zbuf_ptex_lit8,        _poly_zbuf_atex_lit8 },
687       {  _poly_zbuf_atex_mask_lit8,   NULL },
688       {  _poly_zbuf_ptex_mask_lit8,   _poly_zbuf_atex_mask_lit8 },
689       {  _poly_zbuf_atex_trans8,      NULL },
690       {  _poly_zbuf_ptex_trans8,      _poly_zbuf_atex_trans8 },
691       {  _poly_zbuf_atex_mask_trans8, NULL },
692       {  _poly_zbuf_ptex_mask_trans8, _poly_zbuf_atex_mask_trans8 }
693    };
694    #endif
695 
696    #ifdef ALLEGRO_COLOR16
697    static POLYTYPE_INFO polytype_info15z[] =
698    {
699       {  _poly_zbuf_flat16,            NULL },
700       {  _poly_zbuf_grgb15,            NULL },
701       {  _poly_zbuf_grgb15,            NULL },
702       {  _poly_zbuf_atex16,            NULL },
703       {  _poly_zbuf_ptex16,            _poly_zbuf_atex16 },
704       {  _poly_zbuf_atex_mask15,       NULL },
705       {  _poly_zbuf_ptex_mask15,       _poly_zbuf_atex_mask15 },
706       {  _poly_zbuf_atex_lit15,        NULL },
707       {  _poly_zbuf_ptex_lit15,        _poly_zbuf_atex_lit15 },
708       {  _poly_zbuf_atex_mask_lit15,   NULL },
709       {  _poly_zbuf_ptex_mask_lit15,   _poly_zbuf_atex_mask_lit15 },
710       {  _poly_zbuf_atex_trans15,      NULL },
711       {  _poly_zbuf_ptex_trans15,      _poly_zbuf_atex_trans15 },
712       {  _poly_zbuf_atex_mask_trans15, NULL },
713       {  _poly_zbuf_ptex_mask_trans15, _poly_zbuf_atex_mask_trans15 }
714    };
715 
716    static POLYTYPE_INFO polytype_info16z[] =
717    {
718       {  _poly_zbuf_flat16,            NULL },
719       {  _poly_zbuf_grgb16,            NULL },
720       {  _poly_zbuf_grgb16,            NULL },
721       {  _poly_zbuf_atex16,            NULL },
722       {  _poly_zbuf_ptex16,            _poly_zbuf_atex16 },
723       {  _poly_zbuf_atex_mask16,       NULL },
724       {  _poly_zbuf_ptex_mask16,       _poly_zbuf_atex_mask16 },
725       {  _poly_zbuf_atex_lit16,        NULL },
726       {  _poly_zbuf_ptex_lit16,        _poly_zbuf_atex_lit16 },
727       {  _poly_zbuf_atex_mask_lit16,   NULL },
728       {  _poly_zbuf_ptex_mask_lit16,   _poly_zbuf_atex_mask_lit16 },
729       {  _poly_zbuf_atex_trans16,      NULL },
730       {  _poly_zbuf_ptex_trans16,      _poly_zbuf_atex_trans16 },
731       {  _poly_zbuf_atex_mask_trans16, NULL },
732       {  _poly_zbuf_ptex_mask_trans16, _poly_zbuf_atex_mask_trans16 }
733    };
734    #endif
735 
736    #ifdef ALLEGRO_COLOR24
737    static POLYTYPE_INFO polytype_info24z[] =
738    {
739       {  _poly_zbuf_flat24,            NULL },
740       {  _poly_zbuf_grgb24,            NULL },
741       {  _poly_zbuf_grgb24,            NULL },
742       {  _poly_zbuf_atex24,            NULL },
743       {  _poly_zbuf_ptex24,            _poly_zbuf_atex24 },
744       {  _poly_zbuf_atex_mask24,       NULL },
745       {  _poly_zbuf_ptex_mask24,       _poly_zbuf_atex_mask24 },
746       {  _poly_zbuf_atex_lit24,        NULL },
747       {  _poly_zbuf_ptex_lit24,        _poly_zbuf_atex_lit24 },
748       {  _poly_zbuf_atex_mask_lit24,   NULL },
749       {  _poly_zbuf_ptex_mask_lit24,   _poly_zbuf_atex_mask_lit24 },
750       {  _poly_zbuf_atex_trans24,      NULL },
751       {  _poly_zbuf_ptex_trans24,      _poly_zbuf_atex_trans24 },
752       {  _poly_zbuf_atex_mask_trans24, NULL },
753       {  _poly_zbuf_ptex_mask_trans24, _poly_zbuf_atex_mask_trans24 }
754    };
755    #endif
756 
757    #ifdef ALLEGRO_COLOR32
758    static POLYTYPE_INFO polytype_info32z[] =
759    {
760       {  _poly_zbuf_flat32,            NULL },
761       {  _poly_zbuf_grgb32,            NULL },
762       {  _poly_zbuf_grgb32,            NULL },
763       {  _poly_zbuf_atex32,            NULL },
764       {  _poly_zbuf_ptex32,            _poly_zbuf_atex32 },
765       {  _poly_zbuf_atex_mask32,       NULL },
766       {  _poly_zbuf_ptex_mask32,       _poly_zbuf_atex_mask32 },
767       {  _poly_zbuf_atex_lit32,        NULL },
768       {  _poly_zbuf_ptex_lit32,        _poly_zbuf_atex_lit32 },
769       {  _poly_zbuf_atex_mask_lit32,   NULL },
770       {  _poly_zbuf_ptex_mask_lit32,   _poly_zbuf_atex_mask_lit32 },
771       {  _poly_zbuf_atex_trans32,      NULL },
772       {  _poly_zbuf_ptex_trans32,      _poly_zbuf_atex_trans32 },
773       {  _poly_zbuf_atex_mask_trans32, NULL },
774       {  _poly_zbuf_ptex_mask_trans32, _poly_zbuf_atex_mask_trans32 }
775    };
776    #endif
777 
778    int zbuf = type & POLYTYPE_ZBUF;
779 
780    int *interpinfo;
781    POLYTYPE_INFO *typeinfo, *typeinfo_zbuf;
782 
783    #ifdef ALLEGRO_MMX
784    POLYTYPE_INFO *typeinfo_mmx, *typeinfo_3d;
785    #endif
786 
787    switch (bitmap_color_depth(bmp)) {
788 
789       #ifdef ALLEGRO_COLOR8
790 
791 	 case 8:
792 	    interpinfo = polytype_interp_pal;
793 	    typeinfo = polytype_info8;
794 	 #ifdef ALLEGRO_MMX
795 	    typeinfo_mmx = polytype_info8x;
796 	    typeinfo_3d = polytype_info8d;
797 	 #endif
798 	    typeinfo_zbuf = polytype_info8z;
799 	    break;
800 
801       #endif
802 
803       #ifdef ALLEGRO_COLOR16
804 
805 	 case 15:
806 	    interpinfo = polytype_interp_tc;
807 	    typeinfo = polytype_info15;
808 	 #ifdef ALLEGRO_MMX
809 	    typeinfo_mmx = polytype_info15x;
810 	    typeinfo_3d = polytype_info15d;
811 	 #endif
812 	    typeinfo_zbuf = polytype_info15z;
813 	    break;
814 
815 	 case 16:
816 	    interpinfo = polytype_interp_tc;
817 	    typeinfo = polytype_info16;
818 	 #ifdef ALLEGRO_MMX
819 	    typeinfo_mmx = polytype_info16x;
820 	    typeinfo_3d = polytype_info16d;
821 	 #endif
822 	    typeinfo_zbuf = polytype_info16z;
823 	    break;
824 
825       #endif
826 
827       #ifdef ALLEGRO_COLOR24
828 
829 	 case 24:
830 	    interpinfo = polytype_interp_tc;
831 	    typeinfo = polytype_info24;
832 	 #ifdef ALLEGRO_MMX
833 	    typeinfo_mmx = polytype_info24x;
834 	    typeinfo_3d = polytype_info24d;
835 	 #endif
836 	    typeinfo_zbuf = polytype_info24z;
837 	    break;
838 
839       #endif
840 
841       #ifdef ALLEGRO_COLOR32
842 
843 	 case 32:
844 	    interpinfo = polytype_interp_tc;
845 	    typeinfo = polytype_info32;
846 	 #ifdef ALLEGRO_MMX
847 	    typeinfo_mmx = polytype_info32x;
848 	    typeinfo_3d = polytype_info32d;
849 	 #endif
850 	    typeinfo_zbuf = polytype_info32z;
851 	    break;
852 
853       #endif
854 
855       default:
856 	 return NULL;
857    }
858 
859    type = CLAMP(0, type & ~POLYTYPE_ZBUF, POLYTYPE_MAX-1);
860    *flags = interpinfo[type];
861 
862    if (texture) {
863       info->texture = texture->line[0];
864       info->umask = texture->w - 1;
865       info->vmask = texture->h - 1;
866       info->vshift = 0;
867       while ((1 << info->vshift) < texture->w)
868 	 info->vshift++;
869    }
870    else {
871       info->texture = NULL;
872       info->umask = info->vmask = info->vshift = 0;
873    }
874 
875    info->seg = bmp->seg;
876    bmp_select(bmp);
877 
878    if (zbuf) {
879       *flags |= INTERP_Z + INTERP_ZBUF;
880       _optim_alternative_drawer = typeinfo_zbuf[type].alternative;
881       return typeinfo_zbuf[type].filler;
882    }
883 
884    #ifdef ALLEGRO_MMX
885    if ((cpu_capabilities & CPU_MMX) && (typeinfo_mmx[type].filler)) {
886       if ((cpu_capabilities & CPU_3DNOW) && (typeinfo_3d[type].filler)) {
887 	 _optim_alternative_drawer = typeinfo_3d[type].alternative;
888 	 return typeinfo_3d[type].filler;
889       }
890       _optim_alternative_drawer = typeinfo_mmx[type].alternative;
891       return typeinfo_mmx[type].filler;
892    }
893    #endif
894 
895    _optim_alternative_drawer = typeinfo[type].alternative;
896 
897    return typeinfo[type].filler;
898 }
899 
900 
901 
902 /* _clip_polygon_segment_f:
903  *  Updates interpolation state values when skipping several places, eg.
904  *  clipping the first part of a scanline.
905  */
_clip_polygon_segment_f(POLYGON_SEGMENT * info,int gap,int flags)906 void _clip_polygon_segment_f(POLYGON_SEGMENT *info, int gap, int flags)
907 {
908    if (flags & INTERP_1COL)
909       info->c += info->dc * gap;
910 
911    if (flags & INTERP_3COL) {
912       info->r += info->dr * gap;
913       info->g += info->dg * gap;
914       info->b += info->db * gap;
915    }
916 
917    if (flags & INTERP_FIX_UV) {
918       info->u += info->du * gap;
919       info->v += info->dv * gap;
920    }
921 
922    if (flags & INTERP_Z) {
923       info->z += info->dz * gap;
924 
925       if (flags & INTERP_FLOAT_UV) {
926 	 info->fu += info->dfu * gap;
927 	 info->fv += info->dfv * gap;
928       }
929    }
930 }
931 
932 
933 
934 /* draw_polygon_segment:
935  *  Polygon helper function to fill a scanline. Calculates deltas for
936  *  whichever values need interpolating, clips the segment, and then calls
937  *  the lowlevel scanline filler.
938  */
draw_polygon_segment(BITMAP * bmp,int ytop,int ybottom,POLYGON_EDGE * e1,POLYGON_EDGE * e2,SCANLINE_FILLER drawer,int flags,int color,POLYGON_SEGMENT * info)939 static void draw_polygon_segment(BITMAP *bmp, int ytop, int ybottom, POLYGON_EDGE *e1, POLYGON_EDGE *e2, SCANLINE_FILLER drawer, int flags, int color, POLYGON_SEGMENT *info)
940 {
941    int x, y, w, gap;
942    fixed step, width;
943    POLYGON_SEGMENT *s1, *s2;
944    AL_CONST SCANLINE_FILLER save_drawer = drawer;
945 
946    /* ensure that e1 is the left edge and e2 is the right edge */
947    if ((e2->x < e1->x) || ((e1->x == e2->x) && (e2->dx < e1->dx))) {
948       POLYGON_EDGE *et = e1;
949       e1 = e2;
950       e2 = et;
951    }
952 
953    s1 = &(e1->dat);
954    s2 = &(e2->dat);
955 
956    if (flags & INTERP_FLAT)
957       info->c = color;
958 
959    /* for each scanline in the polygon... */
960    for (y=ytop; y<=ybottom; y++) {
961       x = fixceil(e1->x);
962       w = fixceil(e2->x) - x;
963       drawer = save_drawer;
964 
965       if (drawer == _poly_scanline_dummy) {
966          if (w > 0)
967 	    bmp->vtable->hfill(bmp, x, y, x+w-1, color);
968       }
969       else {
970          step = (x << 16) - e1->x;
971          width = e2->x - e1->x;
972 /*
973  *  Nasty trick :
974  *  In order to avoid divisions by zero, width is set to -1. This way s1 and s2
975  *  are still being updated but the scanline is not drawn since w == 0.
976  */
977 	 if (width == 0)
978 	    width = -1 << 16;
979 /*
980  *  End of nasty trick.
981  */
982 	 if (flags & INTERP_1COL) {
983 	    info->dc = fixdiv(s2->c - s1->c, width);
984 	    info->c = s1->c + fixmul(step, info->dc);
985 	    s1->c += s1->dc;
986 	    s2->c += s2->dc;
987 	 }
988 
989 	 if (flags & INTERP_3COL) {
990 	    info->dr = fixdiv(s2->r - s1->r, width);
991 	    info->dg = fixdiv(s2->g - s1->g, width);
992 	    info->db = fixdiv(s2->b - s1->b, width);
993 	    info->r = s1->r + fixmul(step, info->dr);
994 	    info->g = s1->g + fixmul(step, info->dg);
995 	    info->b = s1->b + fixmul(step, info->db);
996 
997 	    s1->r += s1->dr;
998 	    s2->r += s2->dr;
999 	    s1->g += s1->dg;
1000 	    s2->g += s2->dg;
1001 	    s1->b += s1->db;
1002 	    s2->b += s2->db;
1003 	 }
1004 
1005 	 if (flags & INTERP_FIX_UV) {
1006 	    info->du = fixdiv(s2->u - s1->u, width);
1007 	    info->dv = fixdiv(s2->v - s1->v, width);
1008 	    info->u = s1->u + fixmul(step, info->du);
1009 	    info->v = s1->v + fixmul(step, info->dv);
1010 
1011 	    s1->u += s1->du;
1012 	    s2->u += s2->du;
1013 	    s1->v += s1->dv;
1014 	    s2->v += s2->dv;
1015 	 }
1016 
1017 	 if (flags & INTERP_Z) {
1018 	    float step_f = fixtof(step);
1019 	    float w1 = 65536. / width;
1020 
1021 	    info->dz = (s2->z - s1->z) * w1;
1022 	    info->z = s1->z + info->dz * step_f;
1023 	    s1->z += s1->dz;
1024 	    s2->z += s2->dz;
1025 
1026 	    if (flags & INTERP_FLOAT_UV) {
1027 	       info->dfu = (s2->fu - s1->fu) * w1;
1028 	       info->dfv = (s2->fv - s1->fv) * w1;
1029 	       info->fu = s1->fu + info->dfu * step_f;
1030 	       info->fv = s1->fv + info->dfv * step_f;
1031 
1032 	       s1->fu += s1->dfu;
1033 	       s2->fu += s2->dfu;
1034 	       s1->fv += s1->dfv;
1035 	       s2->fv += s2->dfv;
1036 	    }
1037 	 }
1038 
1039 	 /* if clipping is enabled then clip the segment */
1040 	 if (bmp->clip) {
1041 	    if (x < bmp->cl) {
1042 	       gap = bmp->cl - x;
1043 	       x = bmp->cl;
1044 	       w -= gap;
1045 	       _clip_polygon_segment_f(info, gap, flags);
1046 	    }
1047 
1048 	    if (x+w > bmp->cr)
1049 	       w = bmp->cr - x;
1050 	 }
1051 
1052 	 if (w > 0) {
1053 	    int dx = x * BYTES_PER_PIXEL(bitmap_color_depth(bmp));
1054 
1055 	    if ((flags & OPT_FLOAT_UV_TO_FIX) && (info->dz == 0)) {
1056 	       float z1 = 1. / info->z;
1057 	       info->u = info->fu * z1;
1058 	       info->v = info->fv * z1;
1059 	       info->du = info->dfu * z1;
1060 	       info->dv = info->dfv * z1;
1061 	       drawer = _optim_alternative_drawer;
1062 	    }
1063 
1064             if (flags & INTERP_ZBUF)
1065                info->zbuf_addr = bmp_write_line(_zbuffer, y) + x * sizeof(float);
1066 
1067 	    info->read_addr = bmp_read_line(bmp, y) + dx;
1068 	    drawer(bmp_write_line(bmp, y) + dx, w, info);
1069 	 }
1070       }
1071 
1072       e1->x += e1->dx;
1073       e2->x += e2->dx;
1074    }
1075 }
1076 
1077 
1078 
1079 /* do_polygon3d:
1080  *  Helper function for rendering 3d polygon, used by both the fixed point
1081  *  and floating point drawing functions.
1082  */
do_polygon3d(BITMAP * bmp,int top,int bottom,POLYGON_EDGE * left_edge,SCANLINE_FILLER drawer,int flags,int color,POLYGON_SEGMENT * info)1083 static void do_polygon3d(BITMAP *bmp, int top, int bottom, POLYGON_EDGE *left_edge, SCANLINE_FILLER drawer, int flags, int color, POLYGON_SEGMENT *info)
1084 {
1085    int ytop, ybottom;
1086    #ifdef ALLEGRO_DOS
1087       int old87 = 0;
1088    #endif
1089    POLYGON_EDGE *right_edge;
1090    ASSERT(bmp);
1091 
1092    /* set fpu to single-precision, truncate mode */
1093    #ifdef ALLEGRO_DOS
1094       if (flags & (INTERP_Z | INTERP_FLOAT_UV))
1095          old87 = _control87(PC_24 | RC_CHOP, MCW_PC | MCW_RC);
1096    #endif
1097 
1098    acquire_bitmap(bmp);
1099 
1100    if ((left_edge->prev != left_edge->next) && (left_edge->prev->top == top))
1101       left_edge = left_edge->prev;
1102 
1103    right_edge = left_edge->next;
1104 
1105    ytop = top;
1106    for (;;) {
1107       if (right_edge->bottom <= left_edge->bottom)
1108 	 ybottom = right_edge->bottom;
1109       else
1110 	 ybottom = left_edge->bottom;
1111 
1112       /* fill the scanline */
1113       draw_polygon_segment(bmp, ytop, ybottom, left_edge, right_edge, drawer, flags, color, info);
1114 
1115       if (ybottom >= bottom) break;
1116 
1117       /* update edges */
1118       if (ybottom >= left_edge->bottom)
1119 	 left_edge = left_edge->prev;
1120       if (ybottom >= right_edge->bottom)
1121 	 right_edge = right_edge->next;
1122 
1123       ytop = ybottom + 1;
1124    }
1125 
1126    bmp_unwrite_line(bmp);
1127    release_bitmap(bmp);
1128 
1129    /* reset fpu mode */
1130    #ifdef ALLEGRO_DOS
1131       if (flags & (INTERP_Z | INTERP_FLOAT_UV))
1132          _control87(old87, MCW_PC | MCW_RC);
1133    #endif
1134 }
1135 
1136 
1137 
1138 /* polygon3d:
1139  *  Draws a 3d polygon in the specified mode. The vertices parameter should
1140  *  be followed by that many pointers to V3D structures, which describe each
1141  *  vertex of the polygon.
1142  */
_soft_polygon3d(BITMAP * bmp,int type,BITMAP * texture,int vc,V3D * vtx[])1143 void _soft_polygon3d(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D *vtx[])
1144 {
1145    int c;
1146    int flags;
1147    int top = INT_MAX;
1148    int bottom = INT_MIN;
1149    V3D *v1, *v2;
1150    POLYGON_EDGE *edge, *edge0, *start_edge;
1151    POLYGON_EDGE *list_edges = NULL;
1152    POLYGON_SEGMENT info;
1153    SCANLINE_FILLER drawer;
1154    ASSERT(bmp);
1155 
1156    if (vc < 3)
1157       return;
1158 
1159    /* set up the drawing mode */
1160    drawer = _get_scanline_filler(type, &flags, &info, texture, bmp);
1161    if (!drawer)
1162       return;
1163 
1164    /* allocate some space for the active edge table */
1165    _grow_scratch_mem(sizeof(POLYGON_EDGE) * vc);
1166    start_edge = edge0 = edge = (POLYGON_EDGE *)_scratch_mem;
1167 
1168    /* fill the double-linked list of edges (order unimportant) */
1169    v2 = vtx[vc-1];
1170 
1171    for (c=0; c<vc; c++) {
1172       v1 = v2;
1173       v2 = vtx[c];
1174 
1175       if (_fill_3d_edge_structure(edge, v1, v2, flags, bmp)) {
1176 	 if (edge->top < top) {
1177             top = edge->top;
1178 	    start_edge = edge;
1179          }
1180 
1181 	 if (edge->bottom > bottom)
1182             bottom = edge->bottom;
1183 
1184          if (list_edges) {
1185             list_edges->next = edge;
1186 	    edge->prev = list_edges;
1187          }
1188 
1189 	 list_edges = edge;
1190 	 edge++;
1191       }
1192    }
1193 
1194    if (list_edges) {
1195       /* close the double-linked list */
1196       edge0->prev = --edge;
1197       edge->next = edge0;
1198 
1199       /* render the polygon */
1200       do_polygon3d(bmp, top, bottom, start_edge, drawer, flags, vtx[0]->c, &info);
1201    }
1202 }
1203 
1204 
1205 
1206 /* polygon3d_f:
1207  *  Floating point version of polygon3d().
1208  */
_soft_polygon3d_f(BITMAP * bmp,int type,BITMAP * texture,int vc,V3D_f * vtx[])1209 void _soft_polygon3d_f(BITMAP *bmp, int type, BITMAP *texture, int vc, V3D_f *vtx[])
1210 {
1211    int c;
1212    int flags;
1213    int top = INT_MAX;
1214    int bottom = INT_MIN;
1215    V3D_f *v1, *v2;
1216    POLYGON_EDGE *edge, *edge0, *start_edge;
1217    POLYGON_EDGE *list_edges = NULL;
1218    POLYGON_SEGMENT info;
1219    SCANLINE_FILLER drawer;
1220    ASSERT(bmp);
1221 
1222    if (vc < 3)
1223       return;
1224 
1225    /* set up the drawing mode */
1226    drawer = _get_scanline_filler(type, &flags, &info, texture, bmp);
1227    if (!drawer)
1228       return;
1229 
1230    /* allocate some space for the active edge table */
1231    _grow_scratch_mem(sizeof(POLYGON_EDGE) * vc);
1232    start_edge = edge0 = edge = (POLYGON_EDGE *)_scratch_mem;
1233 
1234    /* fill the double-linked list of edges in clockwise order */
1235    v2 = vtx[vc-1];
1236 
1237    for (c=0; c<vc; c++) {
1238       v1 = v2;
1239       v2 = vtx[c];
1240 
1241       if (_fill_3d_edge_structure_f(edge, v1, v2, flags, bmp)) {
1242          if (edge->top < top) {
1243             top = edge->top;
1244 	    start_edge = edge;
1245          }
1246 
1247 	 if (edge->bottom > bottom)
1248             bottom = edge->bottom;
1249 
1250          if (list_edges) {
1251             list_edges->next = edge;
1252 	    edge->prev = list_edges;
1253          }
1254 
1255 	 list_edges = edge;
1256 	 edge++;
1257       }
1258    }
1259 
1260    if (list_edges) {
1261       /* close the double-linked list */
1262       edge0->prev = --edge;
1263       edge->next = edge0;
1264 
1265       /* render the polygon */
1266       do_polygon3d(bmp, top, bottom, start_edge, drawer, flags, vtx[0]->c, &info);
1267    }
1268 }
1269 
1270 
1271 
1272 /* draw_triangle_part:
1273  *  Triangle helper function to fill a triangle part. Computes interpolation,
1274  *  clips the segment, and then calls the lowlevel scanline filler.
1275  */
draw_triangle_part(BITMAP * bmp,int ytop,int ybottom,POLYGON_EDGE * left_edge,POLYGON_EDGE * right_edge,SCANLINE_FILLER drawer,int flags,int color,POLYGON_SEGMENT * info)1276 static void draw_triangle_part(BITMAP *bmp, int ytop, int ybottom, POLYGON_EDGE *left_edge, POLYGON_EDGE *right_edge, SCANLINE_FILLER drawer, int flags, int color, POLYGON_SEGMENT *info)
1277 {
1278    int x, y, w;
1279    int gap;
1280    AL_CONST int test_optim = (flags & OPT_FLOAT_UV_TO_FIX) && (info->dz == 0);
1281    fixed step;
1282    POLYGON_SEGMENT *s1;
1283 
1284    /* ensure that left_edge and right_edge are the right way round */
1285    if ((right_edge->x < left_edge->x) ||
1286      ((left_edge->x == right_edge->x) && (right_edge->dx < left_edge->dx))) {
1287       POLYGON_EDGE *other_edge = left_edge;
1288       left_edge = right_edge;
1289       right_edge = other_edge;
1290    }
1291 
1292    s1 = &(left_edge->dat);
1293 
1294    if (flags & INTERP_FLAT)
1295       info->c = color;
1296 
1297    for (y=ytop; y<=ybottom; y++) {
1298       x = fixceil(left_edge->x);
1299       w = fixceil(right_edge->x) - x;
1300       step = (x << 16) - left_edge->x;
1301 
1302       if (drawer == _poly_scanline_dummy) {
1303          if (w > 0)
1304 	    bmp->vtable->hfill(bmp, x, y, x+w-1, color);
1305       }
1306       else {
1307 	 if (flags & INTERP_1COL) {
1308 	    info->c = s1->c + fixmul(step, info->dc);
1309             s1->c += s1->dc;
1310          }
1311 
1312 	 if (flags & INTERP_3COL) {
1313 	    info->r = s1->r + fixmul(step, info->dr);
1314 	    info->g = s1->g + fixmul(step, info->dg);
1315 	    info->b = s1->b + fixmul(step, info->db);
1316 
1317 	    s1->r += s1->dr;
1318 	    s1->g += s1->dg;
1319 	    s1->b += s1->db;
1320 	 }
1321 
1322 	 if (flags & INTERP_FIX_UV) {
1323 	    info->u = s1->u + fixmul(step, info->du);
1324 	    info->v = s1->v + fixmul(step, info->dv);
1325 
1326 	    s1->u += s1->du;
1327 	    s1->v += s1->dv;
1328 	 }
1329 
1330 	 if (flags & INTERP_Z) {
1331 	    float step_f = fixtof(step);
1332 
1333 	    info->z = s1->z + info->dz * step_f;
1334 	    s1->z += s1->dz;
1335 
1336 	    if (flags & INTERP_FLOAT_UV) {
1337 	       info->fu = s1->fu + info->dfu * step_f;
1338 	       info->fv = s1->fv + info->dfv * step_f;
1339 
1340 	       s1->fu += s1->dfu;
1341 	       s1->fv += s1->dfv;
1342 	    }
1343 	 }
1344 
1345 	 /* if clipping is enabled then clip the segment */
1346 	 if (bmp->clip) {
1347 	    if (x < bmp->cl) {
1348 	       gap = bmp->cl - x;
1349 	       x = bmp->cl;
1350 	       w -= gap;
1351 	       _clip_polygon_segment_f(info, gap, flags);
1352 	    }
1353 
1354 	    if (x+w > bmp->cr)
1355 	       w = bmp->cr - x;
1356 	 }
1357 
1358 	 if (w > 0) {
1359 	    int dx = x * BYTES_PER_PIXEL(bitmap_color_depth(bmp));
1360 
1361 	    if (test_optim) {
1362 	       float z1 = 1. / info->z;
1363 	       info->u = info->fu * z1;
1364 	       info->v = info->fv * z1;
1365 	       info->du = info->dfu * z1;
1366 	       info->dv = info->dfv * z1;
1367 	       drawer = _optim_alternative_drawer;
1368 	    }
1369 
1370             if (flags & INTERP_ZBUF)
1371                info->zbuf_addr = bmp_write_line(_zbuffer, y) + x * sizeof(float);
1372 
1373 	    info->read_addr = bmp_read_line(bmp, y) + dx;
1374 	    drawer(bmp_write_line(bmp, y) + dx, w, info);
1375 	 }
1376       }
1377 
1378       left_edge->x += left_edge->dx;
1379       right_edge->x += right_edge->dx;
1380    }
1381 }
1382 
1383 
1384 
1385 /* _triangle_deltas:
1386  *  Triangle3d helper function to calculate the deltas. (For triangles,
1387  *  deltas are constant over the whole triangle).
1388  */
_triangle_deltas(BITMAP * bmp,fixed w,POLYGON_SEGMENT * s1,POLYGON_SEGMENT * info,AL_CONST V3D * v,int flags)1389 static void _triangle_deltas(BITMAP *bmp, fixed w, POLYGON_SEGMENT *s1, POLYGON_SEGMENT *info, AL_CONST V3D *v, int flags)
1390 {
1391    if (flags & INTERP_1COL)
1392       info->dc = fixdiv(s1->c - itofix(v->c), w);
1393 
1394    if (flags & INTERP_3COL) {
1395       int r, g, b;
1396 
1397       if (flags & COLOR_TO_RGB) {
1398       	 AL_CONST int coldepth = bitmap_color_depth(bmp);
1399 	 r = getr_depth(coldepth, v->c);
1400 	 g = getg_depth(coldepth, v->c);
1401 	 b = getb_depth(coldepth, v->c);
1402       }
1403       else {
1404 	 r = (v->c >> 16) & 0xFF;
1405 	 g = (v->c >> 8) & 0xFF;
1406 	 b = v->c & 0xFF;
1407       }
1408 
1409       info->dr = fixdiv(s1->r - itofix(r), w);
1410       info->dg = fixdiv(s1->g - itofix(g), w);
1411       info->db = fixdiv(s1->b - itofix(b), w);
1412    }
1413 
1414    if (flags & INTERP_FIX_UV) {
1415       info->du = fixdiv(s1->u - v->u, w);
1416       info->dv = fixdiv(s1->v - v->v, w);
1417    }
1418 
1419    if (flags & INTERP_Z) {
1420       float w1 = 65536. / w;
1421 
1422       /* Z (depth) interpolation */
1423       float z1 = 65536. / v->z;
1424 
1425       info->dz = (s1->z - z1) * w1;
1426 
1427       if (flags & INTERP_FLOAT_UV) {
1428 	 /* floating point (perspective correct) texture interpolation */
1429 	 float fu1 = v->u * z1;
1430 	 float fv1 = v->v * z1;
1431 
1432 	 info->dfu = (s1->fu - fu1) * w1;
1433 	 info->dfv = (s1->fv - fv1) * w1;
1434       }
1435    }
1436 }
1437 
1438 
1439 /* _triangle_deltas_f:
1440  *  Floating point version of _triangle_deltas().
1441  */
_triangle_deltas_f(BITMAP * bmp,fixed w,POLYGON_SEGMENT * s1,POLYGON_SEGMENT * info,AL_CONST V3D_f * v,int flags)1442 static void _triangle_deltas_f(BITMAP *bmp, fixed w, POLYGON_SEGMENT *s1, POLYGON_SEGMENT *info, AL_CONST V3D_f *v, int flags)
1443 {
1444    if (flags & INTERP_1COL)
1445       info->dc = fixdiv(s1->c - itofix(v->c), w);
1446 
1447    if (flags & INTERP_3COL) {
1448       int r, g, b;
1449 
1450       if (flags & COLOR_TO_RGB) {
1451       	 AL_CONST int coldepth = bitmap_color_depth(bmp);
1452 	 r = getr_depth(coldepth, v->c);
1453 	 g = getg_depth(coldepth, v->c);
1454 	 b = getb_depth(coldepth, v->c);
1455       }
1456       else {
1457 	 r = (v->c >> 16) & 0xFF;
1458 	 g = (v->c >> 8) & 0xFF;
1459 	 b = v->c & 0xFF;
1460       }
1461 
1462       info->dr = fixdiv(s1->r - itofix(r), w);
1463       info->dg = fixdiv(s1->g - itofix(g), w);
1464       info->db = fixdiv(s1->b - itofix(b), w);
1465    }
1466 
1467    if (flags & INTERP_FIX_UV) {
1468       info->du = fixdiv(s1->u - ftofix(v->u), w);
1469       info->dv = fixdiv(s1->v - ftofix(v->v), w);
1470    }
1471 
1472    if (flags & INTERP_Z) {
1473       float w1 = 65536. / w;
1474 
1475       /* Z (depth) interpolation */
1476       float z1 = 1. / v->z;
1477 
1478       info->dz = (s1->z - z1) * w1;
1479 
1480       if (flags & INTERP_FLOAT_UV) {
1481 	 /* floating point (perspective correct) texture interpolation */
1482 	 float fu1 = v->u * z1 * 65536.;
1483 	 float fv1 = v->v * z1 * 65536.;
1484 
1485 	 info->dfu = (s1->fu - fu1) * w1;
1486 	 info->dfv = (s1->fv - fv1) * w1;
1487       }
1488    }
1489 }
1490 
1491 
1492 
1493 /* _clip_polygon_segment:
1494  *  Fixed point version of _clip_polygon_segment_f().
1495  */
_clip_polygon_segment(POLYGON_SEGMENT * info,fixed gap,int flags)1496 void _clip_polygon_segment(POLYGON_SEGMENT *info, fixed gap, int flags)
1497 {
1498    if (flags & INTERP_1COL)
1499       info->c += fixmul(info->dc, gap);
1500 
1501    if (flags & INTERP_3COL) {
1502       info->r += fixmul(info->dr, gap);
1503       info->g += fixmul(info->dg, gap);
1504       info->b += fixmul(info->db, gap);
1505    }
1506 
1507    if (flags & INTERP_FIX_UV) {
1508       info->u += fixmul(info->du, gap);
1509       info->v += fixmul(info->dv, gap);
1510    }
1511 
1512    if (flags & INTERP_Z) {
1513       float gap_f = fixtof(gap);
1514 
1515       info->z += info->dz * gap_f;
1516 
1517       if (flags & INTERP_FLOAT_UV) {
1518 	 info->fu += info->dfu * gap_f;
1519 	 info->fv += info->dfv * gap_f;
1520       }
1521    }
1522 }
1523 
1524 
1525 
1526 /* triangle3d:
1527  *  Draws a 3d triangle.
1528  */
_soft_triangle3d(BITMAP * bmp,int type,BITMAP * texture,V3D * v1,V3D * v2,V3D * v3)1529 void _soft_triangle3d(BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3)
1530 {
1531    int flags;
1532 
1533    #ifdef ALLEGRO_DOS
1534       int old87 = 0;
1535    #endif
1536 
1537    int color = v1->c;
1538    V3D *vt1, *vt2, *vt3;
1539    POLYGON_EDGE edge1, edge2;
1540    POLYGON_SEGMENT info;
1541    SCANLINE_FILLER drawer;
1542    ASSERT(bmp);
1543 
1544    /* set up the drawing mode */
1545    drawer = _get_scanline_filler(type, &flags, &info, texture, bmp);
1546    if (!drawer)
1547       return;
1548 
1549    /* sort the vertices so that vt1->y <= vt2->y <= vt3->y */
1550    if (v1->y > v2->y) {
1551       vt1 = v2;
1552       vt2 = v1;
1553    }
1554    else {
1555       vt1 = v1;
1556       vt2 = v2;
1557    }
1558 
1559    if (vt1->y > v3->y) {
1560       vt3 = vt1;
1561       vt1 = v3;
1562    }
1563    else
1564       vt3 = v3;
1565 
1566    if (vt2->y > vt3->y) {
1567       V3D* vtemp = vt2;
1568       vt2 = vt3;
1569       vt3 = vtemp;
1570    }
1571 
1572    /* set fpu to single-precision, truncate mode */
1573    #ifdef ALLEGRO_DOS
1574       if (flags & (INTERP_Z | INTERP_FLOAT_UV))
1575 	 old87 = _control87(PC_24 | RC_CHOP, MCW_PC | MCW_RC);
1576    #endif
1577 
1578    /* do 3D triangle*/
1579    if (_fill_3d_edge_structure(&edge1, vt1, vt3, flags, bmp)) {
1580 
1581       acquire_bitmap(bmp);
1582 
1583       /* calculate deltas */
1584       if (drawer != _poly_scanline_dummy) {
1585 	 fixed w, h;
1586 	 POLYGON_SEGMENT s1 = edge1.dat;
1587 
1588 	 h = vt2->y - (edge1.top << 16);
1589 	 _clip_polygon_segment(&s1, h, flags);
1590 
1591 	 w = edge1.x + fixmul(h, edge1.dx) - vt2->x;
1592 	 if (w) _triangle_deltas(bmp, w, &s1, &info, vt2, flags);
1593       }
1594 
1595       /* draws part between y1 and y2 */
1596       if (_fill_3d_edge_structure(&edge2, vt1, vt2, flags, bmp))
1597 	 draw_triangle_part(bmp, edge2.top, edge2.bottom, &edge1, &edge2, drawer, flags, color, &info);
1598 
1599       /* draws part between y2 and y3 */
1600       if (_fill_3d_edge_structure(&edge2, vt2, vt3, flags, bmp))
1601 	 draw_triangle_part(bmp, edge2.top, edge2.bottom, &edge1, &edge2, drawer, flags, color, &info);
1602 
1603       bmp_unwrite_line(bmp);
1604       release_bitmap(bmp);
1605    }
1606 
1607    /* reset fpu mode */
1608    #ifdef ALLEGRO_DOS
1609       if (flags & (INTERP_Z | INTERP_FLOAT_UV))
1610 	 _control87(old87, MCW_PC | MCW_RC);
1611    #endif
1612 }
1613 
1614 
1615 
1616 /* triangle3d_f:
1617  *  Draws a 3d triangle.
1618  */
_soft_triangle3d_f(BITMAP * bmp,int type,BITMAP * texture,V3D_f * v1,V3D_f * v2,V3D_f * v3)1619 void _soft_triangle3d_f(BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3)
1620 {
1621    int flags;
1622 
1623    #ifdef ALLEGRO_DOS
1624       int old87 = 0;
1625    #endif
1626 
1627    int color = v1->c;
1628    V3D_f *vt1, *vt2, *vt3;
1629    POLYGON_EDGE edge1, edge2;
1630    POLYGON_SEGMENT info;
1631    SCANLINE_FILLER drawer;
1632    ASSERT(bmp);
1633 
1634    /* set up the drawing mode */
1635    drawer = _get_scanline_filler(type, &flags, &info, texture, bmp);
1636    if (!drawer)
1637       return;
1638 
1639    /* sort the vertices so that vt1->y <= vt2->y <= vt3->y */
1640    if (v1->y > v2->y) {
1641       vt1 = v2;
1642       vt2 = v1;
1643    }
1644    else {
1645       vt1 = v1;
1646       vt2 = v2;
1647    }
1648 
1649    if (vt1->y > v3->y) {
1650       vt3 = vt1;
1651       vt1 = v3;
1652    }
1653    else
1654       vt3 = v3;
1655 
1656    if (vt2->y > vt3->y) {
1657       V3D_f* vtemp = vt2;
1658       vt2 = vt3;
1659       vt3 = vtemp;
1660    }
1661 
1662    /* set fpu to single-precision, truncate mode */
1663    #ifdef ALLEGRO_DOS
1664       if (flags & (INTERP_Z | INTERP_FLOAT_UV))
1665          old87 = _control87(PC_24 | RC_CHOP, MCW_PC | MCW_RC);
1666    #endif
1667 
1668    /* do 3D triangle*/
1669    if (_fill_3d_edge_structure_f(&edge1, vt1, vt3, flags, bmp)) {
1670 
1671       acquire_bitmap(bmp);
1672 
1673       /* calculate deltas */
1674       if (drawer != _poly_scanline_dummy) {
1675 	 fixed w, h;
1676 	 POLYGON_SEGMENT s1 = edge1.dat;
1677 
1678 	 h = ftofix(vt2->y) - (edge1.top << 16);
1679 	 _clip_polygon_segment(&s1, h, flags);
1680 
1681 	 w = edge1.x + fixmul(h, edge1.dx) - ftofix(vt2->x);
1682 	 if (w) _triangle_deltas_f(bmp, w, &s1, &info, vt2, flags);
1683       }
1684 
1685       /* draws part between y1 and y2 */
1686       if (_fill_3d_edge_structure_f(&edge2, vt1, vt2, flags, bmp))
1687 	 draw_triangle_part(bmp, edge2.top, edge2.bottom, &edge1, &edge2, drawer, flags, color, &info);
1688 
1689       /* draws part between y2 and y3 */
1690       if (_fill_3d_edge_structure_f(&edge2, vt2, vt3, flags, bmp))
1691 	 draw_triangle_part(bmp, edge2.top, edge2.bottom, &edge1, &edge2, drawer, flags, color, &info);
1692 
1693       bmp_unwrite_line(bmp);
1694       release_bitmap(bmp);
1695    }
1696 
1697    /* reset fpu mode */
1698    #ifdef ALLEGRO_DOS
1699       if (flags & (INTERP_Z | INTERP_FLOAT_UV))
1700 	 _control87(old87, MCW_PC | MCW_RC);
1701    #endif
1702 }
1703 
1704 
1705 
1706 /* quad3d:
1707  *  Draws a 3d quad.
1708  */
_soft_quad3d(BITMAP * bmp,int type,BITMAP * texture,V3D * v1,V3D * v2,V3D * v3,V3D * v4)1709 void _soft_quad3d(BITMAP *bmp, int type, BITMAP *texture, V3D *v1, V3D *v2, V3D *v3, V3D *v4)
1710 {
1711    #if (defined ALLEGRO_GCC) && (defined ALLEGRO_I386)
1712       ASSERT(bmp);
1713 
1714       /* dodgy assumption alert! See comments for triangle() */
1715       polygon3d(bmp, type, texture, 4, &v1);
1716 
1717    #else
1718 
1719       V3D *vertex[4];
1720       ASSERT(bmp);
1721 
1722       vertex[0] = v1;
1723       vertex[1] = v2;
1724       vertex[2] = v3;
1725       vertex[3] = v4;
1726       polygon3d(bmp, type, texture, 4, vertex);
1727 
1728    #endif
1729 }
1730 
1731 
1732 
1733 /* quad3d_f:
1734  *  Draws a 3d quad.
1735  */
_soft_quad3d_f(BITMAP * bmp,int type,BITMAP * texture,V3D_f * v1,V3D_f * v2,V3D_f * v3,V3D_f * v4)1736 void _soft_quad3d_f(BITMAP *bmp, int type, BITMAP *texture, V3D_f *v1, V3D_f *v2, V3D_f *v3, V3D_f *v4)
1737 {
1738    #if (defined ALLEGRO_GCC) && (defined ALLEGRO_I386)
1739       ASSERT(bmp);
1740 
1741       /* dodgy assumption alert! See comments for triangle() */
1742       polygon3d_f(bmp, type, texture, 4, &v1);
1743 
1744    #else
1745 
1746       V3D_f *vertex[4];
1747       ASSERT(bmp);
1748 
1749       vertex[0] = v1;
1750       vertex[1] = v2;
1751       vertex[2] = v3;
1752       vertex[3] = v4;
1753       polygon3d_f(bmp, type, texture, 4, vertex);
1754 
1755    #endif
1756 }
1757 
1758 
1759 
1760 /* create_zbuffer:
1761  *  Creates a new Z-buffer the size of the given bitmap.
1762  */
create_zbuffer(BITMAP * bmp)1763 ZBUFFER *create_zbuffer(BITMAP *bmp)
1764 {
1765    ASSERT(bmp);
1766    return create_bitmap_ex(32, bmp->w, bmp->h);
1767 }
1768 
1769 
1770 
1771 /* clear_zbuffer:
1772  *  Clears the given z-buffer, z is the value written in the z-buffer
1773  *  - it is 1/(z coordinate), z=0 meaning far away.
1774  */
clear_zbuffer(ZBUFFER * zbuf,float z)1775 void clear_zbuffer(ZBUFFER *zbuf, float z)
1776 {
1777    union {
1778       float zf;
1779       long zi;
1780    } _zbuf_clip;
1781    ASSERT(zbuf);
1782 
1783    _zbuf_clip.zf = z;
1784    clear_to_color(zbuf, _zbuf_clip.zi);
1785 }
1786 
1787 
1788 
1789 /* destroy_zbuffer:
1790  *  Destroys the given z-buffer.
1791  */
destroy_zbuffer(ZBUFFER * zbuf)1792 void destroy_zbuffer(ZBUFFER *zbuf)
1793 {
1794    if (zbuf) {
1795       if (zbuf == _zbuffer)
1796 	 _zbuffer = NULL;
1797       destroy_bitmap(zbuf);
1798    }
1799 }
1800 
1801 
1802 
1803 /* set_zbuffer:
1804  *  Makes polygon drawing routines use the given BITMAP as z-buffer.
1805  */
set_zbuffer(ZBUFFER * zbuf)1806 void set_zbuffer(ZBUFFER *zbuf)
1807 {
1808    ASSERT(zbuf);
1809    _zbuffer = zbuf;
1810 }
1811 
1812 
1813 
1814 /* create_sub_zbuffer:
1815  *  Creates a new sub-z-buffer of the given z-buffer. A sub-z-buffer is
1816  *  exactly like a sub-bitmap, buf for z-buffers.
1817  */
create_sub_zbuffer(ZBUFFER * parent,int x,int y,int width,int height)1818 ZBUFFER *create_sub_zbuffer(ZBUFFER *parent, int x, int y, int width, int height)
1819 {
1820    ASSERT(parent);
1821    /* For now, just use the code for BITMAPs. */
1822    return create_sub_bitmap(parent, x, y, width, height);
1823 }
1824