1 /* $Id: s_triangle.c,v 1.10 2001/01/29 18:51:25 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.
43 #include "s_aatriangle.h"
44 #include "s_context.h"
46 #include "s_feedback.h"
48 #include "s_triangle.h"
50 GLboolean
gl_cull_triangle( GLcontext
*ctx
,
55 GLfloat ex
= v1
->win
[0] - v0
->win
[0];
56 GLfloat ey
= v1
->win
[1] - v0
->win
[1];
57 GLfloat fx
= v2
->win
[0] - v0
->win
[0];
58 GLfloat fy
= v2
->win
[1] - v0
->win
[1];
59 GLfloat c
= ex
*fy
-ey
*fx
;
61 if (c
* SWRAST_CONTEXT(ctx
)->_backface_sign
> 0)
69 * Render a flat-shaded color index triangle.
71 static void flat_ci_triangle( GLcontext
*ctx
,
78 #define INNER_LOOP( LEFT, RIGHT, Y ) \
80 const GLint n = RIGHT-LEFT; \
82 GLdepth zspan[MAX_WIDTH]; \
83 GLfixed fogspan[MAX_WIDTH]; \
86 zspan[i] = FixedToDepth(ffz); \
88 fogspan[i] = fffog / 256; \
91 gl_write_monoindex_span( ctx, n, LEFT, Y, zspan, \
92 fogspan, v0->index, GL_POLYGON ); \
96 #include "s_tritemp.h"
102 * Render a smooth-shaded color index triangle.
104 static void smooth_ci_triangle( GLcontext
*ctx
,
110 #define INTERP_INDEX 1
112 #define INNER_LOOP( LEFT, RIGHT, Y ) \
114 const GLint n = RIGHT-LEFT; \
116 GLdepth zspan[MAX_WIDTH]; \
117 GLfixed fogspan[MAX_WIDTH]; \
118 GLuint index[MAX_WIDTH]; \
120 for (i=0;i<n;i++) { \
121 zspan[i] = FixedToDepth(ffz); \
123 index[i] = FixedToInt(ffi); \
125 fogspan[i] = fffog / 256; \
128 gl_write_index_span( ctx, n, LEFT, Y, zspan, fogspan, \
129 index, GL_POLYGON ); \
133 #include "s_tritemp.h"
139 * Render a flat-shaded RGBA triangle.
141 static void flat_rgba_triangle( GLcontext
*ctx
,
147 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
149 #define INNER_LOOP( LEFT, RIGHT, Y ) \
151 const GLint n = RIGHT-LEFT; \
153 GLdepth zspan[MAX_WIDTH]; \
154 GLfixed fogspan[MAX_WIDTH]; \
156 for (i=0;i<n;i++) { \
157 zspan[i] = FixedToDepth(ffz); \
159 fogspan[i] = fffog / 256; \
162 gl_write_monocolor_span( ctx, n, LEFT, Y, zspan, \
163 fogspan, v2->color, \
168 #include "s_tritemp.h"
170 ASSERT(!ctx
->Texture
._ReallyEnabled
); /* texturing must be off */
171 ASSERT(ctx
->Light
.ShadeModel
==GL_FLAT
);
177 * Render a smooth-shaded RGBA triangle.
179 static void smooth_rgba_triangle( GLcontext
*ctx
,
186 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
188 #define INTERP_ALPHA 1
190 #define INNER_LOOP( LEFT, RIGHT, Y ) \
192 const GLint n = RIGHT-LEFT; \
194 GLdepth zspan[MAX_WIDTH]; \
195 GLchan rgba[MAX_WIDTH][4]; \
196 GLfixed fogspan[MAX_WIDTH]; \
198 for (i=0;i<n;i++) { \
199 zspan[i] = FixedToDepth(ffz); \
200 rgba[i][RCOMP] = FixedToInt(ffr); \
201 rgba[i][GCOMP] = FixedToInt(ffg); \
202 rgba[i][BCOMP] = FixedToInt(ffb); \
203 rgba[i][ACOMP] = FixedToInt(ffa); \
204 fogspan[i] = fffog / 256; \
212 gl_write_rgba_span( ctx, n, LEFT, Y, \
213 (CONST GLdepth *) zspan, \
215 rgba, GL_POLYGON ); \
219 #include "s_tritemp.h"
221 ASSERT(!ctx
->Texture
._ReallyEnabled
); /* texturing must be off */
222 ASSERT(ctx
->Light
.ShadeModel
==GL_SMOOTH
);
227 * Render an RGB, GL_DECAL, textured triangle.
228 * Interpolate S,T only w/out mipmapping or perspective correction.
232 static void simple_textured_triangle( GLcontext
*ctx
,
237 #define INTERP_INT_TEX 1
238 #define S_SCALE twidth
239 #define T_SCALE theight
241 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
242 GLint b = obj->BaseLevel; \
243 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
244 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
245 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
246 GLchan *texture = obj->Image[b]->Data; \
247 GLint smask = obj->Image[b]->Width - 1; \
248 GLint tmask = obj->Image[b]->Height - 1; \
250 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
252 texture = obj->Image[b]->Data; \
256 #define INNER_LOOP( LEFT, RIGHT, Y ) \
258 CONST GLint n = RIGHT-LEFT; \
260 GLchan rgb[MAX_WIDTH][3]; \
262 ffs -= FIXED_HALF; /* off-by-one error? */ \
264 for (i=0;i<n;i++) { \
265 GLint s = FixedToInt(ffs) & smask; \
266 GLint t = FixedToInt(fft) & tmask; \
267 GLint pos = (t << twidth_log2) + s; \
268 pos = pos + pos + pos; /* multiply by 3 */ \
269 rgb[i][RCOMP] = texture[pos]; \
270 rgb[i][GCOMP] = texture[pos+1]; \
271 rgb[i][BCOMP] = texture[pos+2]; \
275 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
276 (CONST GLchan (*)[3]) rgb, NULL ); \
280 #include "s_tritemp.h"
285 * Render an RGB, GL_DECAL, textured triangle.
286 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
287 * perspective correction.
291 static void simple_z_textured_triangle( GLcontext
*ctx
,
297 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
298 #define INTERP_INT_TEX 1
299 #define S_SCALE twidth
300 #define T_SCALE theight
302 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
303 GLint b = obj->BaseLevel; \
304 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
305 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
306 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
307 GLchan *texture = obj->Image[b]->Data; \
308 GLint smask = obj->Image[b]->Width - 1; \
309 GLint tmask = obj->Image[b]->Height - 1; \
311 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
313 texture = obj->Image[b]->Data; \
317 #define INNER_LOOP( LEFT, RIGHT, Y ) \
319 CONST GLint n = RIGHT-LEFT; \
321 GLchan rgb[MAX_WIDTH][3]; \
322 GLubyte mask[MAX_WIDTH]; \
325 ffs -= FIXED_HALF; /* off-by-one error? */ \
327 for (i=0;i<n;i++) { \
328 GLdepth z = FixedToDepth(ffz); \
330 GLint s = FixedToInt(ffs) & smask; \
331 GLint t = FixedToInt(fft) & tmask; \
332 GLint pos = (t << twidth_log2) + s; \
333 pos = pos + pos + pos; /* multiply by 3 */ \
334 rgb[i][RCOMP] = texture[pos]; \
335 rgb[i][GCOMP] = texture[pos+1]; \
336 rgb[i][BCOMP] = texture[pos+2]; \
347 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
348 (CONST GLchan (*)[3]) rgb, mask ); \
352 #include "s_tritemp.h"
358 * Render an RGB/RGBA textured triangle without perspective correction.
360 static void affine_textured_triangle( GLcontext
*ctx
,
366 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
368 #define INTERP_ALPHA 1
369 #define INTERP_INT_TEX 1
370 #define S_SCALE twidth
371 #define T_SCALE theight
373 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
374 struct gl_texture_object *obj = unit->Current2D; \
375 GLint b = obj->BaseLevel; \
376 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
377 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
378 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
379 GLchan *texture = obj->Image[b]->Data; \
380 GLint smask = obj->Image[b]->Width - 1; \
381 GLint tmask = obj->Image[b]->Height - 1; \
382 GLint format = obj->Image[b]->Format; \
383 GLint filter = obj->MinFilter; \
384 GLint envmode = unit->EnvMode; \
385 GLint comp, tbytesline, tsize; \
386 GLfixed er, eg, eb, ea; \
387 GLint tr, tg, tb, ta; \
389 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
391 texture = obj->Image[b]->Data; \
394 if (envmode == GL_BLEND || envmode == GL_ADD) { \
395 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
396 er = FloatToFixed(unit->EnvColor[0]); \
397 eg = FloatToFixed(unit->EnvColor[1]); \
398 eb = FloatToFixed(unit->EnvColor[2]); \
399 ea = FloatToFixed(unit->EnvColor[3]); \
407 case GL_LUMINANCE_ALPHA: \
417 gl_problem(NULL, "Bad texture format in affine_texture_triangle");\
420 tbytesline = obj->Image[b]->Width * comp; \
421 tsize = theight * tbytesline;
424 /* Instead of defining a function for each mode, a test is done
425 * between the outer and inner loops. This is to reduce code size
426 * and complexity. Observe that an optimizing compiler kills
427 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
430 #define NEAREST_RGB \
437 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
438 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
439 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
440 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
441 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
442 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
445 #define NEAREST_RGBA \
451 #define LINEAR_RGBA \
452 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
453 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
454 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
455 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
456 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
457 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
458 ta = (ti * (si * tex00[3] + sf * tex01[3]) + \
459 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
462 dest[0] = ffr * (tr + 1) >> (FIXED_SHIFT + 8); \
463 dest[1] = ffg * (tg + 1) >> (FIXED_SHIFT + 8); \
464 dest[2] = ffb * (tb + 1) >> (FIXED_SHIFT + 8); \
465 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
468 dest[0] = ((0xff - ta) * ffr + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
469 dest[1] = ((0xff - ta) * ffg + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
470 dest[2] = ((0xff - ta) * ffb + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
471 dest[3] = FixedToInt(ffa)
474 dest[0] = ((0xff - tr) * ffr + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
475 dest[1] = ((0xff - tg) * ffg + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
476 dest[2] = ((0xff - tb) * ffb + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
477 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
486 dest[0] = ((ffr << 8) + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
487 dest[1] = ((ffg << 8) + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
488 dest[2] = ((ffb << 8) + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
489 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
493 #define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE
495 #define NEAREST_RGBA_REPLACE *(GLint *)dest = *(GLint *)tex00
497 #define SPAN1(DO_TEX,COMP) \
498 for (i=0;i<n;i++) { \
499 GLint s = FixedToInt(ffs) & smask; \
500 GLint t = FixedToInt(fft) & tmask; \
501 GLint pos = (t << twidth_log2) + s; \
502 GLchan *tex00 = texture + COMP * pos; \
503 zspan[i] = FixedToDepth(ffz); \
504 fogspan[i] = fffog / 256; \
517 #define SPAN2(DO_TEX,COMP) \
518 for (i=0;i<n;i++) { \
519 GLint s = FixedToInt(ffs) & smask; \
520 GLint t = FixedToInt(fft) & tmask; \
521 GLint sf = ffs & FIXED_FRAC_MASK; \
522 GLint tf = fft & FIXED_FRAC_MASK; \
523 GLint si = FIXED_FRAC_MASK - sf; \
524 GLint ti = FIXED_FRAC_MASK - tf; \
525 GLint pos = (t << twidth_log2) + s; \
526 GLchan *tex00 = texture + COMP * pos; \
527 GLchan *tex10 = tex00 + tbytesline; \
528 GLchan *tex01 = tex00 + COMP; \
529 GLchan *tex11 = tex10 + COMP; \
535 tex01 -= tbytesline; \
536 tex11 -= tbytesline; \
538 zspan[i] = FixedToDepth(ffz); \
539 fogspan[i] = fffog / 256; \
552 /* here comes the heavy part.. (something for the compiler to chew on) */
553 #define INNER_LOOP( LEFT, RIGHT, Y ) \
555 CONST GLint n = RIGHT-LEFT; \
557 GLdepth zspan[MAX_WIDTH]; \
558 GLfixed fogspan[MAX_WIDTH]; \
559 GLchan rgba[MAX_WIDTH][4]; \
561 GLchan *dest = rgba[0]; \
562 ffs -= FIXED_HALF; /* off-by-one error? */ \
570 SPAN1(NEAREST_RGB;MODULATE,3); \
574 SPAN1(NEAREST_RGB_REPLACE,3); \
577 SPAN1(NEAREST_RGB;BLEND,3); \
580 SPAN1(NEAREST_RGB;ADD,3); \
582 default: /* unexpected env mode */ \
589 SPAN1(NEAREST_RGBA;MODULATE,4); \
592 SPAN1(NEAREST_RGBA;DECAL,4); \
595 SPAN1(NEAREST_RGBA;BLEND,4); \
598 SPAN1(NEAREST_RGBA;ADD,4); \
601 SPAN1(NEAREST_RGBA_REPLACE,4); \
603 default: /* unexpected env mode */ \
616 SPAN2(LINEAR_RGB;MODULATE,3); \
620 SPAN2(LINEAR_RGB;REPLACE,3); \
623 SPAN2(LINEAR_RGB;BLEND,3); \
626 SPAN2(LINEAR_RGB;ADD,3); \
628 default: /* unexpected env mode */ \
635 SPAN2(LINEAR_RGBA;MODULATE,4); \
638 SPAN2(LINEAR_RGBA;DECAL,4); \
641 SPAN2(LINEAR_RGBA;BLEND,4); \
644 SPAN2(LINEAR_RGBA;ADD,4); \
647 SPAN2(LINEAR_RGBA;REPLACE,4); \
649 default: /* unexpected env mode */ \
656 gl_write_rgba_span(ctx, n, LEFT, Y, zspan, \
659 /* explicit kill of variables: */ \
660 ffr = ffg = ffb = ffa = 0; \
664 #include "s_tritemp.h"
672 * Render an perspective corrected RGB/RGBA textured triangle.
673 * The Q (aka V in Mesa) coordinate must be zero such that the divide
674 * by interpolated Q/W comes out right.
676 * This function only renders textured triangles that use GL_NEAREST.
677 * Perspective correction works right.
679 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
680 * Send all questions and bug reports to him.
682 #if 0 /* XXX disabled because of texcoord interpolation errors */
683 static void near_persp_textured_triangle(GLcontext
*ctx
,
688 /* The BIAS value is used to shift negative values into positive values.
689 * Without this, negative texture values don't GL_REPEAT correctly at just
690 * below zero, because (int)-0.5 = 0 = (int)0.5. We're not going to worry
691 * about texture coords less than -BIAS. This could be fixed by using
692 * FLOORF etc. instead, but this is slower...
697 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
699 #define INTERP_ALPHA 1
702 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
703 struct gl_texture_object *obj = unit->Current2D; \
704 const GLint b = obj->BaseLevel; \
705 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
706 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
707 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
708 GLchan *texture = obj->Image[b]->Data; \
709 const GLint smask = (obj->Image[b]->Width - 1); \
710 const GLint tmask = (obj->Image[b]->Height - 1); \
711 const GLint format = obj->Image[b]->Format; \
712 const GLint envmode = unit->EnvMode; \
713 GLfloat sscale, tscale; \
714 GLfixed er, eg, eb, ea; \
715 GLint tr, tg, tb, ta; \
717 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
719 texture = obj->Image[b]->Data; \
722 if (envmode == GL_BLEND || envmode == GL_ADD) { \
723 er = FloatToFixed(unit->EnvColor[0]); \
724 eg = FloatToFixed(unit->EnvColor[1]); \
725 eb = FloatToFixed(unit->EnvColor[2]); \
726 ea = FloatToFixed(unit->EnvColor[3]); \
732 #define OLD_SPAN(DO_TEX,COMP) \
733 for (i=0;i<n;i++) { \
734 GLfloat invQ = 1.0f / vv; \
735 GLint s = (int)(SS * invQ + BIAS) & smask; \
736 GLint t = (int)(TT * invQ + BIAS) & tmask; \
737 GLint pos = COMP * ((t << twidth_log2) + s); \
738 GLchan *tex00 = texture + pos; \
739 zspan[i] = FixedToDepth(ffz); \
740 fogspan[i] = fffog / 256; \
754 #define X_Y_TEX_COORD(X, Y) ((((int)(X) & tmask) << twidth_log2) + ((int)(Y) & smask))
755 #define Y_X_TEX_COORD(X, Y) ((((int)(Y) & tmask) << twidth_log2) + ((int)(X) & smask))
757 #define SPAN1(DO_TEX, COMP, TEX_COORD) { \
758 GLfloat x_max = CEILF(x_tex); \
759 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \
760 GLint j, x_m = (int)x_max; \
762 if ((int)y_max != (int)y_tex) { \
763 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \
764 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
765 pos = COMP * TEX_COORD(x_tex, y_tex); \
766 DRAW_LINE (DO_TEX); \
769 nominator += vv * x_max; \
770 denominator -= dvdx * x_max; \
771 j = nominator / denominator; \
772 pos = COMP * TEX_COORD(x_tex, y_tex); \
773 DRAW_LINE (DO_TEX); \
777 if ((int)y_max != (int)y_tex) { \
778 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \
779 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
780 pos = COMP * TEX_COORD(x_m, y_tex); \
781 DRAW_LINE (DO_TEX); \
785 denominator -= dvdx; \
786 j = nominator/denominator; \
787 pos = COMP * TEX_COORD(x_m, y_tex); \
788 DRAW_LINE (DO_TEX); \
793 #define SPAN2(DO_TEX, COMP, TEX_COORD) { \
794 GLfloat x_max = CEILF (x_tex); \
795 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \
796 GLint j, x_m = (int) x_max; \
798 if ((int)y_max != (int)y_tex) { \
799 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \
800 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
801 pos = COMP * TEX_COORD(x_tex, y_tex); \
802 DRAW_LINE (DO_TEX); \
805 nominator += vv * x_max; \
806 denominator -= dvdx * x_max; \
807 j = nominator / denominator; \
808 pos = COMP * TEX_COORD(x_tex, y_tex); \
809 DRAW_LINE (DO_TEX); \
813 if ((int)y_max != (int)y_tex) { \
814 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \
815 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);\
816 pos = COMP * TEX_COORD(x_m, y_tex); \
817 DRAW_LINE (DO_TEX); \
821 denominator -= dvdx; \
822 j = nominator/denominator; \
823 pos = COMP * TEX_COORD(x_m, y_tex); \
824 DRAW_LINE (DO_TEX); \
829 #define SPAN3(DO_TEX, COMP, TEX_COORD) { \
830 GLfloat x_min = FLOORF (x_tex); \
831 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \
832 GLint j, x_m = (int)x_min; \
834 if ((int)y_min != (int)y_tex) { \
835 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \
836 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
837 pos = COMP * TEX_COORD(x_m, y_tex); \
838 DRAW_LINE (DO_TEX); \
841 nominator += vv*x_min; \
842 denominator -= dvdx*x_min; \
843 j = nominator / denominator; \
844 pos = COMP * TEX_COORD(x_m, y_tex); \
845 DRAW_LINE (DO_TEX); \
850 if ((int)y_min != (int)y_tex) { \
851 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \
852 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
853 pos = COMP * TEX_COORD(x_m, y_tex); \
854 DRAW_LINE (DO_TEX); \
858 denominator += dvdx; \
859 j = nominator/denominator; \
860 pos = COMP * TEX_COORD(x_m, y_tex); \
861 DRAW_LINE (DO_TEX); \
865 #define SPAN4(DO_TEX, COMP, TEX_COORD) \
867 GLfloat x_min = FLOORF(x_tex); \
868 GLint x_m = (int)x_min; \
869 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \
872 if ((int)y_min != (int)y_tex) { \
873 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \
874 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
875 pos = COMP * TEX_COORD(x_m, y_tex); \
876 DRAW_LINE (DO_TEX); \
879 nominator += vv * x_min; \
880 denominator -= dvdx * x_min; \
881 j = nominator / denominator; \
882 pos = COMP * TEX_COORD(x_m, y_tex); \
883 DRAW_LINE (DO_TEX); \
888 if ((int)y_min != (int)y_tex) { \
889 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \
890 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
891 pos = COMP * TEX_COORD(x_m, (y_tex)); \
892 DRAW_LINE (DO_TEX); \
896 denominator += dvdx; \
897 j = nominator/denominator; \
898 pos = COMP * TEX_COORD(x_m, y_tex); \
899 DRAW_LINE (DO_TEX); \
903 #define DRAW_LINE(DO_TEX) \
905 GLchan *tex00 = texture + pos; \
906 if (j>n || j<-100000) \
909 zspan[i] = FixedToDepth(ffz); \
910 fogspan[i] = fffog / 256; \
923 #define INNER_LOOP( LEFT, RIGHT, Y ) \
926 const GLint n = RIGHT-LEFT; \
927 GLdepth zspan[MAX_WIDTH]; \
928 GLfixed fogspan[MAX_WIDTH]; \
929 GLchan rgba[MAX_WIDTH][4]; \
930 (void)uu; /* please GCC */ \
932 GLchan *dest = rgba[0]; \
933 GLfloat SS = ss * sscale; \
934 GLfloat TT = tt * tscale; \
935 GLfloat dSdx = dsdx * sscale; \
936 GLfloat dTdx = dtdx * tscale; \
941 if (n<5) /* When line very short, setup-time > speed-gain. */ \
942 goto old_span; /* So: take old method */ \
945 dx_tex = (SS + n * dSdx) / (vv + n * dvdx) - x_tex, \
946 dy_tex = (TT + n * dTdx) / (vv + n * dvdx) - y_tex; \
947 /* Choose between walking over texture or over pixelline: */ \
948 /* If there are few texels, walk over texture otherwise */ \
949 /* walk over pixelarray. The quotient on the right side */ \
950 /* should give the timeratio needed to draw one texel in */ \
951 /* comparison to one pixel. Depends on CPU. */ \
952 if (dx_tex*dx_tex + dy_tex*dy_tex < (n*n)/16) { \
955 if (dx_tex*dx_tex > dy_tex*dy_tex) { \
956 /* if (FABSF(dx_tex) > FABSF(dy_tex)) */ \
957 GLfloat nominator = - SS - vv * BIAS; \
958 GLfloat denominator = dvdx * BIAS + dSdx; \
961 if (dy_tex != 0.0f) { \
962 dy_dx = dy_tex / dx_tex; \
963 dx_dy = 1.0f/dy_dx; \
967 if (dx_tex > 0.0f) { \
968 if (dy_tex > 0.0f) { \
973 SPAN1(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
977 SPAN1(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
980 SPAN1(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
983 SPAN1(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
985 default: /* unexpected env mode */ \
992 SPAN1(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
995 SPAN1(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
998 SPAN1(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1001 SPAN1(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1004 SPAN1(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1006 default: /* unexpected env mode */ \
1012 else { /* dy_tex <= 0.0f */ \
1015 switch (envmode) { \
1017 SPAN2(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1021 SPAN2(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1024 SPAN2(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1027 SPAN2(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1029 default: /* unexpected env mode */ \
1036 SPAN2(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1039 SPAN2(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1042 SPAN2(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1045 SPAN2(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1048 SPAN2(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1050 default: /* unexpected env mode */ \
1057 else { /* dx_tex < 0.0f */ \
1058 if (dy_tex > 0.0f) { \
1061 switch (envmode) { \
1063 SPAN3(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1067 SPAN3(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1070 SPAN3(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1073 SPAN3(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1075 default: /* unexpected env mode */ \
1082 SPAN3(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1085 SPAN3(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1088 SPAN3(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1091 SPAN3(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1094 SPAN3(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1096 default: /* unexpected env mode */ \
1102 else { /* dy_tex <= 0.0f */ \
1105 switch (envmode) { \
1107 SPAN4(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1111 SPAN4(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1114 SPAN4(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1117 SPAN4(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1126 SPAN4(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1129 SPAN4(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1132 SPAN4(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1135 SPAN4(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1138 SPAN4(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1140 default: /* unexpected env mode */ \
1148 else { /* FABSF(dx_tex) > FABSF(dy_tex) */ \
1152 GLfloat nominator, denominator; \
1153 if (dx_tex == 0.0f /* && dy_tex == 0.0f*/) \
1154 goto old_span; /* case so special, that use old */ \
1155 /* swap some x-values and y-values */ \
1158 swap = x_tex, x_tex = y_tex, y_tex = swap; \
1159 swap = dx_tex, dx_tex = dy_tex, dy_tex = swap; \
1160 nominator = - SS - vv * BIAS; \
1161 denominator = dvdx * BIAS + dSdx; \
1162 if (dy_tex != 0.0f) { \
1163 dy_dx = dy_tex / dx_tex; \
1164 dx_dy = 1.0f/dy_dx; \
1168 if (dx_tex > 0.0f) { \
1169 if (dy_tex > 0.0f) { \
1172 switch (envmode) { \
1174 SPAN1(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1178 SPAN1(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1181 SPAN1(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1184 SPAN1(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1186 default: /* unexpected env mode */ \
1193 SPAN1(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1196 SPAN1(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1199 SPAN1(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1202 SPAN1(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1205 SPAN1(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1213 else { /* dy_tex <= 0.0f */ \
1216 switch (envmode) { \
1218 SPAN2(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1222 SPAN2(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1225 SPAN2(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1228 SPAN2(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1237 SPAN2(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1240 SPAN2(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1243 SPAN2(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1246 SPAN2(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1249 SPAN2(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1258 else { /* dx_tex < 0.0f */ \
1259 if (dy_tex > 0.0f) { \
1262 switch (envmode) { \
1264 SPAN3(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1268 SPAN3(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1271 SPAN3(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1274 SPAN3(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1283 SPAN3(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1286 SPAN3(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1289 SPAN3(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1292 SPAN3(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1295 SPAN3(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1303 else { /* dy_tex <= 0.0f */ \
1306 switch (envmode) { \
1308 SPAN4(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1312 SPAN4(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1315 SPAN4(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1318 SPAN4(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1327 SPAN4(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1330 SPAN4(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1333 SPAN4(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1336 SPAN4(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1339 SPAN4(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1354 switch (envmode) { \
1356 OLD_SPAN(NEAREST_RGB;MODULATE,3); \
1360 OLD_SPAN(NEAREST_RGB_REPLACE,3); \
1363 OLD_SPAN(NEAREST_RGB;BLEND,3); \
1366 OLD_SPAN(NEAREST_RGB;ADD,3); \
1375 OLD_SPAN(NEAREST_RGBA;MODULATE,4); \
1378 OLD_SPAN(NEAREST_RGBA;DECAL,4); \
1381 OLD_SPAN(NEAREST_RGBA;BLEND,4); \
1384 OLD_SPAN(NEAREST_RGBA;ADD,4); \
1387 OLD_SPAN(NEAREST_RGBA_REPLACE,4); \
1395 gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1396 fogspan, rgba, GL_POLYGON); \
1397 ffr = ffg = ffb = ffa = 0; \
1401 #include "s_tritemp.h"
1407 #undef X_Y_TEX_COORD
1408 #undef Y_X_TEX_COORD
1416 * Render an perspective corrected RGB/RGBA textured triangle.
1417 * The Q (aka V in Mesa) coordinate must be zero such that the divide
1418 * by interpolated Q/W comes out right.
1420 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
1421 * Send all questions and bug reports to him.
1423 #if 0 /* XXX disabled because of texcoord interpolation errors */
1424 static void lin_persp_textured_triangle( GLcontext
*ctx
,
1427 const SWvertex
*v2
)
1430 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1431 #define INTERP_RGB 1
1432 #define INTERP_ALPHA 1
1433 #define INTERP_TEX 1
1434 #define SETUP_CODE \
1435 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
1436 struct gl_texture_object *obj = unit->Current2D; \
1437 const GLint b = obj->BaseLevel; \
1438 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
1439 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
1440 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
1441 GLchan *texture = obj->Image[b]->Data; \
1442 const GLint smask = (obj->Image[b]->Width - 1); \
1443 const GLint tmask = (obj->Image[b]->Height - 1); \
1444 const GLint format = obj->Image[b]->Format; \
1445 const GLint envmode = unit->EnvMode; \
1446 GLfloat sscale, tscale; \
1447 GLint comp, tbytesline, tsize; \
1448 GLfixed er, eg, eb, ea; \
1449 GLint tr, tg, tb, ta; \
1451 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
1453 texture = obj->Image[b]->Data; \
1456 if (envmode == GL_BLEND || envmode == GL_ADD) { \
1457 er = FloatToFixed(unit->EnvColor[0]); \
1458 eg = FloatToFixed(unit->EnvColor[1]); \
1459 eb = FloatToFixed(unit->EnvColor[2]); \
1460 ea = FloatToFixed(unit->EnvColor[3]); \
1464 case GL_LUMINANCE: \
1465 case GL_INTENSITY: \
1468 case GL_LUMINANCE_ALPHA: \
1478 gl_problem(NULL, "Bad texture format in lin_persp_texture_triangle"); \
1481 sscale = FIXED_SCALE * twidth; \
1482 tscale = FIXED_SCALE * theight; \
1483 tbytesline = obj->Image[b]->Width * comp; \
1484 tsize = theight * tbytesline;
1487 #define SPAN(DO_TEX,COMP) \
1488 for (i=0;i<n;i++) { \
1489 GLfloat invQ = 1.0f / vv; \
1490 GLfixed ffs = (int)(SS * invQ); \
1491 GLfixed fft = (int)(TT * invQ); \
1492 GLint s = FixedToInt(ffs) & smask; \
1493 GLint t = FixedToInt(fft) & tmask; \
1494 GLint sf = ffs & FIXED_FRAC_MASK; \
1495 GLint tf = fft & FIXED_FRAC_MASK; \
1496 GLint si = FIXED_FRAC_MASK - sf; \
1497 GLint ti = FIXED_FRAC_MASK - tf; \
1498 GLint pos = COMP * ((t << twidth_log2) + s); \
1499 GLchan *tex00 = texture + pos; \
1500 GLchan *tex10 = tex00 + tbytesline; \
1501 GLchan *tex01 = tex00 + COMP; \
1502 GLchan *tex11 = tex10 + COMP; \
1508 tex01 -= tbytesline; \
1509 tex11 -= tbytesline; \
1511 zspan[i] = FixedToDepth(ffz); \
1512 fogspan[i] = fffog / 256; \
1526 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1529 const GLint n = RIGHT-LEFT; \
1530 GLdepth zspan[MAX_WIDTH]; \
1531 GLfixed fogspan[MAX_WIDTH]; \
1532 GLchan rgba[MAX_WIDTH][4]; \
1533 (void) uu; /* please GCC */ \
1535 GLfloat SS = ss * sscale; \
1536 GLfloat TT = tt * tscale; \
1537 GLfloat dSdx = dsdx * sscale; \
1538 GLfloat dTdx = dtdx * tscale; \
1539 GLchan *dest = rgba[0]; \
1540 SS -= 0.5f * FIXED_SCALE * vv; \
1541 TT -= 0.5f * FIXED_SCALE * vv; \
1544 switch (envmode) { \
1546 SPAN(LINEAR_RGB;MODULATE,3); \
1550 SPAN(LINEAR_RGB;REPLACE,3); \
1553 SPAN(LINEAR_RGB;BLEND,3); \
1556 SPAN(LINEAR_RGB;ADD,3); \
1563 switch (envmode) { \
1565 SPAN(LINEAR_RGBA;MODULATE,4); \
1568 SPAN(LINEAR_RGBA;DECAL,4); \
1571 SPAN(LINEAR_RGBA;BLEND,4); \
1574 SPAN(LINEAR_RGBA;REPLACE,4); \
1577 SPAN(LINEAR_RGBA;ADD,4); \
1579 default: /* unexpected env mode */ \
1583 gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1585 rgba, GL_POLYGON ); \
1586 ffr = ffg = ffb = ffa = 0; \
1590 #include "s_tritemp.h"
1597 * Render a smooth-shaded, textured, RGBA triangle.
1598 * Interpolate S,T,U with perspective correction, w/out mipmapping.
1599 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
1600 * R is already used for red.
1602 static void general_textured_triangle( GLcontext
*ctx
,
1605 const SWvertex
*v2
)
1608 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1609 #define INTERP_RGB 1
1610 #define INTERP_ALPHA 1
1611 #define INTERP_TEX 1
1612 #define SETUP_CODE \
1613 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1621 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1624 const GLint n = RIGHT-LEFT; \
1625 GLdepth zspan[MAX_WIDTH]; \
1626 GLfixed fogspan[MAX_WIDTH]; \
1627 GLchan rgba[MAX_WIDTH][4]; \
1628 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
1631 for (i=0;i<n;i++) { \
1632 GLdouble invQ = 1.0 / vv; \
1633 zspan[i] = FixedToDepth(ffz); \
1634 fogspan[i] = fffog / 256; \
1635 rgba[i][RCOMP] = r; \
1636 rgba[i][GCOMP] = g; \
1637 rgba[i][BCOMP] = b; \
1638 rgba[i][ACOMP] = a; \
1651 for (i=0;i<n;i++) { \
1652 GLdouble invQ = 1.0 / vv; \
1653 zspan[i] = FixedToDepth(ffz); \
1654 rgba[i][RCOMP] = FixedToInt(ffr); \
1655 rgba[i][GCOMP] = FixedToInt(ffg); \
1656 rgba[i][BCOMP] = FixedToInt(ffb); \
1657 rgba[i][ACOMP] = FixedToInt(ffa); \
1658 fogspan[i] = fffog / 256; \
1674 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1677 NULL, GL_POLYGON ); \
1681 #include "s_tritemp.h"
1686 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1687 * color interpolation.
1688 * Interpolate S,T,U with perspective correction, w/out mipmapping.
1689 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
1690 * R is already used for red.
1692 static void general_textured_spec_triangle1( GLcontext
*ctx
,
1696 GLdepth zspan
[MAX_WIDTH
],
1697 GLfixed fogspan
[MAX_WIDTH
],
1698 GLchan rgba
[MAX_WIDTH
][4],
1699 GLchan spec
[MAX_WIDTH
][4] )
1702 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1703 #define INTERP_RGB 1
1704 #define INTERP_SPEC 1
1705 #define INTERP_ALPHA 1
1706 #define INTERP_TEX 1
1707 #define SETUP_CODE \
1708 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1709 GLint r, g, b, a, sr, sg, sb; \
1715 sr = v2->specular[0]; \
1716 sg = v2->specular[1]; \
1717 sb = v2->specular[2]; \
1719 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1722 const GLint n = RIGHT-LEFT; \
1723 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
1726 for (i=0;i<n;i++) { \
1727 GLdouble invQ = 1.0 / vv; \
1728 zspan[i] = FixedToDepth(ffz); \
1729 fogspan[i] = fffog / 256; \
1730 rgba[i][RCOMP] = r; \
1731 rgba[i][GCOMP] = g; \
1732 rgba[i][BCOMP] = b; \
1733 rgba[i][ACOMP] = a; \
1734 spec[i][RCOMP] = sr; \
1735 spec[i][GCOMP] = sg; \
1736 spec[i][BCOMP] = sb; \
1749 for (i=0;i<n;i++) { \
1750 GLdouble invQ = 1.0 / vv; \
1751 zspan[i] = FixedToDepth(ffz); \
1752 fogspan[i] = fffog / 256; \
1753 rgba[i][RCOMP] = FixedToInt(ffr); \
1754 rgba[i][GCOMP] = FixedToInt(ffg); \
1755 rgba[i][BCOMP] = FixedToInt(ffb); \
1756 rgba[i][ACOMP] = FixedToInt(ffa); \
1757 spec[i][RCOMP] = FixedToInt(ffsr); \
1758 spec[i][GCOMP] = FixedToInt(ffsg); \
1759 spec[i][BCOMP] = FixedToInt(ffsb); \
1778 gl_write_texture_span( ctx, n, LEFT, Y, zspan, \
1780 s, t, u, NULL, rgba, \
1781 (CONST GLchan (*)[4]) spec, \
1786 #include "s_tritemp.h"
1792 * Compute the lambda value for a fragment. (texture level of detail)
1794 static INLINE GLfloat
1795 compute_lambda( GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
1796 GLfloat invQ
, GLfloat width
, GLfloat height
)
1798 GLfloat dudx
= dsdx
* invQ
* width
;
1799 GLfloat dudy
= dsdy
* invQ
* width
;
1800 GLfloat dvdx
= dtdx
* invQ
* height
;
1801 GLfloat dvdy
= dtdy
* invQ
* height
;
1802 GLfloat r1
= dudx
* dudx
+ dudy
* dudy
;
1803 GLfloat r2
= dvdx
* dvdx
+ dvdy
* dvdy
;
1804 GLfloat rho2
= r1
+ r2
; /* used to be: rho2 = MAX2(r1,r2); */
1805 /* return log base 2 of rho */
1806 return log(rho2
) * 1.442695 * 0.5; /* 1.442695 = 1/log(2) */
1811 * Render a smooth-shaded, textured, RGBA triangle.
1812 * Interpolate S,T,U with perspective correction and compute lambda for
1813 * each fragment. Lambda is used to determine whether to use the
1814 * minification or magnification filter. If minification and using
1815 * mipmaps, lambda is also used to select the texture level of detail.
1817 static void lambda_textured_triangle1( GLcontext
*ctx
,
1821 GLfloat s
[MAX_WIDTH
],
1822 GLfloat t
[MAX_WIDTH
],
1823 GLfloat u
[MAX_WIDTH
] )
1826 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1827 #define INTERP_RGB 1
1828 #define INTERP_ALPHA 1
1829 #define INTERP_LAMBDA 1
1830 #define INTERP_TEX 1
1832 #define SETUP_CODE \
1833 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1834 const GLint baseLevel = obj->BaseLevel; \
1835 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1836 const GLfloat twidth = (GLfloat) texImage->Width; \
1837 const GLfloat theight = (GLfloat) texImage->Height; \
1838 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1847 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1850 const GLint n = RIGHT-LEFT; \
1851 GLdepth zspan[MAX_WIDTH]; \
1852 GLfixed fogspan[MAX_WIDTH]; \
1853 GLchan rgba[MAX_WIDTH][4]; \
1854 GLfloat lambda[MAX_WIDTH]; \
1857 for (i=0;i<n;i++) { \
1858 GLdouble invQ = 1.0 / vv; \
1859 zspan[i] = FixedToDepth(ffz); \
1860 fogspan[i] = fffog / 256; \
1861 rgba[i][RCOMP] = r; \
1862 rgba[i][GCOMP] = g; \
1863 rgba[i][BCOMP] = b; \
1864 rgba[i][ACOMP] = a; \
1868 lambda[i] = COMPUTE_LAMBDA(invQ); \
1878 for (i=0;i<n;i++) { \
1879 GLdouble invQ = 1.0 / vv; \
1880 zspan[i] = FixedToDepth(ffz); \
1881 fogspan[i] = fffog / 256; \
1882 rgba[i][RCOMP] = FixedToInt(ffr); \
1883 rgba[i][GCOMP] = FixedToInt(ffg); \
1884 rgba[i][BCOMP] = FixedToInt(ffb); \
1885 rgba[i][ACOMP] = FixedToInt(ffa); \
1889 lambda[i] = COMPUTE_LAMBDA(invQ); \
1902 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1904 rgba, NULL, GL_POLYGON ); \
1908 #include "s_tritemp.h"
1913 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1915 * Interpolate S,T,U with perspective correction and compute lambda for
1916 * each fragment. Lambda is used to determine whether to use the
1917 * minification or magnification filter. If minification and using
1918 * mipmaps, lambda is also used to select the texture level of detail.
1920 static void lambda_textured_spec_triangle1( GLcontext
*ctx
,
1924 GLfloat s
[MAX_WIDTH
],
1925 GLfloat t
[MAX_WIDTH
],
1926 GLfloat u
[MAX_WIDTH
] )
1929 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1930 #define INTERP_RGB 1
1931 #define INTERP_SPEC 1
1932 #define INTERP_ALPHA 1
1933 #define INTERP_TEX 1
1934 #define INTERP_LAMBDA 1
1936 #define SETUP_CODE \
1937 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1938 const GLint baseLevel = obj->BaseLevel; \
1939 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1940 const GLfloat twidth = (GLfloat) texImage->Width; \
1941 const GLfloat theight = (GLfloat) texImage->Height; \
1942 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1943 GLint r, g, b, a, sr, sg, sb; \
1949 sr = v2->specular[0]; \
1950 sg = v2->specular[1]; \
1951 sb = v2->specular[2]; \
1954 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1957 const GLint n = RIGHT-LEFT; \
1958 GLdepth zspan[MAX_WIDTH]; \
1959 GLfixed fogspan[MAX_WIDTH]; \
1960 GLchan spec[MAX_WIDTH][4]; \
1961 GLchan rgba[MAX_WIDTH][4]; \
1962 GLfloat lambda[MAX_WIDTH]; \
1965 for (i=0;i<n;i++) { \
1966 GLdouble invQ = 1.0 / vv; \
1967 zspan[i] = FixedToDepth(ffz); \
1968 fogspan[i] = fffog / 256; \
1969 rgba[i][RCOMP] = r; \
1970 rgba[i][GCOMP] = g; \
1971 rgba[i][BCOMP] = b; \
1972 rgba[i][ACOMP] = a; \
1973 spec[i][RCOMP] = sr; \
1974 spec[i][GCOMP] = sg; \
1975 spec[i][BCOMP] = sb; \
1979 lambda[i] = COMPUTE_LAMBDA(invQ); \
1989 for (i=0;i<n;i++) { \
1990 GLdouble invQ = 1.0 / vv; \
1991 zspan[i] = FixedToDepth(ffz); \
1992 fogspan[i] = fffog / 256; \
1993 rgba[i][RCOMP] = FixedToInt(ffr); \
1994 rgba[i][GCOMP] = FixedToInt(ffg); \
1995 rgba[i][BCOMP] = FixedToInt(ffb); \
1996 rgba[i][ACOMP] = FixedToInt(ffa); \
1997 spec[i][RCOMP] = FixedToInt(ffsr); \
1998 spec[i][GCOMP] = FixedToInt(ffsg); \
1999 spec[i][BCOMP] = FixedToInt(ffsb); \
2003 lambda[i] = COMPUTE_LAMBDA(invQ); \
2019 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
2021 rgba, (CONST GLchan (*)[4]) spec, \
2026 #include "s_tritemp.h"
2031 * This is the big one!
2032 * Interpolate Z, RGB, Alpha, and two sets of texture coordinates.
2036 lambda_multitextured_triangle1( GLcontext
*ctx
,
2040 GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
2041 GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
2042 GLfloat u
[MAX_TEXTURE_UNITS
][MAX_WIDTH
])
2045 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2046 #define INTERP_RGB 1
2047 #define INTERP_ALPHA 1
2048 #define INTERP_MULTITEX 1
2050 #define SETUP_CODE \
2051 GLchan rgba[MAX_WIDTH][4]; \
2052 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
2053 GLfloat twidth[MAX_TEXTURE_UNITS], theight[MAX_TEXTURE_UNITS]; \
2063 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \
2064 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2065 const struct gl_texture_object *obj = ctx->Texture.Unit[unit]._Current; \
2066 const GLint baseLevel = obj->BaseLevel; \
2067 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
2068 twidth[unit] = (GLfloat) texImage->Width; \
2069 theight[unit] = (GLfloat) texImage->Height; \
2076 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2079 const GLint n = RIGHT-LEFT; \
2080 GLdepth zspan[MAX_WIDTH]; \
2081 GLfixed fogspan[MAX_WIDTH]; \
2082 GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; \
2085 for (i=0;i<n;i++) { \
2086 zspan[i] = FixedToDepth(ffz); \
2087 fogspan[i] = fffog / 256; \
2090 rgba[i][RCOMP] = r; \
2091 rgba[i][GCOMP] = g; \
2092 rgba[i][BCOMP] = b; \
2093 rgba[i][ACOMP] = a; \
2096 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \
2097 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2098 GLdouble invQ = 1.0 / vv[unit]; \
2099 s[unit][i] = ss[unit] * invQ; \
2100 t[unit][i] = tt[unit] * invQ; \
2101 u[unit][i] = uu[unit] * invQ; \
2102 lambda[unit][i] = compute_lambda(dsdx[unit], dsdy[unit],\
2103 dtdx[unit], dtdy[unit], invQ, \
2104 twidth[unit], theight[unit] ); \
2105 ss[unit] += dsdx[unit]; \
2106 tt[unit] += dtdx[unit]; \
2107 uu[unit] += dudx[unit]; \
2108 vv[unit] += dvdx[unit]; \
2114 else { /* smooth shade */ \
2115 for (i=0;i<n;i++) { \
2116 zspan[i] = FixedToDepth(ffz); \
2117 fogspan[i] = fffog / 256; \
2120 rgba[i][RCOMP] = FixedToInt(ffr); \
2121 rgba[i][GCOMP] = FixedToInt(ffg); \
2122 rgba[i][BCOMP] = FixedToInt(ffb); \
2123 rgba[i][ACOMP] = FixedToInt(ffa); \
2130 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \
2131 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2132 GLdouble invQ = 1.0 / vv[unit]; \
2133 s[unit][i] = ss[unit] * invQ; \
2134 t[unit][i] = tt[unit] * invQ; \
2135 u[unit][i] = uu[unit] * invQ; \
2136 lambda[unit][i] = compute_lambda(dsdx[unit], dsdy[unit],\
2137 dtdx[unit], dtdy[unit], invQ, \
2138 twidth[unit], theight[unit] ); \
2139 ss[unit] += dsdx[unit]; \
2140 tt[unit] += dtdx[unit]; \
2141 uu[unit] += dudx[unit]; \
2142 vv[unit] += dvdx[unit]; \
2148 gl_write_multitexture_span( ctx, n, LEFT, Y, zspan, fogspan, \
2149 (const GLfloat (*)[MAX_WIDTH]) s, \
2150 (const GLfloat (*)[MAX_WIDTH]) t, \
2151 (const GLfloat (*)[MAX_WIDTH]) u, \
2152 (GLfloat (*)[MAX_WIDTH]) lambda, \
2153 rgba, NULL, GL_POLYGON ); \
2156 #include "s_tritemp.h"
2161 * These wrappers are needed to deal with the 32KB / stack frame limit
2162 * on Mac / PowerPC systems.
2165 static void general_textured_spec_triangle(GLcontext
*ctx
,
2168 const SWvertex
*v2
)
2170 GLdepth zspan
[MAX_WIDTH
];
2171 GLfixed fogspan
[MAX_WIDTH
];
2172 GLchan rgba
[MAX_WIDTH
][4], spec
[MAX_WIDTH
][4];
2173 general_textured_spec_triangle1(ctx
,v0
,v1
,v2
,zspan
,fogspan
,rgba
,spec
);
2176 static void lambda_textured_triangle( GLcontext
*ctx
,
2179 const SWvertex
*v2
)
2181 GLfloat s
[MAX_WIDTH
], t
[MAX_WIDTH
], u
[MAX_WIDTH
];
2182 lambda_textured_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2185 static void lambda_textured_spec_triangle( GLcontext
*ctx
,
2188 const SWvertex
*v2
)
2190 GLfloat s
[MAX_WIDTH
];
2191 GLfloat t
[MAX_WIDTH
];
2192 GLfloat u
[MAX_WIDTH
];
2193 lambda_textured_spec_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2197 static void lambda_multitextured_triangle( GLcontext
*ctx
,
2200 const SWvertex
*v2
)
2203 GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
2204 GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
2205 DEFMARRAY(GLfloat
,u
,MAX_TEXTURE_UNITS
,MAX_WIDTH
);
2206 CHECKARRAY(u
,return);
2208 lambda_multitextured_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2215 static void occlusion_zless_triangle( GLcontext
*ctx
,
2218 const SWvertex
*v2
)
2220 if (ctx
->OcclusionResult
) {
2224 #define DO_OCCLUSION_TEST
2226 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2227 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2230 const GLint len = RIGHT-LEFT; \
2231 for (i=0;i<len;i++) { \
2232 GLdepth z = FixedToDepth(ffz); \
2234 if (z < zRow[i]) { \
2235 ctx->OcclusionResult = GL_TRUE; \
2241 #include "s_tritemp.h"
2249 # define dputs(s) puts(s)
2257 * Determine which triangle rendering function to use given the current
2258 * rendering context.
2260 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
2261 * remove tests to this code.
2264 _swrast_choose_triangle( GLcontext
*ctx
)
2266 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
2267 const GLboolean rgbmode
= ctx
->Visual
.rgbMode
;
2269 if (ctx
->RenderMode
==GL_RENDER
) {
2271 if (ctx
->Polygon
.SmoothFlag
) {
2272 _mesa_set_aa_triangle_function(ctx
);
2273 ASSERT(swrast
->Triangle
);
2277 if (ctx
->Depth
.OcclusionTest
&&
2279 ctx
->Depth
.Mask
== GL_FALSE
&&
2280 ctx
->Depth
.Func
== GL_LESS
&&
2281 !ctx
->Stencil
.Enabled
) {
2283 ctx
->Color
.ColorMask
[0] == 0 &&
2284 ctx
->Color
.ColorMask
[1] == 0 &&
2285 ctx
->Color
.ColorMask
[2] == 0 &&
2286 ctx
->Color
.ColorMask
[3] == 0)
2288 (!rgbmode
&& ctx
->Color
.IndexMask
== 0)) {
2289 dputs("occlusion_test_triangle");
2290 swrast
->Triangle
= occlusion_zless_triangle
;
2295 if (ctx
->Texture
._ReallyEnabled
) {
2296 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
2297 GLint format
, filter
;
2298 const struct gl_texture_object
*current2Dtex
= ctx
->Texture
.Unit
[0].Current2D
;
2299 const struct gl_texture_image
*image
;
2300 /* First see if we can used an optimized 2-D texture function */
2301 if (ctx
->Texture
._ReallyEnabled
==TEXTURE0_2D
2302 && current2Dtex
->WrapS
==GL_REPEAT
2303 && current2Dtex
->WrapT
==GL_REPEAT
2304 && ((image
= current2Dtex
->Image
[current2Dtex
->BaseLevel
]) != 0) /* correct! */
2306 && ((format
= image
->Format
)==GL_RGB
|| format
==GL_RGBA
)
2307 && (filter
= current2Dtex
->MinFilter
)==current2Dtex
->MagFilter
2308 /* ==> current2Dtex->MinFilter != GL_XXX_MIPMAP_XXX */
2309 && ctx
->Light
.Model
.ColorControl
==GL_SINGLE_COLOR
2310 && ctx
->Texture
.Unit
[0].EnvMode
!=GL_COMBINE_EXT
) {
2312 if (ctx
->Hint
.PerspectiveCorrection
==GL_FASTEST
) {
2314 if (filter
==GL_NEAREST
2316 && (ctx
->Texture
.Unit
[0].EnvMode
==GL_REPLACE
2317 || ctx
->Texture
.Unit
[0].EnvMode
==GL_DECAL
)
2318 && ((swrast
->_RasterMask
==DEPTH_BIT
2319 && ctx
->Depth
.Func
==GL_LESS
2320 && ctx
->Depth
.Mask
==GL_TRUE
)
2321 || swrast
->_RasterMask
==0)
2322 && ctx
->Polygon
.StippleFlag
==GL_FALSE
) {
2324 if (swrast
->_RasterMask
==DEPTH_BIT
) {
2325 swrast
->Triangle
= simple_z_textured_triangle
;
2326 dputs("simple_z_textured_triangle");
2329 swrast
->Triangle
= simple_textured_triangle
;
2330 dputs("simple_textured_triangle");
2334 if (ctx
->Texture
.Unit
[0].EnvMode
==GL_ADD
) {
2335 swrast
->Triangle
= general_textured_triangle
;
2336 dputs("general_textured_triangle");
2339 swrast
->Triangle
= affine_textured_triangle
;
2340 dputs("affine_textured_triangle");
2345 #if 00 /* XXX these function have problems with texture coord interpolation */
2346 if (filter
==GL_NEAREST
) {
2347 swrast
->Triangle
= near_persp_textured_triangle
;
2348 dputs("near_persp_textured_triangle");
2351 swrast
->Triangle
= lin_persp_textured_triangle
;
2352 dputs("lin_persp_textured_triangle");
2355 swrast
->Triangle
= general_textured_triangle
;
2359 /* More complicated textures (mipmap, multi-tex, sep specular) */
2360 GLboolean needLambda
;
2361 /* if mag filter != min filter we need to compute lambda */
2362 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
2363 if (obj
&& obj
->MinFilter
!= obj
->MagFilter
)
2364 needLambda
= GL_TRUE
;
2366 needLambda
= GL_FALSE
;
2367 if (swrast
->_MultiTextureEnabled
) {
2368 swrast
->Triangle
= lambda_multitextured_triangle
;
2369 dputs("lambda_multitextured_triangle");
2371 else if ((ctx
->Light
.Enabled
&&
2372 ctx
->Light
.Model
.ColorControl
==GL_SEPARATE_SPECULAR_COLOR
)
2373 || ctx
->Fog
.ColorSumEnabled
) {
2374 /* separate specular color interpolation */
2376 swrast
->Triangle
= lambda_textured_spec_triangle
;
2377 dputs("lambda_textured_spec_triangle");
2380 swrast
->Triangle
= general_textured_spec_triangle
;
2381 dputs("general_textured_spec_triangle");
2386 swrast
->Triangle
= lambda_textured_triangle
;
2387 dputs("lambda_textured_triangle");
2390 swrast
->Triangle
= general_textured_triangle
;
2391 dputs("general_textured_triangle");
2397 if (ctx
->Light
.ShadeModel
==GL_SMOOTH
) {
2398 /* smooth shaded, no texturing, stippled or some raster ops */
2400 dputs("smooth_rgba_triangle");
2401 swrast
->Triangle
= smooth_rgba_triangle
;
2404 dputs("smooth_ci_triangle");
2405 swrast
->Triangle
= smooth_ci_triangle
;
2409 /* flat shaded, no texturing, stippled or some raster ops */
2411 dputs("flat_rgba_triangle");
2412 swrast
->Triangle
= flat_rgba_triangle
;
2415 dputs("flat_ci_triangle");
2416 swrast
->Triangle
= flat_ci_triangle
;
2421 else if (ctx
->RenderMode
==GL_FEEDBACK
) {
2422 swrast
->Triangle
= gl_feedback_triangle
;
2425 /* GL_SELECT mode */
2426 swrast
->Triangle
= gl_select_triangle
;