~ubuntu-branches/ubuntu/quantal/mesa-glw/quantal

« back to all changes in this revision

Viewing changes to src/mesa/swrast/s_triangle.c

  • Committer: Bazaar Package Importer
  • Author(s): Morten Kjeldgaard
  • Date: 2008-05-06 16:19:15 UTC
  • Revision ID: james.westby@ubuntu.com-20080506161915-uynz7nftmfixu6bq
Tags: upstream-7.0.3
ImportĀ upstreamĀ versionĀ 7.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Mesa 3-D graphics library
 
3
 * Version:  6.5.3
 
4
 *
 
5
 * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
 
6
 *
 
7
 * Permission is hereby granted, free of charge, to any person obtaining a
 
8
 * copy of this software and associated documentation files (the "Software"),
 
9
 * to deal in the Software without restriction, including without limitation
 
10
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 
11
 * and/or sell copies of the Software, and to permit persons to whom the
 
12
 * Software is furnished to do so, subject to the following conditions:
 
13
 *
 
14
 * The above copyright notice and this permission notice shall be included
 
15
 * in all copies or substantial portions of the Software.
 
16
 *
 
17
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 
18
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
19
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 
20
 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
21
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
22
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
23
 */
 
24
 
 
25
 
 
26
/*
 
27
 * When the device driver doesn't implement triangle rasterization it
 
28
 * can hook in _swrast_Triangle, which eventually calls one of these
 
29
 * functions to draw triangles.
 
30
 */
 
31
 
 
32
#include "glheader.h"
 
33
#include "context.h"
 
34
#include "colormac.h"
 
35
#include "imports.h"
 
36
#include "macros.h"
 
37
#include "texformat.h"
 
38
 
 
39
#include "s_aatriangle.h"
 
40
#include "s_context.h"
 
41
#include "s_feedback.h"
 
42
#include "s_span.h"
 
43
#include "s_triangle.h"
 
44
 
 
45
 
 
46
/*
 
47
 * Just used for feedback mode.
 
48
 */
 
49
GLboolean
 
50
_swrast_culltriangle( GLcontext *ctx,
 
51
                      const SWvertex *v0,
 
52
                      const SWvertex *v1,
 
53
                      const SWvertex *v2 )
 
54
{
 
55
   GLfloat ex = v1->win[0] - v0->win[0];
 
56
   GLfloat ey = v1->win[1] - v0->win[1];
 
57
   GLfloat fx = v2->win[0] - v0->win[0];
 
58
   GLfloat fy = v2->win[1] - v0->win[1];
 
59
   GLfloat c = ex*fy-ey*fx;
 
60
 
 
61
   if (c * SWRAST_CONTEXT(ctx)->_BackfaceCullSign > 0)
 
62
      return 0;
 
63
 
 
64
   return 1;
 
65
}
 
66
 
 
67
 
 
68
 
 
69
/*
 
70
 * Render a smooth or flat-shaded color index triangle.
 
71
 */
 
72
#define NAME ci_triangle
 
73
#define INTERP_Z 1
 
74
#define INTERP_FOG 1
 
75
#define INTERP_INDEX 1
 
76
#define RENDER_SPAN( span )  _swrast_write_index_span(ctx, &span);
 
77
#include "s_tritemp.h"
 
78
 
 
79
 
 
80
 
 
81
/*
 
82
 * Render a flat-shaded RGBA triangle.
 
83
 */
 
84
#define NAME flat_rgba_triangle
 
85
#define INTERP_Z 1
 
86
#define INTERP_FOG 1
 
87
#define SETUP_CODE                              \
 
88
   ASSERT(ctx->Texture._EnabledCoordUnits == 0);\
 
89
   ASSERT(ctx->Light.ShadeModel==GL_FLAT);      \
 
90
   span.interpMask |= SPAN_RGBA;                \
 
91
   span.red = ChanToFixed(v2->color[0]);        \
 
92
   span.green = ChanToFixed(v2->color[1]);      \
 
93
   span.blue = ChanToFixed(v2->color[2]);       \
 
94
   span.alpha = ChanToFixed(v2->color[3]);      \
 
95
   span.redStep = 0;                            \
 
96
   span.greenStep = 0;                          \
 
97
   span.blueStep = 0;                           \
 
98
   span.alphaStep = 0;
 
99
#define RENDER_SPAN( span )  _swrast_write_rgba_span(ctx, &span);
 
100
#include "s_tritemp.h"
 
101
 
 
102
 
 
103
 
 
104
/*
 
105
 * Render a smooth-shaded RGBA triangle.
 
106
 */
 
107
#define NAME smooth_rgba_triangle
 
108
#define INTERP_Z 1
 
109
#define INTERP_FOG 1
 
110
#define INTERP_RGB 1
 
111
#define INTERP_ALPHA 1
 
112
#define SETUP_CODE                              \
 
113
   {                                            \
 
114
      /* texturing must be off */               \
 
115
      ASSERT(ctx->Texture._EnabledCoordUnits == 0);     \
 
116
      ASSERT(ctx->Light.ShadeModel==GL_SMOOTH); \
 
117
   }
 
118
#define RENDER_SPAN( span )  _swrast_write_rgba_span(ctx, &span);
 
119
#include "s_tritemp.h"
 
120
 
 
121
 
 
122
 
 
123
/*
 
124
 * Render an RGB, GL_DECAL, textured triangle.
 
125
 * Interpolate S,T only w/out mipmapping or perspective correction.
 
126
 *
 
127
 * No fog.  No depth testing.
 
128
 */
 
129
#define NAME simple_textured_triangle
 
130
#define INTERP_INT_TEX 1
 
131
#define S_SCALE twidth
 
132
#define T_SCALE theight
 
133
 
 
134
#define SETUP_CODE                                                      \
 
135
   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];\
 
136
   struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D;      \
 
137
   const GLint b = obj->BaseLevel;                                      \
 
138
   const GLfloat twidth = (GLfloat) obj->Image[0][b]->Width;            \
 
139
   const GLfloat theight = (GLfloat) obj->Image[0][b]->Height;          \
 
140
   const GLint twidth_log2 = obj->Image[0][b]->WidthLog2;               \
 
141
   const GLchan *texture = (const GLchan *) obj->Image[0][b]->Data;     \
 
142
   const GLint smask = obj->Image[0][b]->Width - 1;                     \
 
143
   const GLint tmask = obj->Image[0][b]->Height - 1;                    \
 
144
   if (!texture) {                                                      \
 
145
      /* this shouldn't happen */                                       \
 
146
      return;                                                           \
 
147
   }
 
