Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
57 pj 1
/* $Id: s_tritemp.h,v 1.1 2003-02-28 11:49:43 pj Exp $ */
2
 
3
/*
4
 * Mesa 3-D graphics library
5
 * Version:  3.5
6
 *
7
 * Copyright (C) 1999-2001  Brian Paul   All Rights Reserved.
8
 *
9
 * Permission is hereby granted, free of charge, to any person obtaining a
10
 * copy of this software and associated documentation files (the "Software"),
11
 * to deal in the Software without restriction, including without limitation
12
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13
 * and/or sell copies of the Software, and to permit persons to whom the
14
 * Software is furnished to do so, subject to the following conditions:
15
 *
16
 * The above copyright notice and this permission notice shall be included
17
 * in all copies or substantial portions of the Software.
18
 *
19
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
 */
26
/* $XFree86: xc/extras/Mesa/src/swrast/s_tritemp.h,v 1.2 2002/02/27 21:07:54 tsi Exp $ */
27
 
28
/*
29
 * Triangle Rasterizer Template
30
 *
31
 * This file is #include'd to generate custom triangle rasterizers.
32
 *
33
 * The following macros may be defined to indicate what auxillary information
34
 * must be interplated across the triangle:
35
 *    INTERP_Z        - if defined, interpolate Z values
36
 *    INTERP_FOG      - if defined, interpolate fog values
37
 *    INTERP_RGB      - if defined, interpolate RGB values
38
 *    INTERP_ALPHA    - if defined, interpolate Alpha values (req's INTERP_RGB)
39
 *    INTERP_SPEC     - if defined, interpolate specular RGB values
40
 *    INTERP_INDEX    - if defined, interpolate color index values
41
 *    INTERP_INT_TEX  - if defined, interpolate integer ST texcoords
42
 *                         (fast, simple 2-D texture mapping)
43
 *    INTERP_TEX      - if defined, interpolate set 0 float STRQ texcoords
44
 *                         NOTE:  OpenGL STRQ = Mesa STUV (R was taken for red)
45
 *    INTERP_MULTITEX - if defined, interpolate N units of STRQ texcoords
46
 *    INTERP_FLOAT_RGBA - if defined, interpolate RGBA with floating point
47
 *    INTERP_FLOAT_SPEC - if defined, interpolate specular with floating point
48
 *
49
 * When one can directly address pixels in the color buffer the following
50
 * macros can be defined and used to compute pixel addresses during
51
 * rasterization (see pRow):
52
 *    PIXEL_TYPE          - the datatype of a pixel (GLubyte, GLushort, GLuint)
53
 *    BYTES_PER_ROW       - number of bytes per row in the color buffer
54
 *    PIXEL_ADDRESS(X,Y)  - returns the address of pixel at (X,Y) where
55
 *                          Y==0 at bottom of screen and increases upward.
56
 *
57
 * Similarly, for direct depth buffer access, this type is used for depth
58
 * buffer addressing:
59
 *    DEPTH_TYPE          - either GLushort or GLuint
60
 *
61
 * Optionally, one may provide one-time setup code per triangle:
62
 *    SETUP_CODE    - code which is to be executed once per triangle
63
 *    CLEANUP_CODE    - code to execute at end of triangle
64
 *
65
 * The following macro MUST be defined:
66
 *    RENDER_SPAN(span) - code to write a span of pixels.
67
 *
68
 * This code was designed for the origin to be in the lower-left corner.
69
 *
70
 * Inspired by triangle rasterizer code written by Allen Akin.  Thanks Allen!
71
 */
72
 
73
 
74
/*
75
 * This is a bit of a hack, but it's a centralized place to enable floating-
76
 * point color interpolation when GLchan is actually floating point.
77
 */
78
#if CHAN_TYPE == GL_FLOAT
79
 
80
#if defined(INTERP_RGB)
81
#undef INTERP_RGB
82
#undef INTERP_ALPHA
83
#define INTERP_FLOAT_RGBA
84
#endif
85
 
86
#if defined(INTERP_SPEC)
87
#undef INTERP_SPEC
88
#define INTERP_FLOAT_SPEC
89
#endif
90
 
91
#endif
92
 
93
 
