1 /*
2 
3 Copyright (C) 2015-2018 Night Dive Studios, LLC.
4 
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 
18 */
19 /*
20  * $Source: r:/prj/lib/src/2d/RCS/gencop.c $
21  * $Revision: 1.2 $
22  * $Author: kevin $
23  * $Date: 1994/08/16 12:56:46 $
24  *
25  * full perspective texture mapper.
26  * scanline processors.
27  *
28  */
29 
30 #include "cnvdat.h"
31 #include "fl8tmapdv.h"
32 #include "pertyp.h"
33 #include "plytyp.h"
34 
35 // prototypes
36 void gri_opaque_clut_per_umap_hscan_scanline(grs_per_info *pi, grs_bitmap *bm);
37 void gri_opaque_clut_per_umap_vscan_scanline(grs_per_info *pi, grs_bitmap *bm);
38 void gri_opaque_clut_per_umap_hscan_init(grs_bitmap *bm, grs_per_setup *ps);
39 void gri_opaque_clut_per_umap_vscan_init(grs_bitmap *bm, grs_per_setup *ps);
40 
gri_opaque_clut_per_umap_hscan_scanline(grs_per_info * pi,grs_bitmap * bm)41 void gri_opaque_clut_per_umap_hscan_scanline(grs_per_info *pi, grs_bitmap *bm) {
42     register int k, y_cint;
43     uchar *p;
44 
45     // locals used to speed PPC code
46     fix l_u, l_v, l_du, l_dv, l_y_fix, l_scan_slope, l_dtl, l_dxl, l_dyl, l_dtr, l_dyr;
47     int l_x, l_xl, l_xr, l_xr0, l_u_mask, l_v_mask, l_v_shift;
48     int gr_row, temp_y;
49     uchar *bm_bits;
50     uchar *t_clut;
51 
52     t_clut = pi->clut;
53     gr_row = grd_bm.row;
54     bm_bits = bm->bits;
55     l_dyr = pi->dyr;
56     l_dtr = pi->dtr;
57     l_dyl = pi->dyl;
58     l_dxl = pi->dxl;
59     l_dtl = pi->dtl;
60     l_scan_slope = pi->scan_slope;
61     l_y_fix = pi->y_fix;
62     l_v_shift = pi->v_shift;
63     l_v_mask = pi->v_mask;
64     l_u_mask = pi->u_mask;
65     l_xr0 = pi->xr0;
66     l_x = pi->x;
67     l_xl = pi->xl;
68     l_xr = pi->xr;
69     l_u = pi->u;
70     l_v = pi->v;
71     l_du = pi->du;
72     l_dv = pi->dv;
73 
74     l_y_fix = l_x * l_scan_slope + fix_make(pi->yp, 0xffff);
75 
76 #if InvDiv
77     k = fix_div(fix_make(1, 0), pi->denom);
78     l_u = pi->u0 + fix_mul_asm_safe(pi->unum, k);
79     l_v = pi->v0 + fix_mul_asm_safe(pi->vnum, k);
80     l_du = fix_mul_asm_safe(pi->dunum, k);
81     l_dv = fix_mul_asm_safe(pi->dvnum, k);
82 #else
83     l_u = pi->u0 + fix_div(pi->unum, pi->denom);
84     l_v = pi->v0 + fix_div(pi->vnum, pi->denom);
85     l_du = fix_div(pi->dunum, pi->denom);
86     l_dv = fix_div(pi->dvnum, pi->denom);
87 #endif
88 
89     l_u += l_x * l_du;
90     l_v += l_x * l_dv;
91 
92     y_cint = fix_int(l_y_fix);
93 
94     if (l_scan_slope < 0)
95         gr_row = -gr_row;
96 
97     p = grd_bm.bits + l_x + y_cint * grd_bm.row;
98     if (l_x < l_xl) {
99         fix test = l_x * l_dyl - y_cint * l_dxl + pi->cl;
100         for (; l_x < l_xl; l_x++) {
101             if (test <= 0) {
102                 k = (l_u >> 16) & l_u_mask;
103                 k += (l_v >> l_v_shift) & l_v_mask;
104                 *p = t_clut[bm_bits[k]]; // gr_fill_upixel(t_clut[bm_bits[k]],l_x,y_cint);
105             }
106             temp_y = y_cint;
107             y_cint = fix_int(l_y_fix += l_scan_slope);
108 
109             if (temp_y != y_cint) {
110                 p += gr_row;
111                 test += l_dtl;
112             } else
113                 test += l_dyl;
114 
115             p++;
116             l_u += l_du;
117             l_v += l_dv;
118         }
119     }
120 
121     for (; l_x < l_xr0; l_x++) {
122         k = (l_u >> 16) & l_u_mask;
123         k += (l_v >> l_v_shift) & l_v_mask;
124         *(p++) = t_clut[bm_bits[k]]; // gr_fill_upixel(t_clut[bm_bits[k]],l_x,y_cint);
125         temp_y = y_cint;
126         y_cint = fix_int(l_y_fix += l_scan_slope);
127         if (temp_y != y_cint)
128             p += gr_row;
129 
130         l_u += l_du;
131         l_v += l_dv;
132     }
133 
134     if (l_x < l_xr) {
135         fix test = l_x * l_dyr - y_cint * pi->dxr + pi->cr;
136         p = grd_bm.bits + l_x + y_cint * grd_bm.row;
137         for (; l_x < l_xr; l_x++) {
138             if (test >= 0) {
139                 k = (l_u >> 16) & l_u_mask;
140                 k += (l_v >> l_v_shift) & l_v_mask;
141                 *p = t_clut[bm_bits[k]]; // gr_fill_upixel(t_clut[bm_bits[k]],l_x,y_cint);
142             }
143             temp_y = y_cint;
144             y_cint = fix_int(l_y_fix += l_scan_slope);
145             if (temp_y != y_cint) {
146                 p += gr_row;
147                 test += l_dtr;
148             } else
149                 test += l_dyr;
150 
151             p++;
152             l_u += l_du;
153             l_v += l_dv;
154         }
155     }
156 
157     pi->y_fix = l_y_fix;
158     pi->x = l_x;
159     pi->u = l_u;
160     pi->v = l_v;
161     pi->du = l_du;
162     pi->dv = l_dv;
163 }
164 
gri_opaque_clut_per_umap_vscan_scanline(grs_per_info * pi,grs_bitmap * bm)165 void gri_opaque_clut_per_umap_vscan_scanline(grs_per_info *pi, grs_bitmap *bm) {
166     register int k, x_cint;
167 
168     // locals used to speed PPC code
169     fix l_dxr, l_x_fix, l_u, l_v, l_du, l_dv, l_scan_slope, l_dtl, l_dxl, l_dyl, l_dtr, l_dyr;
170     int l_yl, l_yr0, l_yr, l_y, l_u_mask, l_v_mask, l_v_shift;
171     int gr_row, temp_x;
172     uchar *bm_bits;
173     uchar *p;
174     uchar *t_clut;
175 
176     t_clut = pi->clut;
177     gr_row = grd_bm.row;
178     bm_bits = bm->bits;
179     l_dxr = pi->dxr;
180     l_x_fix = pi->x_fix;
181     l_y = pi->y;
182     l_yr = pi->yr;
183     l_yr0 = pi->yr0;
184     l_yl = pi->yl;
185     l_dyr = pi->dyr;
186     l_dtr = pi->dtr;
187     l_dyl = pi->dyl;
188     l_dxl = pi->dxl;
189     l_dtl = pi->dtl;
190     l_scan_slope = pi->scan_slope;
191     l_v_shift = pi->v_shift;
192     l_v_mask = pi->v_mask;
193     l_u_mask = pi->u_mask;
194     l_u = pi->u;
195     l_v = pi->v;
196     l_du = pi->du;
197     l_dv = pi->dv;
198 
199     l_x_fix = l_y * l_scan_slope + fix_make(pi->xp, 0xffff);
200 
201 #if InvDiv
202     k = fix_div(fix_make(1, 0), pi->denom);
203     l_u = pi->u0 + fix_mul_asm_safe(pi->unum, k);
204     l_v = pi->v0 + fix_mul_asm_safe(pi->vnum, k);
205     l_du = fix_mul_asm_safe(pi->dunum, k);
206     l_dv = fix_mul_asm_safe(pi->dvnum, k);
207 #else
208     l_u = pi->u0 + fix_div(pi->unum, pi->denom);
209     l_v = pi->v0 + fix_div(pi->vnum, pi->denom);
210     l_du = fix_div(pi->dunum, pi->denom);
211     l_dv = fix_div(pi->dvnum, pi->denom);
212 #endif
213     l_u += l_y * l_du;
214     l_v += l_y * l_dv;
215 
216     x_cint = fix_int(l_x_fix);
217     p = grd_bm.bits + x_cint + l_y * gr_row;
218     if (l_y < l_yl) {
219         fix test = l_y * l_dxl - x_cint * l_dyl + pi->cl;
220         for (; l_y < l_yl; l_y++) {
221             if (test <= 0) {
222                 k = (l_u >> 16) & l_u_mask;
223                 k += (l_v >> l_v_shift) & l_v_mask;
224                 *p = t_clut[bm_bits[k]]; // gr_fill_upixel(t_clut[bm_bits[k]],x_cint,l_y);
225             }
226             temp_x = x_cint;
227             x_cint = fix_int(l_x_fix += l_scan_slope);
228             if (temp_x != x_cint) {
229                 test += l_dtl;
230                 p -= (temp_x - x_cint);
231             } else
232                 test += l_dxl;
233 
234             p += gr_row;
235             l_u += l_du;
236             l_v += l_dv;
237         }
238     }
239 
240     for (; l_y < l_yr0; l_y++) {
241         k = (l_u >> 16) & l_u_mask;
242         k += (l_v >> l_v_shift) & l_v_mask;
243         *p = t_clut[bm_bits[k]]; // gr_fill_upixel(t_clut[bm_bits[k]],x_cint,l_y);
244 
245         temp_x = x_cint;
246         x_cint = fix_int(l_x_fix += l_scan_slope);
247         if (temp_x != x_cint)
248             p -= (temp_x - x_cint);
249 
250         p += gr_row;
251         l_u += l_du;
252         l_v += l_dv;
253     }
254 
255     if (l_y < l_yr) {
256         fix test = l_y * l_dxr - x_cint * l_dyr + pi->cr;
257         p = grd_bm.bits + x_cint + l_y * gr_row;
258         for (; l_y < l_yr; l_y++) {
259             if (test >= 0) {
260                 k = (l_u >> 16) & l_u_mask;
261                 k += (l_v >> l_v_shift) & l_v_mask;
262                 *p = t_clut[bm_bits[k]]; // gr_fill_upixel(t_clut[bm_bits[k]],x_cint,l_y);
263             }
264 
265             temp_x = x_cint;
266             x_cint = fix_int(l_x_fix += l_scan_slope);
267             if (temp_x != x_cint) {
268                 test += l_dtr;
269                 p -= (temp_x - x_cint);
270             } else
271                 test += l_dxr;
272 
273             p += gr_row;
274             l_u += l_du;
275             l_v += l_dv;
276         }
277     }
278 
279     pi->x_fix = l_x_fix;
280     pi->y = l_y;
281     pi->u = l_u;
282     pi->v = l_v;
283     pi->du = l_du;
284     pi->dv = l_dv;
285 }
286 
287 extern void gri_per_umap_hscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps);
288 extern void gri_per_umap_vscan(grs_bitmap *bm, int n, grs_vertex **vpl, grs_per_setup *ps);
289 
gri_opaque_clut_per_umap_hscan_init(grs_bitmap * bm,grs_per_setup * ps)290 void gri_opaque_clut_per_umap_hscan_init(grs_bitmap *bm, grs_per_setup *ps) {
291     ps->shell_func = (void (*)())gri_per_umap_hscan;
292     ps->scanline_func = (void (*)())gri_opaque_clut_per_umap_hscan_scanline;
293 }
294 
gri_opaque_clut_per_umap_vscan_init(grs_bitmap * bm,grs_per_setup * ps)295 void gri_opaque_clut_per_umap_vscan_init(grs_bitmap *bm, grs_per_setup *ps) {
296     ps->shell_func = (void (*)())gri_per_umap_vscan;
297     ps->scanline_func = (void (*)())gri_opaque_clut_per_umap_vscan_scanline;
298 }
299