148
 
 
149
#define RENDER_SPAN( span )                                             \
 
150
   GLuint i;                                                            \
 
151
   GLchan rgb[MAX_WIDTH][3];                                            \
 
152
   span.intTex[0] -= FIXED_HALF; /* off-by-one error? */                \
 
153
   span.intTex[1] -= FIXED_HALF;                                        \
 
154
   for (i = 0; i < span.end; i++) {                                     \
 
155
      GLint s = FixedToInt(span.intTex[0]) & smask;                     \
 
156
      GLint t = FixedToInt(span.intTex[1]) & tmask;                     \
 
157
      GLint pos = (t << twidth_log2) + s;                               \
 
158
      pos = pos + pos + pos;  /* multiply by 3 */                       \
 
159
      rgb[i][RCOMP] = texture[pos];                                     \
 
160
      rgb[i][GCOMP] = texture[pos+1];                                   \
 
161
      rgb[i][BCOMP] = texture[pos+2];                                   \
 
162
      span.intTex[0] += span.intTexStep[0];                             \
 
163
      span.intTex[1] += span.intTexStep[1];                             \
 
164
   }                                                                    \
 
165
   rb->PutRowRGB(ctx, rb, span.end, span.x, span.y, rgb, NULL);
 
166
 
 
167
#include "s_tritemp.h"
 
168
 
 
169
 
 
170
 
 
171
/*
 
172
 * Render an RGB, GL_DECAL, textured triangle.
 
173
 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
 
174
 * perspective correction.
 
175
 * Depth buffer bits must be <= sizeof(DEFAULT_SOFTWARE_DEPTH_TYPE)
 
176
 *
 
177
 * No fog.
 
178
 */
 
179
#define NAME simple_z_textured_triangle
 
180
#define INTERP_Z 1
 
181
#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
 
182
#define INTERP_INT_TEX 1
 
183
#define S_SCALE twidth
 
184
#define T_SCALE theight
 
185
 
 
186
#define SETUP_CODE                                                      \
 
187
   struct gl_renderbuffer *rb = ctx->DrawBuffer->_ColorDrawBuffers[0][0];\
 
188
   struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D;      \
 
189
   const GLint b = obj->BaseLevel;                                      \
 
190
   const GLfloat twidth = (GLfloat) obj->Image[0][b]->Width;            \
 
191
   const GLfloat theight = (GLfloat) obj->Image[0][b]->Height;          \
 
192
   const GLint twidth_log2 = obj->Image[0][b]->WidthLog2;               \
 
193
   const GLchan *texture = (const GLchan *) obj->Image[0][b]->Data;     \
 
194
   const GLint smask = obj->Image[0][b]->Width - 1;                     \
 
195
   const GLint tmask = obj->Image[0][b]->Height - 1;                    \
 
196
   if (!texture) {                                                      \
 
197
      /* this shouldn't happen */                                       \
 
198
      return;                                                           \
 
199
   }
 
200
 
 
201
#define RENDER_SPAN( span )                                             \
 
202
   GLuint i;                                                            \
 
203
   GLchan rgb[MAX_WIDTH][3];                                            \
 
204
   span.intTex[0] -= FIXED_HALF; /* off-by-one error? */                \
 
205
   span.intTex[1] -= FIXED_HALF;                                        \
 
206
   for (i = 0; i < span.end; i++) {                                     \
 
207
      const GLuint z = FixedToDepth(span.z);                            \
 
208
      if (z < zRow[i]) {                                                \
 
209
         GLint s = FixedToInt(span.intTex[0]) & smask;                  \
 
210
         GLint t = FixedToInt(span.intTex[1]) & tmask;                  \
 
211
         GLint pos = (t << twidth_log2) + s;                            \
 
212
         pos = pos + pos + pos;  /* multiply by 3 */                    \
 
213
         rgb[i][RCOMP] = texture[pos];                                  \
 
214
         rgb[i][GCOMP] = texture[pos+1];                                \
 
215
         rgb[i][BCOMP] = texture[pos+2];                                \
 
216
         zRow[i] = z;                                                   \
 
217
         span.array->mask[i] = 1;                                       \
 
218
      }                                                                 \
 
219
      else {                                                            \
 
220
         span.array->mask[i] = 0;                                       \
 
221
      }                                                                 \
 
222
      span.intTex[0] += span.intTexStep[0];                             \
 
223
      span.intTex[1] += span.intTexStep[1];                             \
 
224
      span.z += span.zStep;                                             \
 
225
   }                                                                    \
 
226
   rb->PutRowRGB(ctx, rb, span.end, span.x, span.y, rgb, span.array->mask);
 
227
 
 
228
#include "s_tritemp.h"
 
229
 
 
230
 
 
231
 
 
232
#if CHAN_TYPE != GL_FLOAT
 
233
 
 
234
struct affine_info
 
235
{
 
236
   GLenum filter;
 
237
   GLenum format;
 
238
   GLenum envmode;
 
239
   GLint smask, tmask;
 
240
   GLint twidth_log2;
 
241
   const GLchan *texture;
 
242
   GLfixed er, eg, eb, ea;
 
243
   GLint tbytesline, tsize;
 
244
};
 
245
 
 
246
 
 
247
static INLINE GLint
 
248
ilerp(GLint t, GLint a, GLint b)
 
249
{
 
250
   return a + ((t * (b - a)) >> FIXED_SHIFT);
 
251
}
 
252
 
 
253
static INLINE GLint
 
254
ilerp_2d(GLint ia, GLint ib, GLint v00, GLint v10, GLint v01, GLint v11)
 
255
{
 
256
   const GLint temp0 = ilerp(ia, v00, v10);
 
257
   const GLint temp1 = ilerp(ia, v01, v11);
 
258
   return ilerp(ib, temp0, temp1);
 
259
}
 
260
 
 
261
 
 
262
/* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA
 
263
 * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD
 
264
 * texture env modes.
 
265
 */
 
266
static INLINE void
 
267
affine_span(GLcontext *ctx, SWspan *span,
 
268
            struct affine_info *info)
 
269
{
 
270
   GLchan sample[4];  /* the filtered texture sample */
 
271
 
 
272
   /* Instead of defining a function for each mode, a test is done
 
273
    * between the outer and inner loops. This is to reduce code size
 
274
    * and complexity. Observe that an optimizing compiler kills
 
275
    * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
 
276
    */
 
277
 
 
278
#define NEAREST_RGB                     \
 
279
   sample[RCOMP] = tex00[RCOMP];        \
 
280
   sample[GCOMP] = tex00[GCOMP];        \
 
281
   sample[BCOMP] = tex00[BCOMP];        \
 
282
   sample[ACOMP] = CHAN_MAX
 
283
 
 
284
#define LINEAR_RGB                                                      \
 
285
   sample[RCOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0]);\
 
