Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

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