1 /* $Id: s_triangle.c,v 1.40 2001/11/19 01:18:28 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
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.
40 #include "texformat.h"
44 #include "s_aatriangle.h"
45 #include "s_context.h"
47 #include "s_feedback.h"
49 #include "s_triangle.h"
50 #include "s_trispan.h"
54 GLboolean
_mesa_cull_triangle( GLcontext
*ctx
,
59 GLfloat ex
= v1
->win
[0] - v0
->win
[0];
60 GLfloat ey
= v1
->win
[1] - v0
->win
[1];
61 GLfloat fx
= v2
->win
[0] - v0
->win
[0];
62 GLfloat fy
= v2
->win
[1] - v0
->win
[1];
63 GLfloat c
= ex
*fy
-ey
*fx
;
65 if (c
* SWRAST_CONTEXT(ctx
)->_backface_sign
> 0)
74 * Render a flat-shaded color index triangle.
76 static void flat_ci_triangle( GLcontext
*ctx
,
84 #define RENDER_SPAN( span ) \
85 GLdepth zSpan[MAX_WIDTH]; \
86 GLfloat fogSpan[MAX_WIDTH]; \
88 for (i = 0; i < span.count; i++) { \
89 zSpan[i] = FixedToDepth(span.z); \
90 span.z += span.zStep; \
91 fogSpan[i] = span.fog; \
92 span.fog += span.fogStep; \
94 _mesa_write_monoindex_span(ctx, span.count, span.x, span.y, \
95 zSpan, fogSpan, v0->index, NULL, GL_POLYGON );
97 #include "s_tritemp.h"
103 * Render a smooth-shaded color index triangle.
105 static void smooth_ci_triangle( GLcontext
*ctx
,
112 #define INTERP_INDEX 1
114 #define RENDER_SPAN( span ) \
115 GLdepth zSpan[MAX_WIDTH]; \
116 GLfloat fogSpan[MAX_WIDTH]; \
117 GLuint indexSpan[MAX_WIDTH]; \
119 for (i = 0; i < span.count; i++) { \
120 zSpan[i] = FixedToDepth(span.z); \
121 span.z += span.zStep; \
122 indexSpan[i] = FixedToInt(span.index); \
123 span.index += span.indexStep; \
124 fogSpan[i] = span.fog; \
125 span.fog += span.fogStep; \
127 _mesa_write_index_span(ctx, span.count, span.x, span.y, \
128 zSpan, fogSpan, indexSpan, NULL, GL_POLYGON);
130 #include "s_tritemp.h"
136 * Render a flat-shaded RGBA triangle.
138 static void flat_rgba_triangle( GLcontext
*ctx
,
145 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
147 #define RENDER_SPAN( span ) \
148 GLdepth zSpan[MAX_WIDTH]; \
149 GLfloat fogSpan[MAX_WIDTH]; \
151 for (i = 0; i < span.count; i++) { \
152 zSpan[i] = FixedToDepth(span.z); \
153 span.z += span.zStep; \
154 fogSpan[i] = span.fog; \
155 span.fog += span.fogStep; \
157 _mesa_write_monocolor_span(ctx, span.count, span.x, span.y, zSpan, \
158 fogSpan, v2->color, NULL, GL_POLYGON );
160 #include "s_tritemp.h"
162 ASSERT(!ctx
->Texture
._ReallyEnabled
); /* texturing must be off */
163 ASSERT(ctx
->Light
.ShadeModel
==GL_FLAT
);
169 * Render a smooth-shaded RGBA triangle.
171 static void smooth_rgba_triangle( GLcontext
*ctx
,
179 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
181 #define INTERP_ALPHA 1
183 #define RENDER_SPAN( span ) \
184 GLdepth zSpan[MAX_WIDTH]; \
185 GLchan rgbaSpan[MAX_WIDTH][4]; \
186 GLfloat fogSpan[MAX_WIDTH]; \
188 for (i = 0; i < span.count; i++) { \
189 rgbaSpan[i][RCOMP] = FixedToChan(span.red); \
190 rgbaSpan[i][GCOMP] = FixedToChan(span.green); \
191 rgbaSpan[i][BCOMP] = FixedToChan(span.blue); \
192 rgbaSpan[i][ACOMP] = FixedToChan(span.alpha); \
193 span.red += span.redStep; \
194 span.green += span.greenStep; \
195 span.blue += span.blueStep; \
196 span.alpha += span.alphaStep; \
197 zSpan[i] = FixedToDepth(span.z); \
198 span.z += span.zStep; \
199 fogSpan[i] = span.fog; \
200 span.fog += span.fogStep; \
202 _mesa_write_rgba_span(ctx, span.count, span.x, span.y, \
203 (CONST GLdepth *) zSpan, \
204 fogSpan, rgbaSpan, NULL, GL_POLYGON);
206 #include "s_tritemp.h"
208 ASSERT(!ctx
->Texture
._ReallyEnabled
); /* texturing must be off */
209 ASSERT(ctx
->Light
.ShadeModel
==GL_SMOOTH
);
214 * Render an RGB, GL_DECAL, textured triangle.
215 * Interpolate S,T only w/out mipmapping or perspective correction.
219 static void simple_textured_triangle( GLcontext
*ctx
,
224 #define INTERP_INT_TEX 1
225 #define S_SCALE twidth
226 #define T_SCALE theight
229 SWcontext *swrast = SWRAST_CONTEXT(ctx); \
230 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
231 GLint b = obj->BaseLevel; \
232 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
233 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
234 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
235 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
236 const GLint smask = obj->Image[b]->Width - 1; \
237 const GLint tmask = obj->Image[b]->Height - 1; \
239 /* this shouldn't happen */ \
243 #define RENDER_SPAN( span ) \
244 GLchan rgbSpan[MAX_WIDTH][3]; \
246 span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \
247 span.intTex[1] -= FIXED_HALF; \
248 for (i = 0; i < span.count; i++) { \
249 GLint s = FixedToInt(span.intTex[0]) & smask; \
250 GLint t = FixedToInt(span.intTex[1]) & tmask; \
251 GLint pos = (t << twidth_log2) + s; \
252 pos = pos + pos + pos; /* multiply by 3 */ \
253 rgbSpan[i][RCOMP] = texture[pos]; \
254 rgbSpan[i][GCOMP] = texture[pos+1]; \
255 rgbSpan[i][BCOMP] = texture[pos+2]; \
256 span.intTex[0] += span.intTexStep[0]; \
257 span.intTex[1] += span.intTexStep[1]; \
259 (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y, \
260 (CONST GLchan (*)[3]) rgbSpan, NULL );
262 #include "s_tritemp.h"
267 * Render an RGB, GL_DECAL, textured triangle.
268 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
269 * perspective correction.
273 static void simple_z_textured_triangle( GLcontext
*ctx
,
279 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
280 #define INTERP_INT_TEX 1
281 #define S_SCALE twidth
282 #define T_SCALE theight
285 SWcontext *swrast = SWRAST_CONTEXT(ctx); \
286 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
287 GLint b = obj->BaseLevel; \
288 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
289 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
290 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
291 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
292 GLint smask = obj->Image[b]->Width - 1; \
293 GLint tmask = obj->Image[b]->Height - 1; \
295 /* this shouldn't happen */ \
299 #define RENDER_SPAN( span ) \
300 GLchan rgbSpan[MAX_WIDTH][3]; \
301 GLubyte mask[MAX_WIDTH]; \
303 span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \
304 span.intTex[1] -= FIXED_HALF; \
305 for (i = 0; i < span.count; i++) { \
306 const GLdepth z = FixedToDepth(span.z); \
308 GLint s = FixedToInt(span.intTex[0]) & smask; \
309 GLint t = FixedToInt(span.intTex[1]) & tmask; \
310 GLint pos = (t << twidth_log2) + s; \
311 pos = pos + pos + pos; /* multiply by 3 */ \
312 rgbSpan[i][RCOMP] = texture[pos]; \
313 rgbSpan[i][GCOMP] = texture[pos+1]; \
314 rgbSpan[i][BCOMP] = texture[pos+2]; \
321 span.intTex[0] += span.intTexStep[0]; \
322 span.intTex[1] += span.intTexStep[1]; \
323 span.z += span.zStep; \
325 (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y, \
326 (CONST GLchan (*)[3]) rgbSpan, mask );
328 #include "s_tritemp.h"
332 #if CHAN_TYPE != GL_FLOAT
341 const GLchan
*texture
;
342 GLchan er
, eg
, eb
, ea
;
343 GLint tbytesline
, tsize
;
344 GLint fixedToDepthShift
;
348 /* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA
349 * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD
353 affine_span(GLcontext
*ctx
, struct triangle_span
*span
,
354 struct affine_info
*info
)
356 GLchan sample
[4]; /* the filtered texture sample */
358 /* Instead of defining a function for each mode, a test is done
359 * between the outer and inner loops. This is to reduce code size
360 * and complexity. Observe that an optimizing compiler kills
361 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
364 #define NEAREST_RGB \
365 sample[RCOMP] = tex00[RCOMP]; \
366 sample[GCOMP] = tex00[GCOMP]; \
367 sample[BCOMP] = tex00[BCOMP]; \
368 sample[ACOMP] = CHAN_MAX
371 sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \
372 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
373 sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \
374 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
375 sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \
376 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
377 sample[ACOMP] = CHAN_MAX
379 #define NEAREST_RGBA COPY_CHAN4(sample, tex00)
381 #define LINEAR_RGBA \
382 sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \
383 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;\
384 sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \
385 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;\
386 sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \
387 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;\
388 sample[ACOMP] = (ti * (si * tex00[3] + sf * tex01[3]) + \
389 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
392 dest[RCOMP] = span->red * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \
393 dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \
394 dest[BCOMP] = span->blue * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \
395 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8)
398 dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red + \
399 ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT)) \
400 >> (FIXED_SHIFT + 8); \
401 dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green + \
402 ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT)) \
403 >> (FIXED_SHIFT + 8); \
404 dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue + \
405 ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT)) \
406 >> (FIXED_SHIFT + 8); \
407 dest[ACOMP] = FixedToInt(span->alpha)
410 dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red \
411 + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8); \
412 dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green \
413 + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8); \
414 dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue \
415 + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8); \
416 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8)
418 #define REPLACE COPY_CHAN4(dest, sample)
422 GLint rSum = FixedToInt(span->red) + (GLint) sample[RCOMP]; \
423 GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP]; \
424 GLint bSum = FixedToInt(span->blue) + (GLint) sample[BCOMP]; \
425 dest[RCOMP] = MIN2(rSum, CHAN_MAX); \
426 dest[GCOMP] = MIN2(gSum, CHAN_MAX); \
427 dest[BCOMP] = MIN2(bSum, CHAN_MAX); \
428 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \
433 #define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE
435 #define NEAREST_RGBA_REPLACE COPY_CHAN4(dest, tex00)
437 #define SPAN_NEAREST(DO_TEX,COMP) \
438 for (i = 0; i < span->count; i++) { \
439 /* Isn't it necessary to use FixedFloor below?? */ \
440 GLint s = FixedToInt(span->intTex[0]) & info->smask; \
441 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \
442 GLint pos = (t << info->twidth_log2) + s; \
443 const GLchan *tex00 = info->texture + COMP * pos; \
444 zspan[i] = FixedToDepth(span->z); \
445 fogspan[i] = span->fog; \
447 span->fog += span->fogStep; \
448 span->z += span->zStep; \
449 span->red += span->redStep; \
450 span->green += span->greenStep; \
451 span->blue += span->blueStep; \
452 span->alpha += span->alphaStep; \
453 span->intTex[0] += span->intTexStep[0]; \
454 span->intTex[1] += span->intTexStep[1]; \
458 #define SPAN_LINEAR(DO_TEX,COMP) \
459 for (i = 0; i < span->count; i++) { \
460 /* Isn't it necessary to use FixedFloor below?? */ \
461 GLint s = FixedToInt(span->intTex[0]) & info->smask; \
462 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \
463 GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK; \
464 GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK; \
465 GLfixed si = FIXED_FRAC_MASK - sf; \
466 GLfixed ti = FIXED_FRAC_MASK - tf; \
467 GLint pos = (t << info->twidth_log2) + s; \
468 const GLchan *tex00 = info->texture + COMP * pos; \
469 const GLchan *tex10 = tex00 + info->tbytesline; \
470 const GLchan *tex01 = tex00 + COMP; \
471 const GLchan *tex11 = tex10 + COMP; \
474 if (t == info->tmask) { \
475 tex10 -= info->tsize; \
476 tex11 -= info->tsize; \
478 if (s == info->smask) { \
479 tex01 -= info->tbytesline; \
480 tex11 -= info->tbytesline; \
482 zspan[i] = FixedToDepth(span->z); \
483 fogspan[i] = span->fog; \
485 span->fog += span->fogStep; \
486 span->z += span->zStep; \
487 span->red += span->redStep; \
488 span->green += span->greenStep; \
489 span->blue += span->blueStep; \
490 span->alpha += span->alphaStep; \
491 span->intTex[0] += span->intTexStep[0]; \
492 span->intTex[1] += span->intTexStep[1]; \
496 #define FixedToDepth(F) ((F) >> fixedToDepthShift)
499 GLdepth zspan
[MAX_WIDTH
];
500 GLfloat fogspan
[MAX_WIDTH
];
501 GLchan rgba
[MAX_WIDTH
][4];
502 GLchan
*dest
= rgba
[0];
503 const GLint fixedToDepthShift
= info
->fixedToDepthShift
;
505 span
->intTex
[0] -= FIXED_HALF
;
506 span
->intTex
[1] -= FIXED_HALF
;
507 switch (info
->filter
) {
509 switch (info
->format
) {
511 switch (info
->envmode
) {
513 SPAN_NEAREST(NEAREST_RGB
;MODULATE
,3);
517 SPAN_NEAREST(NEAREST_RGB_REPLACE
,3);
520 SPAN_NEAREST(NEAREST_RGB
;BLEND
,3);
523 SPAN_NEAREST(NEAREST_RGB
;ADD
,3);
530 switch(info
->envmode
) {
532 SPAN_NEAREST(NEAREST_RGBA
;MODULATE
,4);
535 SPAN_NEAREST(NEAREST_RGBA
;DECAL
,4);
538 SPAN_NEAREST(NEAREST_RGBA
;BLEND
,4);
541 SPAN_NEAREST(NEAREST_RGBA
;ADD
,4);
544 SPAN_NEAREST(NEAREST_RGBA_REPLACE
,4);
554 span
->intTex
[0] -= FIXED_HALF
;
555 span
->intTex
[1] -= FIXED_HALF
;
556 switch (info
->format
) {
558 switch (info
->envmode
) {
560 SPAN_LINEAR(LINEAR_RGB
;MODULATE
,3);
564 SPAN_LINEAR(LINEAR_RGB
;REPLACE
,3);
567 SPAN_LINEAR(LINEAR_RGB
;BLEND
,3);
570 SPAN_LINEAR(LINEAR_RGB
;ADD
,3);
577 switch (info
->envmode
) {
579 SPAN_LINEAR(LINEAR_RGBA
;MODULATE
,4);
582 SPAN_LINEAR(LINEAR_RGBA
;DECAL
,4);
585 SPAN_LINEAR(LINEAR_RGBA
;BLEND
,4);
588 SPAN_LINEAR(LINEAR_RGBA
;ADD
,4);
591 SPAN_LINEAR(LINEAR_RGBA
;REPLACE
,4);
599 _mesa_write_rgba_span(ctx
, span
->count
, span
->x
, span
->y
,
600 zspan
, fogspan
, rgba
, NULL
, GL_POLYGON
);
610 * Render an RGB/RGBA textured triangle without perspective correction.
612 static void affine_textured_triangle( GLcontext
*ctx
,
619 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
621 #define INTERP_ALPHA 1
622 #define INTERP_INT_TEX 1
623 #define S_SCALE twidth
624 #define T_SCALE theight
627 struct affine_info info; \
628 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
629 struct gl_texture_object *obj = unit->Current2D; \
630 GLint b = obj->BaseLevel; \
631 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
632 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
633 info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\
634 info.texture = (const GLchan *) obj->Image[b]->Data; \
635 info.twidth_log2 = obj->Image[b]->WidthLog2; \
636 info.smask = obj->Image[b]->Width - 1; \
637 info.tmask = obj->Image[b]->Height - 1; \
638 info.format = obj->Image[b]->Format; \
639 info.filter = obj->MinFilter; \
640 info.envmode = unit->EnvMode; \
642 if (info.envmode == GL_BLEND) { \
643 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
644 info.er = FloatToFixed(unit->EnvColor[RCOMP]); \
645 info.eg = FloatToFixed(unit->EnvColor[GCOMP]); \
646 info.eb = FloatToFixed(unit->EnvColor[BCOMP]); \
647 info.ea = FloatToFixed(unit->EnvColor[ACOMP]); \
649 if (!info.texture) { \
650 /* this shouldn't happen */ \
654 switch (info.format) { \
658 info.tbytesline = obj->Image[b]->Width; \
660 case GL_LUMINANCE_ALPHA: \
661 info.tbytesline = obj->Image[b]->Width * 2; \
664 info.tbytesline = obj->Image[b]->Width * 3; \
667 info.tbytesline = obj->Image[b]->Width * 4; \
670 _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
673 info.tsize = obj->Image[b]->Height * info.tbytesline;
675 #define RENDER_SPAN( span ) affine_span(ctx, &span, &info);
677 #include "s_tritemp.h"
690 const GLchan
*texture
;
691 GLchan er
, eg
, eb
, ea
; /* texture env color */
692 GLint tbytesline
, tsize
;
693 GLint fixedToDepthShift
;
698 fast_persp_span(GLcontext
*ctx
, struct triangle_span
*span
,
699 struct persp_info
*info
)
701 GLchan sample
[4]; /* the filtered texture sample */
703 /* Instead of defining a function for each mode, a test is done
704 * between the outer and inner loops. This is to reduce code size
705 * and complexity. Observe that an optimizing compiler kills
706 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
708 #define SPAN_NEAREST(DO_TEX,COMP) \
709 for (i = 0; i < span->count; i++) { \
710 GLdouble invQ = tex_coord[2] ? \
711 (1.0 / tex_coord[2]) : 1.0; \
712 GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \
713 GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \
714 GLint s = IFLOOR(s_tmp) & info->smask; \
715 GLint t = IFLOOR(t_tmp) & info->tmask; \
716 GLint pos = (t << info->twidth_log2) + s; \
717 const GLchan *tex00 = info->texture + COMP * pos; \
718 zspan[i] = FixedToDepth(span->z); \
719 fogspan[i] = span->fog; \
721 span->fog += span->fogStep; \
722 span->z += span->zStep; \
723 span->red += span->redStep; \
724 span->green += span->greenStep; \
725 span->blue += span->blueStep; \
726 span->alpha += span->alphaStep; \
727 tex_coord[0] += tex_step[0]; \
728 tex_coord[1] += tex_step[1]; \
729 tex_coord[2] += tex_step[2]; \
733 #define SPAN_LINEAR(DO_TEX,COMP) \
734 for (i = 0; i < span->count; i++) { \
735 GLdouble invQ = tex_coord[2] ? \
736 (1.0 / tex_coord[2]) : 1.0; \
737 GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \
738 GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \
739 GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF; \
740 GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF; \
741 GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \
742 GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \
743 GLfixed sf = s_fix & FIXED_FRAC_MASK; \
744 GLfixed tf = t_fix & FIXED_FRAC_MASK; \
745 GLfixed si = FIXED_FRAC_MASK - sf; \
746 GLfixed ti = FIXED_FRAC_MASK - tf; \
747 GLint pos = (t << info->twidth_log2) + s; \
748 const GLchan *tex00 = info->texture + COMP * pos; \
749 const GLchan *tex10 = tex00 + info->tbytesline; \
750 const GLchan *tex01 = tex00 + COMP; \
751 const GLchan *tex11 = tex10 + COMP; \
754 if (t == info->tmask) { \
755 tex10 -= info->tsize; \
756 tex11 -= info->tsize; \
758 if (s == info->smask) { \
759 tex01 -= info->tbytesline; \
760 tex11 -= info->tbytesline; \
762 zspan[i] = FixedToDepth(span->z); \
763 fogspan[i] = span->fog; \
765 span->fog += span->fogStep; \
766 span->z += span->zStep; \
767 span->red += span->redStep; \
768 span->green += span->greenStep; \
769 span->blue += span->blueStep; \
770 span->alpha += span->alphaStep; \
771 tex_coord[0] += tex_step[0]; \
772 tex_coord[1] += tex_step[1]; \
773 tex_coord[2] += tex_step[2]; \
777 #define FixedToDepth(F) ((F) >> fixedToDepthShift)
780 GLdepth zspan
[MAX_WIDTH
];
781 GLfloat tex_coord
[3], tex_step
[3];
782 GLfloat fogspan
[MAX_WIDTH
];
783 GLchan rgba
[MAX_WIDTH
][4];
784 GLchan
*dest
= rgba
[0];
785 const GLint fixedToDepthShift
= info
->fixedToDepthShift
;
787 tex_coord
[0] = span
->tex
[0][0] * (info
->smask
+ 1),
788 tex_step
[0] = span
->texStep
[0][0] * (info
->smask
+ 1);
789 tex_coord
[1] = span
->tex
[0][1] * (info
->tmask
+ 1),
790 tex_step
[1] = span
->texStep
[0][1] * (info
->tmask
+ 1);
791 /* span->tex[0][2] only if 3D-texturing, here only 2D */
792 tex_coord
[2] = span
->tex
[0][3],
793 tex_step
[2] = span
->texStep
[0][3];
795 switch (info
->filter
) {
797 switch (info
->format
) {
799 switch (info
->envmode
) {
801 SPAN_NEAREST(NEAREST_RGB
;MODULATE
,3);
805 SPAN_NEAREST(NEAREST_RGB_REPLACE
,3);
808 SPAN_NEAREST(NEAREST_RGB
;BLEND
,3);
811 SPAN_NEAREST(NEAREST_RGB
;ADD
,3);
818 switch(info
->envmode
) {
820 SPAN_NEAREST(NEAREST_RGBA
;MODULATE
,4);
823 SPAN_NEAREST(NEAREST_RGBA
;DECAL
,4);
826 SPAN_NEAREST(NEAREST_RGBA
;BLEND
,4);
829 SPAN_NEAREST(NEAREST_RGBA
;ADD
,4);
832 SPAN_NEAREST(NEAREST_RGBA_REPLACE
,4);
842 switch (info
->format
) {
844 switch (info
->envmode
) {
846 SPAN_LINEAR(LINEAR_RGB
;MODULATE
,3);
850 SPAN_LINEAR(LINEAR_RGB
;REPLACE
,3);
853 SPAN_LINEAR(LINEAR_RGB
;BLEND
,3);
856 SPAN_LINEAR(LINEAR_RGB
;ADD
,3);
863 switch (info
->envmode
) {
865 SPAN_LINEAR(LINEAR_RGBA
;MODULATE
,4);
868 SPAN_LINEAR(LINEAR_RGBA
;DECAL
,4);
871 SPAN_LINEAR(LINEAR_RGBA
;BLEND
,4);
874 SPAN_LINEAR(LINEAR_RGBA
;ADD
,4);
877 SPAN_LINEAR(LINEAR_RGBA
;REPLACE
,4);
886 /* This does not seem to be necessary, but I don't know !! */
887 /* span->tex[0][0] = tex_coord[0] / (info->smask + 1),
888 span->tex[0][1] = tex_coord[1] / (info->tmask + 1),*/
889 /* span->tex[0][2] only if 3D-texturing, here only 2D */
890 /* span->tex[0][3] = tex_coord[2]; */
892 _mesa_write_rgba_span(ctx
, span
->count
, span
->x
, span
->y
,
893 zspan
, fogspan
, rgba
, NULL
, GL_POLYGON
);
903 * Render an perspective corrected RGB/RGBA textured triangle.
904 * The Q (aka V in Mesa) coordinate must be zero such that the divide
905 * by interpolated Q/W comes out right.
908 static void persp_textured_triangle( GLcontext
*ctx
,
915 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
917 #define INTERP_ALPHA 1
921 struct persp_info info; \
922 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
923 struct gl_texture_object *obj = unit->Current2D; \
924 GLint b = obj->BaseLevel; \
925 info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\
926 info.texture = (const GLchan *) obj->Image[b]->Data; \
927 info.twidth_log2 = obj->Image[b]->WidthLog2; \
928 info.smask = obj->Image[b]->Width - 1; \
929 info.tmask = obj->Image[b]->Height - 1; \
930 info.format = obj->Image[b]->Format; \
931 info.filter = obj->MinFilter; \
932 info.envmode = unit->EnvMode; \
934 if (info.envmode == GL_BLEND) { \
935 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
936 info.er = FloatToFixed(unit->EnvColor[RCOMP]); \
937 info.eg = FloatToFixed(unit->EnvColor[GCOMP]); \
938 info.eb = FloatToFixed(unit->EnvColor[BCOMP]); \
939 info.ea = FloatToFixed(unit->EnvColor[ACOMP]); \
941 if (!info.texture) { \
942 /* this shouldn't happen */ \
946 switch (info.format) { \
950 info.tbytesline = obj->Image[b]->Width; \
952 case GL_LUMINANCE_ALPHA: \
953 info.tbytesline = obj->Image[b]->Width * 2; \
956 info.tbytesline = obj->Image[b]->Width * 3; \
959 info.tbytesline = obj->Image[b]->Width * 4; \
962 _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\
965 info.tsize = obj->Image[b]->Height * info.tbytesline;
967 #define RENDER_SPAN( span ) fast_persp_span(ctx, &span, &info);
969 #include "s_tritemp.h"
974 #endif /* CHAN_BITS != GL_FLOAT */
980 * Render a smooth-shaded, textured, RGBA triangle.
981 * Interpolate S,T,R with perspective correction, w/out mipmapping.
983 static void general_textured_triangle( GLcontext
*ctx
,
990 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
992 #define INTERP_ALPHA 1
996 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
997 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
998 DEFARRAY(GLfloat, sSpan, MAX_WIDTH); /* mac 32k limitation */ \
999 DEFARRAY(GLfloat, tSpan, MAX_WIDTH); /* mac 32k limitation */ \
1000 DEFARRAY(GLfloat, uSpan, MAX_WIDTH); /* mac 32k limitation */ \
1001 CHECKARRAY(sSpan, return); /* mac 32k limitation */ \
1002 CHECKARRAY(tSpan, return); /* mac 32k limitation */ \
1003 CHECKARRAY(uSpan, return); /* mac 32k limitation */ \
1004 span.texWidth[0] = (GLfloat) texImage->Width; \
1005 span.texHeight[0] = (GLfloat) texImage->Height; \
1006 (void) fixedToDepthShift;
1008 #define RENDER_SPAN( span ) \
1009 GLdepth zSpan[MAX_WIDTH]; \
1010 GLfloat fogSpan[MAX_WIDTH]; \
1011 GLchan rgbaSpan[MAX_WIDTH][4]; \
1013 /* NOTE: we could just call rasterize_span() here instead */ \
1014 for (i = 0; i < span.count; i++) { \
1015 GLdouble invQ = span.tex[0][3] ? (1.0 / span.tex[0][3]) : 1.0; \
1016 zSpan[i] = FixedToDepth(span.z); \
1017 span.z += span.zStep; \
1018 fogSpan[i] = span.fog; \
1019 span.fog += span.fogStep; \
1020 rgbaSpan[i][RCOMP] = FixedToChan(span.red); \
1021 rgbaSpan[i][GCOMP] = FixedToChan(span.green); \
1022 rgbaSpan[i][BCOMP] = FixedToChan(span.blue); \
1023 rgbaSpan[i][ACOMP] = FixedToChan(span.alpha); \
1024 span.red += span.redStep; \
1025 span.green += span.greenStep; \
1026 span.blue += span.blueStep; \
1027 span.alpha += span.alphaStep; \
1028 sSpan[i] = (GLfloat) (span.tex[0][0] * invQ); \
1029 tSpan[i] = (GLfloat) (span.tex[0][1] * invQ); \
1030 uSpan[i] = (GLfloat) (span.tex[0][2] * invQ); \
1031 span.tex[0][0] += span.texStep[0][0]; \
1032 span.tex[0][1] += span.texStep[0][1]; \
1033 span.tex[0][2] += span.texStep[0][2]; \
1034 span.tex[0][3] += span.texStep[0][3]; \
1036 _mesa_write_texture_span(ctx, span.count, span.x, span.y, \
1037 zSpan, fogSpan, sSpan, tSpan, uSpan, \
1038 NULL, rgbaSpan, NULL, NULL, GL_POLYGON );
1040 #define CLEANUP_CODE \
1041 UNDEFARRAY(sSpan); /* mac 32k limitation */ \
1042 UNDEFARRAY(tSpan); \
1045 #include "s_tritemp.h"
1050 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1051 * color interpolation.
1052 * Interpolate texcoords with perspective correction, w/out mipmapping.
1054 static void general_textured_spec_triangle( GLcontext
*ctx
,
1057 const SWvertex
*v2
)
1060 #define INTERP_FOG 1
1061 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1062 #define INTERP_RGB 1
1063 #define INTERP_SPEC 1
1064 #define INTERP_ALPHA 1
1065 #define INTERP_TEX 1
1067 #define SETUP_CODE \
1068 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1069 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1070 span.texWidth[0] = (GLfloat) texImage->Width; \
1071 span.texHeight[0] = (GLfloat) texImage->Height; \
1072 (void) fixedToDepthShift;
1074 #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
1076 #include "s_tritemp.h"
1081 * Render a smooth-shaded, textured, RGBA triangle.
1082 * Interpolate S,T,R with perspective correction and compute lambda for
1083 * each fragment. Lambda is used to determine whether to use the
1084 * minification or magnification filter. If minification and using
1085 * mipmaps, lambda is also used to select the texture level of detail.
1087 static void lambda_textured_triangle( GLcontext
*ctx
,
1090 const SWvertex
*v2
)
1093 #define INTERP_FOG 1
1094 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1095 #define INTERP_RGB 1
1096 #define INTERP_ALPHA 1
1097 #define INTERP_TEX 1
1098 #define INTERP_LAMBDA 1
1100 #define SETUP_CODE \
1101 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1102 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1103 span.texWidth[0] = (GLfloat) texImage->Width; \
1104 span.texHeight[0] = (GLfloat) texImage->Height; \
1105 (void) fixedToDepthShift;
1107 #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
1109 #include "s_tritemp.h"
1114 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1116 * Interpolate S,T,R with perspective correction and compute lambda for
1117 * each fragment. Lambda is used to determine whether to use the
1118 * minification or magnification filter. If minification and using
1119 * mipmaps, lambda is also used to select the texture level of detail.
1121 static void lambda_textured_spec_triangle( GLcontext
*ctx
,
1124 const SWvertex
*v2
)
1127 #define INTERP_FOG 1
1128 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1129 #define INTERP_RGB 1
1130 #define INTERP_SPEC 1
1131 #define INTERP_ALPHA 1
1132 #define INTERP_TEX 1
1133 #define INTERP_LAMBDA 1
1135 #define SETUP_CODE \
1136 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1137 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1138 span.texWidth[0] = (GLfloat) texImage->Width; \
1139 span.texHeight[0] = (GLfloat) texImage->Height; \
1140 (void) fixedToDepthShift;
1142 #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
1144 #include "s_tritemp.h"
1149 * This is the big one!
1150 * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates
1151 * with lambda (LOD).
1155 lambda_multitextured_triangle( GLcontext
*ctx
,
1158 const SWvertex
*v2
)
1162 #define INTERP_FOG 1
1163 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1164 #define INTERP_RGB 1
1165 #define INTERP_ALPHA 1
1166 #define INTERP_SPEC 1
1167 #define INTERP_MULTITEX 1
1168 #define INTERP_LAMBDA 1
1170 #define SETUP_CODE \
1172 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \
1173 if (ctx->Texture.Unit[u]._ReallyEnabled) { \
1174 const struct gl_texture_object *texObj; \
1175 const struct gl_texture_image *texImage; \
1176 texObj = ctx->Texture.Unit[u]._Current; \
1177 texImage = texObj->Image[texObj->BaseLevel]; \
1178 span.texWidth[u] = (GLfloat) texImage->Width; \
1179 span.texHeight[u] = (GLfloat) texImage->Height; \
1182 (void) fixedToDepthShift;
1184 #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
1186 #include "s_tritemp.h"
1191 static void occlusion_zless_triangle( GLcontext
*ctx
,
1194 const SWvertex
*v2
)
1196 if (ctx
->OcclusionResult
) {
1200 #define DO_OCCLUSION_TEST
1202 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1204 #define RENDER_SPAN( span ) \
1206 for (i = 0; i < span.count; i++) { \
1207 GLdepth z = FixedToDepth(span.z); \
1208 if (z < zRow[i]) { \
1209 ctx->OcclusionResult = GL_TRUE; \
1212 span.z += span.zStep; \
1215 #include "s_tritemp.h"
1218 static void nodraw_triangle( GLcontext
*ctx
,
1221 const SWvertex
*v2
)
1223 (void) (ctx
&& v0
&& v1
&& v2
);
1226 void _swrast_add_spec_terms_triangle( GLcontext
*ctx
,
1229 const SWvertex
*v2
)
1231 SWvertex
*ncv0
= (SWvertex
*)v0
; /* drop const qualifier */
1232 SWvertex
*ncv1
= (SWvertex
*)v1
;
1233 SWvertex
*ncv2
= (SWvertex
*)v2
;
1235 COPY_CHAN4( c
[0], ncv0
->color
);
1236 COPY_CHAN4( c
[1], ncv1
->color
);
1237 COPY_CHAN4( c
[2], ncv2
->color
);
1238 ACC_3V( ncv0
->color
, ncv0
->specular
);
1239 ACC_3V( ncv1
->color
, ncv1
->specular
);
1240 ACC_3V( ncv2
->color
, ncv2
->specular
);
1241 SWRAST_CONTEXT(ctx
)->SpecTriangle( ctx
, ncv0
, ncv1
, ncv2
);
1242 COPY_CHAN4( ncv0
->color
, c
[0] );
1243 COPY_CHAN4( ncv1
->color
, c
[1] );
1244 COPY_CHAN4( ncv2
->color
, c
[2] );
1251 /* record the current triangle function name */
1252 static const char *triFuncName
= NULL
;
1254 #define USE(triFunc) \
1256 triFuncName = #triFunc; \
1257 /*printf("%s\n", triFuncName);*/ \
1258 swrast->Triangle = triFunc; \
1263 #define USE(triFunc) swrast->Triangle = triFunc;
1271 * Determine which triangle rendering function to use given the current
1272 * rendering context.
1274 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
1275 * remove tests to this code.
1278 _swrast_choose_triangle( GLcontext
*ctx
)
1280 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
1281 const GLboolean rgbmode
= ctx
->Visual
.rgbMode
;
1283 if (ctx
->Polygon
.CullFlag
&&
1284 ctx
->Polygon
.CullFaceMode
== GL_FRONT_AND_BACK
) {
1285 USE(nodraw_triangle
);
1289 if (ctx
->RenderMode
==GL_RENDER
) {
1291 if (ctx
->Polygon
.SmoothFlag
) {
1292 _mesa_set_aa_triangle_function(ctx
);
1293 ASSERT(swrast
->Triangle
);
1297 if (ctx
->Depth
.OcclusionTest
&&
1299 ctx
->Depth
.Mask
== GL_FALSE
&&
1300 ctx
->Depth
.Func
== GL_LESS
&&
1301 !ctx
->Stencil
.Enabled
) {
1303 ctx
->Color
.ColorMask
[0] == 0 &&
1304 ctx
->Color
.ColorMask
[1] == 0 &&
1305 ctx
->Color
.ColorMask
[2] == 0 &&
1306 ctx
->Color
.ColorMask
[3] == 0)
1308 (!rgbmode
&& ctx
->Color
.IndexMask
== 0)) {
1309 USE(occlusion_zless_triangle
);
1314 if (ctx
->Texture
._ReallyEnabled
) {
1315 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
1316 const struct gl_texture_object
*texObj2D
;
1317 const struct gl_texture_image
*texImg
;
1318 GLenum minFilter
, magFilter
, envMode
;
1320 texObj2D
= ctx
->Texture
.Unit
[0].Current2D
;
1321 texImg
= texObj2D
? texObj2D
->Image
[texObj2D
->BaseLevel
] : NULL
;
1322 format
= texImg
? texImg
->TexFormat
->MesaFormat
: -1;
1323 minFilter
= texObj2D
? texObj2D
->MinFilter
: (GLenum
) 0;
1324 magFilter
= texObj2D
? texObj2D
->MagFilter
: (GLenum
) 0;
1325 envMode
= ctx
->Texture
.Unit
[0].EnvMode
;
1327 /* First see if we can used an optimized 2-D texture function */
1328 if (ctx
->Texture
._ReallyEnabled
==TEXTURE0_2D
1329 && texObj2D
->WrapS
==GL_REPEAT
1330 && texObj2D
->WrapT
==GL_REPEAT
1331 && texImg
->Border
==0
1332 && (format
== MESA_FORMAT_RGB
|| format
== MESA_FORMAT_RGBA
)
1333 && minFilter
== magFilter
1334 && ctx
->Light
.Model
.ColorControl
== GL_SINGLE_COLOR
1335 && ctx
->Texture
.Unit
[0].EnvMode
!= GL_COMBINE_EXT
) {
1336 if (ctx
->Hint
.PerspectiveCorrection
==GL_FASTEST
) {
1337 if (minFilter
== GL_NEAREST
1338 && format
== MESA_FORMAT_RGB
1339 && (envMode
== GL_REPLACE
|| envMode
== GL_DECAL
)
1340 && ((swrast
->_RasterMask
== (DEPTH_BIT
| TEXTURE_BIT
)
1341 && ctx
->Depth
.Func
== GL_LESS
1342 && ctx
->Depth
.Mask
== GL_TRUE
)
1343 || swrast
->_RasterMask
== TEXTURE_BIT
)
1344 && ctx
->Polygon
.StippleFlag
== GL_FALSE
) {
1345 if (swrast
->_RasterMask
== (DEPTH_BIT
| TEXTURE_BIT
)) {
1346 USE(simple_z_textured_triangle
);
1349 USE(simple_textured_triangle
);
1353 #if CHAN_TYPE == GL_FLOAT
1354 USE(general_textured_triangle
);
1356 USE(affine_textured_triangle
);
1361 #if CHAN_TYPE == GL_FLOAT
1362 USE(general_textured_triangle
);
1364 USE(persp_textured_triangle
);
1369 /* More complicated textures (mipmap, multi-tex, sep specular) */
1370 GLboolean needLambda
;
1371 /* if mag filter != min filter we need to compute lambda */
1372 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
1373 if (obj
&& obj
->MinFilter
!= obj
->MagFilter
)
1374 needLambda
= GL_TRUE
;
1376 needLambda
= GL_FALSE
;
1377 if (ctx
->Texture
._ReallyEnabled
> TEXTURE0_ANY
) {
1378 USE(lambda_multitextured_triangle
);
1380 else if (ctx
->_TriangleCaps
& DD_SEPARATE_SPECULAR
) {
1381 /* separate specular color interpolation */
1383 USE(lambda_textured_spec_triangle
);
1386 USE(general_textured_spec_triangle
);
1391 USE(lambda_textured_triangle
);
1394 USE(general_textured_triangle
);
1400 ASSERT(!ctx
->Texture
._ReallyEnabled
);
1401 if (ctx
->Light
.ShadeModel
==GL_SMOOTH
) {
1402 /* smooth shaded, no texturing, stippled or some raster ops */
1404 USE(smooth_rgba_triangle
);
1407 USE(smooth_ci_triangle
);
1411 /* flat shaded, no texturing, stippled or some raster ops */
1413 USE(flat_rgba_triangle
);
1416 USE(flat_ci_triangle
);
1421 else if (ctx
->RenderMode
==GL_FEEDBACK
) {
1422 USE(_mesa_feedback_triangle
);
1425 /* GL_SELECT mode */
1426 USE(_mesa_select_triangle
);