286
   sample[GCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\
 
287
   sample[BCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\
 
288
   sample[ACOMP] = CHAN_MAX;
 
289
 
 
290
#define NEAREST_RGBA  COPY_CHAN4(sample, tex00)
 
291
 
 
292
#define LINEAR_RGBA                                                     \
 
293
   sample[RCOMP] = ilerp_2d(sf, tf, tex00[0], tex01[0], tex10[0], tex11[0]);\
 
294
   sample[GCOMP] = ilerp_2d(sf, tf, tex00[1], tex01[1], tex10[1], tex11[1]);\
 
295
   sample[BCOMP] = ilerp_2d(sf, tf, tex00[2], tex01[2], tex10[2], tex11[2]);\
 
296
   sample[ACOMP] = ilerp_2d(sf, tf, tex00[3], tex01[3], tex10[3], tex11[3])
 
297
 
 
298
#define MODULATE                                                          \
 
299
   dest[RCOMP] = span->red   * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \
 
300
   dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \
 
301
   dest[BCOMP] = span->blue  * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \
 
302
   dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8)
 
303
 
 
304
#define DECAL                                                           \
 
305
   dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red +              \
 
306
               ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT))    \
 
307
               >> (FIXED_SHIFT + 8);                                    \
 
308
   dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green +            \
 
309
               ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT))    \
 
310
               >> (FIXED_SHIFT + 8);                                    \
 
311
   dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue +             \
 
312
               ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT))    \
 
313
               >> (FIXED_SHIFT + 8);                                    \
 
314
   dest[ACOMP] = FixedToInt(span->alpha)
 
315
 
 
316
#define BLEND                                                           \
 
317
   dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red                \
 
318
               + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8);  \
 
319
   dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green              \
 
320
               + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8);  \
 
321
   dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue               \
 
322
               + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8);  \
 
323
   dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8)
 
324
 
 
325
#define REPLACE  COPY_CHAN4(dest, sample)
 
326
 
 
327
#define ADD                                                             \
 
328
   {                                                                    \
 
329
      GLint rSum = FixedToInt(span->red)   + (GLint) sample[RCOMP];     \
 
330
      GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP];     \
 
331
      GLint bSum = FixedToInt(span->blue)  + (GLint) sample[BCOMP];     \
 
332
      dest[RCOMP] = MIN2(rSum, CHAN_MAX);                               \
 
333
      dest[GCOMP] = MIN2(gSum, CHAN_MAX);                               \
 
334
      dest[BCOMP] = MIN2(bSum, CHAN_MAX);                               \
 
335
      dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \
 
336
  }
 
337
 
 
338
/* shortcuts */
 
339
 
 
340
#define NEAREST_RGB_REPLACE             \
 
341
   NEAREST_RGB;                         \
 
342
   dest[0] = sample[0];                 \
 
343
   dest[1] = sample[1];                 \
 
344
   dest[2] = sample[2];                 \
 
345
   dest[3] = FixedToInt(span->alpha);
 
346
 
 
347
#define NEAREST_RGBA_REPLACE  COPY_CHAN4(dest, tex00)
 
348
 
 
349
#define SPAN_NEAREST(DO_TEX, COMPS)                                     \
 
350
        for (i = 0; i < span->end; i++) {                               \
 
351
           /* Isn't it necessary to use FixedFloor below?? */           \
 
352
           GLint s = FixedToInt(span->intTex[0]) & info->smask;         \
 
353
           GLint t = FixedToInt(span->intTex[1]) & info->tmask;         \
 
354
           GLint pos = (t << info->twidth_log2) + s;                    \
 
355
           const GLchan *tex00 = info->texture + COMPS * pos;           \
 
356
           DO_TEX;                                                      \
 
357
           span->red += span->redStep;                                  \
 
358
           span->green += span->greenStep;                              \
 
359
           span->blue += span->blueStep;                                \
 
360
           span->alpha += span->alphaStep;                              \
 
361
           span->intTex[0] += span->intTexStep[0];                      \
 
362
           span->intTex[1] += span->intTexStep[1];                      \
 
363
           dest += 4;                                                   \
 
364
        }
 
365
 
 
366
#define SPAN_LINEAR(DO_TEX, COMPS)                                      \
 
367
        for (i = 0; i < span->end; i++) {                               \
 
368
           /* Isn't it necessary to use FixedFloor below?? */           \
 
369
           const GLint s = FixedToInt(span->intTex[0]) & info->smask;   \
 
370
           const GLint t = FixedToInt(span->intTex[1]) & info->tmask;   \
 
371
           const GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK;        \
 
372
           const GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK;        \
 
373
           const GLint pos = (t << info->twidth_log2) + s;              \
 
374
           const GLchan *tex00 = info->texture + COMPS * pos;           \
 
375
           const GLchan *tex10 = tex00 + info->tbytesline;              \
 
376
           const GLchan *tex01 = tex00 + COMPS;                         \
 
377
           const GLchan *tex11 = tex10 + COMPS;                         \
 
378
           if (t == info->tmask) {                                      \
 
379
              tex10 -= info->tsize;                                     \
 
380
              tex11 -= info->tsize;                                     \
 
381
           }                                                            \
 
382
           if (s == info->smask) {                                      \
 
383
              tex01 -= info->tbytesline;                                \
 
384
              tex11 -= info->tbytesline;                                \
 
385
           }                                                            \
 
386
           DO_TEX;                                                      \
 
387
           span->red += span->redStep;                                  \
 
388
           span->green += span->greenStep;                              \
 
389
           span->blue += span->blueStep;                                \
 
390
           span->alpha += span->alphaStep;                              \
 
391
           span->intTex[0] += span->intTexStep[0];                      \
 
392
           span->intTex[1] += span->intTexStep[1];                      \
 
393
           dest += 4;                                                   \
 
394
        }
 
395
 
 
396
 
 
397
   GLuint i;
 
398
   GLchan *dest = span->array->rgba[0];
 
399
 
 
400
   span->intTex[0] -= FIXED_HALF;
 
401
   span->intTex[1] -= FIXED_HALF;
 
