1 /* $Id: s_triangle.c,v 1.16 2001/03/08 15:23:46 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 * Triangle rasterizers
30 * When the device driver doesn't implement triangle rasterization Mesa
31 * will use these functions to draw triangles.
44 #include "s_aatriangle.h"
45 #include "s_context.h"
47 #include "s_feedback.h"
49 #include "s_triangle.h"
51 GLboolean
_mesa_cull_triangle( GLcontext
*ctx
,
56 GLfloat ex
= v1
->win
[0] - v0
->win
[0];
57 GLfloat ey
= v1
->win
[1] - v0
->win
[1];
58 GLfloat fx
= v2
->win
[0] - v0
->win
[0];
59 GLfloat fy
= v2
->win
[1] - v0
->win
[1];
60 GLfloat c
= ex
*fy
-ey
*fx
;
62 if (c
* SWRAST_CONTEXT(ctx
)->_backface_sign
> 0)
70 * Render a flat-shaded color index triangle.
72 static void flat_ci_triangle( GLcontext
*ctx
,
79 #define INNER_LOOP( LEFT, RIGHT, Y ) \
81 const GLint n = RIGHT-LEFT; \
83 GLdepth zspan[MAX_WIDTH]; \
84 GLfixed fogspan[MAX_WIDTH]; \
87 zspan[i] = FixedToDepth(ffz); \
89 fogspan[i] = fffog / 256; \
92 _mesa_write_monoindex_span( ctx, n, LEFT, Y, zspan, \
93 fogspan, v0->index, GL_POLYGON ); \
97 #include "s_tritemp.h"
103 * Render a smooth-shaded color index triangle.
105 static void smooth_ci_triangle( GLcontext
*ctx
,
111 #define INTERP_INDEX 1
113 #define INNER_LOOP( LEFT, RIGHT, Y ) \
115 const GLint n = RIGHT-LEFT; \
117 GLdepth zspan[MAX_WIDTH]; \
118 GLfixed fogspan[MAX_WIDTH]; \
119 GLuint index[MAX_WIDTH]; \
121 for (i=0;i<n;i++) { \
122 zspan[i] = FixedToDepth(ffz); \
124 index[i] = FixedToInt(ffi); \
126 fogspan[i] = fffog / 256; \
129 _mesa_write_index_span( ctx, n, LEFT, Y, zspan, fogspan, \
130 index, GL_POLYGON ); \
134 #include "s_tritemp.h"
140 * Render a flat-shaded RGBA triangle.
142 static void flat_rgba_triangle( GLcontext
*ctx
,
148 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
150 #define INNER_LOOP( LEFT, RIGHT, Y ) \
152 const GLint n = RIGHT-LEFT; \
154 GLdepth zspan[MAX_WIDTH]; \
155 GLfixed fogspan[MAX_WIDTH]; \
157 for (i=0;i<n;i++) { \
158 zspan[i] = FixedToDepth(ffz); \
160 fogspan[i] = fffog / 256; \
163 _mesa_write_monocolor_span( ctx, n, LEFT, Y, zspan, \
164 fogspan, v2->color, \
169 #include "s_tritemp.h"
171 ASSERT(!ctx
->Texture
._ReallyEnabled
); /* texturing must be off */
172 ASSERT(ctx
->Light
.ShadeModel
==GL_FLAT
);
178 * Render a smooth-shaded RGBA triangle.
180 static void smooth_rgba_triangle( GLcontext
*ctx
,
187 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
189 #define INTERP_ALPHA 1
191 #define INNER_LOOP( LEFT, RIGHT, Y ) \
193 const GLint n = RIGHT-LEFT; \
195 GLdepth zspan[MAX_WIDTH]; \
196 GLchan rgba[MAX_WIDTH][4]; \
197 GLfixed fogspan[MAX_WIDTH]; \
199 for (i=0;i<n;i++) { \
200 zspan[i] = FixedToDepth(ffz); \
201 rgba[i][RCOMP] = FixedToInt(ffr); \
202 rgba[i][GCOMP] = FixedToInt(ffg); \
203 rgba[i][BCOMP] = FixedToInt(ffb); \
204 rgba[i][ACOMP] = FixedToInt(ffa); \
205 fogspan[i] = fffog / 256; \
213 _mesa_write_rgba_span( ctx, n, LEFT, Y, \
214 (CONST GLdepth *) zspan, \
216 rgba, GL_POLYGON ); \
220 #include "s_tritemp.h"
222 ASSERT(!ctx
->Texture
._ReallyEnabled
); /* texturing must be off */
223 ASSERT(ctx
->Light
.ShadeModel
==GL_SMOOTH
);
228 * Render an RGB, GL_DECAL, textured triangle.
229 * Interpolate S,T only w/out mipmapping or perspective correction.
233 static void simple_textured_triangle( GLcontext
*ctx
,
238 #define INTERP_INT_TEX 1
239 #define S_SCALE twidth
240 #define T_SCALE theight
242 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
243 GLint b = obj->BaseLevel; \
244 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
245 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
246 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
247 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
248 GLint smask = obj->Image[b]->Width - 1; \
249 GLint tmask = obj->Image[b]->Height - 1; \
251 /* this shouldn't happen */ \
255 #define INNER_LOOP( LEFT, RIGHT, Y ) \
257 CONST GLint n = RIGHT-LEFT; \
259 GLchan rgb[MAX_WIDTH][3]; \
261 ffs -= FIXED_HALF; /* off-by-one error? */ \
263 for (i=0;i<n;i++) { \
264 GLint s = FixedToInt(ffs) & smask; \
265 GLint t = FixedToInt(fft) & tmask; \
266 GLint pos = (t << twidth_log2) + s; \
267 pos = pos + pos + pos; /* multiply by 3 */ \
268 rgb[i][RCOMP] = texture[pos]; \
269 rgb[i][GCOMP] = texture[pos+1]; \
270 rgb[i][BCOMP] = texture[pos+2]; \
274 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
275 (CONST GLchan (*)[3]) rgb, NULL ); \
279 #include "s_tritemp.h"
284 * Render an RGB, GL_DECAL, textured triangle.
285 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
286 * perspective correction.
290 static void simple_z_textured_triangle( GLcontext
*ctx
,
296 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
297 #define INTERP_INT_TEX 1
298 #define S_SCALE twidth
299 #define T_SCALE theight
301 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
302 GLint b = obj->BaseLevel; \
303 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
304 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
305 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
306 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
307 GLint smask = obj->Image[b]->Width - 1; \
308 GLint tmask = obj->Image[b]->Height - 1; \
310 /* this shouldn't happen */ \
314 #define INNER_LOOP( LEFT, RIGHT, Y ) \
316 CONST GLint n = RIGHT-LEFT; \
318 GLchan rgb[MAX_WIDTH][3]; \
319 GLubyte mask[MAX_WIDTH]; \
322 ffs -= FIXED_HALF; /* off-by-one error? */ \
324 for (i=0;i<n;i++) { \
325 GLdepth z = FixedToDepth(ffz); \
327 GLint s = FixedToInt(ffs) & smask; \
328 GLint t = FixedToInt(fft) & tmask; \
329 GLint pos = (t << twidth_log2) + s; \
330 pos = pos + pos + pos; /* multiply by 3 */ \
331 rgb[i][RCOMP] = texture[pos]; \
332 rgb[i][GCOMP] = texture[pos+1]; \
333 rgb[i][BCOMP] = texture[pos+2]; \
344 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
345 (CONST GLchan (*)[3]) rgb, mask ); \
349 #include "s_tritemp.h"
355 * Render an RGB/RGBA textured triangle without perspective correction.
357 static void affine_textured_triangle( GLcontext
*ctx
,
363 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
365 #define INTERP_ALPHA 1
366 #define INTERP_INT_TEX 1
367 #define S_SCALE twidth
368 #define T_SCALE theight
370 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
371 struct gl_texture_object *obj = unit->Current2D; \
372 GLint b = obj->BaseLevel; \
373 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
374 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
375 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
376 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
377 GLint smask = obj->Image[b]->Width - 1; \
378 GLint tmask = obj->Image[b]->Height - 1; \
379 GLint format = obj->Image[b]->Format; \
380 GLint filter = obj->MinFilter; \
381 GLint envmode = unit->EnvMode; \
382 GLint comp, tbytesline, tsize; \
383 GLfixed er, eg, eb, ea; \
384 GLint tr, tg, tb, ta; \
386 /* this shouldn't happen */ \
389 if (envmode == GL_BLEND || envmode == GL_ADD) { \
390 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
391 er = FloatToFixed(unit->EnvColor[RCOMP]); \
392 eg = FloatToFixed(unit->EnvColor[GCOMP]); \
393 eb = FloatToFixed(unit->EnvColor[BCOMP]); \
394 ea = FloatToFixed(unit->EnvColor[ACOMP]); \
402 case GL_LUMINANCE_ALPHA: \
412 _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
415 tbytesline = obj->Image[b]->Width * comp; \
416 tsize = obj->Image[b]->Height * tbytesline;
419 /* Instead of defining a function for each mode, a test is done
420 * between the outer and inner loops. This is to reduce code size
421 * and complexity. Observe that an optimizing compiler kills
422 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
425 #define NEAREST_RGB \
432 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
433 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
434 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
435 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
436 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
437 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
440 #define NEAREST_RGBA \
446 #define LINEAR_RGBA \
447 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
448 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
449 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
450 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
451 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
452 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
453 ta = (ti * (si * tex00[3] + sf * tex01[3]) + \
454 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
457 dest[RCOMP] = ffr * (tr + 1) >> (FIXED_SHIFT + 8); \
458 dest[GCOMP] = ffg * (tg + 1) >> (FIXED_SHIFT + 8); \
459 dest[BCOMP] = ffb * (tb + 1) >> (FIXED_SHIFT + 8); \
460 dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
463 dest[RCOMP] = ((0xff - ta) * ffr + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
464 dest[GCOMP] = ((0xff - ta) * ffg + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
465 dest[BCOMP] = ((0xff - ta) * ffb + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
466 dest[ACOMP] = FixedToInt(ffa)
469 dest[RCOMP] = ((0xff - tr) * ffr + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
470 dest[GCOMP] = ((0xff - tg) * ffg + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
471 dest[BCOMP] = ((0xff - tb) * ffb + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
472 dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
481 dest[RCOMP] = ((ffr << 8) + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
482 dest[GCOMP] = ((ffg << 8) + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
483 dest[BCOMP] = ((ffb << 8) + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
484 dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
488 #define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE
490 #define NEAREST_RGBA_REPLACE *(GLint *)dest = *(GLint *)tex00
492 #define SPAN1(DO_TEX,COMP) \
493 for (i=0;i<n;i++) { \
494 GLint s = FixedToInt(ffs) & smask; \
495 GLint t = FixedToInt(fft) & tmask; \
496 GLint pos = (t << twidth_log2) + s; \
497 const GLchan *tex00 = texture + COMP * pos; \
498 zspan[i] = FixedToDepth(ffz); \
499 fogspan[i] = fffog / 256; \
512 #define SPAN2(DO_TEX,COMP) \
513 for (i=0;i<n;i++) { \
514 GLint s = FixedToInt(ffs) & smask; \
515 GLint t = FixedToInt(fft) & tmask; \
516 GLint sf = ffs & FIXED_FRAC_MASK; \
517 GLint tf = fft & FIXED_FRAC_MASK; \
518 GLint si = FIXED_FRAC_MASK - sf; \
519 GLint ti = FIXED_FRAC_MASK - tf; \
520 GLint pos = (t << twidth_log2) + s; \
521 const GLchan *tex00 = texture + COMP * pos; \
522 const GLchan *tex10 = tex00 + tbytesline; \
523 const GLchan *tex01 = tex00 + COMP; \
524 const GLchan *tex11 = tex10 + COMP; \
530 tex01 -= tbytesline; \
531 tex11 -= tbytesline; \
533 zspan[i] = FixedToDepth(ffz); \
534 fogspan[i] = fffog / 256; \
547 /* here comes the heavy part.. (something for the compiler to chew on) */
548 #define INNER_LOOP( LEFT, RIGHT, Y ) \
550 CONST GLint n = RIGHT-LEFT; \
552 GLdepth zspan[MAX_WIDTH]; \
553 GLfixed fogspan[MAX_WIDTH]; \
554 GLchan rgba[MAX_WIDTH][4]; \
556 GLchan *dest = rgba[0]; \
557 ffs -= FIXED_HALF; /* off-by-one error? */ \
565 SPAN1(NEAREST_RGB;MODULATE,3); \
569 SPAN1(NEAREST_RGB_REPLACE,3); \
572 SPAN1(NEAREST_RGB;BLEND,3); \
575 SPAN1(NEAREST_RGB;ADD,3); \
577 default: /* unexpected env mode */ \
584 SPAN1(NEAREST_RGBA;MODULATE,4); \
587 SPAN1(NEAREST_RGBA;DECAL,4); \
590 SPAN1(NEAREST_RGBA;BLEND,4); \
593 SPAN1(NEAREST_RGBA;ADD,4); \
596 SPAN1(NEAREST_RGBA_REPLACE,4); \
598 default: /* unexpected env mode */ \
611 SPAN2(LINEAR_RGB;MODULATE,3); \
615 SPAN2(LINEAR_RGB;REPLACE,3); \
618 SPAN2(LINEAR_RGB;BLEND,3); \
621 SPAN2(LINEAR_RGB;ADD,3); \
623 default: /* unexpected env mode */ \
630 SPAN2(LINEAR_RGBA;MODULATE,4); \
633 SPAN2(LINEAR_RGBA;DECAL,4); \
636 SPAN2(LINEAR_RGBA;BLEND,4); \
639 SPAN2(LINEAR_RGBA;ADD,4); \
642 SPAN2(LINEAR_RGBA;REPLACE,4); \
644 default: /* unexpected env mode */ \
651 _mesa_write_rgba_span(ctx, n, LEFT, Y, zspan, \
654 /* explicit kill of variables: */ \
655 ffr = ffg = ffb = ffa = 0; \
659 #include "s_tritemp.h"
667 * Render an perspective corrected RGB/RGBA textured triangle.
668 * The Q (aka V in Mesa) coordinate must be zero such that the divide
669 * by interpolated Q/W comes out right.
671 * This function only renders textured triangles that use GL_NEAREST.
672 * Perspective correction works right.
674 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
675 * Send all questions and bug reports to him.
677 #if 0 /* XXX disabled because of texcoord interpolation errors */
678 static void near_persp_textured_triangle(GLcontext
*ctx
,
683 /* The BIAS value is used to shift negative values into positive values.
684 * Without this, negative texture values don't GL_REPEAT correctly at just
685 * below zero, because (int)-0.5 = 0 = (int)0.5. We're not going to worry
686 * about texture coords less than -BIAS. This could be fixed by using
687 * FLOORF etc. instead, but this is slower...
692 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
694 #define INTERP_ALPHA 1
697 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
698 struct gl_texture_object *obj = unit->Current2D; \
699 const GLint b = obj->BaseLevel; \
700 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
701 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
702 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
703 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
704 const GLint smask = (obj->Image[b]->Width - 1); \
705 const GLint tmask = (obj->Image[b]->Height - 1); \
706 const GLint format = obj->Image[b]->Format; \
707 const GLint envmode = unit->EnvMode; \
708 GLfloat sscale, tscale; \
709 GLfixed er, eg, eb, ea; \
710 GLint tr, tg, tb, ta; \
712 /* this shouldn't happen */ \
715 if (envmode == GL_BLEND || envmode == GL_ADD) { \
716 er = FloatToFixed(unit->EnvColor[RCOMP]); \
717 eg = FloatToFixed(unit->EnvColor[GCOMP]); \
718 eb = FloatToFixed(unit->EnvColor[BCOMP]); \
719 ea = FloatToFixed(unit->EnvColor[ACOMP]); \
725 #define OLD_SPAN(DO_TEX,COMP) \
726 for (i=0;i<n;i++) { \
727 GLfloat invQ = 1.0f / vv; \
728 GLint s = (int)(SS * invQ + BIAS) & smask; \
729 GLint t = (int)(TT * invQ + BIAS) & tmask; \
730 GLint pos = COMP * ((t << twidth_log2) + s); \
731 const GLchan *tex00 = texture + pos; \
732 zspan[i] = FixedToDepth(ffz); \
733 fogspan[i] = fffog / 256; \
747 #define X_Y_TEX_COORD(X, Y) ((((int)(X) & tmask) << twidth_log2) + ((int)(Y) & smask))
748 #define Y_X_TEX_COORD(X, Y) ((((int)(Y) & tmask) << twidth_log2) + ((int)(X) & smask))
750 #define SPAN1(DO_TEX, COMP, TEX_COORD) { \
751 GLfloat x_max = CEILF(x_tex); \
752 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \
753 GLint j, x_m = (int)x_max; \
755 if ((int)y_max != (int)y_tex) { \
756 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \
757 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
758 pos = COMP * TEX_COORD(x_tex, y_tex); \
759 DRAW_LINE (DO_TEX); \
762 nominator += vv * x_max; \
763 denominator -= dvdx * x_max; \
764 j = nominator / denominator; \
765 pos = COMP * TEX_COORD(x_tex, y_tex); \
766 DRAW_LINE (DO_TEX); \
770 if ((int)y_max != (int)y_tex) { \
771 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \
772 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
773 pos = COMP * TEX_COORD(x_m, y_tex); \
774 DRAW_LINE (DO_TEX); \
778 denominator -= dvdx; \
779 j = nominator/denominator; \
780 pos = COMP * TEX_COORD(x_m, y_tex); \
781 DRAW_LINE (DO_TEX); \
786 #define SPAN2(DO_TEX, COMP, TEX_COORD) { \
787 GLfloat x_max = CEILF (x_tex); \
788 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \
789 GLint j, x_m = (int) x_max; \
791 if ((int)y_max != (int)y_tex) { \
792 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \
793 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
794 pos = COMP * TEX_COORD(x_tex, y_tex); \
795 DRAW_LINE (DO_TEX); \
798 nominator += vv * x_max; \
799 denominator -= dvdx * x_max; \
800 j = nominator / denominator; \
801 pos = COMP * TEX_COORD(x_tex, y_tex); \
802 DRAW_LINE (DO_TEX); \
806 if ((int)y_max != (int)y_tex) { \
807 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \
808 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);\
809 pos = COMP * TEX_COORD(x_m, y_tex); \
810 DRAW_LINE (DO_TEX); \
814 denominator -= dvdx; \
815 j = nominator/denominator; \
816 pos = COMP * TEX_COORD(x_m, y_tex); \
817 DRAW_LINE (DO_TEX); \
822 #define SPAN3(DO_TEX, COMP, TEX_COORD) { \
823 GLfloat x_min = FLOORF (x_tex); \
824 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \
825 GLint j, x_m = (int)x_min; \
827 if ((int)y_min != (int)y_tex) { \
828 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \
829 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
830 pos = COMP * TEX_COORD(x_m, y_tex); \
831 DRAW_LINE (DO_TEX); \
834 nominator += vv*x_min; \
835 denominator -= dvdx*x_min; \
836 j = nominator / denominator; \
837 pos = COMP * TEX_COORD(x_m, y_tex); \
838 DRAW_LINE (DO_TEX); \
843 if ((int)y_min != (int)y_tex) { \
844 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \
845 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
846 pos = COMP * TEX_COORD(x_m, y_tex); \
847 DRAW_LINE (DO_TEX); \
851 denominator += dvdx; \
852 j = nominator/denominator; \
853 pos = COMP * TEX_COORD(x_m, y_tex); \
854 DRAW_LINE (DO_TEX); \
858 #define SPAN4(DO_TEX, COMP, TEX_COORD) \
860 GLfloat x_min = FLOORF(x_tex); \
861 GLint x_m = (int)x_min; \
862 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \
865 if ((int)y_min != (int)y_tex) { \
866 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \
867 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
868 pos = COMP * TEX_COORD(x_m, y_tex); \
869 DRAW_LINE (DO_TEX); \
872 nominator += vv * x_min; \
873 denominator -= dvdx * x_min; \
874 j = nominator / denominator; \
875 pos = COMP * TEX_COORD(x_m, y_tex); \
876 DRAW_LINE (DO_TEX); \
881 if ((int)y_min != (int)y_tex) { \
882 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \
883 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
884 pos = COMP * TEX_COORD(x_m, (y_tex)); \
885 DRAW_LINE (DO_TEX); \
889 denominator += dvdx; \
890 j = nominator/denominator; \
891 pos = COMP * TEX_COORD(x_m, y_tex); \
892 DRAW_LINE (DO_TEX); \
896 #define DRAW_LINE(DO_TEX) \
898 GLchan *tex00 = texture + pos; \
899 if (j>n || j<-100000) \
902 zspan[i] = FixedToDepth(ffz); \
903 fogspan[i] = fffog / 256; \
916 #define INNER_LOOP( LEFT, RIGHT, Y ) \
919 const GLint n = RIGHT-LEFT; \
920 GLdepth zspan[MAX_WIDTH]; \
921 GLfixed fogspan[MAX_WIDTH]; \
922 GLchan rgba[MAX_WIDTH][4]; \
923 (void)uu; /* please GCC */ \
925 GLchan *dest = rgba[0]; \
926 GLfloat SS = ss * sscale; \
927 GLfloat TT = tt * tscale; \
928 GLfloat dSdx = dsdx * sscale; \
929 GLfloat dTdx = dtdx * tscale; \
934 if (n<5) /* When line very short, setup-time > speed-gain. */ \
935 goto old_span; /* So: take old method */ \
938 dx_tex = (SS + n * dSdx) / (vv + n * dvdx) - x_tex, \
939 dy_tex = (TT + n * dTdx) / (vv + n * dvdx) - y_tex; \
940 /* Choose between walking over texture or over pixelline: */ \
941 /* If there are few texels, walk over texture otherwise */ \
942 /* walk over pixelarray. The quotient on the right side */ \
943 /* should give the timeratio needed to draw one texel in */ \
944 /* comparison to one pixel. Depends on CPU. */ \
945 if (dx_tex*dx_tex + dy_tex*dy_tex < (n*n)/16) { \
948 if (dx_tex*dx_tex > dy_tex*dy_tex) { \
949 /* if (FABSF(dx_tex) > FABSF(dy_tex)) */ \
950 GLfloat nominator = - SS - vv * BIAS; \
951 GLfloat denominator = dvdx * BIAS + dSdx; \
954 if (dy_tex != 0.0f) { \
955 dy_dx = dy_tex / dx_tex; \
956 dx_dy = 1.0f/dy_dx; \
960 if (dx_tex > 0.0f) { \
961 if (dy_tex > 0.0f) { \
966 SPAN1(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
970 SPAN1(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
973 SPAN1(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
976 SPAN1(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
978 default: /* unexpected env mode */ \
985 SPAN1(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
988 SPAN1(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
991 SPAN1(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
994 SPAN1(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
997 SPAN1(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
999 default: /* unexpected env mode */ \
1005 else { /* dy_tex <= 0.0f */ \
1008 switch (envmode) { \
1010 SPAN2(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1014 SPAN2(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1017 SPAN2(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1020 SPAN2(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1022 default: /* unexpected env mode */ \
1029 SPAN2(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1032 SPAN2(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1035 SPAN2(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1038 SPAN2(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1041 SPAN2(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1043 default: /* unexpected env mode */ \
1050 else { /* dx_tex < 0.0f */ \
1051 if (dy_tex > 0.0f) { \
1054 switch (envmode) { \
1056 SPAN3(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1060 SPAN3(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1063 SPAN3(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1066 SPAN3(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1068 default: /* unexpected env mode */ \
1075 SPAN3(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1078 SPAN3(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1081 SPAN3(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1084 SPAN3(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1087 SPAN3(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1089 default: /* unexpected env mode */ \
1095 else { /* dy_tex <= 0.0f */ \
1098 switch (envmode) { \
1100 SPAN4(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1104 SPAN4(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1107 SPAN4(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1110 SPAN4(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1119 SPAN4(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1122 SPAN4(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1125 SPAN4(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1128 SPAN4(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1131 SPAN4(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1133 default: /* unexpected env mode */ \
1141 else { /* FABSF(dx_tex) > FABSF(dy_tex) */ \
1145 GLfloat nominator, denominator; \
1146 if (dx_tex == 0.0f /* && dy_tex == 0.0f*/) \
1147 goto old_span; /* case so special, that use old */ \
1148 /* swap some x-values and y-values */ \
1151 swap = x_tex, x_tex = y_tex, y_tex = swap; \
1152 swap = dx_tex, dx_tex = dy_tex, dy_tex = swap; \
1153 nominator = - SS - vv * BIAS; \
1154 denominator = dvdx * BIAS + dSdx; \
1155 if (dy_tex != 0.0f) { \
1156 dy_dx = dy_tex / dx_tex; \
1157 dx_dy = 1.0f/dy_dx; \
1161 if (dx_tex > 0.0f) { \
1162 if (dy_tex > 0.0f) { \
1165 switch (envmode) { \
1167 SPAN1(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1171 SPAN1(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1174 SPAN1(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1177 SPAN1(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1179 default: /* unexpected env mode */ \
1186 SPAN1(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1189 SPAN1(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1192 SPAN1(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1195 SPAN1(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1198 SPAN1(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1206 else { /* dy_tex <= 0.0f */ \
1209 switch (envmode) { \
1211 SPAN2(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1215 SPAN2(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1218 SPAN2(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1221 SPAN2(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1230 SPAN2(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1233 SPAN2(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1236 SPAN2(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1239 SPAN2(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1242 SPAN2(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1251 else { /* dx_tex < 0.0f */ \
1252 if (dy_tex > 0.0f) { \
1255 switch (envmode) { \
1257 SPAN3(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1261 SPAN3(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1264 SPAN3(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1267 SPAN3(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1276 SPAN3(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1279 SPAN3(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1282 SPAN3(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1285 SPAN3(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1288 SPAN3(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1296 else { /* dy_tex <= 0.0f */ \
1299 switch (envmode) { \
1301 SPAN4(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1305 SPAN4(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1308 SPAN4(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1311 SPAN4(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1320 SPAN4(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1323 SPAN4(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1326 SPAN4(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1329 SPAN4(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1332 SPAN4(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1347 switch (envmode) { \
1349 OLD_SPAN(NEAREST_RGB;MODULATE,3); \
1353 OLD_SPAN(NEAREST_RGB_REPLACE,3); \
1356 OLD_SPAN(NEAREST_RGB;BLEND,3); \
1359 OLD_SPAN(NEAREST_RGB;ADD,3); \
1368 OLD_SPAN(NEAREST_RGBA;MODULATE,4); \
1371 OLD_SPAN(NEAREST_RGBA;DECAL,4); \
1374 OLD_SPAN(NEAREST_RGBA;BLEND,4); \
1377 OLD_SPAN(NEAREST_RGBA;ADD,4); \
1380 OLD_SPAN(NEAREST_RGBA_REPLACE,4); \
1388 _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1389 fogspan, rgba, GL_POLYGON); \
1390 ffr = ffg = ffb = ffa = 0; \
1394 #include "s_tritemp.h"
1400 #undef X_Y_TEX_COORD
1401 #undef Y_X_TEX_COORD
1409 * Render an perspective corrected RGB/RGBA textured triangle.
1410 * The Q (aka V in Mesa) coordinate must be zero such that the divide
1411 * by interpolated Q/W comes out right.
1413 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
1414 * Send all questions and bug reports to him.
1416 #if 0 /* XXX disabled because of texcoord interpolation errors */
1417 static void lin_persp_textured_triangle( GLcontext
*ctx
,
1420 const SWvertex
*v2
)
1423 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1424 #define INTERP_RGB 1
1425 #define INTERP_ALPHA 1
1426 #define INTERP_TEX 1
1427 #define SETUP_CODE \
1428 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
1429 struct gl_texture_object *obj = unit->Current2D; \
1430 const GLint b = obj->BaseLevel; \
1431 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
1432 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
1433 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
1434 GLchan *texture = obj->Image[b]->Data; \
1435 const GLint smask = (obj->Image[b]->Width - 1); \
1436 const GLint tmask = (obj->Image[b]->Height - 1); \
1437 const GLint format = obj->Image[b]->Format; \
1438 const GLint envmode = unit->EnvMode; \
1439 GLfloat sscale, tscale; \
1440 GLint comp, tbytesline, tsize; \
1441 GLfixed er, eg, eb, ea; \
1442 GLint tr, tg, tb, ta; \
1446 if (envmode == GL_BLEND || envmode == GL_ADD) { \
1447 er = FloatToFixed(unit->EnvColor[RCOMP]); \
1448 eg = FloatToFixed(unit->EnvColor[GCOMP]); \
1449 eb = FloatToFixed(unit->EnvColor[BCOMP]); \
1450 ea = FloatToFixed(unit->EnvColor[ACOMP]); \
1454 case GL_LUMINANCE: \
1455 case GL_INTENSITY: \
1458 case GL_LUMINANCE_ALPHA: \
1468 _mesa_problem(NULL, "Bad texture format in lin_persp_texture_triangle"); \
1471 sscale = FIXED_SCALE * twidth; \
1472 tscale = FIXED_SCALE * theight; \
1473 tbytesline = obj->Image[b]->Width * comp; \
1474 tsize = theight * tbytesline;
1477 #define SPAN(DO_TEX,COMP) \
1478 for (i=0;i<n;i++) { \
1479 GLfloat invQ = 1.0f / vv; \
1480 GLfixed ffs = (int)(SS * invQ); \
1481 GLfixed fft = (int)(TT * invQ); \
1482 GLint s = FixedToInt(ffs) & smask; \
1483 GLint t = FixedToInt(fft) & tmask; \
1484 GLint sf = ffs & FIXED_FRAC_MASK; \
1485 GLint tf = fft & FIXED_FRAC_MASK; \
1486 GLint si = FIXED_FRAC_MASK - sf; \
1487 GLint ti = FIXED_FRAC_MASK - tf; \
1488 GLint pos = COMP * ((t << twidth_log2) + s); \
1489 GLchan *tex00 = texture + pos; \
1490 GLchan *tex10 = tex00 + tbytesline; \
1491 GLchan *tex01 = tex00 + COMP; \
1492 GLchan *tex11 = tex10 + COMP; \
1498 tex01 -= tbytesline; \
1499 tex11 -= tbytesline; \
1501 zspan[i] = FixedToDepth(ffz); \
1502 fogspan[i] = fffog / 256; \
1516 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1519 const GLint n = RIGHT-LEFT; \
1520 GLdepth zspan[MAX_WIDTH]; \
1521 GLfixed fogspan[MAX_WIDTH]; \
1522 GLchan rgba[MAX_WIDTH][4]; \
1523 (void) uu; /* please GCC */ \
1525 GLfloat SS = ss * sscale; \
1526 GLfloat TT = tt * tscale; \
1527 GLfloat dSdx = dsdx * sscale; \
1528 GLfloat dTdx = dtdx * tscale; \
1529 GLchan *dest = rgba[0]; \
1530 SS -= 0.5f * FIXED_SCALE * vv; \
1531 TT -= 0.5f * FIXED_SCALE * vv; \
1534 switch (envmode) { \
1536 SPAN(LINEAR_RGB;MODULATE,3); \
1540 SPAN(LINEAR_RGB;REPLACE,3); \
1543 SPAN(LINEAR_RGB;BLEND,3); \
1546 SPAN(LINEAR_RGB;ADD,3); \
1553 switch (envmode) { \
1555 SPAN(LINEAR_RGBA;MODULATE,4); \
1558 SPAN(LINEAR_RGBA;DECAL,4); \
1561 SPAN(LINEAR_RGBA;BLEND,4); \
1564 SPAN(LINEAR_RGBA;REPLACE,4); \
1567 SPAN(LINEAR_RGBA;ADD,4); \
1569 default: /* unexpected env mode */ \
1573 _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1575 rgba, GL_POLYGON ); \
1576 ffr = ffg = ffb = ffa = 0; \
1580 #include "s_tritemp.h"
1587 * Render a smooth-shaded, textured, RGBA triangle.
1588 * Interpolate S,T,U with perspective correction, w/out mipmapping.
1589 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
1590 * R is already used for red.
1592 static void general_textured_triangle( GLcontext
*ctx
,
1595 const SWvertex
*v2
)
1598 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1599 #define INTERP_RGB 1
1600 #define INTERP_ALPHA 1
1601 #define INTERP_TEX 1
1602 #define SETUP_CODE \
1603 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1606 r = v2->color[RCOMP]; \
1607 g = v2->color[GCOMP]; \
1608 b = v2->color[BCOMP]; \
1609 a = v2->color[ACOMP]; \
1611 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1614 const GLint n = RIGHT-LEFT; \
1615 GLdepth zspan[MAX_WIDTH]; \
1616 GLfixed fogspan[MAX_WIDTH]; \
1617 GLchan rgba[MAX_WIDTH][4]; \
1618 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
1621 for (i=0;i<n;i++) { \
1622 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1623 zspan[i] = FixedToDepth(ffz); \
1624 fogspan[i] = fffog / 256; \
1625 rgba[i][RCOMP] = r; \
1626 rgba[i][GCOMP] = g; \
1627 rgba[i][BCOMP] = b; \
1628 rgba[i][ACOMP] = a; \
1641 for (i=0;i<n;i++) { \
1642 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1643 zspan[i] = FixedToDepth(ffz); \
1644 rgba[i][RCOMP] = FixedToInt(ffr); \
1645 rgba[i][GCOMP] = FixedToInt(ffg); \
1646 rgba[i][BCOMP] = FixedToInt(ffb); \
1647 rgba[i][ACOMP] = FixedToInt(ffa); \
1648 fogspan[i] = fffog / 256; \
1664 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1667 NULL, GL_POLYGON ); \
1671 #include "s_tritemp.h"
1676 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1677 * color interpolation.
1678 * Interpolate S,T,U with perspective correction, w/out mipmapping.
1679 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
1680 * R is already used for red.
1682 static void general_textured_spec_triangle1( GLcontext
*ctx
,
1686 GLdepth zspan
[MAX_WIDTH
],
1687 GLfixed fogspan
[MAX_WIDTH
],
1688 GLchan rgba
[MAX_WIDTH
][4],
1689 GLchan spec
[MAX_WIDTH
][4] )
1692 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1693 #define INTERP_RGB 1
1694 #define INTERP_SPEC 1
1695 #define INTERP_ALPHA 1
1696 #define INTERP_TEX 1
1697 #define SETUP_CODE \
1698 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1699 GLint r, g, b, a, sr, sg, sb; \
1701 r = v2->color[RCOMP]; \
1702 g = v2->color[GCOMP]; \
1703 b = v2->color[BCOMP]; \
1704 a = v2->color[ACOMP]; \
1705 sr = v2->specular[RCOMP]; \
1706 sg = v2->specular[GCOMP]; \
1707 sb = v2->specular[BCOMP]; \
1709 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1712 const GLint n = RIGHT-LEFT; \
1713 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
1716 for (i=0;i<n;i++) { \
1717 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1718 zspan[i] = FixedToDepth(ffz); \
1719 fogspan[i] = fffog / 256; \
1720 rgba[i][RCOMP] = r; \
1721 rgba[i][GCOMP] = g; \
1722 rgba[i][BCOMP] = b; \
1723 rgba[i][ACOMP] = a; \
1724 spec[i][RCOMP] = sr; \
1725 spec[i][GCOMP] = sg; \
1726 spec[i][BCOMP] = sb; \
1739 for (i=0;i<n;i++) { \
1740 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1741 zspan[i] = FixedToDepth(ffz); \
1742 fogspan[i] = fffog / 256; \
1743 rgba[i][RCOMP] = FixedToInt(ffr); \
1744 rgba[i][GCOMP] = FixedToInt(ffg); \
1745 rgba[i][BCOMP] = FixedToInt(ffb); \
1746 rgba[i][ACOMP] = FixedToInt(ffa); \
1747 spec[i][RCOMP] = FixedToInt(ffsr); \
1748 spec[i][GCOMP] = FixedToInt(ffsg); \
1749 spec[i][BCOMP] = FixedToInt(ffsb); \
1768 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, \
1770 s, t, u, NULL, rgba, \
1771 (CONST GLchan (*)[4]) spec, \
1776 #include "s_tritemp.h"
1781 * Render a smooth-shaded, textured, RGBA triangle.
1782 * Interpolate S,T,U with perspective correction and compute lambda for
1783 * each fragment. Lambda is used to determine whether to use the
1784 * minification or magnification filter. If minification and using
1785 * mipmaps, lambda is also used to select the texture level of detail.
1787 static void lambda_textured_triangle1( GLcontext
*ctx
,
1791 GLfloat s
[MAX_WIDTH
],
1792 GLfloat t
[MAX_WIDTH
],
1793 GLfloat u
[MAX_WIDTH
] )
1796 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1797 #define INTERP_RGB 1
1798 #define INTERP_ALPHA 1
1799 #define INTERP_LAMBDA 1
1800 #define INTERP_TEX 1
1802 #define SETUP_CODE \
1803 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1804 const GLint baseLevel = obj->BaseLevel; \
1805 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1806 const GLfloat twidth = (GLfloat) texImage->Width; \
1807 const GLfloat theight = (GLfloat) texImage->Height; \
1808 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1811 r = v2->color[RCOMP]; \
1812 g = v2->color[GCOMP]; \
1813 b = v2->color[BCOMP]; \
1814 a = v2->color[ACOMP]; \
1817 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1820 const GLint n = RIGHT-LEFT; \
1821 GLdepth zspan[MAX_WIDTH]; \
1822 GLfixed fogspan[MAX_WIDTH]; \
1823 GLchan rgba[MAX_WIDTH][4]; \
1824 GLfloat lambda[MAX_WIDTH]; \
1827 for (i=0;i<n;i++) { \
1828 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1829 zspan[i] = FixedToDepth(ffz); \
1830 fogspan[i] = fffog / 256; \
1831 rgba[i][RCOMP] = r; \
1832 rgba[i][GCOMP] = g; \
1833 rgba[i][BCOMP] = b; \
1834 rgba[i][ACOMP] = a; \
1838 COMPUTE_LAMBDA(lambda[i], invQ); \
1848 for (i=0;i<n;i++) { \
1849 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1850 zspan[i] = FixedToDepth(ffz); \
1851 fogspan[i] = fffog / 256; \
1852 rgba[i][RCOMP] = FixedToInt(ffr); \
1853 rgba[i][GCOMP] = FixedToInt(ffg); \
1854 rgba[i][BCOMP] = FixedToInt(ffb); \
1855 rgba[i][ACOMP] = FixedToInt(ffa); \
1859 COMPUTE_LAMBDA(lambda[i], invQ); \
1872 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1874 rgba, NULL, GL_POLYGON ); \
1878 #include "s_tritemp.h"
1883 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1885 * Interpolate S,T,U with perspective correction and compute lambda for
1886 * each fragment. Lambda is used to determine whether to use the
1887 * minification or magnification filter. If minification and using
1888 * mipmaps, lambda is also used to select the texture level of detail.
1890 static void lambda_textured_spec_triangle1( GLcontext
*ctx
,
1894 GLfloat s
[MAX_WIDTH
],
1895 GLfloat t
[MAX_WIDTH
],
1896 GLfloat u
[MAX_WIDTH
] )
1899 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1900 #define INTERP_RGB 1
1901 #define INTERP_SPEC 1
1902 #define INTERP_ALPHA 1
1903 #define INTERP_TEX 1
1904 #define INTERP_LAMBDA 1
1906 #define SETUP_CODE \
1907 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1908 const GLint baseLevel = obj->BaseLevel; \
1909 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1910 const GLfloat twidth = (GLfloat) texImage->Width; \
1911 const GLfloat theight = (GLfloat) texImage->Height; \
1912 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1913 GLint r, g, b, a, sr, sg, sb; \
1915 r = v2->color[RCOMP]; \
1916 g = v2->color[GCOMP]; \
1917 b = v2->color[BCOMP]; \
1918 a = v2->color[ACOMP]; \
1919 sr = v2->specular[RCOMP]; \
1920 sg = v2->specular[GCOMP]; \
1921 sb = v2->specular[BCOMP]; \
1924 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1927 const GLint n = RIGHT-LEFT; \
1928 GLdepth zspan[MAX_WIDTH]; \
1929 GLfixed fogspan[MAX_WIDTH]; \
1930 GLchan spec[MAX_WIDTH][4]; \
1931 GLchan rgba[MAX_WIDTH][4]; \
1932 GLfloat lambda[MAX_WIDTH]; \
1935 for (i=0;i<n;i++) { \
1936 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1937 zspan[i] = FixedToDepth(ffz); \
1938 fogspan[i] = fffog / 256; \
1939 rgba[i][RCOMP] = r; \
1940 rgba[i][GCOMP] = g; \
1941 rgba[i][BCOMP] = b; \
1942 rgba[i][ACOMP] = a; \
1943 spec[i][RCOMP] = sr; \
1944 spec[i][GCOMP] = sg; \
1945 spec[i][BCOMP] = sb; \
1949 COMPUTE_LAMBDA(lambda[i], invQ); \
1959 for (i=0;i<n;i++) { \
1960 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1961 zspan[i] = FixedToDepth(ffz); \
1962 fogspan[i] = fffog / 256; \
1963 rgba[i][RCOMP] = FixedToInt(ffr); \
1964 rgba[i][GCOMP] = FixedToInt(ffg); \
1965 rgba[i][BCOMP] = FixedToInt(ffb); \
1966 rgba[i][ACOMP] = FixedToInt(ffa); \
1967 spec[i][RCOMP] = FixedToInt(ffsr); \
1968 spec[i][GCOMP] = FixedToInt(ffsg); \
1969 spec[i][BCOMP] = FixedToInt(ffsb); \
1973 COMPUTE_LAMBDA(lambda[i], invQ); \
1989 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1991 rgba, (CONST GLchan (*)[4]) spec, \
1996 #include "s_tritemp.h"
2001 * This is the big one!
2002 * Interpolate Z, RGB, Alpha, and two sets of texture coordinates.
2006 lambda_multitextured_triangle1( GLcontext
*ctx
,
2010 GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
2011 GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
2012 GLfloat u
[MAX_TEXTURE_UNITS
][MAX_WIDTH
])
2015 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2016 #define INTERP_RGB 1
2017 #define INTERP_ALPHA 1
2018 #define INTERP_MULTITEX 1
2019 #define INTERP_MULTILAMBDA 1
2021 #define SETUP_CODE \
2022 GLchan rgba[MAX_WIDTH][4]; \
2023 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
2024 GLfloat twidth[MAX_TEXTURE_UNITS], theight[MAX_TEXTURE_UNITS]; \
2034 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \
2035 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2036 const struct gl_texture_object *obj = ctx->Texture.Unit[unit]._Current; \
2037 const GLint baseLevel = obj->BaseLevel; \
2038 const struct gl_texture_image *texImage = obj->Image[baseLevel];\
2039 twidth[unit] = (GLfloat) texImage->Width; \
2040 theight[unit] = (GLfloat) texImage->Height; \
2045 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2048 const GLint n = RIGHT-LEFT; \
2049 GLdepth zspan[MAX_WIDTH]; \
2050 GLfixed fogspan[MAX_WIDTH]; \
2051 GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; \
2054 for (i=0;i<n;i++) { \
2056 zspan[i] = FixedToDepth(ffz); \
2057 fogspan[i] = fffog / 256; \
2060 rgba[i][RCOMP] = r; \
2061 rgba[i][GCOMP] = g; \
2062 rgba[i][BCOMP] = b; \
2063 rgba[i][ACOMP] = a; \
2064 for (unit=0; unit < ctx->Const.MaxTextureUnits; unit++) {\
2065 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2066 GLdouble invQ = 1.0 / vv[unit]; \
2067 s[unit][i] = ss[unit] * invQ; \
2068 t[unit][i] = tt[unit] * invQ; \
2069 u[unit][i] = uu[unit] * invQ; \
2070 COMPUTE_MULTILAMBDA(lambda[unit][i], invQ, unit); \
2071 ss[unit] += dsdx[unit]; \
2072 tt[unit] += dtdx[unit]; \
2073 uu[unit] += dudx[unit]; \
2074 vv[unit] += dvdx[unit]; \
2079 else { /* smooth shade */ \
2080 for (i=0;i<n;i++) { \
2082 zspan[i] = FixedToDepth(ffz); \
2083 fogspan[i] = fffog / 256; \
2086 rgba[i][RCOMP] = FixedToInt(ffr); \
2087 rgba[i][GCOMP] = FixedToInt(ffg); \
2088 rgba[i][BCOMP] = FixedToInt(ffb); \
2089 rgba[i][ACOMP] = FixedToInt(ffa); \
2094 for (unit=0; unit < ctx->Const.MaxTextureUnits; unit++) {\
2095 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2096 GLdouble invQ = 1.0 / vv[unit]; \
2097 s[unit][i] = ss[unit] * invQ; \
2098 t[unit][i] = tt[unit] * invQ; \
2099 u[unit][i] = uu[unit] * invQ; \
2100 COMPUTE_MULTILAMBDA(lambda[unit][i], invQ, unit); \
2101 ss[unit] += dsdx[unit]; \
2102 tt[unit] += dtdx[unit]; \
2103 uu[unit] += dudx[unit]; \
2104 vv[unit] += dvdx[unit]; \
2109 _mesa_write_multitexture_span(ctx, n, LEFT, Y, zspan, fogspan, \
2110 (const GLfloat (*)[MAX_WIDTH]) s,\
2111 (const GLfloat (*)[MAX_WIDTH]) t,\
2112 (const GLfloat (*)[MAX_WIDTH]) u,\
2113 (GLfloat (*)[MAX_WIDTH]) lambda, \
2114 rgba, NULL, GL_POLYGON ); \
2118 #include "s_tritemp.h"
2123 * These wrappers are needed to deal with the 32KB / stack frame limit
2124 * on Mac / PowerPC systems.
2127 static void general_textured_spec_triangle(GLcontext
*ctx
,
2130 const SWvertex
*v2
)
2132 GLdepth zspan
[MAX_WIDTH
];
2133 GLfixed fogspan
[MAX_WIDTH
];
2134 GLchan rgba
[MAX_WIDTH
][4], spec
[MAX_WIDTH
][4];
2135 general_textured_spec_triangle1(ctx
,v0
,v1
,v2
,zspan
,fogspan
,rgba
,spec
);
2138 static void lambda_textured_triangle( GLcontext
*ctx
,
2141 const SWvertex
*v2
)
2143 GLfloat s
[MAX_WIDTH
], t
[MAX_WIDTH
], u
[MAX_WIDTH
];
2144 lambda_textured_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2147 static void lambda_textured_spec_triangle( GLcontext
*ctx
,
2150 const SWvertex
*v2
)
2152 GLfloat s
[MAX_WIDTH
];
2153 GLfloat t
[MAX_WIDTH
];
2154 GLfloat u
[MAX_WIDTH
];
2155 lambda_textured_spec_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2159 static void lambda_multitextured_triangle( GLcontext
*ctx
,
2162 const SWvertex
*v2
)
2165 GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
2166 GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
2167 DEFMARRAY(GLfloat
,u
,MAX_TEXTURE_UNITS
,MAX_WIDTH
);
2168 CHECKARRAY(u
,return);
2170 lambda_multitextured_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2177 static void occlusion_zless_triangle( GLcontext
*ctx
,
2180 const SWvertex
*v2
)
2182 if (ctx
->OcclusionResult
) {
2186 #define DO_OCCLUSION_TEST
2188 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2189 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2192 const GLint len = RIGHT-LEFT; \
2193 for (i=0;i<len;i++) { \
2194 GLdepth z = FixedToDepth(ffz); \
2196 if (z < zRow[i]) { \
2197 ctx->OcclusionResult = GL_TRUE; \
2203 #include "s_tritemp.h"
2208 void _swrast_add_spec_terms_triangle( GLcontext
*ctx
,
2211 const SWvertex
*v2
)
2213 SWvertex
*ncv0
= (SWvertex
*)v0
; /* drop const qualifier */
2214 SWvertex
*ncv1
= (SWvertex
*)v1
;
2215 SWvertex
*ncv2
= (SWvertex
*)v2
;
2217 COPY_CHAN4( c
[0], ncv0
->color
);
2218 COPY_CHAN4( c
[1], ncv1
->color
);
2219 COPY_CHAN4( c
[2], ncv2
->color
);
2220 ACC_3V( ncv0
->color
, ncv0
->specular
);
2221 ACC_3V( ncv1
->color
, ncv1
->specular
);
2222 ACC_3V( ncv2
->color
, ncv2
->specular
);
2223 SWRAST_CONTEXT(ctx
)->SpecTriangle( ctx
, ncv0
, ncv1
, ncv2
);
2224 COPY_CHAN4( ncv0
->color
, c
[0] );
2225 COPY_CHAN4( ncv1
->color
, c
[1] );
2226 COPY_CHAN4( ncv2
->color
, c
[2] );
2232 # define dputs(s) puts(s)
2240 * Determine which triangle rendering function to use given the current
2241 * rendering context.
2243 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
2244 * remove tests to this code.
2247 _swrast_choose_triangle( GLcontext
*ctx
)
2249 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
2250 const GLboolean rgbmode
= ctx
->Visual
.rgbMode
;
2252 if (ctx
->RenderMode
==GL_RENDER
) {
2254 if (ctx
->Polygon
.SmoothFlag
) {
2255 _mesa_set_aa_triangle_function(ctx
);
2256 ASSERT(swrast
->Triangle
);
2260 if (ctx
->Depth
.OcclusionTest
&&
2262 ctx
->Depth
.Mask
== GL_FALSE
&&
2263 ctx
->Depth
.Func
== GL_LESS
&&
2264 !ctx
->Stencil
.Enabled
) {
2266 ctx
->Color
.ColorMask
[0] == 0 &&
2267 ctx
->Color
.ColorMask
[1] == 0 &&
2268 ctx
->Color
.ColorMask
[2] == 0 &&
2269 ctx
->Color
.ColorMask
[3] == 0)
2271 (!rgbmode
&& ctx
->Color
.IndexMask
== 0)) {
2272 dputs("occlusion_test_triangle");
2273 swrast
->Triangle
= occlusion_zless_triangle
;
2278 if (ctx
->Texture
._ReallyEnabled
) {
2279 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
2280 GLint format
, filter
;
2281 const struct gl_texture_object
*current2Dtex
= ctx
->Texture
.Unit
[0].Current2D
;
2282 const struct gl_texture_image
*image
;
2283 /* First see if we can used an optimized 2-D texture function */
2284 if (ctx
->Texture
._ReallyEnabled
==TEXTURE0_2D
2285 && current2Dtex
->WrapS
==GL_REPEAT
2286 && current2Dtex
->WrapT
==GL_REPEAT
2287 && ((image
= current2Dtex
->Image
[current2Dtex
->BaseLevel
]) != 0) /* correct! */
2289 && ((format
= image
->Format
)==GL_RGB
|| format
==GL_RGBA
)
2290 && image
->Type
== CHAN_TYPE
2291 && (filter
= current2Dtex
->MinFilter
)==current2Dtex
->MagFilter
2292 /* ==> current2Dtex->MinFilter != GL_XXX_MIPMAP_XXX */
2293 && ctx
->Light
.Model
.ColorControl
==GL_SINGLE_COLOR
2294 && ctx
->Texture
.Unit
[0].EnvMode
!=GL_COMBINE_EXT
) {
2296 if (ctx
->Hint
.PerspectiveCorrection
==GL_FASTEST
) {
2298 if (filter
==GL_NEAREST
2300 && (ctx
->Texture
.Unit
[0].EnvMode
==GL_REPLACE
2301 || ctx
->Texture
.Unit
[0].EnvMode
==GL_DECAL
)
2302 && ((swrast
->_RasterMask
==DEPTH_BIT
2303 && ctx
->Depth
.Func
==GL_LESS
2304 && ctx
->Depth
.Mask
==GL_TRUE
)
2305 || swrast
->_RasterMask
==0)
2306 && ctx
->Polygon
.StippleFlag
==GL_FALSE
) {
2308 if (swrast
->_RasterMask
==DEPTH_BIT
) {
2309 swrast
->Triangle
= simple_z_textured_triangle
;
2310 dputs("simple_z_textured_triangle");
2313 swrast
->Triangle
= simple_textured_triangle
;
2314 dputs("simple_textured_triangle");
2318 if (ctx
->Texture
.Unit
[0].EnvMode
==GL_ADD
) {
2319 swrast
->Triangle
= general_textured_triangle
;
2320 dputs("general_textured_triangle");
2323 swrast
->Triangle
= affine_textured_triangle
;
2324 dputs("affine_textured_triangle");
2329 #if 00 /* XXX these function have problems with texture coord interpolation */
2330 if (filter
==GL_NEAREST
) {
2331 swrast
->Triangle
= near_persp_textured_triangle
;
2332 dputs("near_persp_textured_triangle");
2335 swrast
->Triangle
= lin_persp_textured_triangle
;
2336 dputs("lin_persp_textured_triangle");
2339 swrast
->Triangle
= general_textured_triangle
;
2343 /* More complicated textures (mipmap, multi-tex, sep specular) */
2344 GLboolean needLambda
;
2345 /* if mag filter != min filter we need to compute lambda */
2346 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
2347 if (obj
&& obj
->MinFilter
!= obj
->MagFilter
)
2348 needLambda
= GL_TRUE
;
2350 needLambda
= GL_FALSE
;
2351 if (swrast
->_MultiTextureEnabled
) {
2352 swrast
->Triangle
= lambda_multitextured_triangle
;
2353 dputs("lambda_multitextured_triangle");
2355 else if (ctx
->_TriangleCaps
& DD_SEPERATE_SPECULAR
) {
2356 /* separate specular color interpolation */
2358 swrast
->Triangle
= lambda_textured_spec_triangle
;
2359 dputs("lambda_textured_spec_triangle");
2362 swrast
->Triangle
= general_textured_spec_triangle
;
2363 dputs("general_textured_spec_triangle");
2368 swrast
->Triangle
= lambda_textured_triangle
;
2369 dputs("lambda_textured_triangle");
2372 swrast
->Triangle
= general_textured_triangle
;
2373 dputs("general_textured_triangle");
2379 if (ctx
->Light
.ShadeModel
==GL_SMOOTH
) {
2380 /* smooth shaded, no texturing, stippled or some raster ops */
2382 dputs("smooth_rgba_triangle");
2383 swrast
->Triangle
= smooth_rgba_triangle
;
2386 dputs("smooth_ci_triangle");
2387 swrast
->Triangle
= smooth_ci_triangle
;
2391 /* flat shaded, no texturing, stippled or some raster ops */
2393 dputs("flat_rgba_triangle");
2394 swrast
->Triangle
= flat_rgba_triangle
;
2397 dputs("flat_ci_triangle");
2398 swrast
->Triangle
= flat_ci_triangle
;
2403 else if (ctx
->RenderMode
==GL_FEEDBACK
) {
2404 swrast
->Triangle
= _mesa_feedback_triangle
;
2407 /* GL_SELECT mode */
2408 swrast
->Triangle
= _mesa_select_triangle
;