1 /* $Id: s_triangle.c,v 1.3 2000/11/13 20:02:57 keithw 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
,
78 GLuint index = v0->index; \
80 /* set the color index */ \
81 (*ctx->Driver.Index)( ctx, index ); \
84 #define INNER_LOOP( LEFT, RIGHT, Y ) \
86 const GLint n = RIGHT-LEFT; \
88 GLdepth zspan[MAX_WIDTH]; \
89 GLfixed fogspan[MAX_WIDTH]; \
92 zspan[i] = FixedToDepth(ffz); \
94 fogspan[i] = fffog / 256; \
97 gl_write_monoindex_span( ctx, n, LEFT, Y, zspan, \
98 fogspan, index, GL_POLYGON ); \
102 #include "s_tritemp.h"
108 * Render a smooth-shaded color index triangle.
110 static void smooth_ci_triangle( GLcontext
*ctx
,
116 #define INTERP_INDEX 1
118 #define INNER_LOOP( LEFT, RIGHT, Y ) \
120 const GLint n = RIGHT-LEFT; \
122 GLdepth zspan[MAX_WIDTH]; \
123 GLfixed fogspan[MAX_WIDTH]; \
124 GLuint index[MAX_WIDTH]; \
126 for (i=0;i<n;i++) { \
127 zspan[i] = FixedToDepth(ffz); \
129 index[i] = FixedToInt(ffi); \
131 fogspan[i] = fffog / 256; \
134 gl_write_index_span( ctx, n, LEFT, Y, zspan, fogspan, \
135 index, GL_POLYGON ); \
139 #include "s_tritemp.h"
145 * Render a flat-shaded RGBA triangle.
147 static void flat_rgba_triangle( GLcontext
*ctx
,
153 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
157 /* set the color */ \
158 GLchan r = v0->color[0]; \
159 GLchan g = v0->color[1]; \
160 GLchan b = v0->color[2]; \
161 GLchan a = v0->color[3]; \
162 (*ctx->Driver.Color)( ctx, r, g, b, a ); \
165 #define INNER_LOOP( LEFT, RIGHT, Y ) \
167 const GLint n = RIGHT-LEFT; \
169 GLdepth zspan[MAX_WIDTH]; \
170 GLfixed fogspan[MAX_WIDTH]; \
172 for (i=0;i<n;i++) { \
173 zspan[i] = FixedToDepth(ffz); \
175 fogspan[i] = fffog / 256; \
178 gl_write_monocolor_span( ctx, n, LEFT, Y, zspan, \
185 #include "s_tritemp.h"
187 ASSERT(!ctx
->Texture
._ReallyEnabled
); /* texturing must be off */
188 ASSERT(ctx
->Light
.ShadeModel
==GL_FLAT
);
194 * Render a smooth-shaded RGBA triangle.
196 static void smooth_rgba_triangle( GLcontext
*ctx
,
203 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
205 #define INTERP_ALPHA 1
207 #define INNER_LOOP( LEFT, RIGHT, Y ) \
209 const GLint n = RIGHT-LEFT; \
211 GLdepth zspan[MAX_WIDTH]; \
212 GLchan rgba[MAX_WIDTH][4]; \
213 GLfixed fogspan[MAX_WIDTH]; \
215 for (i=0;i<n;i++) { \
216 zspan[i] = FixedToDepth(ffz); \
217 rgba[i][RCOMP] = FixedToInt(ffr); \
218 rgba[i][GCOMP] = FixedToInt(ffg); \
219 rgba[i][BCOMP] = FixedToInt(ffb); \
220 rgba[i][ACOMP] = FixedToInt(ffa); \
221 fogspan[i] = fffog / 256; \
229 gl_write_rgba_span( ctx, n, LEFT, Y, \
230 (CONST GLdepth *) zspan, \
232 rgba, GL_POLYGON ); \
236 #include "s_tritemp.h"
238 ASSERT(!ctx
->Texture
._ReallyEnabled
); /* texturing must be off */
239 ASSERT(ctx
->Light
.ShadeModel
==GL_SMOOTH
);
244 * Render an RGB, GL_DECAL, textured triangle.
245 * Interpolate S,T only w/out mipmapping or perspective correction.
249 static void simple_textured_triangle( GLcontext
*ctx
,
254 #define INTERP_INT_TEX 1
255 #define S_SCALE twidth
256 #define T_SCALE theight
258 struct gl_texture_object *obj = ctx->Texture.Unit[0].CurrentD[2]; \
259 GLint b = obj->BaseLevel; \
260 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
261 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
262 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
263 GLchan *texture = obj->Image[b]->Data; \
264 GLint smask = obj->Image[b]->Width - 1; \
265 GLint tmask = obj->Image[b]->Height - 1; \
267 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
269 texture = obj->Image[b]->Data; \
273 #define INNER_LOOP( LEFT, RIGHT, Y ) \
275 CONST GLint n = RIGHT-LEFT; \
277 GLchan rgb[MAX_WIDTH][3]; \
279 ffs -= FIXED_HALF; /* off-by-one error? */ \
281 for (i=0;i<n;i++) { \
282 GLint s = FixedToInt(ffs) & smask; \
283 GLint t = FixedToInt(fft) & tmask; \
284 GLint pos = (t << twidth_log2) + s; \
285 pos = pos + pos + pos; /* multiply by 3 */ \
286 rgb[i][RCOMP] = texture[pos]; \
287 rgb[i][GCOMP] = texture[pos+1]; \
288 rgb[i][BCOMP] = texture[pos+2]; \
292 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
293 (CONST GLchan (*)[3]) rgb, NULL ); \
297 #include "s_tritemp.h"
302 * Render an RGB, GL_DECAL, textured triangle.
303 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
304 * perspective correction.
308 static void simple_z_textured_triangle( GLcontext
*ctx
,
314 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
315 #define INTERP_INT_TEX 1
316 #define S_SCALE twidth
317 #define T_SCALE theight
319 struct gl_texture_object *obj = ctx->Texture.Unit[0].CurrentD[2]; \
320 GLint b = obj->BaseLevel; \
321 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
322 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
323 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
324 GLchan *texture = obj->Image[b]->Data; \
325 GLint smask = obj->Image[b]->Width - 1; \
326 GLint tmask = obj->Image[b]->Height - 1; \
328 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
330 texture = obj->Image[b]->Data; \
334 #define INNER_LOOP( LEFT, RIGHT, Y ) \
336 CONST GLint n = RIGHT-LEFT; \
338 GLchan rgb[MAX_WIDTH][3]; \
339 GLubyte mask[MAX_WIDTH]; \
342 ffs -= FIXED_HALF; /* off-by-one error? */ \
344 for (i=0;i<n;i++) { \
345 GLdepth z = FixedToDepth(ffz); \
347 GLint s = FixedToInt(ffs) & smask; \
348 GLint t = FixedToInt(fft) & tmask; \
349 GLint pos = (t << twidth_log2) + s; \
350 pos = pos + pos + pos; /* multiply by 3 */ \
351 rgb[i][RCOMP] = texture[pos]; \
352 rgb[i][GCOMP] = texture[pos+1]; \
353 rgb[i][BCOMP] = texture[pos+2]; \
364 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
365 (CONST GLchan (*)[3]) rgb, mask ); \
369 #include "s_tritemp.h"
375 * Render an RGB/RGBA textured triangle without perspective correction.
377 static void affine_textured_triangle( GLcontext
*ctx
,
383 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
385 #define INTERP_ALPHA 1
386 #define INTERP_INT_TEX 1
387 #define S_SCALE twidth
388 #define T_SCALE theight
390 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
391 struct gl_texture_object *obj = unit->CurrentD[2]; \
392 GLint b = obj->BaseLevel; \
393 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
394 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
395 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
396 GLchan *texture = obj->Image[b]->Data; \
397 GLint smask = obj->Image[b]->Width - 1; \
398 GLint tmask = obj->Image[b]->Height - 1; \
399 GLint format = obj->Image[b]->Format; \
400 GLint filter = obj->MinFilter; \
401 GLint envmode = unit->EnvMode; \
402 GLint comp, tbytesline, tsize; \
403 GLfixed er, eg, eb, ea; \
404 GLint tr, tg, tb, ta; \
406 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
408 texture = obj->Image[b]->Data; \
411 if (envmode == GL_BLEND || envmode == GL_ADD) { \
412 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
413 er = FloatToFixed(unit->EnvColor[0]); \
414 eg = FloatToFixed(unit->EnvColor[1]); \
415 eb = FloatToFixed(unit->EnvColor[2]); \
416 ea = FloatToFixed(unit->EnvColor[3]); \
424 case GL_LUMINANCE_ALPHA: \
434 gl_problem(NULL, "Bad texture format in affine_texture_triangle");\
437 tbytesline = obj->Image[b]->Width * comp; \
438 tsize = theight * tbytesline;
441 /* Instead of defining a function for each mode, a test is done
442 * between the outer and inner loops. This is to reduce code size
443 * and complexity. Observe that an optimizing compiler kills
444 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
447 #define NEAREST_RGB \
454 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
455 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
456 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
457 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
458 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
459 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
462 #define NEAREST_RGBA \
468 #define LINEAR_RGBA \
469 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
470 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
471 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
472 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
473 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
474 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
475 ta = (ti * (si * tex00[3] + sf * tex01[3]) + \
476 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
479 dest[0] = ffr * (tr + 1) >> (FIXED_SHIFT + 8); \
480 dest[1] = ffg * (tg + 1) >> (FIXED_SHIFT + 8); \
481 dest[2] = ffb * (tb + 1) >> (FIXED_SHIFT + 8); \
482 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
485 dest[0] = ((0xff - ta) * ffr + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
486 dest[1] = ((0xff - ta) * ffg + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
487 dest[2] = ((0xff - ta) * ffb + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
488 dest[3] = FixedToInt(ffa)
491 dest[0] = ((0xff - tr) * ffr + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
492 dest[1] = ((0xff - tg) * ffg + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
493 dest[2] = ((0xff - tb) * ffb + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
494 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
503 dest[0] = ((ffr << 8) + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
504 dest[1] = ((ffg << 8) + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
505 dest[2] = ((ffb << 8) + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
506 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
510 #define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE
512 #define NEAREST_RGBA_REPLACE *(GLint *)dest = *(GLint *)tex00
514 #define SPAN1(DO_TEX,COMP) \
515 for (i=0;i<n;i++) { \
516 GLint s = FixedToInt(ffs) & smask; \
517 GLint t = FixedToInt(fft) & tmask; \
518 GLint pos = (t << twidth_log2) + s; \
519 GLchan *tex00 = texture + COMP * pos; \
520 zspan[i] = FixedToDepth(ffz); \
521 fogspan[i] = fffog / 256; \
534 #define SPAN2(DO_TEX,COMP) \
535 for (i=0;i<n;i++) { \
536 GLint s = FixedToInt(ffs) & smask; \
537 GLint t = FixedToInt(fft) & tmask; \
538 GLint sf = ffs & FIXED_FRAC_MASK; \
539 GLint tf = fft & FIXED_FRAC_MASK; \
540 GLint si = FIXED_FRAC_MASK - sf; \
541 GLint ti = FIXED_FRAC_MASK - tf; \
542 GLint pos = (t << twidth_log2) + s; \
543 GLchan *tex00 = texture + COMP * pos; \
544 GLchan *tex10 = tex00 + tbytesline; \
545 GLchan *tex01 = tex00 + COMP; \
546 GLchan *tex11 = tex10 + COMP; \
552 tex01 -= tbytesline; \
553 tex11 -= tbytesline; \
555 zspan[i] = FixedToDepth(ffz); \
556 fogspan[i] = fffog / 256; \
569 /* here comes the heavy part.. (something for the compiler to chew on) */
570 #define INNER_LOOP( LEFT, RIGHT, Y ) \
572 CONST GLint n = RIGHT-LEFT; \
574 GLdepth zspan[MAX_WIDTH]; \
575 GLfixed fogspan[MAX_WIDTH]; \
576 GLchan rgba[MAX_WIDTH][4]; \
578 GLchan *dest = rgba[0]; \
579 ffs -= FIXED_HALF; /* off-by-one error? */ \
587 SPAN1(NEAREST_RGB;MODULATE,3); \
591 SPAN1(NEAREST_RGB_REPLACE,3); \
594 SPAN1(NEAREST_RGB;BLEND,3); \
597 SPAN1(NEAREST_RGB;ADD,3); \
599 default: /* unexpected env mode */ \
606 SPAN1(NEAREST_RGBA;MODULATE,4); \
609 SPAN1(NEAREST_RGBA;DECAL,4); \
612 SPAN1(NEAREST_RGBA;BLEND,4); \
615 SPAN1(NEAREST_RGBA;ADD,4); \
618 SPAN1(NEAREST_RGBA_REPLACE,4); \
620 default: /* unexpected env mode */ \
633 SPAN2(LINEAR_RGB;MODULATE,3); \
637 SPAN2(LINEAR_RGB;REPLACE,3); \
640 SPAN2(LINEAR_RGB;BLEND,3); \
643 SPAN2(LINEAR_RGB;ADD,3); \
645 default: /* unexpected env mode */ \
652 SPAN2(LINEAR_RGBA;MODULATE,4); \
655 SPAN2(LINEAR_RGBA;DECAL,4); \
658 SPAN2(LINEAR_RGBA;BLEND,4); \
661 SPAN2(LINEAR_RGBA;ADD,4); \
664 SPAN2(LINEAR_RGBA;REPLACE,4); \
666 default: /* unexpected env mode */ \
673 gl_write_rgba_span(ctx, n, LEFT, Y, zspan, \
676 /* explicit kill of variables: */ \
677 ffr = ffg = ffb = ffa = 0; \
681 #include "s_tritemp.h"
689 * Render an perspective corrected RGB/RGBA textured triangle.
690 * The Q (aka V in Mesa) coordinate must be zero such that the divide
691 * by interpolated Q/W comes out right.
693 * This function only renders textured triangles that use GL_NEAREST.
694 * Perspective correction works right.
696 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
697 * Send all questions and bug reports to him.
699 static void near_persp_textured_triangle(GLcontext
*ctx
,
704 /* The BIAS value is used to shift negative values into positive values.
705 * Without this, negative texture values don't GL_REPEAT correctly at just
706 * below zero, because (int)-0.5 = 0 = (int)0.5. We're not going to worry
707 * about texture coords less than -BIAS. This could be fixed by using
708 * FLOORF etc. instead, but this is slower...
713 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
715 #define INTERP_ALPHA 1
718 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
719 struct gl_texture_object *obj = unit->CurrentD[2]; \
720 const GLint b = obj->BaseLevel; \
721 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
722 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
723 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
724 GLchan *texture = obj->Image[b]->Data; \
725 const GLint smask = (obj->Image[b]->Width - 1); \
726 const GLint tmask = (obj->Image[b]->Height - 1); \
727 const GLint format = obj->Image[b]->Format; \
728 const GLint envmode = unit->EnvMode; \
729 GLfloat sscale, tscale; \
730 GLfixed er, eg, eb, ea; \
731 GLint tr, tg, tb, ta; \
733 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
735 texture = obj->Image[b]->Data; \
738 if (envmode == GL_BLEND || envmode == GL_ADD) { \
739 er = FloatToFixed(unit->EnvColor[0]); \
740 eg = FloatToFixed(unit->EnvColor[1]); \
741 eb = FloatToFixed(unit->EnvColor[2]); \
742 ea = FloatToFixed(unit->EnvColor[3]); \
748 #define OLD_SPAN(DO_TEX,COMP) \
749 for (i=0;i<n;i++) { \
750 GLfloat invQ = 1.0f / vv; \
751 GLint s = (int)(SS * invQ + BIAS) & smask; \
752 GLint t = (int)(TT * invQ + BIAS) & tmask; \
753 GLint pos = COMP * ((t << twidth_log2) + s); \
754 GLchan *tex00 = texture + pos; \
755 zspan[i] = FixedToDepth(ffz); \
756 fogspan[i] = fffog / 256; \
770 #define X_Y_TEX_COORD(X, Y) ((((int)(X) & tmask) << twidth_log2) + ((int)(Y) & smask))
771 #define Y_X_TEX_COORD(X, Y) ((((int)(Y) & tmask) << twidth_log2) + ((int)(X) & smask))
773 #define SPAN1(DO_TEX, COMP, TEX_COORD) { \
774 GLfloat x_max = CEILF(x_tex); \
775 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \
776 GLint j, x_m = (int)x_max; \
778 if ((int)y_max != (int)y_tex) { \
779 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \
780 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
781 pos = COMP * TEX_COORD(x_tex, y_tex); \
782 DRAW_LINE (DO_TEX); \
785 nominator += vv * x_max; \
786 denominator -= dvdx * x_max; \
787 j = nominator / denominator; \
788 pos = COMP * TEX_COORD(x_tex, y_tex); \
789 DRAW_LINE (DO_TEX); \
793 if ((int)y_max != (int)y_tex) { \
794 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \
795 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
796 pos = COMP * TEX_COORD(x_m, y_tex); \
797 DRAW_LINE (DO_TEX); \
801 denominator -= dvdx; \
802 j = nominator/denominator; \
803 pos = COMP * TEX_COORD(x_m, y_tex); \
804 DRAW_LINE (DO_TEX); \
809 #define SPAN2(DO_TEX, COMP, TEX_COORD) { \
810 GLfloat x_max = CEILF (x_tex); \
811 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \
812 GLint j, x_m = (int) x_max; \
814 if ((int)y_max != (int)y_tex) { \
815 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \
816 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
817 pos = COMP * TEX_COORD(x_tex, y_tex); \
818 DRAW_LINE (DO_TEX); \
821 nominator += vv * x_max; \
822 denominator -= dvdx * x_max; \
823 j = nominator / denominator; \
824 pos = COMP * TEX_COORD(x_tex, y_tex); \
825 DRAW_LINE (DO_TEX); \
829 if ((int)y_max != (int)y_tex) { \
830 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \
831 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);\
832 pos = COMP * TEX_COORD(x_m, y_tex); \
833 DRAW_LINE (DO_TEX); \
837 denominator -= dvdx; \
838 j = nominator/denominator; \
839 pos = COMP * TEX_COORD(x_m, y_tex); \
840 DRAW_LINE (DO_TEX); \
845 #define SPAN3(DO_TEX, COMP, TEX_COORD) { \
846 GLfloat x_min = FLOORF (x_tex); \
847 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \
848 GLint j, x_m = (int)x_min; \
850 if ((int)y_min != (int)y_tex) { \
851 GLfloat x_mid = x_tex + (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); \
857 nominator += vv*x_min; \
858 denominator -= dvdx*x_min; \
859 j = nominator / denominator; \
860 pos = COMP * TEX_COORD(x_m, y_tex); \
861 DRAW_LINE (DO_TEX); \
866 if ((int)y_min != (int)y_tex) { \
867 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \
868 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
869 pos = COMP * TEX_COORD(x_m, y_tex); \
870 DRAW_LINE (DO_TEX); \
874 denominator += dvdx; \
875 j = nominator/denominator; \
876 pos = COMP * TEX_COORD(x_m, y_tex); \
877 DRAW_LINE (DO_TEX); \
881 #define SPAN4(DO_TEX, COMP, TEX_COORD) \
883 GLfloat x_min = FLOORF(x_tex); \
884 GLint x_m = (int)x_min; \
885 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \
888 if ((int)y_min != (int)y_tex) { \
889 GLfloat x_mid = x_tex + (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); \
895 nominator += vv * x_min; \
896 denominator -= dvdx * x_min; \
897 j = nominator / denominator; \
898 pos = COMP * TEX_COORD(x_m, y_tex); \
899 DRAW_LINE (DO_TEX); \
904 if ((int)y_min != (int)y_tex) { \
905 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \
906 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
907 pos = COMP * TEX_COORD(x_m, (y_tex)); \
908 DRAW_LINE (DO_TEX); \
912 denominator += dvdx; \
913 j = nominator/denominator; \
914 pos = COMP * TEX_COORD(x_m, y_tex); \
915 DRAW_LINE (DO_TEX); \
919 #define DRAW_LINE(DO_TEX) \
921 GLchan *tex00 = texture + pos; \
922 if (j>n || j<-100000) \
925 zspan[i] = FixedToDepth(ffz); \
926 fogspan[i] = fffog / 256; \
939 #define INNER_LOOP( LEFT, RIGHT, Y ) \
942 const GLint n = RIGHT-LEFT; \
943 GLdepth zspan[MAX_WIDTH]; \
944 GLfixed fogspan[MAX_WIDTH]; \
945 GLchan rgba[MAX_WIDTH][4]; \
946 (void)uu; /* please GCC */ \
948 GLchan *dest = rgba[0]; \
949 GLfloat SS = ss * sscale; \
950 GLfloat TT = tt * tscale; \
951 GLfloat dSdx = dsdx * sscale; \
952 GLfloat dTdx = dtdx * tscale; \
957 if (n<5) /* When line very short, setup-time > speed-gain. */ \
958 goto old_span; /* So: take old method */ \
961 dx_tex = (SS + n * dSdx) / (vv + n * dvdx) - x_tex, \
962 dy_tex = (TT + n * dTdx) / (vv + n * dvdx) - y_tex; \
963 /* Choose between walking over texture or over pixelline: */ \
964 /* If there are few texels, walk over texture otherwise */ \
965 /* walk over pixelarray. The quotient on the right side */ \
966 /* should give the timeratio needed to draw one texel in */ \
967 /* comparison to one pixel. Depends on CPU. */ \
968 if (dx_tex*dx_tex + dy_tex*dy_tex < (n*n)/16) { \
971 if (dx_tex*dx_tex > dy_tex*dy_tex) { \
972 /* if (FABSF(dx_tex) > FABSF(dy_tex)) */ \
973 GLfloat nominator = - SS - vv * BIAS; \
974 GLfloat denominator = dvdx * BIAS + dSdx; \
977 if (dy_tex != 0.0f) { \
978 dy_dx = dy_tex / dx_tex; \
979 dx_dy = 1.0f/dy_dx; \
983 if (dx_tex > 0.0f) { \
984 if (dy_tex > 0.0f) { \
989 SPAN1(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
993 SPAN1(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
996 SPAN1(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
999 SPAN1(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1001 default: /* unexpected env mode */ \
1008 SPAN1(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1011 SPAN1(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1014 SPAN1(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1017 SPAN1(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1020 SPAN1(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1022 default: /* unexpected env mode */ \
1028 else { /* dy_tex <= 0.0f */ \
1031 switch (envmode) { \
1033 SPAN2(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1037 SPAN2(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1040 SPAN2(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1043 SPAN2(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1045 default: /* unexpected env mode */ \
1052 SPAN2(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1055 SPAN2(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1058 SPAN2(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1061 SPAN2(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1064 SPAN2(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1066 default: /* unexpected env mode */ \
1073 else { /* dx_tex < 0.0f */ \
1074 if (dy_tex > 0.0f) { \
1077 switch (envmode) { \
1079 SPAN3(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1083 SPAN3(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1086 SPAN3(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1089 SPAN3(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1091 default: /* unexpected env mode */ \
1098 SPAN3(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1101 SPAN3(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1104 SPAN3(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1107 SPAN3(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1110 SPAN3(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1112 default: /* unexpected env mode */ \
1118 else { /* dy_tex <= 0.0f */ \
1121 switch (envmode) { \
1123 SPAN4(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1127 SPAN4(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1130 SPAN4(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1133 SPAN4(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1142 SPAN4(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1145 SPAN4(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1148 SPAN4(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1151 SPAN4(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1154 SPAN4(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1156 default: /* unexpected env mode */ \
1164 else { /* FABSF(dx_tex) > FABSF(dy_tex) */ \
1168 GLfloat nominator, denominator; \
1169 if (dx_tex == 0.0f /* && dy_tex == 0.0f*/) \
1170 goto old_span; /* case so special, that use old */ \
1171 /* swap some x-values and y-values */ \
1174 swap = x_tex, x_tex = y_tex, y_tex = swap; \
1175 swap = dx_tex, dx_tex = dy_tex, dy_tex = swap; \
1176 nominator = - SS - vv * BIAS; \
1177 denominator = dvdx * BIAS + dSdx; \
1178 if (dy_tex != 0.0f) { \
1179 dy_dx = dy_tex / dx_tex; \
1180 dx_dy = 1.0f/dy_dx; \
1184 if (dx_tex > 0.0f) { \
1185 if (dy_tex > 0.0f) { \
1188 switch (envmode) { \
1190 SPAN1(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1194 SPAN1(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1197 SPAN1(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1200 SPAN1(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1202 default: /* unexpected env mode */ \
1209 SPAN1(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1212 SPAN1(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1215 SPAN1(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1218 SPAN1(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1221 SPAN1(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1229 else { /* dy_tex <= 0.0f */ \
1232 switch (envmode) { \
1234 SPAN2(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1238 SPAN2(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1241 SPAN2(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1244 SPAN2(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1253 SPAN2(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1256 SPAN2(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1259 SPAN2(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1262 SPAN2(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1265 SPAN2(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1274 else { /* dx_tex < 0.0f */ \
1275 if (dy_tex > 0.0f) { \
1278 switch (envmode) { \
1280 SPAN3(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1284 SPAN3(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1287 SPAN3(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1290 SPAN3(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1299 SPAN3(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1302 SPAN3(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1305 SPAN3(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1308 SPAN3(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1311 SPAN3(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1319 else { /* dy_tex <= 0.0f */ \
1322 switch (envmode) { \
1324 SPAN4(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1328 SPAN4(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1331 SPAN4(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1334 SPAN4(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1343 SPAN4(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1346 SPAN4(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1349 SPAN4(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1352 SPAN4(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1355 SPAN4(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1370 switch (envmode) { \
1372 OLD_SPAN(NEAREST_RGB;MODULATE,3); \
1376 OLD_SPAN(NEAREST_RGB_REPLACE,3); \
1379 OLD_SPAN(NEAREST_RGB;BLEND,3); \
1382 OLD_SPAN(NEAREST_RGB;ADD,3); \
1391 OLD_SPAN(NEAREST_RGBA;MODULATE,4); \
1394 OLD_SPAN(NEAREST_RGBA;DECAL,4); \
1397 OLD_SPAN(NEAREST_RGBA;BLEND,4); \
1400 OLD_SPAN(NEAREST_RGBA;ADD,4); \
1403 OLD_SPAN(NEAREST_RGBA_REPLACE,4); \
1411 gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1412 fogspan, rgba, GL_POLYGON); \
1413 ffr = ffg = ffb = ffa = 0; \
1417 #include "s_tritemp.h"
1423 #undef X_Y_TEX_COORD
1424 #undef Y_X_TEX_COORD
1432 * Render an perspective corrected RGB/RGBA textured triangle.
1433 * The Q (aka V in Mesa) coordinate must be zero such that the divide
1434 * by interpolated Q/W comes out right.
1436 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
1437 * Send all questions and bug reports to him.
1439 static void lin_persp_textured_triangle( GLcontext
*ctx
,
1445 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1446 #define INTERP_RGB 1
1447 #define INTERP_ALPHA 1
1448 #define INTERP_TEX 1
1449 #define SETUP_CODE \
1450 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
1451 struct gl_texture_object *obj = unit->CurrentD[2]; \
1452 const GLint b = obj->BaseLevel; \
1453 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
1454 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
1455 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
1456 GLchan *texture = obj->Image[b]->Data; \
1457 const GLint smask = (obj->Image[b]->Width - 1); \
1458 const GLint tmask = (obj->Image[b]->Height - 1); \
1459 const GLint format = obj->Image[b]->Format; \
1460 const GLint envmode = unit->EnvMode; \
1461 GLfloat sscale, tscale; \
1462 GLint comp, tbytesline, tsize; \
1463 GLfixed er, eg, eb, ea; \
1464 GLint tr, tg, tb, ta; \
1466 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
1468 texture = obj->Image[b]->Data; \
1471 if (envmode == GL_BLEND || envmode == GL_ADD) { \
1472 er = FloatToFixed(unit->EnvColor[0]); \
1473 eg = FloatToFixed(unit->EnvColor[1]); \
1474 eb = FloatToFixed(unit->EnvColor[2]); \
1475 ea = FloatToFixed(unit->EnvColor[3]); \
1479 case GL_LUMINANCE: \
1480 case GL_INTENSITY: \
1483 case GL_LUMINANCE_ALPHA: \
1493 gl_problem(NULL, "Bad texture format in lin_persp_texture_triangle"); \
1496 sscale = FIXED_SCALE * twidth; \
1497 tscale = FIXED_SCALE * theight; \
1498 tbytesline = obj->Image[b]->Width * comp; \
1499 tsize = theight * tbytesline;
1502 #define SPAN(DO_TEX,COMP) \
1503 for (i=0;i<n;i++) { \
1504 GLfloat invQ = 1.0f / vv; \
1505 GLfixed ffs = (int)(SS * invQ); \
1506 GLfixed fft = (int)(TT * invQ); \
1507 GLint s = FixedToInt(ffs) & smask; \
1508 GLint t = FixedToInt(fft) & tmask; \
1509 GLint sf = ffs & FIXED_FRAC_MASK; \
1510 GLint tf = fft & FIXED_FRAC_MASK; \
1511 GLint si = FIXED_FRAC_MASK - sf; \
1512 GLint ti = FIXED_FRAC_MASK - tf; \
1513 GLint pos = COMP * ((t << twidth_log2) + s); \
1514 GLchan *tex00 = texture + pos; \
1515 GLchan *tex10 = tex00 + tbytesline; \
1516 GLchan *tex01 = tex00 + COMP; \
1517 GLchan *tex11 = tex10 + COMP; \
1523 tex01 -= tbytesline; \
1524 tex11 -= tbytesline; \
1526 zspan[i] = FixedToDepth(ffz); \
1527 fogspan[i] = fffog / 256; \
1541 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1544 const GLint n = RIGHT-LEFT; \
1545 GLdepth zspan[MAX_WIDTH]; \
1546 GLfixed fogspan[MAX_WIDTH]; \
1547 GLchan rgba[MAX_WIDTH][4]; \
1548 (void) uu; /* please GCC */ \
1550 GLfloat SS = ss * sscale; \
1551 GLfloat TT = tt * tscale; \
1552 GLfloat dSdx = dsdx * sscale; \
1553 GLfloat dTdx = dtdx * tscale; \
1554 GLchan *dest = rgba[0]; \
1555 SS -= 0.5f * FIXED_SCALE * vv; \
1556 TT -= 0.5f * FIXED_SCALE * vv; \
1559 switch (envmode) { \
1561 SPAN(LINEAR_RGB;MODULATE,3); \
1565 SPAN(LINEAR_RGB;REPLACE,3); \
1568 SPAN(LINEAR_RGB;BLEND,3); \
1571 SPAN(LINEAR_RGB;ADD,3); \
1578 switch (envmode) { \
1580 SPAN(LINEAR_RGBA;MODULATE,4); \
1583 SPAN(LINEAR_RGBA;DECAL,4); \
1586 SPAN(LINEAR_RGBA;BLEND,4); \
1589 SPAN(LINEAR_RGBA;REPLACE,4); \
1592 SPAN(LINEAR_RGBA;ADD,4); \
1594 default: /* unexpected env mode */ \
1598 gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1600 rgba, GL_POLYGON ); \
1601 ffr = ffg = ffb = ffa = 0; \
1606 #include "s_tritemp.h"
1613 * Render a smooth-shaded, textured, RGBA triangle.
1614 * Interpolate S,T,U with perspective correction, w/out mipmapping.
1615 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
1616 * R is already used for red.
1618 static void general_textured_triangle( GLcontext
*ctx
,
1624 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1625 #define INTERP_RGB 1
1626 #define INTERP_ALPHA 1
1627 #define INTERP_TEX 1
1628 #define SETUP_CODE \
1629 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1637 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1640 const GLint n = RIGHT-LEFT; \
1641 GLdepth zspan[MAX_WIDTH]; \
1642 GLfixed fogspan[MAX_WIDTH]; \
1643 GLchan rgba[MAX_WIDTH][4]; \
1644 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
1647 for (i=0;i<n;i++) { \
1648 GLdouble invQ = 1.0 / vv; \
1649 zspan[i] = FixedToDepth(ffz); \
1650 fogspan[i] = fffog / 256; \
1651 rgba[i][RCOMP] = r; \
1652 rgba[i][GCOMP] = g; \
1653 rgba[i][BCOMP] = b; \
1654 rgba[i][ACOMP] = a; \
1667 for (i=0;i<n;i++) { \
1668 GLdouble invQ = 1.0 / vv; \
1669 zspan[i] = FixedToDepth(ffz); \
1670 rgba[i][RCOMP] = FixedToInt(ffr); \
1671 rgba[i][GCOMP] = FixedToInt(ffg); \
1672 rgba[i][BCOMP] = FixedToInt(ffb); \
1673 rgba[i][ACOMP] = FixedToInt(ffa); \
1674 fogspan[i] = fffog / 256; \
1690 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1693 NULL, GL_POLYGON ); \
1697 #include "s_tritemp.h"
1702 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1703 * color interpolation.
1704 * Interpolate S,T,U with perspective correction, w/out mipmapping.
1705 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
1706 * R is already used for red.
1708 static void general_textured_spec_triangle1( GLcontext
*ctx
,
1712 GLdepth zspan
[MAX_WIDTH
],
1713 GLfixed fogspan
[MAX_WIDTH
],
1714 GLchan rgba
[MAX_WIDTH
][4],
1715 GLchan spec
[MAX_WIDTH
][4] )
1718 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1719 #define INTERP_RGB 1
1720 #define INTERP_SPEC 1
1721 #define INTERP_ALPHA 1
1722 #define INTERP_TEX 1
1723 #define SETUP_CODE \
1724 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1725 GLint r, g, b, a, sr, sg, sb; \
1731 sr = v0->specular[0]; \
1732 sg = v0->specular[1]; \
1733 sb = v0->specular[2]; \
1735 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1738 const GLint n = RIGHT-LEFT; \
1739 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
1742 for (i=0;i<n;i++) { \
1743 GLdouble invQ = 1.0 / vv; \
1744 zspan[i] = FixedToDepth(ffz); \
1745 fogspan[i] = fffog / 256; \
1746 rgba[i][RCOMP] = r; \
1747 rgba[i][GCOMP] = g; \
1748 rgba[i][BCOMP] = b; \
1749 rgba[i][ACOMP] = a; \
1750 spec[i][RCOMP] = sr; \
1751 spec[i][GCOMP] = sg; \
1752 spec[i][BCOMP] = sb; \
1765 for (i=0;i<n;i++) { \
1766 GLdouble invQ = 1.0 / vv; \
1767 zspan[i] = FixedToDepth(ffz); \
1768 fogspan[i] = fffog / 256; \
1769 rgba[i][RCOMP] = FixedToInt(ffr); \
1770 rgba[i][GCOMP] = FixedToInt(ffg); \
1771 rgba[i][BCOMP] = FixedToInt(ffb); \
1772 rgba[i][ACOMP] = FixedToInt(ffa); \
1773 spec[i][RCOMP] = FixedToInt(ffsr); \
1774 spec[i][GCOMP] = FixedToInt(ffsg); \
1775 spec[i][BCOMP] = FixedToInt(ffsb); \
1794 gl_write_texture_span( ctx, n, LEFT, Y, zspan, \
1796 s, t, u, NULL, rgba, \
1797 (CONST GLchan (*)[4]) spec, \
1802 #include "s_tritemp.h"
1808 * Compute the lambda value for a fragment. (texture level of detail)
1810 static INLINE GLfloat
1811 compute_lambda( GLfloat dsdx
, GLfloat dsdy
, GLfloat dtdx
, GLfloat dtdy
,
1812 GLfloat invQ
, GLfloat width
, GLfloat height
)
1814 GLfloat dudx
= dsdx
* invQ
* width
;
1815 GLfloat dudy
= dsdy
* invQ
* width
;
1816 GLfloat dvdx
= dtdx
* invQ
* height
;
1817 GLfloat dvdy
= dtdy
* invQ
* height
;
1818 GLfloat r1
= dudx
* dudx
+ dudy
* dudy
;
1819 GLfloat r2
= dvdx
* dvdx
+ dvdy
* dvdy
;
1820 GLfloat rho2
= r1
+ r2
; /* used to be: rho2 = MAX2(r1,r2); */
1821 /* return log base 2 of rho */
1822 return log(rho2
) * 1.442695 * 0.5; /* 1.442695 = 1/log(2) */
1827 * Render a smooth-shaded, textured, RGBA triangle.
1828 * Interpolate S,T,U with perspective correction and compute lambda for
1829 * each fragment. Lambda is used to determine whether to use the
1830 * minification or magnification filter. If minification and using
1831 * mipmaps, lambda is also used to select the texture level of detail.
1833 static void lambda_textured_triangle1( GLcontext
*ctx
,
1837 GLfloat s
[MAX_WIDTH
],
1838 GLfloat t
[MAX_WIDTH
],
1839 GLfloat u
[MAX_WIDTH
] )
1842 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1843 #define INTERP_RGB 1
1844 #define INTERP_ALPHA 1
1845 #define INTERP_TEX 1
1847 #define SETUP_CODE \
1848 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1849 const GLint baseLevel = obj->BaseLevel; \
1850 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1851 const GLfloat twidth = (GLfloat) texImage->Width; \
1852 const GLfloat theight = (GLfloat) texImage->Height; \
1853 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1862 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1865 const GLint n = RIGHT-LEFT; \
1866 GLdepth zspan[MAX_WIDTH]; \
1867 GLfixed fogspan[MAX_WIDTH]; \
1868 GLchan rgba[MAX_WIDTH][4]; \
1869 GLfloat lambda[MAX_WIDTH]; \
1872 for (i=0;i<n;i++) { \
1873 GLdouble invQ = 1.0 / vv; \
1874 zspan[i] = FixedToDepth(ffz); \
1875 fogspan[i] = fffog / 256; \
1876 rgba[i][RCOMP] = r; \
1877 rgba[i][GCOMP] = g; \
1878 rgba[i][BCOMP] = b; \
1879 rgba[i][ACOMP] = a; \
1883 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
1884 invQ, twidth, theight );\
1894 for (i=0;i<n;i++) { \
1895 GLdouble invQ = 1.0 / vv; \
1896 zspan[i] = FixedToDepth(ffz); \
1897 fogspan[i] = fffog / 256; \
1898 rgba[i][RCOMP] = FixedToInt(ffr); \
1899 rgba[i][GCOMP] = FixedToInt(ffg); \
1900 rgba[i][BCOMP] = FixedToInt(ffb); \
1901 rgba[i][ACOMP] = FixedToInt(ffa); \
1905 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
1906 invQ, twidth, theight );\
1919 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1921 rgba, NULL, GL_POLYGON ); \
1925 #include "s_tritemp.h"
1930 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1932 * Interpolate S,T,U with perspective correction and compute lambda for
1933 * each fragment. Lambda is used to determine whether to use the
1934 * minification or magnification filter. If minification and using
1935 * mipmaps, lambda is also used to select the texture level of detail.
1937 static void lambda_textured_spec_triangle1( GLcontext
*ctx
,
1941 GLfloat s
[MAX_WIDTH
],
1942 GLfloat t
[MAX_WIDTH
],
1943 GLfloat u
[MAX_WIDTH
] )
1946 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1947 #define INTERP_RGB 1
1948 #define INTERP_SPEC 1
1949 #define INTERP_ALPHA 1
1950 #define INTERP_TEX 1
1952 #define SETUP_CODE \
1953 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1954 const GLint baseLevel = obj->BaseLevel; \
1955 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1956 const GLfloat twidth = (GLfloat) texImage->Width; \
1957 const GLfloat theight = (GLfloat) texImage->Height; \
1958 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1959 GLint r, g, b, a, sr, sg, sb; \
1965 sr = v0->specular[0]; \
1966 sg = v0->specular[1]; \
1967 sb = v0->specular[2]; \
1970 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1973 const GLint n = RIGHT-LEFT; \
1974 GLdepth zspan[MAX_WIDTH]; \
1975 GLfixed fogspan[MAX_WIDTH]; \
1976 GLchan spec[MAX_WIDTH][4]; \
1977 GLchan rgba[MAX_WIDTH][4]; \
1978 GLfloat lambda[MAX_WIDTH]; \
1981 for (i=0;i<n;i++) { \
1982 GLdouble invQ = 1.0 / vv; \
1983 zspan[i] = FixedToDepth(ffz); \
1984 fogspan[i] = fffog / 256; \
1985 rgba[i][RCOMP] = r; \
1986 rgba[i][GCOMP] = g; \
1987 rgba[i][BCOMP] = b; \
1988 rgba[i][ACOMP] = a; \
1989 spec[i][RCOMP] = sr; \
1990 spec[i][GCOMP] = sg; \
1991 spec[i][BCOMP] = sb; \
1995 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
1996 invQ, twidth, theight );\
2006 for (i=0;i<n;i++) { \
2007 GLdouble invQ = 1.0 / vv; \
2008 zspan[i] = FixedToDepth(ffz); \
2009 fogspan[i] = fffog / 256; \
2010 rgba[i][RCOMP] = FixedToInt(ffr); \
2011 rgba[i][GCOMP] = FixedToInt(ffg); \
2012 rgba[i][BCOMP] = FixedToInt(ffb); \
2013 rgba[i][ACOMP] = FixedToInt(ffa); \
2014 spec[i][RCOMP] = FixedToInt(ffsr); \
2015 spec[i][GCOMP] = FixedToInt(ffsg); \
2016 spec[i][BCOMP] = FixedToInt(ffsb); \
2020 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
2021 invQ, twidth, theight );\
2037 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
2039 rgba, (CONST GLchan (*)[4]) spec, \
2044 #include "s_tritemp.h"
2049 * This is the big one!
2050 * Interpolate Z, RGB, Alpha, and two sets of texture coordinates.
2054 lambda_multitextured_triangle1( GLcontext
*ctx
,
2058 GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
2059 GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
],
2060 GLfloat u
[MAX_TEXTURE_UNITS
][MAX_WIDTH
])
2063 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2064 #define INTERP_RGB 1
2065 #define INTERP_ALPHA 1
2066 #define INTERP_MULTITEX 1
2068 #define SETUP_CODE \
2069 GLchan rgba[MAX_WIDTH][4]; \
2070 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
2071 GLfloat twidth[MAX_TEXTURE_UNITS], theight[MAX_TEXTURE_UNITS]; \
2081 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \
2082 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2083 const struct gl_texture_object *obj = ctx->Texture.Unit[unit]._Current; \
2084 const GLint baseLevel = obj->BaseLevel; \
2085 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
2086 twidth[unit] = (GLfloat) texImage->Width; \
2087 theight[unit] = (GLfloat) texImage->Height; \
2094 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2097 const GLint n = RIGHT-LEFT; \
2098 GLdepth zspan[MAX_WIDTH]; \
2099 GLfixed fogspan[MAX_WIDTH]; \
2100 GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; \
2103 for (i=0;i<n;i++) { \
2104 zspan[i] = FixedToDepth(ffz); \
2105 fogspan[i] = fffog / 256; \
2108 rgba[i][RCOMP] = r; \
2109 rgba[i][GCOMP] = g; \
2110 rgba[i][BCOMP] = b; \
2111 rgba[i][ACOMP] = a; \
2114 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \
2115 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2116 GLdouble invQ = 1.0 / vv[unit]; \
2117 s[unit][i] = ss[unit] * invQ; \
2118 t[unit][i] = tt[unit] * invQ; \
2119 u[unit][i] = uu[unit] * invQ; \
2120 lambda[unit][i] = compute_lambda(dsdx[unit], dsdy[unit],\
2121 dtdx[unit], dtdy[unit], invQ, \
2122 twidth[unit], theight[unit] ); \
2123 ss[unit] += dsdx[unit]; \
2124 tt[unit] += dtdx[unit]; \
2125 uu[unit] += dudx[unit]; \
2126 vv[unit] += dvdx[unit]; \
2132 else { /* smooth shade */ \
2133 for (i=0;i<n;i++) { \
2134 zspan[i] = FixedToDepth(ffz); \
2135 fogspan[i] = fffog / 256; \
2138 rgba[i][RCOMP] = FixedToInt(ffr); \
2139 rgba[i][GCOMP] = FixedToInt(ffg); \
2140 rgba[i][BCOMP] = FixedToInt(ffb); \
2141 rgba[i][ACOMP] = FixedToInt(ffa); \
2148 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \
2149 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2150 GLdouble invQ = 1.0 / vv[unit]; \
2151 s[unit][i] = ss[unit] * invQ; \
2152 t[unit][i] = tt[unit] * invQ; \
2153 u[unit][i] = uu[unit] * invQ; \
2154 lambda[unit][i] = compute_lambda(dsdx[unit], dsdy[unit],\
2155 dtdx[unit], dtdy[unit], invQ, \
2156 twidth[unit], theight[unit] ); \
2157 ss[unit] += dsdx[unit]; \
2158 tt[unit] += dtdx[unit]; \
2159 uu[unit] += dudx[unit]; \
2160 vv[unit] += dvdx[unit]; \
2166 gl_write_multitexture_span( ctx, n, LEFT, Y, zspan, fogspan, \
2167 (const GLfloat (*)[MAX_WIDTH]) s, \
2168 (const GLfloat (*)[MAX_WIDTH]) t, \
2169 (const GLfloat (*)[MAX_WIDTH]) u, \
2170 (GLfloat (*)[MAX_WIDTH]) lambda, \
2171 rgba, NULL, GL_POLYGON ); \
2174 #include "s_tritemp.h"
2179 * These wrappers are needed to deal with the 32KB / stack frame limit
2180 * on Mac / PowerPC systems.
2183 static void general_textured_spec_triangle(GLcontext
*ctx
,
2188 GLdepth zspan
[MAX_WIDTH
];
2189 GLfixed fogspan
[MAX_WIDTH
];
2190 GLchan rgba
[MAX_WIDTH
][4], spec
[MAX_WIDTH
][4];
2191 general_textured_spec_triangle1(ctx
,v0
,v1
,v2
,zspan
,fogspan
,rgba
,spec
);
2194 static void lambda_textured_triangle( GLcontext
*ctx
,
2199 GLfloat s
[MAX_WIDTH
], t
[MAX_WIDTH
], u
[MAX_WIDTH
];
2200 lambda_textured_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2203 static void lambda_textured_spec_triangle( GLcontext
*ctx
,
2208 GLfloat s
[MAX_WIDTH
];
2209 GLfloat t
[MAX_WIDTH
];
2210 GLfloat u
[MAX_WIDTH
];
2211 lambda_textured_spec_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2215 static void lambda_multitextured_triangle( GLcontext
*ctx
,
2221 GLfloat s
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
2222 GLfloat t
[MAX_TEXTURE_UNITS
][MAX_WIDTH
];
2223 DEFMARRAY(GLfloat
,u
,MAX_TEXTURE_UNITS
,MAX_WIDTH
);
2224 CHECKARRAY(u
,return);
2226 lambda_multitextured_triangle1(ctx
,v0
,v1
,v2
,s
,t
,u
);
2233 static void occlusion_zless_triangle( GLcontext
*ctx
,
2238 if (ctx
->OcclusionResult
) {
2242 #define DO_OCCLUSION_TEST
2244 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2245 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2248 const GLint len = RIGHT-LEFT; \
2249 for (i=0;i<len;i++) { \
2250 GLdepth z = FixedToDepth(ffz); \
2252 if (z < zRow[i]) { \
2253 ctx->OcclusionResult = GL_TRUE; \
2259 #include "s_tritemp.h"
2267 # define dputs(s) puts(s)
2275 * Determine which triangle rendering function to use given the current
2276 * rendering context.
2278 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
2279 * remove tests to this code.
2282 _swrast_choose_triangle( GLcontext
*ctx
)
2284 SWcontext
*swrast
= SWRAST_CONTEXT(ctx
);
2285 const GLboolean rgbmode
= ctx
->Visual
.RGBAflag
;
2287 if (ctx
->RenderMode
==GL_RENDER
) {
2289 if (ctx
->Polygon
.SmoothFlag
) {
2290 _mesa_set_aa_triangle_function(ctx
);
2291 ASSERT(swrast
->Triangle
);
2295 if (ctx
->Depth
.OcclusionTest
&&
2297 ctx
->Depth
.Mask
== GL_FALSE
&&
2298 ctx
->Depth
.Func
== GL_LESS
&&
2299 !ctx
->Stencil
.Enabled
) {
2301 ctx
->Color
.ColorMask
[0] == 0 &&
2302 ctx
->Color
.ColorMask
[1] == 0 &&
2303 ctx
->Color
.ColorMask
[2] == 0 &&
2304 ctx
->Color
.ColorMask
[3] == 0)
2306 (!rgbmode
&& ctx
->Color
.IndexMask
== 0)) {
2307 dputs("occlusion_test_triangle");
2308 swrast
->Triangle
= occlusion_zless_triangle
;
2313 if (ctx
->Texture
._ReallyEnabled
) {
2314 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
2315 GLint format
, filter
;
2316 const struct gl_texture_object
*current2Dtex
= ctx
->Texture
.Unit
[0].CurrentD
[2];
2317 const struct gl_texture_image
*image
;
2318 /* First see if we can used an optimized 2-D texture function */
2319 if (ctx
->Texture
._ReallyEnabled
==TEXTURE0_2D
2320 && current2Dtex
->WrapS
==GL_REPEAT
2321 && current2Dtex
->WrapT
==GL_REPEAT
2322 && ((image
= current2Dtex
->Image
[current2Dtex
->BaseLevel
]) != 0) /* correct! */
2324 && ((format
= image
->Format
)==GL_RGB
|| format
==GL_RGBA
)
2325 && (filter
= current2Dtex
->MinFilter
)==current2Dtex
->MagFilter
2326 && ctx
->Light
.Model
.ColorControl
==GL_SINGLE_COLOR
2327 && ctx
->Texture
.Unit
[0].EnvMode
!=GL_COMBINE_EXT
) {
2329 if (ctx
->Hint
.PerspectiveCorrection
==GL_FASTEST
) {
2331 if (filter
==GL_NEAREST
2333 && (ctx
->Texture
.Unit
[0].EnvMode
==GL_REPLACE
2334 || ctx
->Texture
.Unit
[0].EnvMode
==GL_DECAL
)
2335 && ((swrast
->_RasterMask
==DEPTH_BIT
2336 && ctx
->Depth
.Func
==GL_LESS
2337 && ctx
->Depth
.Mask
==GL_TRUE
)
2338 || swrast
->_RasterMask
==0)
2339 && ctx
->Polygon
.StippleFlag
==GL_FALSE
) {
2341 if (swrast
->_RasterMask
==DEPTH_BIT
) {
2342 swrast
->Triangle
= simple_z_textured_triangle
;
2343 dputs("simple_z_textured_triangle");
2346 swrast
->Triangle
= simple_textured_triangle
;
2347 dputs("simple_textured_triangle");
2351 if (ctx
->Texture
.Unit
[0].EnvMode
==GL_ADD
) {
2352 swrast
->Triangle
= general_textured_triangle
;
2353 dputs("general_textured_triangle");
2356 swrast
->Triangle
= affine_textured_triangle
;
2357 dputs("affine_textured_triangle");
2362 if (filter
==GL_NEAREST
) {
2363 swrast
->Triangle
= near_persp_textured_triangle
;
2364 dputs("near_persp_textured_triangle");
2367 swrast
->Triangle
= lin_persp_textured_triangle
;
2368 dputs("lin_persp_textured_triangle");
2373 /* More complicated textures (mipmap, multi-tex, sep specular) */
2374 GLboolean needLambda
;
2375 /* if mag filter != min filter we need to compute lambda */
2376 const struct gl_texture_object
*obj
= ctx
->Texture
.Unit
[0]._Current
;
2377 if (obj
&& obj
->MinFilter
!= obj
->MagFilter
)
2378 needLambda
= GL_TRUE
;
2380 needLambda
= GL_FALSE
;
2381 if (swrast
->_MultiTextureEnabled
) {
2382 swrast
->Triangle
= lambda_multitextured_triangle
;
2383 dputs("lambda_multitextured_triangle");
2385 else if ((ctx
->Light
.Enabled
&&
2386 ctx
->Light
.Model
.ColorControl
==GL_SEPARATE_SPECULAR_COLOR
)
2387 || ctx
->Fog
.ColorSumEnabled
) {
2388 /* separate specular color interpolation */
2390 swrast
->Triangle
= lambda_textured_spec_triangle
;
2391 dputs("lambda_textured_spec_triangle");
2394 swrast
->Triangle
= general_textured_spec_triangle
;
2395 dputs("general_textured_spec_triangle");
2400 swrast
->Triangle
= lambda_textured_triangle
;
2401 dputs("lambda_textured_triangle");
2404 swrast
->Triangle
= general_textured_triangle
;
2405 dputs("general_textured_triangle");
2411 if (ctx
->Light
.ShadeModel
==GL_SMOOTH
) {
2412 /* smooth shaded, no texturing, stippled or some raster ops */
2414 dputs("smooth_rgba_triangle");
2415 swrast
->Triangle
= smooth_rgba_triangle
;
2418 dputs("smooth_ci_triangle");
2419 swrast
->Triangle
= smooth_ci_triangle
;
2423 /* flat shaded, no texturing, stippled or some raster ops */
2425 dputs("flat_rgba_triangle");
2426 swrast
->Triangle
= flat_rgba_triangle
;
2429 dputs("flat_ci_triangle");
2430 swrast
->Triangle
= flat_ci_triangle
;
2435 else if (ctx
->RenderMode
==GL_FEEDBACK
) {
2436 swrast
->Triangle
= gl_feedback_triangle
;
2439 /* GL_SELECT mode */
2440 swrast
->Triangle
= gl_select_triangle
;