402
   switch (info->filter) {
 
403
   case GL_NEAREST:
 
404
      switch (info->format) {
 
405
      case GL_RGB:
 
406
         switch (info->envmode) {
 
407
         case GL_MODULATE:
 
408
            SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
 
409
            break;
 
410
         case GL_DECAL:
 
411
         case GL_REPLACE:
 
412
            SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
 
413
            break;
 
414
         case GL_BLEND:
 
415
            SPAN_NEAREST(NEAREST_RGB;BLEND,3);
 
416
            break;
 
417
         case GL_ADD:
 
418
            SPAN_NEAREST(NEAREST_RGB;ADD,3);
 
419
            break;
 
420
         default:
 
421
            _mesa_problem(ctx, "bad tex env mode in SPAN_LINEAR");
 
422
            return;
 
423
         }
 
424
         break;
 
425
      case GL_RGBA:
 
426
         switch(info->envmode) {
 
427
         case GL_MODULATE:
 
428
            SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
 
429
            break;
 
430
         case GL_DECAL:
 
431
            SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
 
432
            break;
 
433
         case GL_BLEND:
 
434
            SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
 
435
            break;
 
436
         case GL_ADD:
 
437
            SPAN_NEAREST(NEAREST_RGBA;ADD,4);
 
438
            break;
 
439
         case GL_REPLACE:
 
440
            SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
 
441
            break;
 
442
         default:
 
443
            _mesa_problem(ctx, "bad tex env mode (2) in SPAN_LINEAR");
 
444
            return;
 
445
         }
 
446
         break;
 
447
      }
 
448
      break;
 
449
 
 
450
   case GL_LINEAR:
 
451
      span->intTex[0] -= FIXED_HALF;
 
452
      span->intTex[1] -= FIXED_HALF;
 
453
      switch (info->format) {
 
454
      case GL_RGB:
 
455
         switch (info->envmode) {
 
456
         case GL_MODULATE:
 
457
            SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
 
458
            break;
 
459
         case GL_DECAL:
 
460
         case GL_REPLACE:
 
461
            SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
 
462
            break;
 
463
         case GL_BLEND:
 
464
            SPAN_LINEAR(LINEAR_RGB;BLEND,3);
 
465
            break;
 
466
         case GL_ADD:
 
467
            SPAN_LINEAR(LINEAR_RGB;ADD,3);
 
468
            break;
 
469
         default:
 
470
            _mesa_problem(ctx, "bad tex env mode (3) in SPAN_LINEAR");
 
471
            return;
 
472
         }
 
473
         break;
 
474
      case GL_RGBA:
 
475
         switch (info->envmode) {
 
476
         case GL_MODULATE:
 
477
            SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
 
478
            break;
 
479
         case GL_DECAL:
 
480
            SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
 
481
            break;
 
482
         case GL_BLEND:
 
483
            SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
 
484
            break;
 
485
         case GL_ADD:
 
486
            SPAN_LINEAR(LINEAR_RGBA;ADD,4);
 
487
            break;
 
488
         case GL_REPLACE:
 
489
            SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
 
490
            break;
 
491
         default:
 
492
            _mesa_problem(ctx, "bad tex env mode (4) in SPAN_LINEAR");
 
493
            return;
 
494
         }
 
495
         break;
 
496
      }
 
497
      break;
 
498
   }
 
499
   span->interpMask &= ~SPAN_RGBA;
 
500
   ASSERT(span->arrayMask & SPAN_RGBA);
 
501
   _swrast_write_rgba_span(ctx, span);
 
502
 
 
503
#undef SPAN_NEAREST
 
504
#undef SPAN_LINEAR
 
505
}
 
506
 
 
507
 
 
508
 
 
509
/*
 
510
 * Render an RGB/RGBA textured triangle without perspective correction.
 
511
 */
 
512
#define NAME affine_textured_triangle
 
513
#define INTERP_Z 1
 
514
#define INTERP_FOG 1
 
515
#define INTERP_RGB 1
 
516
#define INTERP_ALPHA 1
 
517
#define INTERP_INT_TEX 1
 
518
#define S_SCALE twidth
 
519
#define T_SCALE theight
 
520
 
 
521
#define SETUP_CODE                                                      \
 
522
   struct affine_info info;                                             \
 
523
   struct gl_texture_unit *unit = ctx->Texture.Unit+0;                  \
 
524
   struct gl_texture_object *obj = unit->Current2D;                     \
 
525
   const GLint b = obj->BaseLevel;                                      \
 
526
   const GLfloat twidth = (GLfloat) obj->Image[0][b]->Width;            \
 
527
   const GLfloat theight = (GLfloat) obj->Image[0][b]->Height;          \
 
528
   info.texture = (const GLchan *) obj->Image[0][b]->Data;              \
 
529
   info.twidth_log2 = obj->Image[0][b]->WidthLog2;                      \
 
530
   info.smask = obj->Image[0][b]->Width - 1;                            \
 
531
   info.tmask = obj->Image[0][b]->Height - 1;                           \
 
532
   info.format = obj->Image[0][b]->_BaseFormat;                         \
 
533
   info.filter = obj->MinFilter;                                        \
 
534
   info.envmode = unit->EnvMode;                                        \
 
535
   span.arrayMask |= SPAN_RGBA;                                         \
 
536
                                                                        \
 
537
   if (info.envmode == GL_BLEND) {                                      \
 
538
      /* potential off-by-one error here? (1.0f -> 2048 -> 0) */        \
 
539
      info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF);        \
 
540
      info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF);        \
 
541
      info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF);        \
 
542
      info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF);        \
 
543
   }                                                                    \
 
544
   if (!info.texture) {                                                 \
 
545
      /* this shouldn't happen */                                       \
 
546
      return;                                                           \
 
547
   }                                                                    \
 
548
                                                                        \
 
549
   switch (info.format) {                                               \
 
550
   case GL_ALPHA:                                                       \
 
551
   case GL_LUMINANCE:                                                   \
 
552
   case GL_INTENSITY:                                                   \
 
553
      info.tbytesline = obj->Image[0][b]->Width;                        \
 
554
      break;                                                            \
 
555
   case GL_LUMINANCE_ALPHA:                                             \
 
556
      info.tbytesline = obj->Image[0][b]->Width * 2;                    \
 
557
      break;                                                            \
 
558
   case GL_RGB:                                                         \
 
559
      info.tbytesline = obj->Image[0][b]->Width * 3;                    \
 
560
      break;                                                            \
 
561
   case GL_RGBA:                                                        \
 
562
      info.tbytesline = obj->Image[0][b]->Width * 4;                    \
 
563
      break;                                                            \
 
564
   default:                                                             \
 
565
      _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
 
566
      return;                                                           \
 
567
   }                                                                    \
 
