1 /* $Id: s_triangle.c,v 1.5 2000/11/19 23:10:26 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 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
,
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 gl_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 gl_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
152 #define INNER_LOOP( LEFT, RIGHT, Y ) \
154 const GLint n = RIGHT-LEFT; \
156 GLdepth zspan[MAX_WIDTH]; \
157 GLfixed fogspan[MAX_WIDTH]; \
159 for (i=0;i<n;i++) { \
160 zspan[i] = FixedToDepth(ffz); \
162 fogspan[i] = fffog / 256; \
165 gl_write_monocolor_span( ctx, n, LEFT, Y, zspan, \
166 fogspan, v0->color, \
171 #include "s_tritemp.h"
173 ASSERT(!ctx
->Texture
._ReallyEnabled
); /* texturing must be off */
174 ASSERT(ctx
->Light
.ShadeModel
==GL_FLAT
);
180 * Render a smooth-shaded RGBA triangle.
182 static void smooth_rgba_triangle( GLcontext
*ctx
,
189 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
191 #define INTERP_ALPHA 1
193 #define INNER_LOOP( LEFT, RIGHT, Y ) \
195 const GLint n = RIGHT-LEFT; \
197 GLdepth zspan[MAX_WIDTH]; \
198 GLchan rgba[MAX_WIDTH][4]; \
199 GLfixed fogspan[MAX_WIDTH]; \
201 for (i=0;i<n;i++) { \
202 zspan[i] = FixedToDepth(ffz); \
203 rgba[i][RCOMP] = FixedToInt(ffr); \
204 rgba[i][GCOMP] = FixedToInt(ffg); \
205 rgba[i][BCOMP] = FixedToInt(ffb); \
206 rgba[i][ACOMP] = FixedToInt(ffa); \
207 fogspan[i] = fffog / 256; \
215 gl_write_rgba_span( ctx, n, LEFT, Y, \
216 (CONST GLdepth *) zspan, \
218 rgba, GL_POLYGON ); \
222 #include "s_tritemp.h"
224 ASSERT(!ctx
->Texture
._ReallyEnabled
); /* texturing must be off */
225 ASSERT(ctx
->Light
.ShadeModel
==GL_SMOOTH
);
230 * Render an RGB, GL_DECAL, textured triangle.
231 * Interpolate S,T only w/out mipmapping or perspective correction.
235 static void simple_textured_triangle( GLcontext
*ctx
,
240 #define INTERP_INT_TEX 1
241 #define S_SCALE twidth
242 #define T_SCALE theight
244 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
245 GLint b = obj->BaseLevel; \
246 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
247 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
248 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
249 GLchan *texture = obj->Image[b]->Data; \
250 GLint smask = obj->Image[b]->Width - 1; \
251 GLint tmask = obj->Image[b]->Height - 1; \
253 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
255 texture = obj->Image[b]->Data; \
259 #define INNER_LOOP( LEFT, RIGHT, Y ) \
261 CONST GLint n = RIGHT-LEFT; \
263 GLchan rgb[MAX_WIDTH][3]; \
265 ffs -= FIXED_HALF; /* off-by-one error? */ \
267 for (i=0;i<n;i++) { \
268 GLint s = FixedToInt(ffs) & smask; \
269 GLint t = FixedToInt(fft) & tmask; \
270 GLint pos = (t << twidth_log2) + s; \
271 pos = pos + pos + pos; /* multiply by 3 */ \
272 rgb[i][RCOMP] = texture[pos]; \
273 rgb[i][GCOMP] = texture[pos+1]; \
274 rgb[i][BCOMP] = texture[pos+2]; \
278 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
279 (CONST GLchan (*)[3]) rgb, NULL ); \
283 #include "s_tritemp.h"
288 * Render an RGB, GL_DECAL, textured triangle.
289 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
290 * perspective correction.
294 static void simple_z_textured_triangle( GLcontext
*ctx
,
300 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
301 #define INTERP_INT_TEX 1
302 #define S_SCALE twidth
303 #define T_SCALE theight
305 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
306 GLint b = obj->BaseLevel; \
307 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
308 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
309 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
310 GLchan *texture = obj->Image[b]->Data; \
311 GLint smask = obj->Image[b]->Width - 1; \
312 GLint tmask = obj->Image[b]->Height - 1; \
314 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
316 texture = obj->Image[b]->Data; \
320 #define INNER_LOOP( LEFT, RIGHT, Y ) \
322 CONST GLint n = RIGHT-LEFT; \
324 GLchan rgb[MAX_WIDTH][3]; \
325 GLubyte mask[MAX_WIDTH]; \
328 ffs -= FIXED_HALF; /* off-by-one error? */ \
330 for (i=0;i<n;i++) { \
331 GLdepth z = FixedToDepth(ffz); \
333 GLint s = FixedToInt(ffs) & smask; \
334 GLint t = FixedToInt(fft) & tmask; \
335 GLint pos = (t << twidth_log2) + s; \
336 pos = pos + pos + pos; /* multiply by 3 */ \
337 rgb[i][RCOMP] = texture[pos]; \
338 rgb[i][GCOMP] = texture[pos+1]; \
339 rgb[i][BCOMP] = texture[pos+2]; \
350 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
351 (CONST GLchan (*)[3]) rgb, mask ); \
355 #include "s_tritemp.h"
361 * Render an RGB/RGBA textured triangle without perspective correction.
363 static void affine_textured_triangle( GLcontext
*ctx
,
369 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
371 #define INTERP_ALPHA 1
372 #define INTERP_INT_TEX 1
373 #define S_SCALE twidth
374 #define T_SCALE theight
376 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
377 struct gl_texture_object *obj = unit->Current2D; \
378 GLint b = obj->BaseLevel; \
379 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
380 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
381 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
382 GLchan *texture = obj->Image[b]->Data; \
383 GLint smask = obj->Image[b]->Width - 1; \
384 GLint tmask = obj->Image[b]->Height - 1; \
385 GLint format = obj->Image[b]->Format; \
386 GLint filter = obj->MinFilter; \
387 GLint envmode = unit->EnvMode; \
388 GLint comp, tbytesline, tsize; \
389 GLfixed er, eg, eb, ea; \
390 GLint tr, tg, tb, ta; \
392 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
394 texture = obj->Image[b]->Data; \
397 if (envmode == GL_BLEND || envmode == GL_ADD) { \
398 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
399 er = FloatToFixed(unit->EnvColor[0]); \
400 eg = FloatToFixed(unit->EnvColor[1]); \
401 eb = FloatToFixed(unit->EnvColor[2]); \
402 ea = FloatToFixed(unit->EnvColor[3]); \
410 case GL_LUMINANCE_ALPHA: \
420 gl_problem(NULL, "Bad texture format in affine_texture_triangle");\
423 tbytesline = obj->Image[b]->Width * comp; \
424 tsize = theight * tbytesline;
427 /* Instead of defining a function for each mode, a test is done
428 * between the outer and inner loops. This is to reduce code size
429 * and complexity. Observe that an optimizing compiler kills
430 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
433 #define NEAREST_RGB \
440 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
441 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
442 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
443 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
444 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
445 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
448 #define NEAREST_RGBA \
454 #define LINEAR_RGBA \
455 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
456 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
457 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
458 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
459 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
460 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
461 ta = (ti * (si * tex00[3] + sf * tex01[3]) + \
462 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
465 dest[0] = ffr * (tr + 1) >> (FIXED_SHIFT + 8); \
466 dest[1] = ffg * (tg + 1) >> (FIXED_SHIFT + 8); \
467 dest[2] = ffb * (tb + 1) >> (FIXED_SHIFT + 8); \
468 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
471 dest[0] = ((0xff - ta) * ffr + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
472 dest[1] = ((0xff - ta) * ffg + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
473 dest[2] = ((0xff - ta) * ffb + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
474 dest[3] = FixedToInt(ffa)
477 dest[0] = ((0xff - tr) * ffr + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
478 dest[1] = ((0xff - tg) * ffg + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
479 dest[2] = ((0xff - tb) * ffb + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
480 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
489 dest[0] = ((ffr << 8) + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
490 dest[1] = ((ffg << 8) + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
491 dest[2] = ((ffb << 8) + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
492 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
496 #define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE
498 #define NEAREST_RGBA_REPLACE *(GLint *)dest = *(GLint *)tex00
500 #define SPAN1(DO_TEX,COMP) \
501 for (i=0;i<n;i++) { \
502 GLint s = FixedToInt(ffs) & smask; \
503 GLint t = FixedToInt(fft) & tmask; \
504 GLint pos = (t << twidth_log2) + s; \
505 GLchan *tex00 = texture + COMP * pos; \
506 zspan[i] = FixedToDepth(ffz); \
507 fogspan[i] = fffog / 256; \
520 #define SPAN2(DO_TEX,COMP) \
521 for (i=0;i<n;i++) { \
522 GLint s = FixedToInt(ffs) & smask; \
523 GLint t = FixedToInt(fft) & tmask; \
524 GLint sf = ffs & FIXED_FRAC_MASK; \
525 GLint tf = fft & FIXED_FRAC_MASK; \
526 GLint si = FIXED_FRAC_MASK - sf; \
527 GLint ti = FIXED_FRAC_MASK - tf; \
528 GLint pos = (t << twidth_log2) + s; \
529 GLchan *tex00 = texture + COMP * pos; \
530 GLchan *tex10 = tex00 + tbytesline; \
531 GLchan *tex01 = tex00 + COMP; \
532 GLchan *tex11 = tex10 + COMP; \
538 tex01 -= tbytesline; \
539 tex11 -= tbytesline; \
541 zspan[i] = FixedToDepth(ffz); \
542 fogspan[i] = fffog / 256; \
555 /* here comes the heavy part.. (something for the compiler to chew on) */
556 #define INNER_LOOP( LEFT, RIGHT, Y ) \
558 CONST GLint n = RIGHT-LEFT; \
560 GLdepth zspan[MAX_WIDTH]; \
561 GLfixed fogspan[MAX_WIDTH]; \
562 GLchan rgba[MAX_WIDTH][4]; \
564 GLchan *dest = rgba[0]; \
565 ffs -= FIXED_HALF; /* off-by-one error? */ \
573 SPAN1(NEAREST_RGB;MODULATE,3); \
577 SPAN1(NEAREST_RGB_REPLACE,3); \
580 SPAN1(NEAREST_RGB;BLEND,3); \
583 SPAN1(NEAREST_RGB;ADD,3); \
585 default: /* unexpected env mode */ \
592 SPAN1(NEAREST_RGBA;MODULATE,4); \
595 SPAN1(NEAREST_RGBA;DECAL,4); \
598 SPAN1(NEAREST_RGBA;BLEND,4); \
601 SPAN1(NEAREST_RGBA;ADD,4); \
604 SPAN1(NEAREST_RGBA_REPLACE,4); \
606 default: /* unexpected env mode */ \
619 SPAN2(LINEAR_RGB;MODULATE,3); \
623 SPAN2(LINEAR_RGB;REPLACE,3); \
626 SPAN2(LINEAR_RGB;BLEND,3); \
629 SPAN2(LINEAR_RGB;ADD,3); \
631 default: /* unexpected env mode */ \
638 SPAN2(LINEAR_RGBA;MODULATE,4); \
641 SPAN2(LINEAR_RGBA;DECAL,4); \
644 SPAN2(LINEAR_RGBA;BLEND,4); \
647 SPAN2(LINEAR_RGBA;ADD,4); \
650 SPAN2(LINEAR_RGBA;REPLACE,4); \
652 default: /* unexpected env mode */ \
659 gl_write_rgba_span(ctx, n, LEFT, Y, zspan, \
662 /* explicit kill of variables: */ \
663 ffr = ffg = ffb = ffa = 0; \
667 #include "s_tritemp.h"
675 * Render an perspective corrected RGB/RGBA textured triangle.
676 * The Q (aka V in Mesa) coordinate must be zero such that the divide
677 * by interpolated Q/W comes out right.
679 * This function only renders textured triangles that use GL_NEAREST.
680 * Perspective correction works right.
682 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
683 * Send all questions and bug reports to him.
685 static void near_persp_textured_triangle(GLcontext
*ctx
,
690 /* The BIAS value is used to shift negative values into positive values.
691 * Without this, negative texture values don't GL_REPEAT correctly at just
692 * below zero, because (int)-0.5 = 0 = (int)0.5. We're not going to worry
693 * about texture coords less than -BIAS. This could be fixed by using
694 * FLOORF etc. instead, but this is slower...
699 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
701 #define INTERP_ALPHA 1
704 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
705 struct gl_texture_object *obj = unit->Current2D; \
706 const GLint b = obj->BaseLevel; \
707 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
708 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
709 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
710 GLchan *texture = obj->Image[b]->Data; \
711 const GLint smask = (obj->Image[b]->Width - 1); \
712 const GLint tmask = (obj->Image[b]->Height - 1); \
713 const GLint format = obj->Image[b]->Format; \
714 const GLint envmode = unit->EnvMode; \
715 GLfloat sscale, tscale; \
716 GLfixed er, eg, eb, ea; \
717 GLint tr, tg, tb, ta; \
719 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
721 texture = obj->Image[b]->Data; \
724 if (envmode == GL_BLEND || envmode == GL_ADD) { \
725 er = FloatToFixed(unit->EnvColor[0]); \
726 eg = FloatToFixed(unit->EnvColor[1]); \
727 eb = FloatToFixed(unit->EnvColor[2]); \
728 ea = FloatToFixed(unit->EnvColor[3]); \
734 #define OLD_SPAN(DO_TEX,COMP) \
735 for (i=0;i<n;i++) { \
736 GLfloat invQ = 1.0f / vv; \
737 GLint s = (int)(SS * invQ + BIAS) & smask; \
738 GLint t = (int)(TT * invQ + BIAS) & tmask; \
739 GLint pos = COMP * ((t << twidth_log2) + s); \
740 GLchan *tex00 = texture + pos; \
741 zspan[i] = FixedToDepth(ffz); \
742 fogspan[i] = fffog / 256; \
756 #define X_Y_TEX_COORD(X, Y) ((((int)(X) & tmask) << twidth_log2) + ((int)(Y) & smask))
757 #define Y_X_TEX_COORD(X, Y) ((((int)(Y) & tmask) << twidth_log2) + ((int)(X) & smask))
759 #define SPAN1(DO_TEX, COMP, TEX_COORD) { \
760 GLfloat x_max = CEILF(x_tex); \
761 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \
762 GLint j, x_m = (int)x_max; \
764 if ((int)y_max != (int)y_tex) { \
765 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \
766 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
767 pos = COMP * TEX_COORD(x_tex, y_tex); \
768 DRAW_LINE (DO_TEX); \
771 nominator += vv * x_max; \
772 denominator -= dvdx * x_max; \
773 j = nominator / denominator; \
774 pos = COMP * TEX_COORD(x_tex, y_tex); \
775 DRAW_LINE (DO_TEX); \
779 if ((int)y_max != (int)y_tex) { \
780 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \
781 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
782 pos = COMP * TEX_COORD(x_m, y_tex); \
783 DRAW_LINE (DO_TEX); \
787 denominator -= dvdx; \
788 j = nominator/denominator; \
789 pos = COMP * TEX_COORD(x_m, y_tex); \
790 DRAW_LINE (DO_TEX); \
795 #define SPAN2(DO_TEX, COMP, TEX_COORD) { \
796 GLfloat x_max = CEILF (x_tex); \
797 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \
798 GLint j, x_m = (int) x_max; \
800 if ((int)y_max != (int)y_tex) { \
801 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \
802 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
803 pos = COMP * TEX_COORD(x_tex, y_tex); \
804 DRAW_LINE (DO_TEX); \
807 nominator += vv * x_max; \
808 denominator -= dvdx * x_max; \
809 j = nominator / denominator; \
810 pos = COMP * TEX_COORD(x_tex, y_tex); \
811 DRAW_LINE (DO_TEX); \
815 if ((int)y_max != (int)y_tex) { \
816 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \
817 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);\
818 pos = COMP * TEX_COORD(x_m, y_tex); \
819 DRAW_LINE (DO_TEX); \
823 denominator -= dvdx; \
824 j = nominator/denominator; \
825 pos = COMP * TEX_COORD(x_m, y_tex); \
826 DRAW_LINE (DO_TEX); \
831 #define SPAN3(DO_TEX, COMP, TEX_COORD) { \
832 GLfloat x_min = FLOORF (x_tex); \
833 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \
834 GLint j, x_m = (int)x_min; \
836 if ((int)y_min != (int)y_tex) { \
837 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \
838 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
839 pos = COMP * TEX_COORD(x_m, y_tex); \
840 DRAW_LINE (DO_TEX); \
843 nominator += vv*x_min; \
844 denominator -= dvdx*x_min; \
845 j = nominator / denominator; \
846 pos = COMP * TEX_COORD(x_m, y_tex); \
847 DRAW_LINE (DO_TEX); \
852 if ((int)y_min != (int)y_tex) { \
853 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \
854 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
855 pos = COMP * TEX_COORD(x_m, y_tex); \
856 DRAW_LINE (DO_TEX); \
860 denominator += dvdx; \
861 j = nominator/denominator; \
862 pos = COMP * TEX_COORD(x_m, y_tex); \
863 DRAW_LINE (DO_TEX); \
867 #define SPAN4(DO_TEX, COMP, TEX_COORD) \
869 GLfloat x_min = FLOORF(x_tex); \
870 GLint x_m = (int)x_min; \
871 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \
874 if ((int)y_min != (int)y_tex) { \
875 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \
876 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
877 pos = COMP * TEX_COORD(x_m, y_tex); \
878 DRAW_LINE (DO_TEX); \
881 nominator += vv * x_min; \
882 denominator -= dvdx * x_min; \
883 j = nominator / denominator; \
884 pos = COMP * TEX_COORD(x_m, y_tex); \
885 DRAW_LINE (DO_TEX); \
890 if ((int)y_min != (int)y_tex) { \
891 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \
892 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
893 pos = COMP * TEX_COORD(x_m, (y_tex)); \
894 DRAW_LINE (DO_TEX); \
898 denominator += dvdx; \
899 j = nominator/denominator; \
900 pos = COMP * TEX_COORD(x_m, y_tex); \
901 DRAW_LINE (DO_TEX); \
905 #define DRAW_LINE(DO_TEX) \
907 GLchan *tex00 = texture + pos; \
908 if (j>n || j<-100000) \
911 zspan[i] = FixedToDepth(ffz); \
912 fogspan[i] = fffog / 256; \
925 #define INNER_LOOP( LEFT, RIGHT, Y ) \
928 const GLint n = RIGHT-LEFT; \
929 GLdepth zspan[MAX_WIDTH]; \
930 GLfixed fogspan[MAX_WIDTH]; \
931 GLchan rgba[MAX_WIDTH][4]; \
932 (void)uu; /* please GCC */ \
934 GLchan *dest = rgba[0]; \
935 GLfloat SS = ss * sscale; \
936 GLfloat TT = tt * tscale; \
937 GLfloat dSdx = dsdx * sscale; \
938 GLfloat dTdx = dtdx * tscale; \
943 if (n<5) /* When line very short, setup-time > speed-gain. */ \
944 goto old_span; /* So: take old method */ \
947 dx_tex = (SS + n * dSdx) / (vv + n * dvdx) - x_tex, \
948 dy_tex = (TT + n * dTdx) / (vv + n * dvdx) - y_tex; \
949 /* Choose between walking over texture or over pixelline: */ \
950 /* If there are few texels, walk over texture otherwise */ \
951 /* walk over pixelarray. The quotient on the right side */ \
952 /* should give the timeratio needed to draw one texel in */ \
953 /* comparison to one pixel. Depends on CPU. */ \
954 if (dx_tex*dx_tex + dy_tex*dy_tex < (n*n)/16) { \
957 if (dx_tex*dx_tex > dy_tex*dy_tex) { \
958 /* if (FABSF(dx_tex) > FABSF(dy_tex)) */ \
959 GLfloat nominator = - SS - vv * BIAS; \
960 GLfloat denominator = dvdx * BIAS + dSdx; \
963 if (dy_tex != 0.0f) { \
964 dy_dx = dy_tex / dx_tex; \
965 dx_dy = 1.0f/dy_dx; \
969 if (dx_tex > 0.0f) { \
970 if (dy_tex > 0.0f) { \
975 SPAN1(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
979 SPAN1(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
982 SPAN1(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
985 SPAN1(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
987 default: /* unexpected env mode */ \
994 SPAN1(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
997 SPAN1(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1000 SPAN1(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1003 SPAN1(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1006 SPAN1(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1008 default: /* unexpected env mode */ \
1014 else { /* dy_tex <= 0.0f */ \
1017 switch (envmode) { \
1019 SPAN2(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1023 SPAN2(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1026 SPAN2(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1029 SPAN2(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1031 default: /* unexpected env mode */ \
1038 SPAN2(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1041 SPAN2(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1044 SPAN2(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1047 SPAN2(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1050 SPAN2(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1052 default: /* unexpected env mode */ \
1059 else { /* dx_tex < 0.0f */ \
1060 if (dy_tex > 0.0f) { \
1063 switch (envmode) { \
1065 SPAN3(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1069 SPAN3(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1072 SPAN3(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1075 SPAN3(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1077 default: /* unexpected env mode */ \
1084 SPAN3(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1087 SPAN3(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1090 SPAN3(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1093 SPAN3(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1096 SPAN3(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1098 default: /* unexpected env mode */ \
1104 else { /* dy_tex <= 0.0f */ \
1107 switch (envmode) { \
1109 SPAN4(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1113 SPAN4(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1116 SPAN4(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1119 SPAN4(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1128 SPAN4(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1131 SPAN4(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1134 SPAN4(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1137 SPAN4(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1140 SPAN4(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1142 default: /* unexpected env mode */ \
1150 else { /* FABSF(dx_tex) > FABSF(dy_tex) */ \
1154 GLfloat nominator, denominator; \
1155 if (dx_tex == 0.0f /* && dy_tex == 0.0f*/) \
1156 goto old_span; /* case so special, that use old */ \
1157 /* swap some x-values and y-values */ \
1160 swap = x_tex, x_tex = y_tex, y_tex = swap; \
1161 swap = dx_tex, dx_tex = dy_tex, dy_tex = swap; \
1162 nominator = - SS - vv * BIAS; \
1163 denominator = dvdx * BIAS + dSdx; \
1164 if (dy_tex != 0.0f) { \
1165 dy_dx = dy_tex / dx_tex; \
1166 dx_dy = 1.0f/dy_dx; \
1170 if (dx_tex > 0.0f) { \
1171 if (dy_tex > 0.0f) { \
1174 switch (envmode) { \
1176 SPAN1(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1180 SPAN1(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1183 SPAN1(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1186 SPAN1(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1188 default: /* unexpected env mode */ \
1195 SPAN1(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1198 SPAN1(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1201 SPAN1(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1204 SPAN1(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1207 SPAN1(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1215 else { /* dy_tex <= 0.0f */ \
1218 switch (envmode) { \
1220 SPAN2(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1224 SPAN2(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1227 SPAN2(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1230 SPAN2(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1239 SPAN2(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1242 SPAN2(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1245 SPAN2(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1248 SPAN2(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1251 SPAN2(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1260 else { /* dx_tex < 0.0f */ \
1261 if (dy_tex > 0.0f) { \
1264 switch (envmode) { \
1266 SPAN3(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1270 SPAN3(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1273 SPAN3(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1276 SPAN3(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1285 SPAN3(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1288 SPAN3(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1291 SPAN3(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1294 SPAN3(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1297 SPAN3(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1305 else { /* dy_tex <= 0.0f */ \
1308 switch (envmode) { \
1310 SPAN4(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1314 SPAN4(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1317 SPAN4(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1320 SPAN4(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1329 SPAN4(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1332 SPAN4(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1335 SPAN4(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1338 SPAN4(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1341 SPAN4(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1356 switch (envmode) { \
1358 OLD_SPAN(NEAREST_RGB;MODULATE,3); \
1362 OLD_SPAN(NEAREST_RGB_REPLACE,3); \
1365 OLD_SPAN(NEAREST_RGB;BLEND,3); \
1368 OLD_SPAN(NEAREST_RGB;ADD,3); \
1377 OLD_SPAN(NEAREST_RGBA;MODULATE,4); \
1380 OLD_SPAN(NEAREST_RGBA;DECAL,4); \
1383 OLD_SPAN(NEAREST_RGBA;BLEND,4); \
1386 OLD_SPAN(NEAREST_RGBA;ADD,4); \
1389 OLD_SPAN(NEAREST_RGBA_REPLACE,4); \
1397 gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1398 fogspan, rgba, GL_POLYGON); \
1399 ffr = ffg = ffb = ffa = 0; \
1403 #include "s_tritemp.h"
1409 #undef X_Y_TEX_COORD
1410 #undef Y_X_TEX_COORD
1418 * Render an perspective corrected RGB/RGBA textured triangle.
1419 * The Q (aka V in Mesa) coordinate must be zero such that the divide
1420 * by interpolated Q/W comes out right.
1422 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
1423 * Send all questions and bug reports to him.
1425 static void lin_persp_textured_triangle( GLcontext
*ctx
,
1428 const SWvertex
*v2
)
1431 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1432 #define INTERP_RGB 1
1433 #define INTERP_ALPHA 1
1434 #define INTERP_TEX 1
1435 #define SETUP_CODE \
1436 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
1437 struct gl_texture_object *obj = unit->Current2D; \
1438 const GLint b = obj->BaseLevel; \
1439 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
1440 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
1441 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
1442 GLchan *texture = obj->Image[b]->Data; \
1443 const GLint smask = (obj->Image[b]->Width - 1); \
1444 const GLint tmask = (obj->Image[b]->Height - 1); \
1445 const GLint format = obj->Image[b]->Format; \
1446 const GLint envmode = unit->EnvMode; \
1447 GLfloat sscale, tscale; \
1448 GLint comp, tbytesline, tsize; \
1449 GLfixed er, eg, eb, ea; \
1450 GLint tr, tg, tb, ta; \
1452 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
1454 texture = obj->Image[b]->Data; \
1457 if (envmode == GL_BLEND || envmode == GL_ADD) { \
1458 er = FloatToFixed(unit->EnvColor[0]); \
1459 eg = FloatToFixed(unit->EnvColor[1]); \
1460 eb = FloatToFixed(unit->EnvColor[2]); \
1461 ea = FloatToFixed(unit->EnvColor[3]); \
1465 case GL_LUMINANCE: \
1466 case GL_INTENSITY: \
1469 case GL_LUMINANCE_ALPHA: \
1479 gl_problem(NULL, "Bad texture format in lin_persp_texture_triangle"); \
1482 sscale = FIXED_SCALE * twidth; \
1483 tscale = FIXED_SCALE * theight; \
1484 tbytesline = obj->Image[b]->Width * comp; \
1485 tsize = theight * tbytesline;
1488 #define SPAN(DO_TEX,COMP) \
1489 for (i=0;i<n;i++) { \
1490 GLfloat invQ = 1.0f / vv; \
1491 GLfixed ffs = (int)(SS * invQ); \
1492 GLfixed fft = (int)(TT * invQ); \
1493 GLint s = FixedToInt(ffs) & smask; \
1494 GLint t = FixedToInt(fft) & tmask; \
1495 GLint sf = ffs & FIXED_FRAC_MASK; \
1496 GLint tf = fft & FIXED_FRAC_MASK; \
1497 GLint si = FIXED_FRAC_MASK - sf; \
1498 GLint ti = FIXED_FRAC_MASK - tf; \
1499 GLint pos = COMP * ((t << twidth_log2) + s); \
1500 GLchan *tex00 = texture + pos; \
1501 GLchan *tex10 = tex00 + tbytesline; \
1502 GLchan *tex01 = tex00 + COMP; \
1503 GLchan *tex11 = tex10 + COMP; \
1509 tex01 -= tbytesline; \
1510 tex11 -= tbytesline; \
1512 zspan[i] = FixedToDepth(ffz); \
1513 fogspan[i] = fffog / 256; \
1527 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1530 const GLint n = RIGHT-LEFT; \
1531 GLdepth zspan[MAX_WIDTH]; \
1532 GLfixed fogspan[MAX_WIDTH]; \
1533 GLchan rgba[MAX_WIDTH][4]; \
1534 (void) uu; /* please GCC */ \
1536 GLfloat SS = ss * sscale; \
1537 GLfloat TT = tt * tscale; \
1538 GLfloat dSdx = dsdx * sscale; \
1539 GLfloat dTdx = dtdx * tscale; \
1540 GLchan *dest = rgba[0]; \
1541 SS -= 0.5f * FIXED_SCALE * vv; \
1542 TT -= 0.5f * FIXED_SCALE * vv; \
1545 switch (envmode) { \
1547 SPAN(LINEAR_RGB;MODULATE,3); \
1551 SPAN(LINEAR_RGB;REPLACE,3); \
1554 SPAN(LINEAR_RGB;BLEND,3); \
1557 SPAN(LINEAR_RGB;ADD,3); \
1564 switch (envmode) { \
1566 SPAN(LINEAR_RGBA;MODULATE,4); \
1569 SPAN(LINEAR_RGBA;DECAL,4); \
1572 SPAN(LINEAR_RGBA;BLEND,4); \
1575 SPAN(LINEAR_RGBA;REPLACE,4); \
1578 SPAN(LINEAR_RGBA;ADD,4); \
1580 default: /* unexpected env mode */ \
1584 gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1586 rgba, GL_POLYGON ); \
1587 ffr = ffg = ffb = ffa = 0; \
1592 #include "s_tritemp.h"
1599 * Render a smooth-shaded, textured, RGBA triangle.
1600 * Interpolate S,T,U with perspective correction, w/out mipmapping.
1601 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
1602 * R is already used for red.
1604 static void general_textured_triangle( GLcontext
*ctx
,
1607 const SWvertex
*v2
)
1610 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1611 #define INTERP_RGB 1
1612 #define INTERP_ALPHA 1
1613 #define INTERP_TEX 1
1614 #define SETUP_CODE \
1615 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1623 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1626 const GLint n = RIGHT-LEFT; \
1627 GLdepth zspan[MAX_WIDTH]; \
1628 GLfixed fogspan[MAX_WIDTH]; \
1629 GLchan rgba[MAX_WIDTH][4]; \
1630 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
1633 for (i=0;i<n;i++) { \
1634 GLdouble invQ = 1.0 / vv; \
1635 zspan[i] = FixedToDepth(ffz); \
1636 fogspan[i] = fffog / 256; \
1637 rgba[i][RCOMP] = r; \
1638 rgba[i][GCOMP] = g; \
1639 rgba[i][BCOMP] = b; \
1640 rgba[i][ACOMP] = a; \
1653 for (i=0;i<n;i++) { \
1654 GLdouble invQ = 1.0 / vv; \
1655 zspan[i] = FixedToDepth(ffz); \
1656 rgba[i][RCOMP] = FixedToInt(ffr); \
1657 rgba[i][GCOMP] = FixedToInt(ffg); \
1658 rgba[i][BCOMP] = FixedToInt(ffb); \
1659 rgba[i][ACOMP] = FixedToInt(ffa); \
1660 fogspan[i] = fffog / 256; \
1676 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1679 NULL, GL_POLYGON ); \
1683 #include "s_tritemp.h"
1688 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1689 * color interpolation.
1690 * Interpolate S,T,U with perspective correction, w/out mipmapping.
1691 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
1692 * R is already used for red.
1694 static void general_textured_spec_triangle1( GLcontext
*ctx
,
1698 GLdepth zspan
[MAX_WIDTH
],
1699 GLfixed fogspan
[MAX_WIDTH
],
1700 GLchan rgba
[MAX_WIDTH
][4],
1701 GLchan spec
[MAX_WIDTH
][4] )
1704 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1705 #define INTERP_RGB 1
1706 #define INTERP_SPEC 1
1707 #define INTERP_ALPHA 1
1708 #define INTERP_TEX 1
1709 #define SETUP_CODE \
1710 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1711 GLint r, g, b, a, sr, sg, sb; \
1717 sr = v0->specular[0]; \
1718 sg = v0->specular[1]; \
1719 sb = v0->specular[2]; \
1721 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1724 const GLint n = RIGHT-LEFT; \
1725 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
1728 for (i=0;i<n;i++) { \
1729 GLdouble invQ = 1.0 / vv; \
1730 zspan[i] = FixedToDepth(ffz); \
1731 fogspan[i] = fffog / 256; \
1732 rgba[i][RCOMP] = r; \
1733 rgba[i][GCOMP] = g; \
1734 rgba[i][BCOMP] = b; \
1735 rgba[i][ACOMP] = a; \
1736 spec[i][RCOMP] = sr; \
1737 spec[i][GCOMP] = sg; \
1738 spec[i][BCOMP] = sb; \
1751 for (i=0;i<n;i++) { \
1752 GLdouble invQ = 1.0 / vv; \
1753 zspan[i] = FixedToDepth(ffz); \
1754 fogspan[i] = fffog / 256; \
1755 rgba[i][RCOMP] = FixedToInt(ffr); \
1756 rgba[i][GCOMP] = FixedToInt(ffg); \
1757 rgba[i][BCOMP] = FixedToInt(ffb); \
1758 rgba[i][ACOMP] = FixedToInt(ffa); \
1759 spec[i][RCOMP] = FixedToInt(ffsr); \
1760 spec[i][GCOMP] = FixedToInt(ffsg); \
1761 spec[i][BCOMP] = FixedToInt(ffsb); \
1780 gl_write_texture_span( ctx, n, LEFT, Y, zspan, \
1782 s, t, u, NULL, rgba, \
1783 (CONST GLchan (*)[4]) spec, \
1788 #include "s_tritemp.h"
1794 * Compute the lambda value for a fragment. (texture level of detail)
1796 static INLINE GLfloat
1797 compute_lambda( GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
1798 GLfloat invQ
, GLfloat width
, GLfloat height
)
1800 GLfloat dudx
= dsdx
* invQ
* width
;
1801 GLfloat dudy
= dsdy
* invQ
* width
;
1802 GLfloat dvdx
= dtdx
* invQ
* height
;
1803 GLfloat dvdy
= dtdy
* invQ
* height
;
1804 GLfloat r1
= dudx
* dudx
+ dudy
* dudy
;
1805 GLfloat r2
= dvdx
* dvdx
+ dvdy
* dvdy
;
1806 GLfloat rho2
= r1
+ r2
; /* used to be: rho2 = MAX2(r1,r2); */
1807 /* return log base 2 of rho */
1808 return log(rho2
) * 1.442695 * 0.5; /* 1.442695 = 1/log(2) */
1813 * Render a smooth-shaded, textured, RGBA triangle.
1814 * Interpolate S,T,U with perspective correction and compute lambda for
1815 * each fragment. Lambda is used to determine whether to use the
1816 * minification or magnification filter. If minification and using
1817 * mipmaps, lambda is also used to select the texture level of detail.
1819 static void lambda_textured_triangle1( GLcontext
*ctx
,
1823 GLfloat s
[MAX_WIDTH
],
1824 GLfloat t
[MAX_WIDTH
],
1825 GLfloat u
[MAX_WIDTH
] )
1828 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1829 #define INTERP_RGB 1
1830 #define INTERP_ALPHA 1
1831 #define INTERP_TEX 1
1833 #define SETUP_CODE \
1834 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1835 const GLint baseLevel = obj->BaseLevel; \
1836 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1837 const GLfloat twidth = (GLfloat) texImage->Width; \
1838 const GLfloat theight = (GLfloat) texImage->Height; \
1839 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1848 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1851 const GLint n = RIGHT-LEFT; \
1852 GLdepth zspan[MAX_WIDTH]; \
1853 GLfixed fogspan[MAX_WIDTH]; \
1854 GLchan rgba[MAX_WIDTH][4]; \
1855 GLfloat lambda[MAX_WIDTH]; \
1858 for (i=0;i<n;i++) { \
1859 GLdouble invQ = 1.0 / vv; \
1860 zspan[i] = FixedToDepth(ffz); \
1861 fogspan[i] = fffog / 256; \
1862 rgba[i][RCOMP] = r; \
1863 rgba[i][GCOMP] = g; \
1864 rgba[i][BCOMP] = b; \
1865 rgba[i][ACOMP] = a; \
1869 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
1870 invQ, twidth, theight );\
1880 for (i=0;i<n;i++) { \
1881 GLdouble invQ = 1.0 / vv; \
1882 zspan[i] = FixedToDepth(ffz); \
1883 fogspan[i] = fffog / 256; \
1884 rgba[i][RCOMP] = FixedToInt(ffr); \
1885 rgba[i][GCOMP] = FixedToInt(ffg); \
1886 rgba[i][BCOMP] = FixedToInt(ffb); \
1887 rgba[i][ACOMP] = FixedToInt(ffa); \
1891 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
1892 invQ, twidth, theight );\
1905 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1907 rgba, NULL, GL_POLYGON ); \
1911 #include "s_tritemp.h"
1916 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1918 * Interpolate S,T,U with perspective correction and compute lambda for
1919 * each fragment. Lambda is used to determine whether to use the
1920 * minification or magnification filter. If minification and using
1921 * mipmaps, lambda is also used to select the texture level of detail.
1923 static void lambda_textured_spec_triangle1( GLcontext
*ctx
,
1927 GLfloat s
[MAX_WIDTH
],
1928 GLfloat t
[MAX_WIDTH
],
1929 GLfloat u
[MAX_WIDTH
] )
1932 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1933 #define INTERP_RGB 1
1934 #define INTERP_SPEC 1
1935 #define INTERP_ALPHA 1
1936 #define INTERP_TEX 1
1938 #define SETUP_CODE \
1939 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1940 const GLint baseLevel = obj->BaseLevel; \
1941 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1942 const GLfloat twidth = (GLfloat) texImage->Width; \
1943 const GLfloat theight = (GLfloat) texImage->Height; \
1944 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1945 GLint r, g, b, a, sr, sg, sb; \
1951 sr = v0->specular[0]; \
1952 sg = v0->specular[1]; \
1953 sb = v0->specular[2]; \
1956 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1959 const GLint n = RIGHT-LEFT; \
1960 GLdepth zspan[MAX_WIDTH]; \
1961 GLfixed fogspan[MAX_WIDTH]; \
1962 GLchan spec[MAX_WIDTH][4]; \
1963 GLchan rgba[MAX_WIDTH][4]; \
1964 GLfloat lambda[MAX_WIDTH]; \
1967 for (i=0;i<n;i++) { \
1968 GLdouble invQ = 1.0 / vv; \
1969 zspan[i] = FixedToDepth(ffz); \
1970 fogspan[i] = fffog / 256; \
1971 rgba[i][RCOMP] = r; \
1972 rgba[i][GCOMP] = g; \
1973 rgba[i][BCOMP] = b; \
1974 rgba[i][ACOMP] = a; \
1975 spec[i][RCOMP] = sr; \
1976 spec[i][GCOMP] = sg; \
1977 spec[i][BCOMP] = sb; \
1981 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
1982 invQ, twidth, theight );\
1992 for (i=0;i<n;i++) { \
1993 GLdouble invQ = 1.0 / vv; \
1994 zspan[i] = FixedToDepth(ffz); \
1995 fogspan[i] = fffog / 256; \
1996 rgba[i][RCOMP] = FixedToInt(ffr); \
1997 rgba[i][GCOMP] = FixedToInt(ffg); \
1998 rgba[i][BCOMP] = FixedToInt(ffb); \
1999 rgba[i][ACOMP] = FixedToInt(ffa); \
2000 spec[i][RCOMP] = FixedToInt(ffsr); \
2001 spec[i][GCOMP] = FixedToInt(ffsg); \
2002 spec[i][BCOMP] = FixedToInt(ffsb); \
2006 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
2007 invQ, twidth, theight );\
2023 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
2025 rgba, (CONST GLchan (*)[4]) spec, \
2030 #include "s_tritemp.h"
2035 * This is the big one!
2036 * Interpolate Z, RGB, Alpha, and two sets of texture coordinates.
2040 lambda_multitextured_triangle1( GLcontext
*ctx
,
2044 GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
2045 GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
2046 GLfloat u
[MAX_TEXTURE_UNITS
][MAX_WIDTH
])
2049 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2050 #define INTERP_RGB 1
2051 #define INTERP_ALPHA 1
2052 #define INTERP_MULTITEX 1
2054 #define SETUP_CODE \
2055 GLchan rgba[MAX_WIDTH][4]; \
2056 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
2057 GLfloat twidth[MAX_TEXTURE_UNITS], theight[MAX_TEXTURE_UNITS]; \
2067 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \
2068 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2069 const struct gl_texture_object *obj = ctx->Texture.Unit[unit]._Current; \
2070 const GLint baseLevel = obj->BaseLevel; \
2071 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
2072 twidth[unit] = (GLfloat) texImage->Width; \
2073 theight[unit] = (GLfloat) texImage->Height; \
2080 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2083 const GLint n = RIGHT-LEFT; \
2084 GLdepth zspan[MAX_WIDTH]; \
2085 GLfixed fogspan[MAX_WIDTH]; \
2086 GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; \
2089 for (i=0;i<n;i++) { \
2090 zspan[i] = FixedToDepth(ffz); \
2091 fogspan[i] = fffog / 256; \
2094 rgba[i][RCOMP] = r; \
2095 rgba[i][GCOMP] = g; \
2096 rgba[i][BCOMP] = b; \
2097 rgba[i][ACOMP] = a; \
2100 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \
2101 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2102 GLdouble invQ = 1.0 / vv[unit]; \
2103 s[unit][i] = ss[unit] * invQ; \
2104 t[unit][i] = tt[unit] * invQ; \
2105 u[unit][i] = uu[unit] * invQ; \
2106 lambda[unit][i] = compute_lambda(dsdx[unit], dsdy[unit],\
2107 dtdx[unit], dtdy[unit], invQ, \
2108 twidth[unit], theight[unit] ); \
2109 ss[unit] += dsdx[unit]; \
2110 tt[unit] += dtdx[unit]; \
2111 uu[unit] += dudx[unit]; \
2112 vv[unit] += dvdx[unit]; \
2118 else { /* smooth shade */ \
2119 for (i=0;i<n;i++) { \
2120 zspan[i] = FixedToDepth(ffz); \
2121 fogspan[i] = fffog / 256; \
2124 rgba[i][RCOMP] = FixedToInt(ffr); \
2125 rgba[i][GCOMP] = FixedToInt(ffg); \
2126 rgba[i][BCOMP] = FixedToInt(ffb); \
2127 rgba[i][ACOMP] = FixedToInt(ffa); \
2134 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \
2135 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2136 GLdouble invQ = 1.0 / vv[unit]; \
2137 s[unit][i] = ss[unit] * invQ; \
2138 t[unit][i] = tt[unit] * invQ; \
2139 u[unit][i] = uu[unit] * invQ; \
2140 lambda[unit][i] = compute_lambda(dsdx[unit], dsdy[unit],\
2141 dtdx[unit], dtdy[unit], invQ, \
2142 twidth[unit], theight[unit] ); \
2143 ss[unit] += dsdx[unit]; \
2144 tt[unit] += dtdx[unit]; \
2145 uu[unit] += dudx[unit]; \
2146 vv[unit] += dvdx[unit]; \
2152 gl_write_multitexture_span( ctx, n, LEFT, Y, zspan, fogspan, \
2153 (const GLfloat (*)[MAX_WIDTH]) s, \
2154 (const GLfloat (*)[MAX_WIDTH]) t, \
2155 (const GLfloat (*)[MAX_WIDTH]) u, \
2156 (GLfloat (*)[MAX_WIDTH]) lambda, \
2157 rgba, NULL, GL_POLYGON ); \
2160 #include "s_tritemp.h"
2165 * These wrappers are needed to deal with the 32KB / stack frame limit
2166 * on Mac / PowerPC systems.
2169 static void general_textured_spec_triangle(GLcontext
*ctx
,
2172 const SWvertex
*v2
)
2174 GLdepth zspan
[MAX_WIDTH
];
2175 GLfixed fogspan
[MAX_WIDTH
];
2176 GLchan rgba
[MAX_WIDTH
][4], spec
[MAX_WIDTH
][4];
2177 general_textured_spec_triangle1(ctx
,v0
,v1
,v2
,zspan
,fogspan
,rgba
,spec
);
2180 static void lambda_textured_triangle( GLcontext
*ctx
,
2183 const SWvertex
*v2
)
2185 GLfloat s
[MAX_WIDTH
], t
[MAX_WIDTH
], u
[MAX_WIDTH
];
2186 lambda_textured_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2189 static void lambda_textured_spec_triangle( GLcontext
*ctx
,
2192 const SWvertex
*v2
)
2194 GLfloat s
[MAX_WIDTH
];
2195 GLfloat t
[MAX_WIDTH
];
2196 GLfloat u
[MAX_WIDTH
];
2197 lambda_textured_spec_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2201 static void lambda_multitextured_triangle( GLcontext
*ctx
,
2204 const SWvertex
*v2
)
2207 GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
2208 GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
2209 DEFMARRAY(GLfloat
,u
,MAX_TEXTURE_UNITS
,MAX_WIDTH
);
2210 CHECKARRAY(u
,return);
2212 lambda_multitextured_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2219 static void occlusion_zless_triangle( GLcontext
*ctx
,
2222 const SWvertex
*v2
)
2224 if (ctx
->OcclusionResult
) {
2228 #define DO_OCCLUSION_TEST
2230 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2231 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2234 const GLint len = RIGHT-LEFT; \
2235 for (i=0;i<len;i++) { \
2236 GLdepth z = FixedToDepth(ffz); \
2238 if (z < zRow[i]) { \
2239 ctx->OcclusionResult = GL_TRUE; \
2245 #include "s_tritemp.h"
2253 # define dputs(s) puts(s)
2261 * Determine which triangle rendering function to use given the current
2262 * rendering context.
2264 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
2265 * remove tests to this code.
2268 _swrast_choose_triangle( GLcontext
*ctx
)
2270 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
2271 const GLboolean rgbmode
= ctx
->Visual
.RGBAflag
;
2273 if (ctx
->RenderMode
==GL_RENDER
) {
2275 if (ctx
->Polygon
.SmoothFlag
) {
2276 _mesa_set_aa_triangle_function(ctx
);
2277 ASSERT(swrast
->Triangle
);
2281 if (ctx
->Depth
.OcclusionTest
&&
2283 ctx
->Depth
.Mask
== GL_FALSE
&&
2284 ctx
->Depth
.Func
== GL_LESS
&&
2285 !ctx
->Stencil
.Enabled
) {
2287 ctx
->Color
.ColorMask
[0] == 0 &&
2288 ctx
->Color
.ColorMask
[1] == 0 &&
2289 ctx
->Color
.ColorMask
[2] == 0 &&
2290 ctx
->Color
.ColorMask
[3] == 0)
2292 (!rgbmode
&& ctx
->Color
.IndexMask
== 0)) {
2293 dputs("occlusion_test_triangle");
2294 swrast
->Triangle
= occlusion_zless_triangle
;
2299 if (ctx
->Texture
._ReallyEnabled
) {
2300 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
2301 GLint format
, filter
;
2302 const struct gl_texture_object
*current2Dtex
= ctx
->Texture
.Unit
[0].Current2D
;
2303 const struct gl_texture_image
*image
;
2304 /* First see if we can used an optimized 2-D texture function */
2305 if (ctx
->Texture
._ReallyEnabled
==TEXTURE0_2D
2306 && current2Dtex
->WrapS
==GL_REPEAT
2307 && current2Dtex
->WrapT
==GL_REPEAT
2308 && ((image
= current2Dtex
->Image
[current2Dtex
->BaseLevel
]) != 0) /* correct! */
2310 && ((format
= image
->Format
)==GL_RGB
|| format
==GL_RGBA
)
2311 && (filter
= current2Dtex
->MinFilter
)==current2Dtex
->MagFilter
2312 && ctx
->Light
.Model
.ColorControl
==GL_SINGLE_COLOR
2313 && ctx
->Texture
.Unit
[0].EnvMode
!=GL_COMBINE_EXT
) {
2315 if (ctx
->Hint
.PerspectiveCorrection
==GL_FASTEST
) {
2317 if (filter
==GL_NEAREST
2319 && (ctx
->Texture
.Unit
[0].EnvMode
==GL_REPLACE
2320 || ctx
->Texture
.Unit
[0].EnvMode
==GL_DECAL
)
2321 && ((swrast
->_RasterMask
==DEPTH_BIT
2322 && ctx
->Depth
.Func
==GL_LESS
2323 && ctx
->Depth
.Mask
==GL_TRUE
)
2324 || swrast
->_RasterMask
==0)
2325 && ctx
->Polygon
.StippleFlag
==GL_FALSE
) {
2327 if (swrast
->_RasterMask
==DEPTH_BIT
) {
2328 swrast
->Triangle
= simple_z_textured_triangle
;
2329 dputs("simple_z_textured_triangle");
2332 swrast
->Triangle
= simple_textured_triangle
;
2333 dputs("simple_textured_triangle");
2337 if (ctx
->Texture
.Unit
[0].EnvMode
==GL_ADD
) {
2338 swrast
->Triangle
= general_textured_triangle
;
2339 dputs("general_textured_triangle");
2342 swrast
->Triangle
= affine_textured_triangle
;
2343 dputs("affine_textured_triangle");
2348 if (filter
==GL_NEAREST
) {
2349 swrast
->Triangle
= near_persp_textured_triangle
;
2350 dputs("near_persp_textured_triangle");
2353 swrast
->Triangle
= lin_persp_textured_triangle
;
2354 dputs("lin_persp_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
;