94
/*void triangle( GLcontext *ctx, SWvertex *v0, SWvertex *v1, SWvertex *v2 )*/
95
{
96
   typedef struct {
97
        const SWvertex *v0, *v1;   /* Y(v0) < Y(v1) */
98
        GLfloat dx;     /* X(v1) - X(v0) */
99
        GLfloat dy;     /* Y(v1) - Y(v0) */
100
        GLfixed fdxdy;  /* dx/dy in fixed-point */
101
        GLfixed fsx;    /* first sample point x coord */
102
        GLfixed fsy;
103
        GLfloat adjy;   /* adjust from v[0]->fy to fsy, scaled */
104
        GLint lines;    /* number of lines to be sampled on this edge */
105
        GLfixed fx0;    /* fixed pt X of lower endpoint */
106
   } EdgeT;
107
 
108
#ifdef INTERP_Z
109
   const GLint depthBits = ctx->Visual.depthBits;
110
   const GLint fixedToDepthShift = depthBits <= 16 ? FIXED_SHIFT : 0;
111
   const GLfloat maxDepth = ctx->DepthMaxF;
112
#define FixedToDepth(F)  ((F) >> fixedToDepthShift)
113
#endif
114
   EdgeT eMaj, eTop, eBot;
115
   GLfloat oneOverArea;
116
   const SWvertex *vMin, *vMid, *vMax;  /* Y(vMin)<=Y(vMid)<=Y(vMax) */
117
   float bf = SWRAST_CONTEXT(ctx)->_backface_sign;
118
   const GLint snapMask = ~((FIXED_ONE / (1 << SUB_PIXEL_BITS)) - 1); /* for x/y coord snapping */
119
   GLfixed vMin_fx, vMin_fy, vMid_fx, vMid_fy, vMax_fx, vMax_fy;
120
 
121
   struct sw_span span;
122
 
123
   INIT_SPAN(span, GL_POLYGON, 0, 0, 0);
124
 
125
#ifdef INTERP_Z
126
   (void) fixedToDepthShift;
127
#endif
128
 
129
   /*
130
   printf("%s()\n", __FUNCTION__);
131
   printf("  %g, %g, %g\n", v0->win[0], v0->win[1], v0->win[2]);
132
   printf("  %g, %g, %g\n", v1->win[0], v1->win[1], v1->win[2]);
133
   printf("  %g, %g, %g\n", v2->win[0], v2->win[1], v2->win[2]);
134
   */
135
 
136
   /* Compute fixed point x,y coords w/ half-pixel offsets and snapping.
137
    * And find the order of the 3 vertices along the Y axis.
138
    */
139
   {
140
      const GLfixed fy0 = FloatToFixed(v0->win[1] - 0.5F) & snapMask;
141
      const GLfixed fy1 = FloatToFixed(v1->win[1] - 0.5F) & snapMask;
142
      const GLfixed fy2 = FloatToFixed(v2->win[1] - 0.5F) & snapMask;
143
 
144
      if (fy0 <= fy1) {
145
         if (fy1 <= fy2) {
146
            /* y0 <= y1 <= y2 */
147
            vMin = v0;   vMid = v1;   vMax = v2;
148
            vMin_fy = fy0;  vMid_fy = fy1;  vMax_fy = fy2;
149
         }
150
         else if (fy2 <= fy0) {
151
            /* y2 <= y0 <= y1 */
152
            vMin = v2;   vMid = v0;   vMax = v1;
153
            vMin_fy = fy2;  vMid_fy = fy0;  vMax_fy = fy1;
154
         }
155
         else {
156
            /* y0 <= y2 <= y1 */
157
            vMin = v0;   vMid = v2;   vMax = v1;
158
            vMin_fy = fy0;  vMid_fy = fy2;  vMax_fy = fy1;
159
            bf = -bf;
160
         }
161
      }
162
      else {
163
         if (fy0 <= fy2) {
164
            /* y1 <= y0 <= y2 */
165
            vMin = v1;   vMid = v0;   vMax = v2;
166
            vMin_fy = fy1;  vMid_fy = fy0;  vMax_fy = fy2;
167
            bf = -bf;
168
         }
169
         else if (fy2 <= fy1) {
170
            /* y2 <= y1 <= y0 */
171
            vMin = v2;   vMid = v1;   vMax = v0;
172
            vMin_fy = fy2;  vMid_fy = fy1;  vMax_fy = fy0;
173
            bf = -bf;
174
         }
175
         else {
176
            /* y1 <= y2 <= y0 */
177
            vMin = v1;   vMid = v2;   vMax = v0;
178
            vMin_fy = fy1;  vMid_fy = fy2;  vMax_fy = fy0;
179
         }
180
      }
181
 
182
      /* fixed point X coords */
183
      vMin_fx = FloatToFixed(vMin->win[0] + 0.5F) & snapMask;
184
      vMid_fx = FloatToFixed(vMid->win[0] + 0.5F) & snapMask;
185
      vMax_fx = FloatToFixed(vMax->win[0] + 0.5F) & snapMask;
186
   }
187
 
188
   /* vertex/edge relationship */
189
   eMaj.v0 = vMin;   eMaj.v1 = vMax;   /*TODO: .v1's not needed */
190
   eTop.v0 = vMid;   eTop.v1 = vMax;
191
   eBot.v0 = vMin;   eBot.v1 = vMid;
192
 
193
   /* compute deltas for each edge:  vertex[upper] - vertex[lower] */
194
   eMaj.dx = FixedToFloat(vMax_fx - vMin_fx);
195
   eMaj.dy = FixedToFloat(vMax_fy - vMin_fy);
196
   eTop.dx = FixedToFloat(vMax_fx - vMid_fx);
197
   eTop.dy = FixedToFloat(vMax_fy - vMid_fy);
198
   eBot.dx = FixedToFloat(vMid_fx - vMin_fx);
199
   eBot.dy = FixedToFloat(vMid_fy - vMin_fy);
200
 
201
   /* compute area, oneOverArea and perform backface culling */
202
   {
203
      const GLfloat area = eMaj.dx * eBot.dy - eBot.dx * eMaj.dy;
204
 
205
      /* Do backface culling */
206
      if (area * bf < 0.0)
207
         return;
208
 
209
      if (IS_INF_OR_NAN(area) || area == 0.0F)
210
         return;
211
 
212
      oneOverArea = 1.0F / area;
213
   }
214
 
215
#ifndef DO_OCCLUSION_TEST
216
   ctx->OcclusionResult = GL_TRUE;
217
#endif
218
   span.facing = ctx->_Facing; /* for 2-sided stencil test */
219
 
220
   /* Edge setup.  For a triangle strip these could be reused... */
221
   {
222
      eMaj.fsy = FixedCeil(vMin_fy);
223
      eMaj.lines = FixedToInt(FixedCeil(vMax_fy - eMaj.fsy));
224
      if (eMaj.lines > 0) {
225
         GLfloat dxdy = eMaj.dx / eMaj.dy;
226
         eMaj.fdxdy = SignedFloatToFixed(dxdy);
227
         eMaj.adjy = (GLfloat) (eMaj.fsy - vMin_fy);  /* SCALED! */
228
         eMaj.fx0 = vMin_fx;
229
         eMaj.fsx = eMaj.fx0 + (GLfixed) (eMaj.adjy * dxdy);
230
      }
231
      else {
232
         return;  /*CULLED*/
233
      }
234
 
235
      eTop.fsy = FixedCeil(vMid_fy);
236
      eTop.lines = FixedToInt(FixedCeil(vMax_fy - eTop.fsy));
237
      if (eTop.lines > 0) {
238
         GLfloat dxdy = eTop.dx / eTop.dy;
239
         eTop.fdxdy = SignedFloatToFixed(dxdy);
240
         eTop.adjy = (GLfloat) (eTop.fsy - vMid_fy); /* SCALED! */
241
         eTop.fx0 = vMid_fx;
242
         eTop.fsx = eTop.fx0 + (GLfixed) (eTop.adjy * dxdy);
243
      }
244
 
245
      eBot.fsy = FixedCeil(vMin_fy);
246
      eBot.lines = FixedToInt(FixedCeil(vMid_fy - eBot.fsy));
247
      if (eBot.lines > 0) {
248
         GLfloat dxdy = eBot.dx / eBot.dy;
249
         eBot.fdxdy = SignedFloatToFixed(dxdy);
250
         eBot.adjy = (GLfloat) (eBot.fsy - vMin_fy);  /* SCALED! */
251
         eBot.fx0 = vMin_fx;
252
         eBot.fsx = eBot.fx0 + (GLfixed) (eBot.adjy * dxdy);
253
      }
254
   }
255
 
256
   /*
257
    * Conceptually, we view a triangle as two subtriangles
258
    * separated by a perfectly horizontal line.  The edge that is
259
    * intersected by this line is one with maximal absolute dy; we
260
    * call it a ``major'' edge.  The other two edges are the
261
    * ``top'' edge (for the upper subtriangle) and the ``bottom''
262
    * edge (for the lower subtriangle).  If either of these two
263
    * edges is horizontal or very close to horizontal, the
264
    * corresponding subtriangle might cover zero sample points;
265
    * we take care to handle such cases, for performance as well
266
    * as correctness.
267
    *
268
    * By stepping rasterization parameters along the major edge,
269
    * we can avoid recomputing them at the discontinuity where
270
    * the top and bottom edges meet.  However, this forces us to
271
    * be able to scan both left-to-right and right-to-left.
272
    * Also, we must determine whether the major edge is at the
273
    * left or right side of the triangle.  We do this by
274
    * computing the magnitude of the cross-product of the major
275
    * and top edges.  Since this magnitude depends on the sine of
276
    * the angle between the two edges, its sign tells us whether
277
    * we turn to the left or to the right when travelling along
278
    * the major edge to the top edge, and from this we infer
279
    * whether the major edge is on the left or the right.
280
    *
281
    * Serendipitously, this cross-product magnitude is also a
282
    * value we need to compute the iteration parameter
283
    * derivatives for the triangle, and it can be used to perform
284
    * backface culling because its sign tells us whether the
285
    * triangle is clockwise or counterclockwise.  In this code we
286
    * refer to it as ``area'' because it's also proportional to
287
    * the pixel area of the triangle.
288
    */
289
 
290
   {
291
      GLint scan_from_left_to_right;  /* true if scanning left-to-right */
292
#ifdef INTERP_Z
293
      GLfloat dzdx, dzdy;
294
#endif
295
#ifdef INTERP_FOG
296
      GLfloat dfogdy;
297
#endif
298
#if defined(INTERP_RGB) || defined(INTERP_FLOAT_RGBA)
299
      GLfloat drdx, drdy;
300
      GLfloat dgdx, dgdy;
301
      GLfloat dbdx, dbdy;
302
#endif
303
#if defined(INTERP_ALPHA) || defined(INTERP_FLOAT_RGBA)
304
      GLfloat dadx, dady;
305
#endif
306
#if defined(INTERP_SPEC) || defined(INTERP_FLOAT_SPEC)
307
      GLfloat dsrdx, dsrdy;
308
      GLfloat dsgdx, dsgdy;
309
      GLfloat dsbdx, dsbdy;
310
#endif
311
#ifdef INTERP_INDEX
312
      GLfloat didx, didy;
313
#endif
314
#ifdef INTERP_INT_TEX
315
      GLfloat dsdx, dsdy;
316
      GLfloat dtdx, dtdy;
317
#endif
318
#ifdef INTERP_TEX
319
      GLfloat dsdx, dsdy;
320
      GLfloat dtdx, dtdy;
321
      GLfloat dudx, dudy;
322
      GLfloat dvdx, dvdy;
323
#endif
324
#ifdef INTERP_MULTITEX
325
      GLfloat dsdx[MAX_TEXTURE_UNITS], dsdy[MAX_TEXTURE_UNITS];
326
      GLfloat dtdx[MAX_TEXTURE_UNITS], dtdy[MAX_TEXTURE_UNITS];
327
      GLfloat dudx[MAX_TEXTURE_UNITS], dudy[MAX_TEXTURE_UNITS];
328
      GLfloat dvdx[MAX_TEXTURE_UNITS], dvdy[MAX_TEXTURE_UNITS];
329
#endif
330
 
331
      /*
332
       * Execute user-supplied setup code
333
       */
334
#ifdef SETUP_CODE
335
      SETUP_CODE
336
#endif
337
 
338
      scan_from_left_to_right = (oneOverArea < 0.0F);
339
 
340
 
341
      /* compute d?/dx and d?/dy derivatives */
342
#ifdef INTERP_Z
343
      span.interpMask |= SPAN_Z;
344
      {
345
         GLfloat eMaj_dz, eBot_dz;
346
         eMaj_dz = vMax->win[2] - vMin->win[2];
347
         eBot_dz = vMid->win[2] - vMin->win[2];
348
         dzdx = oneOverArea * (eMaj_dz * eBot.dy - eMaj.dy * eBot_dz);
349
         if (dzdx > maxDepth || dzdx < -maxDepth) {
350
            /* probably a sliver triangle */
351
            dzdx = 0.0;
352
            dzdy = 0.0;
353
         }
354
         else {
355
            dzdy = oneOverArea * (eMaj.dx * eBot_dz - eMaj_dz * eBot.dx);
356
         }
357
         if (depthBits <= 16)
358
            span.zStep = SignedFloatToFixed(dzdx);
359
         else
360
            span.zStep = (GLint) dzdx;
361
      }
362
#endif
363
#ifdef INTERP_FOG
364
      span.interpMask |= SPAN_FOG;
365
      {
366
         const GLfloat eMaj_dfog = vMax->fog - vMin->fog;
367
         const GLfloat eBot_dfog = vMid->fog - vMin->fog;
368
         span.fogStep = oneOverArea * (eMaj_dfog * eBot.dy - eMaj.dy * eBot_dfog);
369
         dfogdy = oneOverArea * (eMaj.dx * eBot_dfog - eMaj_dfog * eBot.dx);
370
      }
371
#endif
372
#ifdef INTERP_RGB
373
      span.interpMask |= SPAN_RGBA;
374
      if (ctx->Light.ShadeModel == GL_SMOOTH) {
375
         GLfloat eMaj_dr, eBot_dr;
376
         GLfloat eMaj_dg, eBot_dg;
377
         GLfloat eMaj_db, eBot_db;
378
#  ifdef INTERP_ALPHA
379
         GLfloat eMaj_da, eBot_da;
380
#  endif
381
         eMaj_dr = (GLfloat) ((GLint) vMax->color[RCOMP] -
382
                              (GLint) vMin->color[RCOMP]);
383
         eBot_dr = (GLfloat) ((GLint) vMid->color[RCOMP] -
384
                              (GLint) vMin->color[RCOMP]);
385
         drdx = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
386
         span.redStep = SignedFloatToFixed(drdx);
387
         drdy = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
388
         eMaj_dg = (GLfloat) ((GLint) vMax->color[GCOMP] -
389
                              (GLint) vMin->color[GCOMP]);
390
         eBot_dg = (GLfloat) ((GLint) vMid->color[GCOMP] -
391
                              (GLint) vMin->color[GCOMP]);
392
         dgdx = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
393
         span.greenStep = SignedFloatToFixed(dgdx);
394
         dgdy = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
395
         eMaj_db = (GLfloat) ((GLint) vMax->color[BCOMP] -
396
                              (GLint) vMin->color[BCOMP]);
397
         eBot_db = (GLfloat) ((GLint) vMid->color[BCOMP] -
398
                              (GLint) vMin->color[BCOMP]);
399
         dbdx = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
400
         span.blueStep = SignedFloatToFixed(dbdx);
401
         dbdy = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
402
#  ifdef INTERP_ALPHA
403
         eMaj_da = (GLfloat) ((GLint) vMax->color[ACOMP] -
404
                              (GLint) vMin->color[ACOMP]);
405
         eBot_da = (GLfloat) ((GLint) vMid->color[ACOMP] -
406
                              (GLint) vMin->color[ACOMP]);
407
         dadx = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
408
         span.alphaStep = SignedFloatToFixed(dadx);
409
         dady = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
410
#  endif
411
      }
412
      else {
413
         ASSERT (ctx->Light.ShadeModel == GL_FLAT);
414
         span.interpMask |= SPAN_FLAT;
415
         drdx = drdy = 0.0F;
416
         dgdx = dgdy = 0.0F;
417
         dbdx = dbdy = 0.0F;
418
         span.redStep = 0;
419
         span.greenStep = 0;
420
         span.blueStep = 0;
421
#  ifdef INTERP_ALPHA
422
         dadx = dady = 0.0F;
423
         span.alphaStep = 0;
424
#  endif
425
      }
426
#endif
427
#ifdef INTERP_FLOAT_RGBA
428
      span.interpMask |= SPAN_RGBA;
429
      if (ctx->Light.ShadeModel == GL_SMOOTH) {
430
         GLfloat eMaj_dr, eBot_dr;
431
         GLfloat eMaj_dg, eBot_dg;
432
         GLfloat eMaj_db, eBot_db;
433
         GLfloat eMaj_da, eBot_da;
434
         eMaj_dr = vMax->color[RCOMP] - vMin->color[RCOMP];
435
         eBot_dr = vMid->color[RCOMP] - vMin->color[RCOMP];
436
         drdx = oneOverArea * (eMaj_dr * eBot.dy - eMaj.dy * eBot_dr);
437
         span.redStep = drdx;
438
         drdy = oneOverArea * (eMaj.dx * eBot_dr - eMaj_dr * eBot.dx);
439
         eMaj_dg = vMax->color[GCOMP] - vMin->color[GCOMP];
440
         eBot_dg = vMid->color[GCOMP] - vMin->color[GCOMP];
441
         dgdx = oneOverArea * (eMaj_dg * eBot.dy - eMaj.dy * eBot_dg);
442
         span.greenStep = dgdx;
443
         dgdy = oneOverArea * (eMaj.dx * eBot_dg - eMaj_dg * eBot.dx);
444
         eMaj_db = vMax->color[BCOMP] - vMin->color[BCOMP];
445
         eBot_db = vMid->color[BCOMP] - vMin->color[BCOMP];
446
         dbdx = oneOverArea * (eMaj_db * eBot.dy - eMaj.dy * eBot_db);
447
         span.blueStep = dbdx;
448
         dbdy = oneOverArea * (eMaj.dx * eBot_db - eMaj_db * eBot.dx);
449
         eMaj_da = vMax->color[ACOMP] - vMin->color[ACOMP];
450
         eBot_da = vMid->color[ACOMP] - vMin->color[ACOMP];
451
         dadx = oneOverArea * (eMaj_da * eBot.dy - eMaj.dy * eBot_da);
452
         span.alphaStep = dadx;
453
         dady = oneOverArea * (eMaj.dx * eBot_da - eMaj_da * eBot.dx);
454
      }
455
      else {
456
         drdx = drdy = span.redStep = 0.0F;
457
         dgdx = dgdy = span.greenStep = 0.0F;
458
         dbdx = dbdy = span.blueStep = 0.0F;
459
         dadx = dady = span.alphaStep = 0.0F;
460
      }
461
#endif
462
#ifdef INTERP_SPEC
463
      span.interpMask |= SPAN_SPEC;
464
      if (ctx->Light.ShadeModel == GL_SMOOTH) {
465
         GLfloat eMaj_dsr, eBot_dsr;
466
         GLfloat eMaj_dsg, eBot_dsg;
467
         GLfloat eMaj_dsb, eBot_dsb;
468
         eMaj_dsr = (GLfloat) ((GLint) vMax->specular[RCOMP] -
469
                               (GLint) vMin->specular[RCOMP]);
470
         eBot_dsr = (GLfloat) ((GLint) vMid->specular[RCOMP] -
471
                               (GLint) vMin->specular[RCOMP]);
472
         dsrdx = oneOverArea * (eMaj_dsr * eBot.dy - eMaj.dy * eBot_dsr);
473
         span.specRedStep = SignedFloatToFixed(dsrdx);
474
         dsrdy = oneOverArea * (eMaj.dx * eBot_dsr - eMaj_dsr * eBot.dx);
475
         eMaj_dsg = (GLfloat) ((GLint) vMax->specular[GCOMP] -
476
                               (GLint) vMin->specular[GCOMP]);
477
         eBot_dsg = (GLfloat) ((GLint) vMid->specular[GCOMP] -
478
                               (GLint) vMin->specular[GCOMP]);
479
         dsgdx = oneOverArea * (eMaj_dsg * eBot.dy - eMaj.dy * eBot_dsg);
480
         span.specGreenStep = SignedFloatToFixed(dsgdx);
481
         dsgdy = oneOverArea * (eMaj.dx * eBot_dsg - eMaj_dsg * eBot.dx);
482
         eMaj_dsb = (GLfloat) ((GLint) vMax->specular[BCOMP] -
483
                               (GLint) vMin->specular[BCOMP]);
484
         eBot_dsb = (GLfloat) ((GLint) vMid->specular[BCOMP] -
485
                               (GLint) vMin->specular[BCOMP]);
486
         dsbdx = oneOverArea * (eMaj_dsb * eBot.dy - eMaj.dy * eBot_dsb);
487
         span.specBlueStep = SignedFloatToFixed(dsbdx);
488
         dsbdy = oneOverArea * (eMaj.dx * eBot_dsb - eMaj_dsb * eBot.dx);
489
      }
490
      else {
491
         dsrdx = dsrdy = 0.0F;
492
         dsgdx = dsgdy = 0.0F;
493
         dsbdx = dsbdy = 0.0F;
494
         span.specRedStep = 0;
495
         span.specGreenStep = 0;
496
         span.specBlueStep = 0;
497
      }
498
#endif
499
#ifdef INTERP_FLOAT_SPEC
500
      span.interpMask |= SPAN_SPEC;
501
      if (ctx->Light.ShadeModel == GL_SMOOTH) {
502
         GLfloat eMaj_dsr, eBot_dsr;
503
         GLfloat eMaj_dsg, eBot_dsg;
504
         GLfloat eMaj_dsb, eBot_dsb;
505
         eMaj_dsr = vMax->specular[RCOMP] - vMin->specular[RCOMP];
506
         eBot_dsr = vMid->specular[RCOMP] - vMin->specular[RCOMP];
507
         dsrdx = oneOverArea * (eMaj_dsr * eBot.dy - eMaj.dy * eBot_dsr);
508
         span.specRedStep = dsrdx;
509
         dsrdy = oneOverArea * (eMaj.dx * eBot_dsr - eMaj_dsr * eBot.dx);
510
         eMaj_dsg = vMax->specular[GCOMP] - vMin->specular[GCOMP];
511
         eBot_dsg = vMid->specular[GCOMP] - vMin->specular[GCOMP];
512
         dsgdx = oneOverArea * (eMaj_dsg * eBot.dy - eMaj.dy * eBot_dsg);
513
         span.specGreenStep = dsgdx;
514
         dsgdy = oneOverArea * (eMaj.dx * eBot_dsg - eMaj_dsg * eBot.dx);
515
         eMaj_dsb = vMax->specular[BCOMP] - vMin->specular[BCOMP];
516
         eBot_dsb = vMid->specular[BCOMP] - vMin->specular[BCOMP];
517
         dsbdx = oneOverArea * (eMaj_dsb * eBot.dy - eMaj.dy * eBot_dsb);
518
         span.specBlueStep = dsbdx;
519
         dsbdy = oneOverArea * (eMaj.dx * eBot_dsb - eMaj_dsb * eBot.dx);
520
      }
521
      else {
522
         dsrdx = dsrdy = span.specRedStep = 0;
523
         dsgdx = dsgdy = span.specGreenStep = 0;
524
         dsbdx = dsbdy = span.specBlueStep = 0;
525
      }
526
#endif
527
#ifdef INTERP_INDEX
528
      span.interpMask |= SPAN_INDEX;
529
      if (ctx->Light.ShadeModel == GL_SMOOTH) {
530
         GLfloat eMaj_di, eBot_di;
531
         eMaj_di = (GLfloat) ((GLint) vMax->index - (GLint) vMin->index);
532
         eBot_di = (GLfloat) ((GLint) vMid->index - (GLint) vMin->index);
533
         didx = oneOverArea * (eMaj_di * eBot.dy - eMaj.dy * eBot_di);
534
         span.indexStep = SignedFloatToFixed(didx);
535
         didy = oneOverArea * (eMaj.dx * eBot_di - eMaj_di * eBot.dx);
536
      }
537
      else {
538
         span.interpMask |= SPAN_FLAT;
539
         didx = didy = 0.0F;
540
         span.indexStep = 0;
541
      }
542
#endif
543
#ifdef INTERP_INT_TEX
544
      span.interpMask |= SPAN_INT_TEXTURE;
545
      {
546
         GLfloat eMaj_ds, eBot_ds;
547
         eMaj_ds = (vMax->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
548
         eBot_ds = (vMid->texcoord[0][0] - vMin->texcoord[0][0]) * S_SCALE;
549
         dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
550
         span.intTexStep[0] = SignedFloatToFixed(dsdx);
551
         dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
552
      }
553
      {
554
         GLfloat eMaj_dt, eBot_dt;
555
         eMaj_dt = (vMax->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
556
         eBot_dt = (vMid->texcoord[0][1] - vMin->texcoord[0][1]) * T_SCALE;
557
         dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
558
         span.intTexStep[1] = SignedFloatToFixed(dtdx);
559
         dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
560
      }
561
 
562
#endif
563
#ifdef INTERP_TEX
564
      span.interpMask |= SPAN_TEXTURE;
565
      {
566
         GLfloat wMax = vMax->win[3];
567
         GLfloat wMin = vMin->win[3];
568
         GLfloat wMid = vMid->win[3];
569
         GLfloat eMaj_ds, eBot_ds;
570
         GLfloat eMaj_dt, eBot_dt;
571
         GLfloat eMaj_du, eBot_du;
572
         GLfloat eMaj_dv, eBot_dv;
573
 
574
         eMaj_ds = vMax->texcoord[0][0] * wMax - vMin->texcoord[0][0] * wMin;
575
         eBot_ds = vMid->texcoord[0][0] * wMid - vMin->texcoord[0][0] * wMin;
576
         dsdx = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
577
         dsdy = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
578
         span.texStepX[0][0] = dsdx;
579
         span.texStepY[0][0] = dsdy;
580
 
581
         eMaj_dt = vMax->texcoord[0][1] * wMax - vMin->texcoord[0][1] * wMin;
582
         eBot_dt = vMid->texcoord[0][1] * wMid - vMin->texcoord[0][1] * wMin;
583
         dtdx = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
584
         dtdy = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
585
         span.texStepX[0][1] = dtdx;
586
         span.texStepY[0][1] = dtdy;
587
 
588
         eMaj_du = vMax->texcoord[0][2] * wMax - vMin->texcoord[0][2] * wMin;
589
         eBot_du = vMid->texcoord[0][2] * wMid - vMin->texcoord[0][2] * wMin;
590
         dudx = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
591
         dudy = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
592
         span.texStepX[0][2] = dudx;
593
         span.texStepY[0][2] = dudy;
594
 
595
         eMaj_dv = vMax->texcoord[0][3] * wMax - vMin->texcoord[0][3] * wMin;
596
         eBot_dv = vMid->texcoord[0][3] * wMid - vMin->texcoord[0][3] * wMin;
597
         dvdx = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
598
         dvdy = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
599
         span.texStepX[0][3] = dvdx;
600
         span.texStepY[0][3] = dvdy;
601
      }
602
#endif
603
#ifdef INTERP_MULTITEX
604
      span.interpMask |= SPAN_TEXTURE;
605
      {
606
         GLfloat wMax = vMax->win[3];
607
         GLfloat wMin = vMin->win[3];
608
         GLfloat wMid = vMid->win[3];
609
         GLuint u;
610
         for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
611
            if (ctx->Texture.Unit[u]._ReallyEnabled) {
612
               GLfloat eMaj_ds, eBot_ds;
613
               GLfloat eMaj_dt, eBot_dt;
614
               GLfloat eMaj_du, eBot_du;
615
               GLfloat eMaj_dv, eBot_dv;
616
               eMaj_ds = vMax->texcoord[u][0] * wMax
617
                       - vMin->texcoord[u][0] * wMin;
618
               eBot_ds = vMid->texcoord[u][0] * wMid
619
                       - vMin->texcoord[u][0] * wMin;
620
               dsdx[u] = oneOverArea * (eMaj_ds * eBot.dy - eMaj.dy * eBot_ds);
621
               dsdy[u] = oneOverArea * (eMaj.dx * eBot_ds - eMaj_ds * eBot.dx);
622
               span.texStepX[u][0] = dsdx[u];
623
               span.texStepY[u][0] = dsdy[u];
624
 
625
               eMaj_dt = vMax->texcoord[u][1] * wMax
626
                       - vMin->texcoord[u][1] * wMin;
627
               eBot_dt = vMid->texcoord[u][1] * wMid
628
                       - vMin->texcoord[u][1] * wMin;
629
               dtdx[u] = oneOverArea * (eMaj_dt * eBot.dy - eMaj.dy * eBot_dt);
630
               dtdy[u] = oneOverArea * (eMaj.dx * eBot_dt - eMaj_dt * eBot.dx);
631
               span.texStepX[u][1] = dtdx[u];
632
               span.texStepY[u][1] = dtdy[u];
633
 
634
               eMaj_du = vMax->texcoord[u][2] * wMax
635
                       - vMin->texcoord[u][2] * wMin;
636
               eBot_du = vMid->texcoord[u][2] * wMid
637
                       - vMin->texcoord[u][2] * wMin;
638
               dudx[u] = oneOverArea * (eMaj_du * eBot.dy - eMaj.dy * eBot_du);
639
               dudy[u] = oneOverArea * (eMaj.dx * eBot_du - eMaj_du * eBot.dx);
640
               span.texStepX[u][2] = dudx[u];
641
               span.texStepY[u][2] = dudy[u];
642
 
643
               eMaj_dv = vMax->texcoord[u][3] * wMax
644
                       - vMin->texcoord[u][3] * wMin;
645
               eBot_dv = vMid->texcoord[u][3] * wMid
646
                       - vMin->texcoord[u][3] * wMin;
647
               dvdx[u] = oneOverArea * (eMaj_dv * eBot.dy - eMaj.dy * eBot_dv);
648
               dvdy[u] = oneOverArea * (eMaj.dx * eBot_dv - eMaj_dv * eBot.dx);
649
               span.texStepX[u][3] = dvdx[u];
650
               span.texStepY[u][3] = dvdy[u];
651
            }
652
         }
653
      }
654
#endif
655
 
656
      /*
657
       * We always sample at pixel centers.  However, we avoid
658
       * explicit half-pixel offsets in this code by incorporating
659
       * the proper offset in each of x and y during the
660
       * transformation to window coordinates.
661
       *
662
       * We also apply the usual rasterization rules to prevent
663
       * cracks and overlaps.  A pixel is considered inside a
664
       * subtriangle if it meets all of four conditions: it is on or
665
       * to the right of the left edge, strictly to the left of the
666
       * right edge, on or below the top edge, and strictly above
667
       * the bottom edge.  (Some edges may be degenerate.)
668
       *
669
       * The following discussion assumes left-to-right scanning
670
       * (that is, the major edge is on the left); the right-to-left
671
       * case is a straightforward variation.
672
       *
673
       * We start by finding the half-integral y coordinate that is
674
       * at or below the top of the triangle.  This gives us the
675
       * first scan line that could possibly contain pixels that are
676
       * inside the triangle.
677
       *
678
       * Next we creep down the major edge until we reach that y,
679
       * and compute the corresponding x coordinate on the edge.
680
       * Then we find the half-integral x that lies on or just
681
       * inside the edge.  This is the first pixel that might lie in
682
       * the interior of the triangle.  (We won't know for sure
683
       * until we check the other edges.)
684
       *
685
       * As we rasterize the triangle, we'll step down the major
686
       * edge.  For each step in y, we'll move an integer number
687
       * of steps in x.  There are two possible x step sizes, which
688
       * we'll call the ``inner'' step (guaranteed to land on the
689
       * edge or inside it) and the ``outer'' step (guaranteed to
690
       * land on the edge or outside it).  The inner and outer steps
691
       * differ by one.  During rasterization we maintain an error
692
       * term that indicates our distance from the true edge, and
693
       * select either the inner step or the outer step, whichever
694
       * gets us to the first pixel that falls inside the triangle.
695
       *
696
       * All parameters (z, red, etc.) as well as the buffer
697
       * addresses for color and z have inner and outer step values,
698
       * so that we can increment them appropriately.  This method
699
       * eliminates the need to adjust parameters by creeping a
700
       * sub-pixel amount into the triangle at each scanline.
701
       */
702
 
703
      {
704
         int subTriangle;
705
         GLfixed fx;
706
         GLfixed fxLeftEdge = 0, fxRightEdge = 0;
707
         GLfixed fdxLeftEdge = 0, fdxRightEdge = 0;
708
         GLfixed fdxOuter;
709
         int idxOuter;
710
         float dxOuter;
711
         GLfixed fError = 0, fdError = 0;
712
         float adjx, adjy;
713
         GLfixed fy;
714
#ifdef PIXEL_ADDRESS
715
         PIXEL_TYPE *pRow = NULL;
716
         int dPRowOuter = 0, dPRowInner;  /* offset in bytes */
717
#endif
718
#ifdef INTERP_Z
719
#  ifdef DEPTH_TYPE
720
         DEPTH_TYPE *zRow = NULL;
721
         int dZRowOuter = 0, dZRowInner;  /* offset in bytes */
722
#  endif
723
         GLfixed fz = 0, fdzOuter = 0, fdzInner;
724
#endif
725
#ifdef INTERP_FOG
726
         GLfloat fogLeft = 0, dfogOuter = 0, dfogInner;
727
#endif
728
#ifdef INTERP_RGB
729
         GLfixed fr = 0, fdrOuter = 0, fdrInner;
730
         GLfixed fg = 0, fdgOuter = 0, fdgInner;
731
         GLfixed fb = 0, fdbOuter = 0, fdbInner;
732
#endif
733
#ifdef INTERP_ALPHA
734
         GLfixed fa = 0, fdaOuter = 0, fdaInner;
735
#endif
736
#ifdef INTERP_FLOAT_RGBA
737
         GLfloat fr, fdrOuter, fdrInner;
738
         GLfloat fg, fdgOuter, fdgInner;
739
         GLfloat fb, fdbOuter, fdbInner;
740
         GLfloat fa, fdaOuter, fdaInner;
741
#endif
742
#ifdef INTERP_SPEC
743
         GLfixed fsr=0, fdsrOuter=0, fdsrInner;
744
         GLfixed fsg=0, fdsgOuter=0, fdsgInner;
745
         GLfixed fsb=0, fdsbOuter=0, fdsbInner;
746
#endif
747
#ifdef INTERP_FLOAT_SPEC
748
         GLfloat fsr=0, fdsrOuter=0, fdsrInner;
749
         GLfloat fsg=0, fdsgOuter=0, fdsgInner;
750
         GLfloat fsb=0, fdsbOuter=0, fdsbInner;
751
#endif
752
#ifdef INTERP_INDEX
753
         GLfixed fi=0, fdiOuter=0, fdiInner;
754
#endif
755
#ifdef INTERP_INT_TEX
756
         GLfixed fs=0, fdsOuter=0, fdsInner;
757
         GLfixed ft=0, fdtOuter=0, fdtInner;
758
#endif
759
#ifdef INTERP_TEX
760
         GLfloat sLeft=0, dsOuter=0, dsInner;
761
         GLfloat tLeft=0, dtOuter=0, dtInner;
762
         GLfloat uLeft=0, duOuter=0, duInner;
763
         GLfloat vLeft=0, dvOuter=0, dvInner;
764
#endif
765
#ifdef INTERP_MULTITEX
766
         GLfloat sLeft[MAX_TEXTURE_UNITS];
767
         GLfloat tLeft[MAX_TEXTURE_UNITS];
768
         GLfloat uLeft[MAX_TEXTURE_UNITS];
769
         GLfloat vLeft[MAX_TEXTURE_UNITS];
770
         GLfloat dsOuter[MAX_TEXTURE_UNITS], dsInner[MAX_TEXTURE_UNITS];
771
         GLfloat dtOuter[MAX_TEXTURE_UNITS], dtInner[MAX_TEXTURE_UNITS];
772
         GLfloat duOuter[MAX_TEXTURE_UNITS], duInner[MAX_TEXTURE_UNITS];
773
         GLfloat dvOuter[MAX_TEXTURE_UNITS], dvInner[MAX_TEXTURE_UNITS];
774
#endif
775
 
776
         for (subTriangle=0; subTriangle<=1; subTriangle++) {
777
            EdgeT *eLeft, *eRight;
778
            int setupLeft, setupRight;
779
            int lines;
780
 
781
            if (subTriangle==0) {
782
               /* bottom half */
783
               if (scan_from_left_to_right) {
784
                  eLeft = &eMaj;
785
                  eRight = &eBot;
786
                  lines = eRight->lines;
787
                  setupLeft = 1;
788
                  setupRight = 1;
789
               }
790
               else {
791
                  eLeft = &eBot;
792
                  eRight = &eMaj;
793
                  lines = eLeft->lines;
794
                  setupLeft = 1;
795
                  setupRight = 1;
796
               }
797
            }
798
            else {
799
               /* top half */
800
               if (scan_from_left_to_right) {
801
                  eLeft = &eMaj;
802
                  eRight = &eTop;
803
                  lines = eRight->lines;
804
                  setupLeft = 0;
805
                  setupRight = 1;
806
               }
807
               else {
808
                  eLeft = &eTop;
809
                  eRight = &eMaj;
810
                  lines = eLeft->lines;
811
                  setupLeft = 1;
812
                  setupRight = 0;
813
               }
814
               if (lines == 0)
815
                  return;
816
            }
817
 
818
            if (setupLeft && eLeft->lines > 0) {
819
               const SWvertex *vLower;
820
               GLfixed fsx = eLeft->fsx;
821
               fx = FixedCeil(fsx);
822
               fError = fx - fsx - FIXED_ONE;
823
               fxLeftEdge = fsx - FIXED_EPSILON;
824
               fdxLeftEdge = eLeft->fdxdy;
825
               fdxOuter = FixedFloor(fdxLeftEdge - FIXED_EPSILON);
826
               fdError = fdxOuter - fdxLeftEdge + FIXED_ONE;
827
               idxOuter = FixedToInt(fdxOuter);
828
               dxOuter = (float) idxOuter;
829
               (void) dxOuter;
830
 
831
               fy = eLeft->fsy;
832
               span.y = FixedToInt(fy);
833
 
834
               adjx = (float)(fx - eLeft->fx0);  /* SCALED! */
835
               adjy = eLeft->adjy;               /* SCALED! */
836
               (void) adjx;  /* silence compiler warnings */
837
               (void) adjy;  /* silence compiler warnings */
838
 
839
               vLower = eLeft->v0;
840
               (void) vLower;  /* silence compiler warnings */
841
 
842
#ifdef PIXEL_ADDRESS
843
               {
844
                  pRow = (PIXEL_TYPE *) PIXEL_ADDRESS(FixedToInt(fxLeftEdge), span.y);
845
                  dPRowOuter = -((int)BYTES_PER_ROW) + idxOuter * sizeof(PIXEL_TYPE);
846
                  /* negative because Y=0 at bottom and increases upward */
847
               }
848
#endif
849
               /*
850
                * Now we need the set of parameter (z, color, etc.) values at
851
                * the point (fx, fy).  This gives us properly-sampled parameter
852
                * values that we can step from pixel to pixel.  Furthermore,
853
                * although we might have intermediate results that overflow
854
                * the normal parameter range when we step temporarily outside
855
                * the triangle, we shouldn't overflow or underflow for any
856
                * pixel that's actually inside the triangle.
857
                */
858
 
859
#ifdef INTERP_Z
860
               {
861
                  GLfloat z0 = vLower->win[2];
862
                  if (depthBits <= 16) {
863
                     /* interpolate fixed-pt values */
864
                     GLfloat tmp = (z0 * FIXED_SCALE +
865
                                    dzdx * adjx + dzdy * adjy) + FIXED_HALF;
866
                     if (tmp < MAX_GLUINT / 2)
867
                        fz = (GLfixed) tmp;
868
                     else
869
                        fz = MAX_GLUINT / 2;
870
                     fdzOuter = SignedFloatToFixed(dzdy + dxOuter * dzdx);
871
                  }
872
                  else {
873
                     /* interpolate depth values exactly */
874
                     fz = (GLint) (z0 + dzdx * FixedToFloat(adjx)
875
                                   + dzdy * FixedToFloat(adjy));
876
                     fdzOuter = (GLint) (dzdy + dxOuter * dzdx);
877
                  }
878
#  ifdef DEPTH_TYPE
879
                  zRow = (DEPTH_TYPE *)
880
                    _mesa_zbuffer_address(ctx, FixedToInt(fxLeftEdge), span.y);
881
                  dZRowOuter = (ctx->DrawBuffer->Width + idxOuter) * sizeof(DEPTH_TYPE);
882
#  endif
883
               }
884
#endif
885
#ifdef INTERP_FOG
886
               fogLeft = vLower->fog + (span.fogStep * adjx + dfogdy * adjy)
887
                                       * (1.0F/FIXED_SCALE);
888
               dfogOuter = dfogdy + dxOuter * span.fogStep;
889
#endif
890
#ifdef INTERP_RGB
891
               if (ctx->Light.ShadeModel == GL_SMOOTH) {
892
                  fr = (GLfixed) (ChanToFixed(vLower->color[RCOMP])
893
                                   + drdx * adjx + drdy * adjy) + FIXED_HALF;
894
                  fdrOuter = SignedFloatToFixed(drdy + dxOuter * drdx);
895
                  fg = (GLfixed) (ChanToFixed(vLower->color[GCOMP])
896
                                   + dgdx * adjx + dgdy * adjy) + FIXED_HALF;
897
                  fdgOuter = SignedFloatToFixed(dgdy + dxOuter * dgdx);
898
                  fb = (GLfixed) (ChanToFixed(vLower->color[BCOMP])
899
                                    + dbdx * adjx + dbdy * adjy) + FIXED_HALF;
900
                  fdbOuter = SignedFloatToFixed(dbdy + dxOuter * dbdx);
901
#  ifdef INTERP_ALPHA
902
                  fa = (GLfixed) (ChanToFixed(vLower->color[ACOMP])
903
                                   + dadx * adjx + dady * adjy) + FIXED_HALF;
904
                  fdaOuter = SignedFloatToFixed(dady + dxOuter * dadx);
905
#  endif
906
               }
907
               else {
908
                  ASSERT (ctx->Light.ShadeModel == GL_FLAT);
909
                  fr = ChanToFixed(v2->color[RCOMP]);
910
                  fg = ChanToFixed(v2->color[GCOMP]);
911
                  fb = ChanToFixed(v2->color[BCOMP]);
912
                  fdrOuter = fdgOuter = fdbOuter = 0;
913
#  ifdef INTERP_ALPHA
914
                  fa =  ChanToFixed(v2->color[ACOMP]);
915
                  fdaOuter = 0;
916
#  endif
917
               }
918
#endif
919
#ifdef INTERP_FLOAT_RGBA
920
               if (ctx->Light.ShadeModel == GL_SMOOTH) {
921
                  fr = vLower->color[RCOMP]
922
                     + (drdx * adjx + drdy * adjy) * (1.0F / FIXED_SCALE);
923
                  fdrOuter = drdy + dxOuter * drdx;
924
                  fg = vLower->color[GCOMP]
925
                     + (dgdx * adjx + dgdy * adjy) * (1.0F / FIXED_SCALE);
926
                  fdgOuter = dgdy + dxOuter * dgdx;
927
                  fb = vLower->color[BCOMP]
928
                     + (dbdx * adjx + dbdy * adjy) * (1.0F / FIXED_SCALE);
929
                  fdbOuter = dbdy + dxOuter * dbdx;
930
                  fa = vLower->color[ACOMP]
931
                     + (dadx * adjx + dady * adjy) * (1.0F / FIXED_SCALE);
932
                  fdaOuter = dady + dxOuter * dadx;
933
               }
934
               else {
935
                  fr = v2->color[RCOMP];
936
                  fg = v2->color[GCOMP];
937
                  fb = v2->color[BCOMP];
938
                  fa = v2->color[ACOMP];
939
                  fdrOuter = fdgOuter = fdbOuter = fdaOuter = 0.0F;
940
               }
941
#endif
942
#ifdef INTERP_SPEC
943
               if (ctx->Light.ShadeModel == GL_SMOOTH) {
944
                  fsr = (GLfixed) (ChanToFixed(vLower->specular[RCOMP])
945
                                   + dsrdx * adjx + dsrdy * adjy) + FIXED_HALF;
946
                  fdsrOuter = SignedFloatToFixed(dsrdy + dxOuter * dsrdx);
947
                  fsg = (GLfixed) (ChanToFixed(vLower->specular[GCOMP])
948
                                   + dsgdx * adjx + dsgdy * adjy) + FIXED_HALF;
949
                  fdsgOuter = SignedFloatToFixed(dsgdy + dxOuter * dsgdx);
950
                  fsb = (GLfixed) (ChanToFixed(vLower->specular[BCOMP])
951
                                   + dsbdx * adjx + dsbdy * adjy) + FIXED_HALF;
952
                  fdsbOuter = SignedFloatToFixed(dsbdy + dxOuter * dsbdx);
953
               }
954
               else {
955
                  fsr = ChanToFixed(v2->specular[RCOMP]);
956
                  fsg = ChanToFixed(v2->specular[GCOMP]);
957
                  fsb = ChanToFixed(v2->specular[BCOMP]);
958
                  fdsrOuter = fdsgOuter = fdsbOuter = 0;
959
               }
960
#endif
961
#ifdef INTERP_FLOAT_SPEC
962
               if (ctx->Light.ShadeModel == GL_SMOOTH) {
963
                  fsr = vLower->specular[RCOMP]
964
                     + (dsrdx * adjx + dsrdy * adjy) * (1.0F / FIXED_SCALE);
965
                  fdsrOuter = dsrdy + dxOuter * dsrdx;
966
                  fsg = vLower->specular[GCOMP]
967
                     + (dsgdx * adjx + dsgdy * adjy) * (1.0F / FIXED_SCALE);
968
                  fdsgOuter = dsgdy + dxOuter * dsgdx;
969
                  fsb = vLower->specular[BCOMP]
970
                     + (dsbdx * adjx + dsbdy * adjy) * (1.0F / FIXED_SCALE);
971
                  fdsbOuter = dsbdy + dxOuter * dsbdx;
972
               }
973
               else {
974
                  fsr = v2->specular[RCOMP];
975
                  fsg = v2->specular[GCOMP];
976
                  fsb = v2->specular[BCOMP];
977
                  fdsrOuter = fdsgOuter = fdsbOuter = 0.0F;
978
               }
979
#endif
980
#ifdef INTERP_INDEX
981
               if (ctx->Light.ShadeModel == GL_SMOOTH) {
982
                  fi = (GLfixed)(vLower->index * FIXED_SCALE
983
                                 + didx * adjx + didy * adjy) + FIXED_HALF;
984
                  fdiOuter = SignedFloatToFixed(didy + dxOuter * didx);
985
               }
986
               else {
987
                  fi = (GLfixed) (v2->index * FIXED_SCALE);
988
                  fdiOuter = 0;
989
               }
990
#endif
991
#ifdef INTERP_INT_TEX
992
               {
993
                  GLfloat s0, t0;
994
                  s0 = vLower->texcoord[0][0] * S_SCALE;
995
                  fs = (GLfixed)(s0 * FIXED_SCALE + dsdx * adjx
996
                                 + dsdy * adjy) + FIXED_HALF;
997
                  fdsOuter = SignedFloatToFixed(dsdy + dxOuter * dsdx);
998
 
999
                  t0 = vLower->texcoord[0][1] * T_SCALE;
1000
                  ft = (GLfixed)(t0 * FIXED_SCALE + dtdx * adjx
1001
                                 + dtdy * adjy) + FIXED_HALF;
1002
                  fdtOuter = SignedFloatToFixed(dtdy + dxOuter * dtdx);
1003
               }
1004
#endif
1005
#ifdef INTERP_TEX
1006
               {
1007
                  GLfloat invW = vLower->win[3];
1008
                  GLfloat s0, t0, u0, v0;
1009
                  s0 = vLower->texcoord[0][0] * invW;
1010
                  sLeft = s0 + (span.texStepX[0][0] * adjx + dsdy * adjy)
1011
                     * (1.0F/FIXED_SCALE);
1012
                  dsOuter = dsdy + dxOuter * span.texStepX[0][0];
1013
                  t0 = vLower->texcoord[0][1] * invW;
1014
                  tLeft = t0 + (span.texStepX[0][1] * adjx + dtdy * adjy)
1015
                     * (1.0F/FIXED_SCALE);
1016
                  dtOuter = dtdy + dxOuter * span.texStepX[0][1];
1017
                  u0 = vLower->texcoord[0][2] * invW;
1018
                  uLeft = u0 + (span.texStepX[0][2] * adjx + dudy * adjy)
1019
                     * (1.0F/FIXED_SCALE);
1020
                  duOuter = dudy + dxOuter * span.texStepX[0][2];
1021
                  v0 = vLower->texcoord[0][3] * invW;
1022
                  vLeft = v0 + (span.texStepX[0][3] * adjx + dvdy * adjy)
1023
                     * (1.0F/FIXED_SCALE);
1024
                  dvOuter = dvdy + dxOuter * span.texStepX[0][3];
1025
               }
1026
#endif
1027
#ifdef INTERP_MULTITEX
1028
               {
1029
                  GLuint u;
1030
                  for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
1031
                     if (ctx->Texture.Unit[u]._ReallyEnabled) {
1032
                        GLfloat invW = vLower->win[3];
1033
                        GLfloat s0, t0, u0, v0;
1034
                        s0 = vLower->texcoord[u][0] * invW;
1035
                        sLeft[u] = s0 + (span.texStepX[u][0] * adjx + dsdy[u]
1036
                                         * adjy) * (1.0F/FIXED_SCALE);
1037
                        dsOuter[u] = dsdy[u] + dxOuter * span.texStepX[u][0];
1038
                        t0 = vLower->texcoord[u][1] * invW;
1039
                        tLeft[u] = t0 + (span.texStepX[u][1] * adjx + dtdy[u]
1040
                                         * adjy) * (1.0F/FIXED_SCALE);
1041
                        dtOuter[u] = dtdy[u] + dxOuter * span.texStepX[u][1];
1042
                        u0 = vLower->texcoord[u][2] * invW;
1043
                        uLeft[u] = u0 + (span.texStepX[u][2] * adjx + dudy[u]
1044
                                         * adjy) * (1.0F/FIXED_SCALE);
1045
                        duOuter[u] = dudy[u] + dxOuter * span.texStepX[u][2];
1046
                        v0 = vLower->texcoord[u][3] * invW;
1047
                        vLeft[u] = v0 + (span.texStepX[u][3] * adjx + dvdy[u]
1048
                                         * adjy) * (1.0F/FIXED_SCALE);
1049
                        dvOuter[u] = dvdy[u] + dxOuter * span.texStepX[u][3];
1050
                     }
1051
                  }
1052
               }
1053
#endif
1054
 
1055
            } /*if setupLeft*/
1056
 
1057
 
1058
            if (setupRight && eRight->lines>0) {
1059
               fxRightEdge = eRight->fsx - FIXED_EPSILON;
1060
               fdxRightEdge = eRight->fdxdy;
1061
            }
1062
 
1063
            if (lines==0) {
1064
               continue;
1065
            }
1066
 
1067
 
1068
            /* Rasterize setup */
1069
#ifdef PIXEL_ADDRESS
1070
            dPRowInner = dPRowOuter + sizeof(PIXEL_TYPE);
1071
#endif
1072
#ifdef INTERP_Z
1073
#  ifdef DEPTH_TYPE
1074
            dZRowInner = dZRowOuter + sizeof(DEPTH_TYPE);
1075
#  endif
1076
            fdzInner = fdzOuter + span.zStep;
1077
#endif
1078
#ifdef INTERP_FOG
1079
            dfogInner = dfogOuter + span.fogStep;
1080
#endif
1081
#if defined(INTERP_RGB) || defined(INTERP_FLOAT_RGBA)
1082
            fdrInner = fdrOuter + span.redStep;
1083
            fdgInner = fdgOuter + span.greenStep;
1084
            fdbInner = fdbOuter + span.blueStep;
1085
#endif
1086
#if defined(INTERP_ALPHA) || defined(INTERP_FLOAT_RGBA)
1087
            fdaInner = fdaOuter + span.alphaStep;
1088
#endif
1089
#if defined(INTERP_SPEC) || defined(INTERP_FLOAT_SPEC)
1090
            fdsrInner = fdsrOuter + span.specRedStep;
1091
            fdsgInner = fdsgOuter + span.specGreenStep;
1092
            fdsbInner = fdsbOuter + span.specBlueStep;
1093
#endif
1094
#ifdef INTERP_INDEX
1095
            fdiInner = fdiOuter + span.indexStep;
1096
#endif
1097
#ifdef INTERP_INT_TEX
1098
            fdsInner = fdsOuter + span.intTexStep[0];
1099
            fdtInner = fdtOuter + span.intTexStep[1];
1100
#endif
1101
#ifdef INTERP_TEX
1102
            dsInner = dsOuter + span.texStepX[0][0];
1103
            dtInner = dtOuter + span.texStepX[0][1];
1104
            duInner = duOuter + span.texStepX[0][2];
1105
            dvInner = dvOuter + span.texStepX[0][3];
1106
#endif
1107
#ifdef INTERP_MULTITEX
1108
            {
1109
               GLuint u;
1110
               for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
1111
                  if (ctx->Texture.Unit[u]._ReallyEnabled) {
1112
                     dsInner[u] = dsOuter[u] + span.texStepX[u][0];
1113
                     dtInner[u] = dtOuter[u] + span.texStepX[u][1];
1114
                     duInner[u] = duOuter[u] + span.texStepX[u][2];
1115
                     dvInner[u] = dvOuter[u] + span.texStepX[u][3];
1116
                  }
1117
               }
1118
            }
1119
#endif
1120
 
1121
            while (lines > 0) {
1122
               /* initialize the span interpolants to the leftmost value */
1123
               /* ff = fixed-pt fragment */
1124
               const GLint right = FixedToInt(fxRightEdge);
1125
 
1126
               span.x = FixedToInt(fxLeftEdge);
1127
 
1128
               if (right <= span.x)
1129
                  span.end = 0;
1130
               else
1131
                  span.end = right - span.x;
1132
 
1133
#ifdef INTERP_Z
1134
               span.z = fz;
1135
#endif
1136
#ifdef INTERP_FOG
1137
               span.fog = fogLeft;
1138
#endif
1139
#if defined(INTERP_RGB) || defined(INTERP_FLOAT_RGBA)
1140
               span.red = fr;
1141
               span.green = fg;
1142
               span.blue = fb;
1143
#endif
1144
#if defined(INTERP_ALPHA) || defined(INTERP_FLOAT_RGBA)
1145
               span.alpha = fa;
1146
#endif
1147
#if defined(INTERP_SPEC) || defined(INTERP_FLOAT_SPEC)
1148
               span.specRed = fsr;
1149
               span.specGreen = fsg;
1150
               span.specBlue = fsb;
1151
#endif
1152
#ifdef INTERP_INDEX
1153
               span.index = fi;
1154
#endif
1155
#ifdef INTERP_INT_TEX
1156
               span.intTex[0] = fs;
1157
               span.intTex[1] = ft;
1158
#endif
1159
 
1160
#ifdef INTERP_TEX
1161
               span.tex[0][0] = sLeft;
1162
               span.tex[0][1] = tLeft;
1163
               span.tex[0][2] = uLeft;
1164
               span.tex[0][3] = vLeft;
1165
#endif
1166
 
1167
#ifdef INTERP_MULTITEX
1168
               {
1169
                  GLuint u;
1170
                  for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
1171
                     if (ctx->Texture.Unit[u]._ReallyEnabled) {
1172
                        span.tex[u][0] = sLeft[u];
1173
                        span.tex[u][1] = tLeft[u];
1174
                        span.tex[u][2] = uLeft[u];
1175
                        span.tex[u][3] = vLeft[u];
1176
                     }
1177
                  }
1178
               }
1179
#endif
1180
 
1181
#ifdef INTERP_RGB
1182
               {
1183
                  /* need this to accomodate round-off errors */
1184
                  const GLint len = right - span.x - 1;
1185
                  GLfixed ffrend = span.red + len * span.redStep;
1186
                  GLfixed ffgend = span.green + len * span.greenStep;
1187
                  GLfixed ffbend = span.blue + len * span.blueStep;
1188
                  if (ffrend < 0) {
1189
                     span.red -= ffrend;
1190
                     if (span.red < 0)
1191
                        span.red = 0;
1192
                  }
1193
                  if (ffgend < 0) {
1194
                     span.green -= ffgend;
1195
                     if (span.green < 0)
1196
                        span.green = 0;
1197
                  }
1198
                  if (ffbend < 0) {
1199
                     span.blue -= ffbend;
1200
                     if (span.blue < 0)
1201
                        span.blue = 0;
1202
                  }
1203
               }
1204
#endif
1205
#ifdef INTERP_ALPHA
1206
               {
1207
                  const GLint len = right - span.x - 1;
1208
                  GLfixed ffaend = span.alpha + len * span.alphaStep;
1209
                  if (ffaend < 0) {
1210
                     span.alpha -= ffaend;
1211
                     if (span.alpha < 0)
1212
                        span.alpha = 0;
1213
                  }
1214
               }
1215
#endif
1216
#ifdef INTERP_SPEC
1217
               {
1218
                  /* need this to accomodate round-off errors */
1219
                  const GLint len = right - span.x - 1;
1220
                  GLfixed ffsrend = span.specRed + len * span.specRedStep;
1221
                  GLfixed ffsgend = span.specGreen + len * span.specGreenStep;
1222
                  GLfixed ffsbend = span.specBlue + len * span.specBlueStep;
1223
                  if (ffsrend < 0) {
1224
                     span.specRed -= ffsrend;
1225
                     if (span.specRed < 0)
1226
                        span.specRed = 0;
1227
                  }
1228
                  if (ffsgend < 0) {
1229
                     span.specGreen -= ffsgend;
1230
                     if (span.specGreen < 0)
1231
                        span.specGreen = 0;
1232
                  }
1233
                  if (ffsbend < 0) {
1234
                     span.specBlue -= ffsbend;
1235
                     if (span.specBlue < 0)
1236
                        span.specBlue = 0;
1237
                  }
1238
               }
1239
#endif
1240
#ifdef INTERP_INDEX
1241
               if (span.index < 0)  span.index = 0;
1242
#endif
1243
 
1244
               /* This is where we actually generate fragments */
1245
               if (span.end > 0) {
1246
                  RENDER_SPAN( span );
1247
               }
1248
 
1249
               /*
1250
                * Advance to the next scan line.  Compute the
1251
                * new edge coordinates, and adjust the
1252
                * pixel-center x coordinate so that it stays
1253
                * on or inside the major edge.
1254
                */
1255
               (span.y)++;
1256
               lines--;
1257
 
1258
               fxLeftEdge += fdxLeftEdge;
1259
               fxRightEdge += fdxRightEdge;
1260
 
1261
 
1262
               fError += fdError;
1263
               if (fError >= 0) {
1264
                  fError -= FIXED_ONE;
1265
#ifdef PIXEL_ADDRESS
1266
                  pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowOuter);
1267
#endif
1268
#ifdef INTERP_Z
1269
#  ifdef DEPTH_TYPE
1270
                  zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowOuter);
1271
#  endif
1272
                  fz += fdzOuter;
1273
#endif
1274
#ifdef INTERP_FOG
1275
                  fogLeft += dfogOuter;
1276
#endif
1277
#if defined(INTERP_RGB) || defined(INTERP_FLOAT_RGBA)
1278
                  fr += fdrOuter;
1279
                  fg += fdgOuter;
1280
                  fb += fdbOuter;
1281
#endif
1282
#if defined(INTERP_ALPHA) || defined(INTERP_FLOAT_RGBA)
1283
                  fa += fdaOuter;
1284
#endif
1285
#if defined(INTERP_SPEC) || defined(INTERP_FLOAT_SPEC)
1286
                  fsr += fdsrOuter;
1287
                  fsg += fdsgOuter;
1288
                  fsb += fdsbOuter;
1289
#endif
1290
#ifdef INTERP_INDEX
1291
                  fi += fdiOuter;
1292
#endif
1293
#ifdef INTERP_INT_TEX
1294
                  fs += fdsOuter;
1295
                  ft += fdtOuter;
1296
#endif
1297
#ifdef INTERP_TEX
1298
                  sLeft += dsOuter;
1299
                  tLeft += dtOuter;
1300
                  uLeft += duOuter;
1301
                  vLeft += dvOuter;
1302
#endif
1303
#ifdef INTERP_MULTITEX
1304
                  {
1305
                     GLuint u;
1306
                     for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
1307
                        if (ctx->Texture.Unit[u]._ReallyEnabled) {
1308
                           sLeft[u] += dsOuter[u];
1309
                           tLeft[u] += dtOuter[u];
1310
                           uLeft[u] += duOuter[u];
1311
                           vLeft[u] += dvOuter[u];
1312
                        }
1313
                     }
1314
                  }
1315
#endif
1316
               }