568
   info.tsize = obj->Image[0][b]->Height * info.tbytesline;
 
569
 
 
570
#define RENDER_SPAN( span )   affine_span(ctx, &span, &info);
 
571
 
 
572
#include "s_tritemp.h"
 
573
 
 
574
 
 
575
 
 
576
struct persp_info
 
577
{
 
578
   GLenum filter;
 
579
   GLenum format;
 
580
   GLenum envmode;
 
581
   GLint smask, tmask;
 
582
   GLint twidth_log2;
 
583
   const GLchan *texture;
 
584
   GLfixed er, eg, eb, ea;   /* texture env color */
 
585
   GLint tbytesline, tsize;
 
586
};
 
587
 
 
588
 
 
589
static INLINE void
 
590
fast_persp_span(GLcontext *ctx, SWspan *span,
 
591
                struct persp_info *info)
 
592
{
 
593
   GLchan sample[4];  /* the filtered texture sample */
 
594
 
 
595
  /* Instead of defining a function for each mode, a test is done
 
596
   * between the outer and inner loops. This is to reduce code size
 
597
   * and complexity. Observe that an optimizing compiler kills
 
598
   * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
 
599
   */
 
600
#define SPAN_NEAREST(DO_TEX,COMP)                                       \
 
601
        for (i = 0; i < span->end; i++) {                               \
 
602
           GLdouble invQ = tex_coord[2] ?                               \
 
603
                                 (1.0 / tex_coord[2]) : 1.0;            \
 
604
           GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ);             \
 
605
           GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ);             \
 
606
           GLint s = IFLOOR(s_tmp) & info->smask;                       \
 
607
           GLint t = IFLOOR(t_tmp) & info->tmask;                       \
 
608
           GLint pos = (t << info->twidth_log2) + s;                    \
 
609
           const GLchan *tex00 = info->texture + COMP * pos;            \
 
610
           DO_TEX;                                                      \
 
611
           span->red += span->redStep;                                  \
 
612
           span->green += span->greenStep;                              \
 
613
           span->blue += span->blueStep;                                \
 
614
           span->alpha += span->alphaStep;                              \
 
615
           tex_coord[0] += tex_step[0];                                 \
 
616
           tex_coord[1] += tex_step[1];                                 \
 
617
           tex_coord[2] += tex_step[2];                                 \
 
618
           dest += 4;                                                   \
 
619
        }
 
620
 
 
621
#define SPAN_LINEAR(DO_TEX,COMP)                                        \
 
622
        for (i = 0; i < span->end; i++) {                               \
 
623
           GLdouble invQ = tex_coord[2] ?                               \
 
624
                                 (1.0 / tex_coord[2]) : 1.0;            \
 
625
           const GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ);       \
 
626
           const GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ);       \
 
627
           const GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF;      \
 
628
           const GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF;      \
 
629
           const GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \
 
630
           const GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \
 
631
           const GLfixed sf = s_fix & FIXED_FRAC_MASK;                  \
 
632
           const GLfixed tf = t_fix & FIXED_FRAC_MASK;                  \
 
633
           const GLint pos = (t << info->twidth_log2) + s;              \
 
634
           const GLchan *tex00 = info->texture + COMP * pos;            \
 
635
           const GLchan *tex10 = tex00 + info->tbytesline;              \
 
636
           const GLchan *tex01 = tex00 + COMP;                          \
 
637
           const GLchan *tex11 = tex10 + COMP;                          \
 
638
           if (t == info->tmask) {                                      \
 
639
              tex10 -= info->tsize;                                     \
 
640
              tex11 -= info->tsize;                                     \
 
641
           }                                                            \
 
642
           if (s == info->smask) {                                      \
 
643
              tex01 -= info->tbytesline;                                \
 
644
              tex11 -= info->tbytesline;                                \
 
645
           }                                                            \
 
646
           DO_TEX;                                                      \
 
647
           span->red   += span->redStep;                                \
 
648
           span->green += span->greenStep;                              \
 
649
           span->blue  += span->blueStep;                               \
 
650
           span->alpha += span->alphaStep;                              \
 
651
           tex_coord[0] += tex_step[0];                                 \
 
652
           tex_coord[1] += tex_step[1];                                 \
 
653
           tex_coord[2] += tex_step[2];                                 \
 
654
           dest += 4;                                                   \
 
655
        }
 
656
 
 
657
   GLuint i;
 
658
   GLfloat tex_coord[3], tex_step[3];
 
659
   GLchan *dest = span->array->rgba[0];
 
660
 
 
661
   const GLuint savedTexEnable = ctx->Texture._EnabledUnits;
 
662
   ctx->Texture._EnabledUnits = 0;
 
663
 
 
664
   tex_coord[0] = span->attrStart[FRAG_ATTRIB_TEX0][0]  * (info->smask + 1);
 
665
   tex_step[0] = span->attrStepX[FRAG_ATTRIB_TEX0][0] * (info->smask + 1);
 
666
   tex_coord[1] = span->attrStart[FRAG_ATTRIB_TEX0][1] * (info->tmask + 1);
 
667
   tex_step[1] = span->attrStepX[FRAG_ATTRIB_TEX0][1] * (info->tmask + 1);
 
668
   /* span->attrStart[FRAG_ATTRIB_TEX0][2] only if 3D-texturing, here only 2D */
 
669
   tex_coord[2] = span->attrStart[FRAG_ATTRIB_TEX0][3];
 
670
   tex_step[2] = span->attrStepX[FRAG_ATTRIB_TEX0][3];
 
