1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12
13 See the 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, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
19 */
20 // d_scan.c
21 //
22 // Portable C scan-level rasterization code, all pixel depths.
23
24 #include "r_local.h"
25
26 unsigned char *r_turb_pbase, *r_turb_pdest;
27 fixed16_t r_turb_s, r_turb_t, r_turb_sstep, r_turb_tstep;
28 int *r_turb_turb;
29 int r_turb_spancount;
30
31 void D_DrawTurbulent8Span (void);
32
33
34 /*
35 =============
36 D_WarpScreen
37
38 this performs a slight compression of the screen at the same time as
39 the sine warp, to keep the edges from wrapping
40 =============
41 */
D_WarpScreen(void)42 void D_WarpScreen (void)
43 {
44 int w, h;
45 int u,v, u2, v2;
46 byte *dest;
47 int *turb;
48 int *col;
49 byte **row;
50
51 static int cached_width, cached_height;
52 static byte *rowptr[1200+AMP2*2];
53 static int column[1600+AMP2*2];
54
55 //
56 // these are constant over resolutions, and can be saved
57 //
58 w = r_newrefdef.width;
59 h = r_newrefdef.height;
60 if (w != cached_width || h != cached_height)
61 {
62 cached_width = w;
63 cached_height = h;
64 for (v=0 ; v<h+AMP2*2 ; v++)
65 {
66 v2 = (int)((float)v/(h + AMP2 * 2) * r_refdef.vrect.height);
67 rowptr[v] = r_warpbuffer + (WARP_WIDTH * v2);
68 }
69
70 for (u=0 ; u<w+AMP2*2 ; u++)
71 {
72 u2 = (int)((float)u/(w + AMP2 * 2) * r_refdef.vrect.width);
73 column[u] = u2;
74 }
75 }
76
77 turb = intsintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
78 dest = vid.buffer + r_newrefdef.y * vid.rowbytes + r_newrefdef.x;
79
80 for (v=0 ; v<h ; v++, dest += vid.rowbytes)
81 {
82 col = &column[turb[v]];
83 row = &rowptr[v];
84 for (u=0 ; u<w ; u+=4)
85 {
86 dest[u+0] = row[turb[u+0]][col[u+0]];
87 dest[u+1] = row[turb[u+1]][col[u+1]];
88 dest[u+2] = row[turb[u+2]][col[u+2]];
89 dest[u+3] = row[turb[u+3]][col[u+3]];
90 }
91 }
92 }
93
94
95 #if !id386
96
97 /*
98 =============
99 D_DrawTurbulent8Span
100 =============
101 */
D_DrawTurbulent8Span(void)102 void D_DrawTurbulent8Span (void)
103 {
104 int sturb, tturb;
105
106 do
107 {
108 sturb = ((r_turb_s + r_turb_turb[(r_turb_t>>16)&(CYCLE-1)])>>16)&63;
109 tturb = ((r_turb_t + r_turb_turb[(r_turb_s>>16)&(CYCLE-1)])>>16)&63;
110 *r_turb_pdest++ = *(r_turb_pbase + (tturb<<6) + sturb);
111 r_turb_s += r_turb_sstep;
112 r_turb_t += r_turb_tstep;
113 } while (--r_turb_spancount > 0);
114 }
115
116 #endif // !id386
117
118
119 /*
120 =============
121 Turbulent8
122 =============
123 */
Turbulent8(espan_t * pspan)124 void Turbulent8 (espan_t *pspan)
125 {
126 int count;
127 fixed16_t snext, tnext;
128 float sdivz, tdivz, zi, z, du, dv, spancountminus1;
129 float sdivz16stepu, tdivz16stepu, zi16stepu;
130
131 r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
132
133 r_turb_sstep = 0; // keep compiler happy
134 r_turb_tstep = 0; // ditto
135
136 r_turb_pbase = (unsigned char *)cacheblock;
137
138 sdivz16stepu = d_sdivzstepu * 16;
139 tdivz16stepu = d_tdivzstepu * 16;
140 zi16stepu = d_zistepu * 16;
141
142 do
143 {
144 r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
145 (r_screenwidth * pspan->v) + pspan->u);
146
147 count = pspan->count;
148
149 // calculate the initial s/z, t/z, 1/z, s, and t and clamp
150 du = (float)pspan->u;
151 dv = (float)pspan->v;
152
153 sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
154 tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
155 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
156 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
157
158 r_turb_s = (int)(sdivz * z) + sadjust;
159 if (r_turb_s > bbextents)
160 r_turb_s = bbextents;
161 else if (r_turb_s < 0)
162 r_turb_s = 0;
163
164 r_turb_t = (int)(tdivz * z) + tadjust;
165 if (r_turb_t > bbextentt)
166 r_turb_t = bbextentt;
167 else if (r_turb_t < 0)
168 r_turb_t = 0;
169
170 do
171 {
172 // calculate s and t at the far end of the span
173 if (count >= 16)
174 r_turb_spancount = 16;
175 else
176 r_turb_spancount = count;
177
178 count -= r_turb_spancount;
179
180 if (count)
181 {
182 // calculate s/z, t/z, zi->fixed s and t at far end of span,
183 // calculate s and t steps across span by shifting
184 sdivz += sdivz16stepu;
185 tdivz += tdivz16stepu;
186 zi += zi16stepu;
187 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
188
189 snext = (int)(sdivz * z) + sadjust;
190 if (snext > bbextents)
191 snext = bbextents;
192 else if (snext < 16)
193 snext = 16; // prevent round-off error on <0 steps from
194 // from causing overstepping & running off the
195 // edge of the texture
196
197 tnext = (int)(tdivz * z) + tadjust;
198 if (tnext > bbextentt)
199 tnext = bbextentt;
200 else if (tnext < 16)
201 tnext = 16; // guard against round-off error on <0 steps
202
203 r_turb_sstep = (snext - r_turb_s) >> 4;
204 r_turb_tstep = (tnext - r_turb_t) >> 4;
205 }
206 else
207 {
208 // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
209 // can't step off polygon), clamp, calculate s and t steps across
210 // span by division, biasing steps low so we don't run off the
211 // texture
212 spancountminus1 = (float)(r_turb_spancount - 1);
213 sdivz += d_sdivzstepu * spancountminus1;
214 tdivz += d_tdivzstepu * spancountminus1;
215 zi += d_zistepu * spancountminus1;
216 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
217 snext = (int)(sdivz * z) + sadjust;
218 if (snext > bbextents)
219 snext = bbextents;
220 else if (snext < 16)
221 snext = 16; // prevent round-off error on <0 steps from
222 // from causing overstepping & running off the
223 // edge of the texture
224
225 tnext = (int)(tdivz * z) + tadjust;
226 if (tnext > bbextentt)
227 tnext = bbextentt;
228 else if (tnext < 16)
229 tnext = 16; // guard against round-off error on <0 steps
230
231 if (r_turb_spancount > 1)
232 {
233 r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
234 r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
235 }
236 }
237
238 r_turb_s = r_turb_s & ((CYCLE<<16)-1);
239 r_turb_t = r_turb_t & ((CYCLE<<16)-1);
240
241 D_DrawTurbulent8Span ();
242
243 r_turb_s = snext;
244 r_turb_t = tnext;
245
246 } while (count > 0);
247
248 } while ((pspan = pspan->pnext) != NULL);
249 }
250
251 //====================
252 //PGM
253 /*
254 =============
255 NonTurbulent8 - this is for drawing scrolling textures. they're warping water textures
256 but the turbulence is automatically 0.
257 =============
258 */
NonTurbulent8(espan_t * pspan)259 void NonTurbulent8 (espan_t *pspan)
260 {
261 int count;
262 fixed16_t snext, tnext;
263 float sdivz, tdivz, zi, z, du, dv, spancountminus1;
264 float sdivz16stepu, tdivz16stepu, zi16stepu;
265
266 // r_turb_turb = sintable + ((int)(r_newrefdef.time*SPEED)&(CYCLE-1));
267 r_turb_turb = blanktable;
268
269 r_turb_sstep = 0; // keep compiler happy
270 r_turb_tstep = 0; // ditto
271
272 r_turb_pbase = (unsigned char *)cacheblock;
273
274 sdivz16stepu = d_sdivzstepu * 16;
275 tdivz16stepu = d_tdivzstepu * 16;
276 zi16stepu = d_zistepu * 16;
277
278 do
279 {
280 r_turb_pdest = (unsigned char *)((byte *)d_viewbuffer +
281 (r_screenwidth * pspan->v) + pspan->u);
282
283 count = pspan->count;
284
285 // calculate the initial s/z, t/z, 1/z, s, and t and clamp
286 du = (float)pspan->u;
287 dv = (float)pspan->v;
288
289 sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
290 tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
291 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
292 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
293
294 r_turb_s = (int)(sdivz * z) + sadjust;
295 if (r_turb_s > bbextents)
296 r_turb_s = bbextents;
297 else if (r_turb_s < 0)
298 r_turb_s = 0;
299
300 r_turb_t = (int)(tdivz * z) + tadjust;
301 if (r_turb_t > bbextentt)
302 r_turb_t = bbextentt;
303 else if (r_turb_t < 0)
304 r_turb_t = 0;
305
306 do
307 {
308 // calculate s and t at the far end of the span
309 if (count >= 16)
310 r_turb_spancount = 16;
311 else
312 r_turb_spancount = count;
313
314 count -= r_turb_spancount;
315
316 if (count)
317 {
318 // calculate s/z, t/z, zi->fixed s and t at far end of span,
319 // calculate s and t steps across span by shifting
320 sdivz += sdivz16stepu;
321 tdivz += tdivz16stepu;
322 zi += zi16stepu;
323 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
324
325 snext = (int)(sdivz * z) + sadjust;
326 if (snext > bbextents)
327 snext = bbextents;
328 else if (snext < 16)
329 snext = 16; // prevent round-off error on <0 steps from
330 // from causing overstepping & running off the
331 // edge of the texture
332
333 tnext = (int)(tdivz * z) + tadjust;
334 if (tnext > bbextentt)
335 tnext = bbextentt;
336 else if (tnext < 16)
337 tnext = 16; // guard against round-off error on <0 steps
338
339 r_turb_sstep = (snext - r_turb_s) >> 4;
340 r_turb_tstep = (tnext - r_turb_t) >> 4;
341 }
342 else
343 {
344 // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
345 // can't step off polygon), clamp, calculate s and t steps across
346 // span by division, biasing steps low so we don't run off the
347 // texture
348 spancountminus1 = (float)(r_turb_spancount - 1);
349 sdivz += d_sdivzstepu * spancountminus1;
350 tdivz += d_tdivzstepu * spancountminus1;
351 zi += d_zistepu * spancountminus1;
352 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
353 snext = (int)(sdivz * z) + sadjust;
354 if (snext > bbextents)
355 snext = bbextents;
356 else if (snext < 16)
357 snext = 16; // prevent round-off error on <0 steps from
358 // from causing overstepping & running off the
359 // edge of the texture
360
361 tnext = (int)(tdivz * z) + tadjust;
362 if (tnext > bbextentt)
363 tnext = bbextentt;
364 else if (tnext < 16)
365 tnext = 16; // guard against round-off error on <0 steps
366
367 if (r_turb_spancount > 1)
368 {
369 r_turb_sstep = (snext - r_turb_s) / (r_turb_spancount - 1);
370 r_turb_tstep = (tnext - r_turb_t) / (r_turb_spancount - 1);
371 }
372 }
373
374 r_turb_s = r_turb_s & ((CYCLE<<16)-1);
375 r_turb_t = r_turb_t & ((CYCLE<<16)-1);
376
377 D_DrawTurbulent8Span ();
378
379 r_turb_s = snext;
380 r_turb_t = tnext;
381
382 } while (count > 0);
383
384 } while ((pspan = pspan->pnext) != NULL);
385 }
386 //PGM
387 //====================
388
389
390 #if !id386
391
392 /*
393 =============
394 D_DrawSpans16
395
396 FIXME: actually make this subdivide by 16 instead of 8!!!
397 =============
398 */
D_DrawSpans16(espan_t * pspan)399 void D_DrawSpans16 (espan_t *pspan)
400 {
401 int count, spancount;
402 unsigned char *pbase, *pdest;
403 fixed16_t s, t, snext, tnext, sstep, tstep;
404 float sdivz, tdivz, zi, z, du, dv, spancountminus1;
405 float sdivz8stepu, tdivz8stepu, zi8stepu;
406
407 sstep = 0; // keep compiler happy
408 tstep = 0; // ditto
409
410 pbase = (unsigned char *)cacheblock;
411
412 sdivz8stepu = d_sdivzstepu * 8;
413 tdivz8stepu = d_tdivzstepu * 8;
414 zi8stepu = d_zistepu * 8;
415
416 do
417 {
418 pdest = (unsigned char *)((byte *)d_viewbuffer +
419 (r_screenwidth * pspan->v) + pspan->u);
420
421 count = pspan->count;
422
423 // calculate the initial s/z, t/z, 1/z, s, and t and clamp
424 du = (float)pspan->u;
425 dv = (float)pspan->v;
426
427 sdivz = d_sdivzorigin + dv*d_sdivzstepv + du*d_sdivzstepu;
428 tdivz = d_tdivzorigin + dv*d_tdivzstepv + du*d_tdivzstepu;
429 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
430 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
431
432 s = (int)(sdivz * z) + sadjust;
433 if (s > bbextents)
434 s = bbextents;
435 else if (s < 0)
436 s = 0;
437
438 t = (int)(tdivz * z) + tadjust;
439 if (t > bbextentt)
440 t = bbextentt;
441 else if (t < 0)
442 t = 0;
443
444 do
445 {
446 // calculate s and t at the far end of the span
447 if (count >= 8)
448 spancount = 8;
449 else
450 spancount = count;
451
452 count -= spancount;
453
454 if (count)
455 {
456 // calculate s/z, t/z, zi->fixed s and t at far end of span,
457 // calculate s and t steps across span by shifting
458 sdivz += sdivz8stepu;
459 tdivz += tdivz8stepu;
460 zi += zi8stepu;
461 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
462
463 snext = (int)(sdivz * z) + sadjust;
464 if (snext > bbextents)
465 snext = bbextents;
466 else if (snext < 8)
467 snext = 8; // prevent round-off error on <0 steps from
468 // from causing overstepping & running off the
469 // edge of the texture
470
471 tnext = (int)(tdivz * z) + tadjust;
472 if (tnext > bbextentt)
473 tnext = bbextentt;
474 else if (tnext < 8)
475 tnext = 8; // guard against round-off error on <0 steps
476
477 sstep = (snext - s) >> 3;
478 tstep = (tnext - t) >> 3;
479 }
480 else
481 {
482 // calculate s/z, t/z, zi->fixed s and t at last pixel in span (so
483 // can't step off polygon), clamp, calculate s and t steps across
484 // span by division, biasing steps low so we don't run off the
485 // texture
486 spancountminus1 = (float)(spancount - 1);
487 sdivz += d_sdivzstepu * spancountminus1;
488 tdivz += d_tdivzstepu * spancountminus1;
489 zi += d_zistepu * spancountminus1;
490 z = (float)0x10000 / zi; // prescale to 16.16 fixed-point
491 snext = (int)(sdivz * z) + sadjust;
492 if (snext > bbextents)
493 snext = bbextents;
494 else if (snext < 8)
495 snext = 8; // prevent round-off error on <0 steps from
496 // from causing overstepping & running off the
497 // edge of the texture
498
499 tnext = (int)(tdivz * z) + tadjust;
500 if (tnext > bbextentt)
501 tnext = bbextentt;
502 else if (tnext < 8)
503 tnext = 8; // guard against round-off error on <0 steps
504
505 if (spancount > 1)
506 {
507 sstep = (snext - s) / (spancount - 1);
508 tstep = (tnext - t) / (spancount - 1);
509 }
510 }
511
512 do
513 {
514 *pdest++ = *(pbase + (s >> 16) + (t >> 16) * cachewidth);
515 s += sstep;
516 t += tstep;
517 } while (--spancount > 0);
518
519 s = snext;
520 t = tnext;
521
522 } while (count > 0);
523
524 } while ((pspan = pspan->pnext) != NULL);
525 }
526
527 #endif
528
529
530 #if !id386
531
532 /*
533 =============
534 D_DrawZSpans
535 =============
536 */
D_DrawZSpans(espan_t * pspan)537 void D_DrawZSpans (espan_t *pspan)
538 {
539 int count, doublecount, izistep;
540 int izi;
541 short *pdest;
542 unsigned ltemp;
543 float zi;
544 float du, dv;
545
546 // FIXME: check for clamping/range problems
547 // we count on FP exceptions being turned off to avoid range problems
548 izistep = (int)(d_zistepu * 0x8000 * 0x10000);
549
550 do
551 {
552 pdest = d_pzbuffer + (d_zwidth * pspan->v) + pspan->u;
553
554 count = pspan->count;
555
556 // calculate the initial 1/z
557 du = (float)pspan->u;
558 dv = (float)pspan->v;
559
560 zi = d_ziorigin + dv*d_zistepv + du*d_zistepu;
561 // we count on FP exceptions being turned off to avoid range problems
562 izi = (int)(zi * 0x8000 * 0x10000);
563
564 if ((long)pdest & 0x02)
565 {
566 *pdest++ = (short)(izi >> 16);
567 izi += izistep;
568 count--;
569 }
570
571 if ((doublecount = count >> 1) > 0)
572 {
573 do
574 {
575 ltemp = izi >> 16;
576 izi += izistep;
577 ltemp |= izi & 0xFFFF0000;
578 izi += izistep;
579 *(int *)pdest = ltemp;
580 pdest += 2;
581 } while (--doublecount > 0);
582 }
583
584 if (count & 1)
585 *pdest = (short)(izi >> 16);
586
587 } while ((pspan = pspan->pnext) != NULL);
588 }
589
590 #endif
591
592