1317
               else {
1318
#ifdef PIXEL_ADDRESS
1319
                  pRow = (PIXEL_TYPE *) ((GLubyte *) pRow + dPRowInner);
1320
#endif
1321
#ifdef INTERP_Z
1322
#  ifdef DEPTH_TYPE
1323
                  zRow = (DEPTH_TYPE *) ((GLubyte *) zRow + dZRowInner);
1324
#  endif
1325
                  fz += fdzInner;
1326
#endif
1327
#ifdef INTERP_FOG
1328
                  fogLeft += dfogInner;
1329
#endif
1330
#if defined(INTERP_RGB) || defined(INTERP_FLOAT_RGBA)
1331
                  fr += fdrInner;
1332
                  fg += fdgInner;
1333
                  fb += fdbInner;
1334
#endif
1335
#if defined(INTERP_ALPHA) || defined(INTERP_FLOAT_RGBA)
1336
                  fa += fdaInner;
1337
#endif
1338
#if defined(INTERP_SPEC) || defined(INTERP_FLOAT_SPEC)
1339
                  fsr += fdsrInner;
1340
                  fsg += fdsgInner;
1341
                  fsb += fdsbInner;
1342
#endif
1343
#ifdef INTERP_INDEX
1344
                  fi += fdiInner;
1345
#endif
1346
#ifdef INTERP_INT_TEX
1347
                  fs += fdsInner;
1348
                  ft += fdtInner;
1349
#endif
1350
#ifdef INTERP_TEX
1351
                  sLeft += dsInner;
1352
                  tLeft += dtInner;
1353
                  uLeft += duInner;
1354
                  vLeft += dvInner;
1355
#endif
1356
#ifdef INTERP_MULTITEX
1357
                  {
1358
                     GLuint u;
1359
                     for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
1360
                        if (ctx->Texture.Unit[u]._ReallyEnabled) {
1361
                           sLeft[u] += dsInner[u];
1362
                           tLeft[u] += dtInner[u];
1363
                           uLeft[u] += duInner[u];
1364
                           vLeft[u] += dvInner[u];
1365
                        }
1366
                     }
1367
                  }
1368
#endif
1369
               }
1370
            } /*while lines>0*/
1371
 
1372
         } /* for subTriangle */
1373
 
1374
      }
1375
#ifdef CLEANUP_CODE
1376
      CLEANUP_CODE
1377
#endif
1378
   }
1379
}
1380
 
1381
#undef SETUP_CODE
1382
#undef CLEANUP_CODE
1383
#undef RENDER_SPAN
1384
 
1385
#undef PIXEL_TYPE
1386
#undef BYTES_PER_ROW
1387
#undef PIXEL_ADDRESS
1388
 
1389
#undef INTERP_Z
1390
#undef INTERP_FOG
1391
#undef INTERP_RGB
1392
#undef INTERP_ALPHA
1393
#undef INTERP_SPEC
1394
#undef INTERP_INDEX
1395
#undef INTERP_INT_TEX
1396
#undef INTERP_TEX
1397
#undef INTERP_MULTITEX
1398
#undef INTERP_FLOAT_RGBA
1399
#undef INTERP_FLOAT_SPEC
1400
 
1401
#undef S_SCALE
1402
#undef T_SCALE
1403
 
1404
#undef FixedToDepth
1405
 
1406
#undef DO_OCCLUSION_TEST