671
 
 
672
   switch (info->filter) {
 
673
   case GL_NEAREST:
 
674
      switch (info->format) {
 
675
      case GL_RGB:
 
676
         switch (info->envmode) {
 
677
         case GL_MODULATE:
 
678
            SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
 
679
            break;
 
680
         case GL_DECAL:
 
681
         case GL_REPLACE:
 
682
            SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
 
683
            break;
 
684
         case GL_BLEND:
 
685
            SPAN_NEAREST(NEAREST_RGB;BLEND,3);
 
686
            break;
 
687
         case GL_ADD:
 
688
            SPAN_NEAREST(NEAREST_RGB;ADD,3);
 
689
            break;
 
690
         default:
 
691
            _mesa_problem(ctx, "bad tex env mode (5) in SPAN_LINEAR");
 
692
            return;
 
693
         }
 
694
         break;
 
695
      case GL_RGBA:
 
696
         switch(info->envmode) {
 
697
         case GL_MODULATE:
 
698
            SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
 
699
            break;
 
700
         case GL_DECAL:
 
701
            SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
 
702
            break;
 
703
         case GL_BLEND:
 
704
            SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
 
705
            break;
 
706
         case GL_ADD:
 
707
            SPAN_NEAREST(NEAREST_RGBA;ADD,4);
 
708
            break;
 
709
         case GL_REPLACE:
 
710
            SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
 
711
            break;
 
712
         default:
 
713
            _mesa_problem(ctx, "bad tex env mode (6) in SPAN_LINEAR");
 
714
            return;
 
715
         }
 
716
         break;
 
717
      }
 
718
      break;
 
719
 
 
720
   case GL_LINEAR:
 
721
      switch (info->format) {
 
722
      case GL_RGB:
 
723
         switch (info->envmode) {
 
724
         case GL_MODULATE:
 
725
            SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
 
726
            break;
 
727
         case GL_DECAL:
 
728
         case GL_REPLACE:
 
729
            SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
 
730
            break;
 
731
         case GL_BLEND:
 
732
            SPAN_LINEAR(LINEAR_RGB;BLEND,3);
 
733
            break;
 
734
         case GL_ADD:
 
735
            SPAN_LINEAR(LINEAR_RGB;ADD,3);
 
736
            break;
 
737
         default:
 
738
            _mesa_problem(ctx, "bad tex env mode (7) in SPAN_LINEAR");
 
739
            return;
 
740
         }
 
741
         break;
 
742
      case GL_RGBA:
 
743
         switch (info->envmode) {
 
744
         case GL_MODULATE:
 
745
            SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
 
746
            break;
 
747
         case GL_DECAL:
 
748
            SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
 
749
            break;
 
750
         case GL_BLEND:
 
751
            SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
 
752
            break;
 
753
         case GL_ADD:
 
754
            SPAN_LINEAR(LINEAR_RGBA;ADD,4);
 
755
            break;
 
756
         case GL_REPLACE:
 
757
            SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
 
758
            break;
 
759
         default:
 
760
            _mesa_problem(ctx, "bad tex env mode (8) in SPAN_LINEAR");
 
761
            return;
 
762
         }
 
763
         break;
 
764
      }
 
765
      break;
 
766
   }
 
767
   
 
768
   ASSERT(span->arrayMask & SPAN_RGBA);
 
769
   _swrast_write_rgba_span(ctx, span);
 
770
 
 
771
#undef SPAN_NEAREST
 
772
#undef SPAN_LINEAR
 
773
 
 
774
   /* restore state */
 
775
   ctx->Texture._EnabledUnits = savedTexEnable;
 
776
}
 
777
 
 
778
 
 
779
/*
 
780
 * Render an perspective corrected RGB/RGBA textured triangle.
 
781
 * The Q (aka V in Mesa) coordinate must be zero such that the divide
 
782
 * by interpolated Q/W comes out right.
 
783
 *
 
784
 */
 
785
#define NAME persp_textured_triangle
 
786
#define INTERP_Z 1
 
787
#define INTERP_W 1
 
788
#define INTERP_FOG 1
 
789
#define INTERP_RGB 1
 
790
#define INTERP_ALPHA 1
 
791
#define INTERP_ATTRIBS 1
 
792
 
 
793
#define SETUP_CODE                                                      \
 
794
   struct persp_info info;                                              \
 
795
   const struct gl_texture_unit *unit = ctx->Texture.Unit+0;            \
 
796
   const struct gl_texture_object *obj = unit->Current2D;               \
 
797
   const GLint b = obj->BaseLevel;                                      \
 
798
   info.texture = (const GLchan *) obj->Image[0][b]->Data;              \
 
799
   info.twidth_log2 = obj->Image[0][b]->WidthLog2;                      \
 
800
   info.smask = obj->Image[0][b]->Width - 1;                            \
 
801
   info.tmask = obj->Image[0][b]->Height - 1;                           \
 
802
   info.format = obj->Image[0][b]->_BaseFormat;                         \
 
803
   info.filter = obj->MinFilter;                                        \
 
804
   info.envmode = unit->EnvMode;                                        \
 
805
                                                                        \
 
806
   if (info.envmode == GL_BLEND) {                                      \
 
807
      /* potential off-by-one error here? (1.0f -> 2048 -> 0) */        \
 
808
      info.er = FloatToFixed(unit->EnvColor[RCOMP] * CHAN_MAXF);        \
 
809
      info.eg = FloatToFixed(unit->EnvColor[GCOMP] * CHAN_MAXF);        \
 
810
      info.eb = FloatToFixed(unit->EnvColor[BCOMP] * CHAN_MAXF);        \
 
811
      info.ea = FloatToFixed(unit->EnvColor[ACOMP] * CHAN_MAXF);        \
 
812
   }                                                                    \
 
813
   if (!info.texture) {                                                 \
 
814
      /* this shouldn't happen */                                       \
 
815
      return;                                                           \
 
816
   }                                                                    \
 
817
                                                                        \
 
818
   switch (info.format) {                                               \
 
819
   case GL_ALPHA:                                                       \
 
820
   case GL_LUMINANCE:                                                   \
 
821
   case GL_INTENSITY:                                                   \
 
822
      info.tbytesline = obj->Image[0][b]->Width;                        \
 
823
      break;                                                            \
 
824
   case GL_LUMINANCE_ALPHA:                                             \
 
825
      info.tbytesline = obj->Image[0][b]->Width * 2;                    \
 
826
      break;                                                            \
 
827
   case GL_RGB:                                                         \
 
828
      info.tbytesline = obj->Image[0][b]->Width * 3;                    \
 
829
      break;                                                            \
 
830
   case GL_RGBA:                                                        \
 
831
      info.tbytesline = obj->Image[0][b]->Width * 4;                    \
 
832
      break;                                                            \
 
833
   default:                                                             \
 
834
      _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\
 
835
      return;                                                           \
 
836
   }                                                                    \
 
837
   info.tsize = obj->Image[0][b]->Height * info.tbytesline;
 
838
 
 
839
#define RENDER_SPAN( span )                     \
 
840
   span.interpMask &= ~SPAN_RGBA;               \
 
841
   span.arrayMask |= SPAN_RGBA;                 \
 
842
   fast_persp_span(ctx, &span, &info);
 
843
 
 
844
#include "s_tritemp.h"
 
