1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      Polygon scanline filler helpers (gouraud shading, tmapping, etc).
12  *
13  *      By Michael Bukin.
14  *
15  *	Scanline subdivision in *_PTEX functions and transparency modes
16  *	added by Bertrand Coconnier.
17  *
18  *      See readme.txt for copyright information.
19  */
20 
21 #ifndef __bma_cscan_h
22 #define __bma_cscan_h
23 
24 #ifdef _bma_scan_gcol
25 
26 /* _poly_scanline_gcol:
27  *  Fills a single-color gouraud shaded polygon scanline.
28  */
FUNC_POLY_SCANLINE_GCOL(uintptr_t addr,int w,POLYGON_SEGMENT * info)29 void FUNC_POLY_SCANLINE_GCOL(uintptr_t addr, int w, POLYGON_SEGMENT *info)
30 {
31    int x;
32    fixed c, dc;
33    PIXEL_PTR d;
34 
35    ASSERT(addr);
36    ASSERT(info);
37 
38    c = info->c;
39    dc = info->dc;
40    d = (PIXEL_PTR) addr;
41 
42    for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) {
43       PUT_PIXEL(d, (c >> 16));
44       c += dc;
45    }
46 }
47 
48 #endif /* _bma_scan_gcol */
49 
50 
51 
52 /* _poly_scanline_grgb:
53  *  Fills an gouraud shaded polygon scanline.
54  */
FUNC_POLY_SCANLINE_GRGB(uintptr_t addr,int w,POLYGON_SEGMENT * info)55 void FUNC_POLY_SCANLINE_GRGB(uintptr_t addr, int w, POLYGON_SEGMENT *info)
56 {
57    int x;
58    fixed r, g, b;
59    fixed dr, dg, db;
60    PIXEL_PTR d;
61 
62    ASSERT(addr);
63    ASSERT(info);
64 
65    r = info->r;
66    g = info->g;
67    b = info->b;
68    dr = info->dr;
69    dg = info->dg;
70    db = info->db;
71    d = (PIXEL_PTR) addr;
72 
73    for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) {
74       PUT_RGB(d, (r >> 16), (g >> 16), (b >> 16));
75       r += dr;
76       g += dg;
77       b += db;
78    }
79 }
80 
81 
82 
83 /* _poly_scanline_atex:
84  *  Fills an affine texture mapped polygon scanline.
85  */
FUNC_POLY_SCANLINE_ATEX(uintptr_t addr,int w,POLYGON_SEGMENT * info)86 void FUNC_POLY_SCANLINE_ATEX(uintptr_t addr, int w, POLYGON_SEGMENT *info)
87 {
88    int x;
89    int vmask, vshift, umask;
90    fixed u, v, du, dv;
91    PIXEL_PTR texture;
92    PIXEL_PTR d;
93 
94    ASSERT(addr);
95    ASSERT(info);
96 
97    vmask = info->vmask << info->vshift;
98    vshift = 16 - info->vshift;
99    umask = info->umask;
100    u = info->u;
101    v = info->v;
102    du = info->du;
103    dv = info->dv;
104    texture = (PIXEL_PTR) (info->texture);
105    d = (PIXEL_PTR) addr;
106 
107    for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) {
108       PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
109       unsigned long color = GET_MEMORY_PIXEL(s);
110 
111       PUT_PIXEL(d, color);
112       u += du;
113       v += dv;
114    }
115 }
116 
117 
118 
119 /* _poly_scanline_atex_mask:
120  *  Fills a masked affine texture mapped polygon scanline.
121  */
FUNC_POLY_SCANLINE_ATEX_MASK(uintptr_t addr,int w,POLYGON_SEGMENT * info)122 void FUNC_POLY_SCANLINE_ATEX_MASK(uintptr_t addr, int w, POLYGON_SEGMENT *info)
123 {
124    int x;
125    int vmask, vshift, umask;
126    fixed u, v, du, dv;
127    PIXEL_PTR texture;
128    PIXEL_PTR d;
129 
130    ASSERT(addr);
131    ASSERT(info);
132 
133    vmask = info->vmask << info->vshift;
134    vshift = 16 - info->vshift;
135    umask = info->umask;
136    u = info->u;
137    v = info->v;
138    du = info->du;
139    dv = info->dv;
140    texture = (PIXEL_PTR) (info->texture);
141    d = (PIXEL_PTR) addr;
142 
143    for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) {
144       PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
145       unsigned long color = GET_MEMORY_PIXEL(s);
146 
147       if (!IS_MASK(color)) {
148 	 PUT_PIXEL(d, color);
149       }
150       u += du;
151       v += dv;
152    }
153 }
154 
155 
156 
157 /* _poly_scanline_atex_lit:
158  *  Fills a lit affine texture mapped polygon scanline.
159  */
FUNC_POLY_SCANLINE_ATEX_LIT(uintptr_t addr,int w,POLYGON_SEGMENT * info)160 void FUNC_POLY_SCANLINE_ATEX_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info)
161 {
162    int x;
163    int vmask, vshift, umask;
164    fixed u, v, c, du, dv, dc;
165    PS_BLENDER blender;
166    PIXEL_PTR texture;
167    PIXEL_PTR d;
168 
169    ASSERT(addr);
170    ASSERT(info);
171 
172    vmask = info->vmask << info->vshift;
173    vshift = 16 - info->vshift;
174    umask = info->umask;
175    u = info->u;
176    v = info->v;
177    c = info->c;
178    du = info->du;
179    dv = info->dv;
180    dc = info->dc;
181    blender = MAKE_PS_BLENDER();
182    texture = (PIXEL_PTR) (info->texture);
183    d = (PIXEL_PTR) addr;
184 
185    for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) {
186       PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
187       unsigned long color = GET_MEMORY_PIXEL(s);
188       color = PS_BLEND(blender, (c >> 16), color);
189 
190       PUT_PIXEL(d, color);
191       u += du;
192       v += dv;
193       c += dc;
194    }
195 }
196 
197 
198 
199 /* _poly_scanline_atex_mask_lit:
200  *  Fills a masked lit affine texture mapped polygon scanline.
201  */
FUNC_POLY_SCANLINE_ATEX_MASK_LIT(uintptr_t addr,int w,POLYGON_SEGMENT * info)202 void FUNC_POLY_SCANLINE_ATEX_MASK_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info)
203 {
204    int x;
205    int vmask, vshift, umask;
206    fixed u, v, c, du, dv, dc;
207    PS_BLENDER blender;
208    PIXEL_PTR texture;
209    PIXEL_PTR d;
210 
211    ASSERT(addr);
212    ASSERT(info);
213 
214    vmask = info->vmask << info->vshift;
215    vshift = 16 - info->vshift;
216    umask = info->umask;
217    u = info->u;
218    v = info->v;
219    c = info->c;
220    du = info->du;
221    dv = info->dv;
222    dc = info->dc;
223    blender = MAKE_PS_BLENDER();
224    texture = (PIXEL_PTR) (info->texture);
225    d = (PIXEL_PTR) addr;
226 
227    for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), x--) {
228       PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
229       unsigned long color = GET_MEMORY_PIXEL(s);
230 
231       if (!IS_MASK(color)) {
232 	 color = PS_BLEND(blender, (c >> 16), color);
233 	 PUT_PIXEL(d, color);
234       }
235       u += du;
236       v += dv;
237       c += dc;
238    }
239 }
240 
241 
242 
243 /* _poly_scanline_ptex:
244  *  Fills a perspective correct texture mapped polygon scanline.
245  */
FUNC_POLY_SCANLINE_PTEX(uintptr_t addr,int w,POLYGON_SEGMENT * info)246 void FUNC_POLY_SCANLINE_PTEX(uintptr_t addr, int w, POLYGON_SEGMENT *info)
247 {
248    int x, i, imax = 3;
249    int vmask, vshift, umask;
250    double fu, fv, fz, dfu, dfv, dfz, z1;
251    PIXEL_PTR texture;
252    PIXEL_PTR d;
253    int64_t u, v;
254 
255    ASSERT(addr);
256    ASSERT(info);
257 
258    vmask = info->vmask << info->vshift;
259    vshift = 16 - info->vshift;
260    umask = info->umask;
261    fu = info->fu;
262    fv = info->fv;
263    fz = info->z;
264    dfu = info->dfu * 4;
265    dfv = info->dfv * 4;
266    dfz = info->dz * 4;
267    z1 = 1. / fz;
268    texture = (PIXEL_PTR) (info->texture);
269    d = (PIXEL_PTR) addr;
270    u = fu * z1;
271    v = fv * z1;
272 
273    /* update depth */
274    fz += dfz;
275    z1 = 1. / fz;
276 
277    for (x = w - 1; x >= 0; x -= 4) {
278       int64_t nextu, nextv, du, dv;
279       PIXEL_PTR s;
280       unsigned long color;
281 
282       fu += dfu;
283       fv += dfv;
284       fz += dfz;
285       nextu = fu * z1;
286       nextv = fv * z1;
287       z1 = 1. / fz;
288       du = (nextu - u) >> 2;
289       dv = (nextv - v) >> 2;
290 
291       /* scanline subdivision */
292       if (x < 3)
293          imax = x;
294       for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d)) {
295          s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
296          color = GET_MEMORY_PIXEL(s);
297 
298          PUT_PIXEL(d, color);
299          u += du;
300          v += dv;
301       }
302    }
303 }
304 
305 
306 
307 /* _poly_scanline_ptex_mask:
308  *  Fills a masked perspective correct texture mapped polygon scanline.
309  */
FUNC_POLY_SCANLINE_PTEX_MASK(uintptr_t addr,int w,POLYGON_SEGMENT * info)310 void FUNC_POLY_SCANLINE_PTEX_MASK(uintptr_t addr, int w, POLYGON_SEGMENT *info)
311 {
312    int x, i, imax = 3;
313    int vmask, vshift, umask;
314    double fu, fv, fz, dfu, dfv, dfz, z1;
315    PIXEL_PTR texture;
316    PIXEL_PTR d;
317    int64_t u, v;
318 
319    ASSERT(addr);
320    ASSERT(info);
321 
322    vmask = info->vmask << info->vshift;
323    vshift = 16 - info->vshift;
324    umask = info->umask;
325    fu = info->fu;
326    fv = info->fv;
327    fz = info->z;
328    dfu = info->dfu * 4;
329    dfv = info->dfv * 4;
330    dfz = info->dz * 4;
331    z1 = 1. / fz;
332    texture = (PIXEL_PTR) (info->texture);
333    d = (PIXEL_PTR) addr;
334    u = fu * z1;
335    v = fv * z1;
336 
337    /* update depth */
338    fz += dfz;
339    z1 = 1. / fz;
340 
341    for (x = w - 1; x >= 0; x-= 4) {
342       int64_t nextu, nextv, du, dv;
343       PIXEL_PTR s;
344       unsigned long color;
345 
346       fu += dfu;
347       fv += dfv;
348       fz += dfz;
349       nextu = fu * z1;
350       nextv = fv * z1;
351       z1 = 1. / fz;
352       du = (nextu - u) >> 2;
353       dv = (nextv - v) >> 2;
354 
355       /* scanline subdivision */
356       if (x < 3)
357          imax = x;
358       for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d)) {
359          s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
360          color = GET_MEMORY_PIXEL(s);
361 
362          if (!IS_MASK(color)) {
363 	    PUT_PIXEL(d, color);
364          }
365          u += du;
366          v += dv;
367       }
368    }
369 }
370 
371 
372 
373 /* _poly_scanline_ptex_lit:
374  *  Fills a lit perspective correct texture mapped polygon scanline.
375  */
FUNC_POLY_SCANLINE_PTEX_LIT(uintptr_t addr,int w,POLYGON_SEGMENT * info)376 void FUNC_POLY_SCANLINE_PTEX_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info)
377 {
378    int x, i, imax = 3;
379    int vmask, vshift, umask;
380    fixed c, dc;
381    double fu, fv, fz, dfu, dfv, dfz, z1;
382    PS_BLENDER blender;
383    PIXEL_PTR texture;
384    PIXEL_PTR d;
385    int64_t u, v;
386 
387    ASSERT(addr);
388    ASSERT(info);
389 
390    vmask = info->vmask << info->vshift;
391    vshift = 16 - info->vshift;
392    umask = info->umask;
393    c = info->c;
394    dc = info->dc;
395    fu = info->fu;
396    fv = info->fv;
397    fz = info->z;
398    dfu = info->dfu * 4;
399    dfv = info->dfv * 4;
400    dfz = info->dz * 4;
401    z1 = 1. / fz;
402    blender = MAKE_PS_BLENDER();
403    texture = (PIXEL_PTR) (info->texture);
404    d = (PIXEL_PTR) addr;
405    u = fu * z1;
406    v = fv * z1;
407 
408    /* update depth */
409    fz += dfz;
410    z1 = 1. / fz;
411 
412    for (x = w - 1; x >= 0; x-= 4) {
413       int64_t nextu, nextv, du, dv;
414 
415       fu += dfu;
416       fv += dfv;
417       fz += dfz;
418       nextu = fu * z1;
419       nextv = fv * z1;
420       z1 = 1. / fz;
421       du = (nextu - u) >> 2;
422       dv = (nextv - v) >> 2;
423 
424       /* scanline subdivision */
425       if (x < 3)
426          imax = x;
427       for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d)) {
428          PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
429          unsigned long color = GET_MEMORY_PIXEL(s);
430          color = PS_BLEND(blender, (c >> 16), color);
431 
432          PUT_PIXEL(d, color);
433          u += du;
434          v += dv;
435 	 c += dc;
436       }
437    }
438 }
439 
440 
441 
442 /* _poly_scanline_ptex_mask_lit:
443  *  Fills a masked lit perspective correct texture mapped polygon scanline.
444  */
FUNC_POLY_SCANLINE_PTEX_MASK_LIT(uintptr_t addr,int w,POLYGON_SEGMENT * info)445 void FUNC_POLY_SCANLINE_PTEX_MASK_LIT(uintptr_t addr, int w, POLYGON_SEGMENT *info)
446 {
447    int x, i, imax = 3;
448    int vmask, vshift, umask;
449    fixed c, dc;
450    double fu, fv, fz, dfu, dfv, dfz, z1;
451    PS_BLENDER blender;
452    PIXEL_PTR texture;
453    PIXEL_PTR d;
454    int64_t u, v;
455 
456    ASSERT(addr);
457    ASSERT(info);
458 
459    vmask = info->vmask << info->vshift;
460    vshift = 16 - info->vshift;
461    umask = info->umask;
462    c = info->c;
463    dc = info->dc;
464    fu = info->fu;
465    fv = info->fv;
466    fz = info->z;
467    dfu = info->dfu * 4;
468    dfv = info->dfv * 4;
469    dfz = info->dz * 4;
470    z1 = 1. / fz;
471    blender = MAKE_PS_BLENDER();
472    texture = (PIXEL_PTR) (info->texture);
473    d = (PIXEL_PTR) addr;
474    u = fu * z1;
475    v = fv * z1;
476 
477    /* update depth */
478    fz += dfz;
479    z1 = 1. / fz;
480 
481    for (x = w - 1; x >= 0; x-= 4) {
482       int64_t nextu, nextv, du, dv;
483 
484       fu += dfu;
485       fv += dfv;
486       fz += dfz;
487       nextu = fu * z1;
488       nextv = fv * z1;
489       z1 = 1. / fz;
490       du = (nextu - u) >> 2;
491       dv = (nextv - v) >> 2;
492 
493       /* scanline subdivision */
494       if (x < 3)
495          imax = x;
496       for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d)) {
497          PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
498          unsigned long color = GET_MEMORY_PIXEL(s);
499 
500          if (!IS_MASK(color)) {
501             color = PS_BLEND(blender, (c >> 16), color);
502 	    PUT_PIXEL(d, color);
503          }
504          u += du;
505          v += dv;
506 	 c += dc;
507       }
508    }
509 }
510 
511 
512 
513 /* _poly_scanline_atex_trans:
514  *  Fills a trans affine texture mapped polygon scanline.
515  */
FUNC_POLY_SCANLINE_ATEX_TRANS(uintptr_t addr,int w,POLYGON_SEGMENT * info)516 void FUNC_POLY_SCANLINE_ATEX_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info)
517 {
518    int x;
519    int vmask, vshift, umask;
520    fixed u, v, du, dv;
521    PIXEL_PTR texture;
522    PIXEL_PTR d;
523    PIXEL_PTR r;
524    PS_BLENDER blender;
525 
526    ASSERT(addr);
527    ASSERT(info);
528 
529    vmask = info->vmask << info->vshift;
530    vshift = 16 - info->vshift;
531    umask = info->umask;
532    u = info->u;
533    v = info->v;
534    du = info->du;
535    dv = info->dv;
536    blender = MAKE_PS_BLENDER();
537    texture = (PIXEL_PTR) (info->texture);
538    d = (PIXEL_PTR) addr;
539    r = (PIXEL_PTR) info->read_addr;
540 
541    for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) {
542       PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
543       unsigned long color = GET_MEMORY_PIXEL(s);
544       color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r));
545 
546       PUT_PIXEL(d, color);
547       u += du;
548       v += dv;
549    }
550 }
551 
552 
553 
554 /* _poly_scanline_atex_mask_trans:
555  *  Fills a trans masked affine texture mapped polygon scanline.
556  */
FUNC_POLY_SCANLINE_ATEX_MASK_TRANS(uintptr_t addr,int w,POLYGON_SEGMENT * info)557 void FUNC_POLY_SCANLINE_ATEX_MASK_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info)
558 {
559    int x;
560    int vmask, vshift, umask;
561    fixed u, v, du, dv;
562    PIXEL_PTR texture;
563    PIXEL_PTR d;
564    PIXEL_PTR r;
565    PS_BLENDER blender;
566 
567    ASSERT(addr);
568    ASSERT(info);
569 
570    vmask = info->vmask << info->vshift;
571    vshift = 16 - info->vshift;
572    umask = info->umask;
573    u = info->u;
574    v = info->v;
575    du = info->du;
576    dv = info->dv;
577    blender = MAKE_PS_BLENDER();
578    texture = (PIXEL_PTR) (info->texture);
579    d = (PIXEL_PTR) addr;
580    r = (PIXEL_PTR) info->read_addr;
581 
582    for (x = w - 1; x >= 0; INC_PIXEL_PTR(d), INC_PIXEL_PTR(r), x--) {
583       PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
584       unsigned long color = GET_MEMORY_PIXEL(s);
585 
586       if (!IS_MASK(color)) {
587          color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r));
588          PUT_PIXEL(d, color);
589       }
590       u += du;
591       v += dv;
592    }
593 }
594 
595 
596 
597 /* _poly_scanline_ptex_trans:
598  *  Fills a trans perspective correct texture mapped polygon scanline.
599  */
FUNC_POLY_SCANLINE_PTEX_TRANS(uintptr_t addr,int w,POLYGON_SEGMENT * info)600 void FUNC_POLY_SCANLINE_PTEX_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info)
601 {
602    int x, i, imax = 3;
603    int vmask, vshift, umask;
604    double fu, fv, fz, dfu, dfv, dfz, z1;
605    PS_BLENDER blender;
606    PIXEL_PTR texture;
607    PIXEL_PTR d;
608    PIXEL_PTR r;
609    int64_t u, v;
610 
611    ASSERT(addr);
612    ASSERT(info);
613 
614    vmask = info->vmask << info->vshift;
615    vshift = 16 - info->vshift;
616    umask = info->umask;
617    fu = info->fu;
618    fv = info->fv;
619    fz = info->z;
620    dfu = info->dfu * 4;
621    dfv = info->dfv * 4;
622    dfz = info->dz * 4;
623    z1 = 1. / fz;
624    blender = MAKE_PS_BLENDER();
625    texture = (PIXEL_PTR) (info->texture);
626    d = (PIXEL_PTR) addr;
627    r = (PIXEL_PTR) info->read_addr;
628    u = fu * z1;
629    v = fv * z1;
630 
631    /* update depth */
632    fz += dfz;
633    z1 = 1. / fz;
634 
635    for (x = w - 1; x >= 0; x-= 4) {
636       int64_t nextu, nextv, du, dv;
637 
638       fu += dfu;
639       fv += dfv;
640       fz += dfz;
641       nextu = fu * z1;
642       nextv = fv * z1;
643       z1 = 1. / fz;
644       du = (nextu - u) >> 2;
645       dv = (nextv - v) >> 2;
646 
647       /* scanline subdivision */
648       if (x < 3)
649          imax = x;
650       for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d), INC_PIXEL_PTR(r)) {
651          PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
652          unsigned long color = GET_MEMORY_PIXEL(s);
653 
654          color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r));
655          PUT_PIXEL(d, color);
656          u += du;
657          v += dv;
658       }
659    }
660 }
661 
662 
663 
664 /* _poly_scanline_ptex_mask_trans:
665  *  Fills a trans masked perspective correct texture mapped polygon scanline.
666  */
FUNC_POLY_SCANLINE_PTEX_MASK_TRANS(uintptr_t addr,int w,POLYGON_SEGMENT * info)667 void FUNC_POLY_SCANLINE_PTEX_MASK_TRANS(uintptr_t addr, int w, POLYGON_SEGMENT *info)
668 {
669    int x, i, imax = 3;
670    int vmask, vshift, umask;
671    double fu, fv, fz, dfu, dfv, dfz, z1;
672    PS_BLENDER blender;
673    PIXEL_PTR texture;
674    PIXEL_PTR d;
675    PIXEL_PTR r;
676    int64_t u, v;
677 
678    ASSERT(addr);
679    ASSERT(info);
680 
681    vmask = info->vmask << info->vshift;
682    vshift = 16 - info->vshift;
683    umask = info->umask;
684    fu = info->fu;
685    fv = info->fv;
686    fz = info->z;
687    dfu = info->dfu * 4;
688    dfv = info->dfv * 4;
689    dfz = info->dz * 4;
690    z1 = 1. / fz;
691    blender = MAKE_PS_BLENDER();
692    texture = (PIXEL_PTR) (info->texture);
693    d = (PIXEL_PTR) addr;
694    r = (PIXEL_PTR) info->read_addr;
695    u = fu * z1;
696    v = fv * z1;
697 
698    /* update depth */
699    fz += dfz;
700    z1 = 1. / fz;
701 
702    for (x = w - 1; x >= 0; x-= 4) {
703       int64_t nextu, nextv, du, dv;
704 
705       fu += dfu;
706       fv += dfv;
707       fz += dfz;
708       nextu = fu * z1;
709       nextv = fv * z1;
710       z1 = 1. / fz;
711       du = (nextu - u) >> 2;
712       dv = (nextv - v) >> 2;
713 
714       /* scanline subdivision */
715       if (x < 3)
716          imax = x;
717       for (i = imax; i >= 0; i--, INC_PIXEL_PTR(d), INC_PIXEL_PTR(r)) {
718          PIXEL_PTR s = OFFSET_PIXEL_PTR(texture, ((v >> vshift) & vmask) + ((u >> 16) & umask));
719          unsigned long color = GET_MEMORY_PIXEL(s);
720 
721 	 if (!IS_MASK(color)) {
722             color = PS_ALPHA_BLEND(blender, color, GET_PIXEL(r));
723             PUT_PIXEL(d, color);
724 	 }
725          u += du;
726          v += dv;
727       }
728    }
729 }
730 
731 #endif /* !__bma_cscan_h */
732 
733