845
 
 
846
 
 
847
#endif /* CHAN_BITS != GL_FLOAT */
 
848
 
 
849
                
 
850
 
 
851
 
 
852
/*
 
853
 * Render an RGBA triangle with arbitrary attributes.
 
854
 */
 
855
#define NAME general_triangle
 
856
#define INTERP_Z 1
 
857
#define INTERP_W 1
 
858
#define INTERP_FOG 1
 
859
#define INTERP_RGB 1
 
860
#define INTERP_SPEC 1
 
861
#define INTERP_ALPHA 1
 
862
#define INTERP_ATTRIBS 1
 
863
#define RENDER_SPAN( span )   _swrast_write_rgba_span(ctx, &span);
 
864
#include "s_tritemp.h"
 
865
 
 
866
 
 
867
 
 
868
 
 
869
/*
 
870
 * Special tri function for occlusion testing
 
871
 */
 
872
#define NAME occlusion_zless_triangle
 
873
#define INTERP_Z 1
 
874
#define SETUP_CODE                                                      \
 
875
   struct gl_renderbuffer *rb = ctx->DrawBuffer->_DepthBuffer;          \
 
876
   struct gl_query_object *q = ctx->Query.CurrentOcclusionObject;       \
 
877
   ASSERT(ctx->Depth.Test);                                             \
 
878
   ASSERT(!ctx->Depth.Mask);                                            \
 
879
   ASSERT(ctx->Depth.Func == GL_LESS);                                  \
 
880
   if (!q) {                                                            \
 
881
      return;                                                           \
 
882
   }
 
883
#define RENDER_SPAN( span )                                             \
 
884
   if (rb->DepthBits <= 16) {                                           \
 
885
      GLuint i;                                                         \
 
886
      const GLushort *zRow = (const GLushort *)                         \
 
887
         rb->GetPointer(ctx, rb, span.x, span.y);                       \
 
888
      for (i = 0; i < span.end; i++) {                                  \
 
889
         GLuint z = FixedToDepth(span.z);                               \
 
890
         if (z < zRow[i]) {                                             \
 
891
            q->Result++;                                                \
 
892
         }                                                              \
 
893
         span.z += span.zStep;                                          \
 
894
      }                                                                 \
 
895
   }                                                                    \
 
896
   else {                                                               \
 
897
      GLuint i;                                                         \
 
898
      const GLuint *zRow = (const GLuint *)                             \
 
899
         rb->GetPointer(ctx, rb, span.x, span.y);                       \
 
900
      for (i = 0; i < span.end; i++) {                                  \
 
901
         if ((GLuint)span.z < zRow[i]) {                                \
 
902
            q->Result++;                                                \
 
903
         }                                                              \
 
904
         span.z += span.zStep;                                          \
 
905
      }                                                                 \
 
906
   }
 
907
#include "s_tritemp.h"
 
908
 
 
909
 
 
910
 
 
911
static void
 
912
nodraw_triangle( GLcontext *ctx,
 
913
                 const SWvertex *v0,
 
914
                 const SWvertex *v1,
 
915
                 const SWvertex *v2 )
 
916
{
 
917
   (void) (ctx && v0 && v1 && v2);
 
918
}
 
919
 
 
920
 
 
921
/*
 
922
 * This is used when separate specular color is enabled, but not
 
923
 * texturing.  We add the specular color to the primary color,
 
924
 * draw the triangle, then restore the original primary color.
 
925
 * Inefficient, but seldom needed.
 
926
 */
 
927
void _swrast_add_spec_terms_triangle( GLcontext *ctx,
 
928
                                      const SWvertex *v0,
 
929
                                      const SWvertex *v1,
 
930
                                      const SWvertex *v2 )
 
931
{
 
932
   SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */
 
933
   SWvertex *ncv1 = (SWvertex *)v1;
 
934
   SWvertex *ncv2 = (SWvertex *)v2;
 
935
#if CHAN_TYPE == GL_FLOAT
 
936
   GLfloat rSum, gSum, bSum;
 
937
#else
 
938
   GLint rSum, gSum, bSum;
 
939
#endif
 
940
   GLchan c[3][4];
 
941
   /* save original colors */
 
942
   COPY_CHAN4( c[0], ncv0->color );
 
943
   COPY_CHAN4( c[1], ncv1->color );
 
944
   COPY_CHAN4( c[2], ncv2->color );
 
945
   /* sum v0 */
 
946
   rSum = ncv0->color[0] + ncv0->specular[0];
 
947
   gSum = ncv0->color[1] + ncv0->specular[1];
 
948
   bSum = ncv0->color[2] + ncv0->specular[2];
 
949
   ncv0->color[0] = MIN2(rSum, CHAN_MAX);
 
950
   ncv0->color[1] = MIN2(gSum, CHAN_MAX);
 
951
   ncv0->color[2] = MIN2(bSum, CHAN_MAX);
 
952
   /* sum v1 */
 
953
   rSum = ncv1->color[0] + ncv1->specular[0];
 
954
   gSum = ncv1->color[1] + ncv1->specular[1];
 
955
   bSum = ncv1->color[2] + ncv1->specular[2];
 
956
   ncv1->color[0] = MIN2(rSum, CHAN_MAX);
 
957
   ncv1->color[1] = MIN2(gSum, CHAN_MAX);
 
958
   ncv1->color[2] = MIN2(bSum, CHAN_MAX);
 
959
   /* sum v2 */
 
960
   rSum = ncv2->color[0] + ncv2->specular[0];
 
961
   gSum = ncv2->color[1] + ncv2->specular[1];
 
962
   bSum = ncv2->color[2] + ncv2->specular[2];
 
963
   ncv2->color[0] = MIN2(rSum, CHAN_MAX);
 
964
   ncv2->color[1] = MIN2(gSum, CHAN_MAX);
 
965
   ncv2->color[2] = MIN2(bSum, CHAN_MAX);
 
966
   /* draw */
 
967
   SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 );
 
968
   /* restore original colors */
 
969
   COPY_CHAN4( ncv0->color, c[0] );
 
970
   COPY_CHAN4( ncv1->color, c[1] );
 
971
   COPY_CHAN4( ncv2->color, c[2] );
 
972
}
 
973
 
 
974
 
 
975
 
 
976
#ifdef DEBUG
 
977
 
 
978
/* record the current triangle function name */
 
979
const char *_mesa_triFuncName = NULL;
 
980
 
 
981
#define USE(triFunc)                            \
 
982
do {                                            \
 
983
    _mesa_triFuncName = #triFunc;               \
 
984
    /*printf("%s\n", _mesa_triFuncName);*/      \
 
985
    swrast->Triangle = triFunc;                 \
 
986
} while (0)
 
987
 
 
988
#else
 
989
 
 
990
#define USE(triFunc)  swrast->Triangle = triFunc;
 
991
 
 
992
#endif
 
993
 
 
994
 
 
995
 
 
996
 
 
997
/*
 
998
 * Determine which triangle rendering function to use given the current
 
999
 * rendering context.
 
1000
 *
 
1001
 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
 
1002
 * remove tests to this code.
 
1003
 */
 
1004
void
 
1005
_swrast_choose_triangle( GLcontext *ctx )
 
1006
{
 
1007
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
1008
   const GLboolean rgbmode = ctx->Visual.rgbMode;
 
1009
 
 
1010
   if (ctx->Polygon.CullFlag &&
 
1011
       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
 
1012
      USE(nodraw_triangle);
 
1013
      return;
 
1014
   }
 
1015
 
 
1016
   if (ctx->RenderMode==GL_RENDER) {
 
1017
 
 
1018
      if (ctx->Polygon.SmoothFlag) {
 
1019
         _swrast_set_aa_triangle_function(ctx);
 
1020
         ASSERT(swrast->Triangle);
 
1021
         return;
 
1022
      }
 
1023
 
 
1024
      /* special case for occlusion testing */
 
1025
      if (ctx->Query.CurrentOcclusionObject &&
 
1026
          ctx->Depth.Test &&
 
1027
          ctx->Depth.Mask == GL_FALSE &&
 
1028
          ctx->Depth.Func == GL_LESS &&
 
1029
          !ctx->Stencil.Enabled) {
 
1030
         if ((rgbmode &&
 
1031
              ctx->Color.ColorMask[0] == 0 &&
 
1032
              ctx->Color.ColorMask[1] == 0 &&
 
1033
              ctx->Color.ColorMask[2] == 0 &&
 
1034
              ctx->Color.ColorMask[3] == 0)
 
1035
             ||
 
1036
             (!rgbmode && ctx->Color.IndexMask == 0)) {
 
1037
            USE(occlusion_zless_triangle);
 
1038
            return;
 
1039
         }
 
1040
      }
 
1041
 
 
1042
      if (!rgbmode) {
 
1043
         USE(ci_triangle);
 
1044
         return;
 
1045
      }
 
1046
 
 
1047
      if (ctx->Texture._EnabledCoordUnits ||
 
1048
          ctx->FragmentProgram._Current ||
 
1049
          ctx->ATIFragmentShader._Enabled) {
 
1050
         /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
 
1051
         const struct gl_texture_object *texObj2D;
 
1052
         const struct gl_texture_image *texImg;
 
1053
         GLenum minFilter, magFilter, envMode;
 
1054
         GLint format;
 
1055
         texObj2D = ctx->Texture.Unit[0].Current2D;
 
1056
         texImg = texObj2D ? texObj2D->Image[0][texObj2D->BaseLevel] : NULL;
 
1057
         format = texImg ? texImg->TexFormat->MesaFormat : -1;
 
1058
         minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0;
 
1059
         magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0;
 
1060
         envMode = ctx->Texture.Unit[0].EnvMode;
 
1061
 
 
1062
         /* First see if we can use an optimized 2-D texture function */
 
1063
         if (ctx->Texture._EnabledCoordUnits == 0x1
 
1064
             && !ctx->FragmentProgram._Current
 
1065
             && !ctx->ATIFragmentShader._Enabled
 
1066
             && ctx->Texture.Unit[0]._ReallyEnabled == TEXTURE_2D_BIT
 
1067
             && texObj2D->WrapS == GL_REPEAT
 
1068
             && texObj2D->WrapT == GL_REPEAT
 
1069
             && texImg->_IsPowerOfTwo
 
1070
             && texImg->Border == 0
 
1071
             && texImg->Width == texImg->RowStride
 
1072
             && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA)
 
1073
             && minFilter == magFilter
 
1074
             && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR
 
1075
             && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) {
 
1076
            if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
 
1077
               if (minFilter == GL_NEAREST
 
1078
                   && format == MESA_FORMAT_RGB
 
1079
                   && (envMode == GL_REPLACE || envMode == GL_DECAL)
 
1080
                   && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)
 
1081
                        && ctx->Depth.Func == GL_LESS
 
1082
                        && ctx->Depth.Mask == GL_TRUE)
 
1083
                       || swrast->_RasterMask == TEXTURE_BIT)
 
1084
                   && ctx->Polygon.StippleFlag == GL_FALSE
 
1085
                   && ctx->DrawBuffer->Visual.depthBits <= 16) {
 
1086
                  if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) {
 
1087
                     USE(simple_z_textured_triangle);
 
1088
                  }
 
1089
                  else {
 
1090
                     USE(simple_textured_triangle);
 
1091
                  }
 
1092
               }
 
1093
               else {
 
1094
#if (CHAN_BITS == 16 || CHAN_BITS == 32)
 
1095
                  USE(general_triangle);
 
1096
#else
 
1097
                  USE(affine_textured_triangle);
 
1098
#endif
 
1099
               }
 
1100
            }
 
1101
            else {
 
1102
#if (CHAN_BITS == 16 || CHAN_BITS == 32)
 
1103
               USE(general_triangle);
 
1104
#else
 
1105
               USE(persp_textured_triangle);
 
1106
#endif
 
1107
            }
 
1108
         }
 
1109
         else {
 
1110
            /* general case textured triangles */
 
1111
            USE(general_triangle);
 
1112
         }
 
1113
      }
 
1114
      else {
 
1115
         ASSERT(!ctx->Texture._EnabledCoordUnits);
 
1116
         if (ctx->Light.ShadeModel==GL_SMOOTH) {
 
1117
            /* smooth shaded, no texturing, stippled or some raster ops */
 
1118
            USE(smooth_rgba_triangle);
 
1119
         }
 
1120
         else {
 
1121
            /* flat shaded, no texturing, stippled or some raster ops */
 
1122
            USE(flat_rgba_triangle);
 
1123
         }
 
1124
      }
 
1125
   }
 
1126
   else if (ctx->RenderMode==GL_FEEDBACK) {
 
1127
      USE(_swrast_feedback_triangle);
 
1128
   }
 
1129
   else {
 
1130
      /* GL_SELECT mode */
 
1131
      USE(_swrast_select_triangle);
 
1132
   }
 
1133
}