Cleanup of derived state calculation prior to seperating software T&L
[mesa.git] / src / mesa / swrast / s_triangle.c
1 /* $Id: s_triangle.c,v 1.3 2000/11/13 20:02:57 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27
28 /*
29 * Triangle rasterizers
30 * When the device driver doesn't implement triangle rasterization Mesa
31 * will use these functions to draw triangles.
32 */
33
34
35 #include "glheader.h"
36 #include "context.h"
37 #include "macros.h"
38 #include "mem.h"
39 #include "mmath.h"
40 #include "teximage.h"
41 #include "texstate.h"
42
43 #include "s_aatriangle.h"
44 #include "s_context.h"
45 #include "s_depth.h"
46 #include "s_feedback.h"
47 #include "s_span.h"
48 #include "s_triangle.h"
49
50 GLboolean gl_cull_triangle( GLcontext *ctx,
51 SWvertex *v0,
52 SWvertex *v1,
53 SWvertex *v2 )
54 {
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;
60
61 if (c * SWRAST_CONTEXT(ctx)->_backface_sign > 0)
62 return 0;
63
64 return 1;
65 }
66
67
68 /*
69 * Render a flat-shaded color index triangle.
70 */
71 static void flat_ci_triangle( GLcontext *ctx,
72 SWvertex *v0,
73 SWvertex *v1,
74 SWvertex *v2 )
75 {
76 #define INTERP_Z 1
77 #define SETUP_CODE \
78 GLuint index = v0->index; \
79 if (1) { \
80 /* set the color index */ \
81 (*ctx->Driver.Index)( ctx, index ); \
82 }
83
84 #define INNER_LOOP( LEFT, RIGHT, Y ) \
85 { \
86 const GLint n = RIGHT-LEFT; \
87 GLint i; \
88 GLdepth zspan[MAX_WIDTH]; \
89 GLfixed fogspan[MAX_WIDTH]; \
90 if (n>0) { \
91 for (i=0;i<n;i++) { \
92 zspan[i] = FixedToDepth(ffz); \
93 ffz += fdzdx; \
94 fogspan[i] = fffog / 256; \
95 fffog += fdfogdx; \
96 } \
97 gl_write_monoindex_span( ctx, n, LEFT, Y, zspan, \
98 fogspan, index, GL_POLYGON ); \
99 } \
100 }
101
102 #include "s_tritemp.h"
103 }
104
105
106
107 /*
108 * Render a smooth-shaded color index triangle.
109 */
110 static void smooth_ci_triangle( GLcontext *ctx,
111 SWvertex *v0,
112 SWvertex *v1,
113 SWvertex *v2 )
114 {
115 #define INTERP_Z 1
116 #define INTERP_INDEX 1
117
118 #define INNER_LOOP( LEFT, RIGHT, Y ) \
119 { \
120 const GLint n = RIGHT-LEFT; \
121 GLint i; \
122 GLdepth zspan[MAX_WIDTH]; \
123 GLfixed fogspan[MAX_WIDTH]; \
124 GLuint index[MAX_WIDTH]; \
125 if (n>0) { \
126 for (i=0;i<n;i++) { \
127 zspan[i] = FixedToDepth(ffz); \
128 ffz += fdzdx; \
129 index[i] = FixedToInt(ffi); \
130 ffi += fdidx; \
131 fogspan[i] = fffog / 256; \
132 fffog += fdfogdx; \
133 } \
134 gl_write_index_span( ctx, n, LEFT, Y, zspan, fogspan, \
135 index, GL_POLYGON ); \
136 } \
137 }
138
139 #include "s_tritemp.h"
140 }
141
142
143
144 /*
145 * Render a flat-shaded RGBA triangle.
146 */
147 static void flat_rgba_triangle( GLcontext *ctx,
148 SWvertex *v0,
149 SWvertex *v1,
150 SWvertex *v2 )
151 {
152 #define INTERP_Z 1
153 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
154
155 #define SETUP_CODE \
156 if (1) { \
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 ); \
163 }
164
165 #define INNER_LOOP( LEFT, RIGHT, Y ) \
166 { \
167 const GLint n = RIGHT-LEFT; \
168 GLint i; \
169 GLdepth zspan[MAX_WIDTH]; \
170 GLfixed fogspan[MAX_WIDTH]; \
171 if (n>0) { \
172 for (i=0;i<n;i++) { \
173 zspan[i] = FixedToDepth(ffz); \
174 ffz += fdzdx; \
175 fogspan[i] = fffog / 256; \
176 fffog += fdfogdx; \
177 } \
178 gl_write_monocolor_span( ctx, n, LEFT, Y, zspan, \
179 fogspan, \
180 v0->color, \
181 GL_POLYGON ); \
182 } \
183 }
184
185 #include "s_tritemp.h"
186
187 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */
188 ASSERT(ctx->Light.ShadeModel==GL_FLAT);
189 }
190
191
192
193 /*
194 * Render a smooth-shaded RGBA triangle.
195 */
196 static void smooth_rgba_triangle( GLcontext *ctx,
197 SWvertex *v0,
198 SWvertex *v1,
199 SWvertex *v2 )
200 {
201
202 #define INTERP_Z 1
203 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
204 #define INTERP_RGB 1
205 #define INTERP_ALPHA 1
206
207 #define INNER_LOOP( LEFT, RIGHT, Y ) \
208 { \
209 const GLint n = RIGHT-LEFT; \
210 GLint i; \
211 GLdepth zspan[MAX_WIDTH]; \
212 GLchan rgba[MAX_WIDTH][4]; \
213 GLfixed fogspan[MAX_WIDTH]; \
214 if (n>0) { \
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; \
222 fffog += fdfogdx; \
223 ffz += fdzdx; \
224 ffr += fdrdx; \
225 ffg += fdgdx; \
226 ffb += fdbdx; \
227 ffa += fdadx; \
228 } \
229 gl_write_rgba_span( ctx, n, LEFT, Y, \
230 (CONST GLdepth *) zspan, \
231 fogspan, \
232 rgba, GL_POLYGON ); \
233 } \
234 }
235
236 #include "s_tritemp.h"
237
238 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */
239 ASSERT(ctx->Light.ShadeModel==GL_SMOOTH);
240 }
241
242
243 /*
244 * Render an RGB, GL_DECAL, textured triangle.
245 * Interpolate S,T only w/out mipmapping or perspective correction.
246 *
247 * No fog.
248 */
249 static void simple_textured_triangle( GLcontext *ctx,
250 SWvertex *v0,
251 SWvertex *v1,
252 SWvertex *v2 )
253 {
254 #define INTERP_INT_TEX 1
255 #define S_SCALE twidth
256 #define T_SCALE theight
257 #define SETUP_CODE \
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; \
266 if (!texture) { \
267 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
268 return; \
269 texture = obj->Image[b]->Data; \
270 ASSERT(texture); \
271 }
272
273 #define INNER_LOOP( LEFT, RIGHT, Y ) \
274 { \
275 CONST GLint n = RIGHT-LEFT; \
276 GLint i; \
277 GLchan rgb[MAX_WIDTH][3]; \
278 if (n>0) { \
279 ffs -= FIXED_HALF; /* off-by-one error? */ \
280 fft -= FIXED_HALF; \
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]; \
289 ffs += fdsdx; \
290 fft += fdtdx; \
291 } \
292 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
293 (CONST GLchan (*)[3]) rgb, NULL ); \
294 } \
295 }
296
297 #include "s_tritemp.h"
298 }
299
300
301 /*
302 * Render an RGB, GL_DECAL, textured triangle.
303 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
304 * perspective correction.
305 *
306 * No fog.
307 */
308 static void simple_z_textured_triangle( GLcontext *ctx,
309 SWvertex *v0,
310 SWvertex *v1,
311 SWvertex *v2 )
312 {
313 #define INTERP_Z 1
314 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
315 #define INTERP_INT_TEX 1
316 #define S_SCALE twidth
317 #define T_SCALE theight
318 #define SETUP_CODE \
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; \
327 if (!texture) { \
328 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
329 return; \
330 texture = obj->Image[b]->Data; \
331 ASSERT(texture); \
332 }
333
334 #define INNER_LOOP( LEFT, RIGHT, Y ) \
335 { \
336 CONST GLint n = RIGHT-LEFT; \
337 GLint i; \
338 GLchan rgb[MAX_WIDTH][3]; \
339 GLubyte mask[MAX_WIDTH]; \
340 (void) fffog; \
341 if (n>0) { \
342 ffs -= FIXED_HALF; /* off-by-one error? */ \
343 fft -= FIXED_HALF; \
344 for (i=0;i<n;i++) { \
345 GLdepth z = FixedToDepth(ffz); \
346 if (z < zRow[i]) { \
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]; \
354 zRow[i] = z; \
355 mask[i] = 1; \
356 } \
357 else { \
358 mask[i] = 0; \
359 } \
360 ffz += fdzdx; \
361 ffs += fdsdx; \
362 fft += fdtdx; \
363 } \
364 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
365 (CONST GLchan (*)[3]) rgb, mask ); \
366 } \
367 }
368
369 #include "s_tritemp.h"
370 }
371
372
373
374 /*
375 * Render an RGB/RGBA textured triangle without perspective correction.
376 */
377 static void affine_textured_triangle( GLcontext *ctx,
378 SWvertex *v0,
379 SWvertex *v1,
380 SWvertex *v2 )
381 {
382 #define INTERP_Z 1
383 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
384 #define INTERP_RGB 1
385 #define INTERP_ALPHA 1
386 #define INTERP_INT_TEX 1
387 #define S_SCALE twidth
388 #define T_SCALE theight
389 #define SETUP_CODE \
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; \
405 if (!texture) { \
406 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
407 return; \
408 texture = obj->Image[b]->Data; \
409 ASSERT(texture); \
410 } \
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]); \
417 } \
418 switch (format) { \
419 case GL_ALPHA: \
420 case GL_LUMINANCE: \
421 case GL_INTENSITY: \
422 comp = 1; \
423 break; \
424 case GL_LUMINANCE_ALPHA: \
425 comp = 2; \
426 break; \
427 case GL_RGB: \
428 comp = 3; \
429 break; \
430 case GL_RGBA: \
431 comp = 4; \
432 break; \
433 default: \
434 gl_problem(NULL, "Bad texture format in affine_texture_triangle");\
435 return; \
436 } \
437 tbytesline = obj->Image[b]->Width * comp; \
438 tsize = theight * tbytesline;
439
440
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).
445 */
446
447 #define NEAREST_RGB \
448 tr = tex00[0]; \
449 tg = tex00[1]; \
450 tb = tex00[2]; \
451 ta = 0xff
452
453 #define LINEAR_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; \
460 ta = 0xff
461
462 #define NEAREST_RGBA \
463 tr = tex00[0]; \
464 tg = tex00[1]; \
465 tb = tex00[2]; \
466 ta = tex00[3]
467
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
477
478 #define MODULATE \
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)
483
484 #define DECAL \
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)
489
490 #define BLEND \
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)
495
496 #define REPLACE \
497 dest[0] = tr; \
498 dest[1] = tg; \
499 dest[2] = tb; \
500 dest[3] = ta
501
502 #define ADD \
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)
507
508 /* shortcuts */
509
510 #define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE
511
512 #define NEAREST_RGBA_REPLACE *(GLint *)dest = *(GLint *)tex00
513
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; \
522 DO_TEX; \
523 fffog += fdfogdx; \
524 ffz += fdzdx; \
525 ffr += fdrdx; \
526 ffg += fdgdx; \
527 ffb += fdbdx; \
528 ffa += fdadx; \
529 ffs += fdsdx; \
530 fft += fdtdx; \
531 dest += 4; \
532 }
533
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; \
547 if (t == tmask) { \
548 tex10 -= tsize; \
549 tex11 -= tsize; \
550 } \
551 if (s == smask) { \
552 tex01 -= tbytesline; \
553 tex11 -= tbytesline; \
554 } \
555 zspan[i] = FixedToDepth(ffz); \
556 fogspan[i] = fffog / 256; \
557 DO_TEX; \
558 fffog += fdfogdx; \
559 ffz += fdzdx; \
560 ffr += fdrdx; \
561 ffg += fdgdx; \
562 ffb += fdbdx; \
563 ffa += fdadx; \
564 ffs += fdsdx; \
565 fft += fdtdx; \
566 dest += 4; \
567 }
568
569 /* here comes the heavy part.. (something for the compiler to chew on) */
570 #define INNER_LOOP( LEFT, RIGHT, Y ) \
571 { \
572 CONST GLint n = RIGHT-LEFT; \
573 GLint i; \
574 GLdepth zspan[MAX_WIDTH]; \
575 GLfixed fogspan[MAX_WIDTH]; \
576 GLchan rgba[MAX_WIDTH][4]; \
577 if (n>0) { \
578 GLchan *dest = rgba[0]; \
579 ffs -= FIXED_HALF; /* off-by-one error? */ \
580 fft -= FIXED_HALF; \
581 switch (filter) { \
582 case GL_NEAREST: \
583 switch (format) { \
584 case GL_RGB: \
585 switch (envmode) { \
586 case GL_MODULATE: \
587 SPAN1(NEAREST_RGB;MODULATE,3); \
588 break; \
589 case GL_DECAL: \
590 case GL_REPLACE: \
591 SPAN1(NEAREST_RGB_REPLACE,3); \
592 break; \
593 case GL_BLEND: \
594 SPAN1(NEAREST_RGB;BLEND,3); \
595 break; \
596 case GL_ADD: \
597 SPAN1(NEAREST_RGB;ADD,3); \
598 break; \
599 default: /* unexpected env mode */ \
600 abort(); \
601 } \
602 break; \
603 case GL_RGBA: \
604 switch(envmode) { \
605 case GL_MODULATE: \
606 SPAN1(NEAREST_RGBA;MODULATE,4); \
607 break; \
608 case GL_DECAL: \
609 SPAN1(NEAREST_RGBA;DECAL,4); \
610 break; \
611 case GL_BLEND: \
612 SPAN1(NEAREST_RGBA;BLEND,4); \
613 break; \
614 case GL_ADD: \
615 SPAN1(NEAREST_RGBA;ADD,4); \
616 break; \
617 case GL_REPLACE: \
618 SPAN1(NEAREST_RGBA_REPLACE,4); \
619 break; \
620 default: /* unexpected env mode */ \
621 abort(); \
622 } \
623 break; \
624 } \
625 break; \
626 case GL_LINEAR: \
627 ffs -= FIXED_HALF; \
628 fft -= FIXED_HALF; \
629 switch (format) { \
630 case GL_RGB: \
631 switch (envmode) { \
632 case GL_MODULATE: \
633 SPAN2(LINEAR_RGB;MODULATE,3); \
634 break; \
635 case GL_DECAL: \
636 case GL_REPLACE: \
637 SPAN2(LINEAR_RGB;REPLACE,3); \
638 break; \
639 case GL_BLEND: \
640 SPAN2(LINEAR_RGB;BLEND,3); \
641 break; \
642 case GL_ADD: \
643 SPAN2(LINEAR_RGB;ADD,3); \
644 break; \
645 default: /* unexpected env mode */ \
646 abort(); \
647 } \
648 break; \
649 case GL_RGBA: \
650 switch (envmode) { \
651 case GL_MODULATE: \
652 SPAN2(LINEAR_RGBA;MODULATE,4); \
653 break; \
654 case GL_DECAL: \
655 SPAN2(LINEAR_RGBA;DECAL,4); \
656 break; \
657 case GL_BLEND: \
658 SPAN2(LINEAR_RGBA;BLEND,4); \
659 break; \
660 case GL_ADD: \
661 SPAN2(LINEAR_RGBA;ADD,4); \
662 break; \
663 case GL_REPLACE: \
664 SPAN2(LINEAR_RGBA;REPLACE,4); \
665 break; \
666 default: /* unexpected env mode */ \
667 abort(); \
668 } \
669 break; \
670 } \
671 break; \
672 } \
673 gl_write_rgba_span(ctx, n, LEFT, Y, zspan, \
674 fogspan, \
675 rgba, GL_POLYGON); \
676 /* explicit kill of variables: */ \
677 ffr = ffg = ffb = ffa = 0; \
678 } \
679 }
680
681 #include "s_tritemp.h"
682 #undef SPAN1
683 #undef SPAN2
684 }
685
686
687
688 /*
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.
692 *
693 * This function only renders textured triangles that use GL_NEAREST.
694 * Perspective correction works right.
695 *
696 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
697 * Send all questions and bug reports to him.
698 */
699 static void near_persp_textured_triangle(GLcontext *ctx,
700 SWvertex *v0,
701 SWvertex *v1,
702 SWvertex *v2 )
703 {
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...
709 */
710 #define BIAS 4096.0F
711
712 #define INTERP_Z 1
713 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
714 #define INTERP_RGB 1
715 #define INTERP_ALPHA 1
716 #define INTERP_TEX 1
717 #define SETUP_CODE \
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; \
732 if (!texture) { \
733 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
734 return; \
735 texture = obj->Image[b]->Data; \
736 ASSERT(texture); \
737 } \
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]); \
743 } \
744 sscale = twidth; \
745 tscale = theight; \
746
747
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; \
757 DO_TEX; \
758 fffog += fdfogdx; \
759 ffz += fdzdx; \
760 ffr += fdrdx; \
761 ffg += fdgdx; \
762 ffb += fdbdx; \
763 ffa += fdadx; \
764 SS += dSdx; \
765 TT += dTdx; \
766 vv += dvdx; \
767 dest += 4; \
768 }
769
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))
772
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; \
777 GLint pos; \
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); \
783 y_tex = y_max; \
784 } \
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); \
790 while (i<n) { \
791 y_tex = y_max; \
792 y_max += dy_dx; \
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); \
798 y_tex = y_max; \
799 } \
800 nominator += vv; \
801 denominator -= dvdx; \
802 j = nominator/denominator; \
803 pos = COMP * TEX_COORD(x_m, y_tex); \
804 DRAW_LINE (DO_TEX); \
805 x_m ++; \
806 } \
807 }
808
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; \
813 GLint pos; \
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); \
819 y_tex = y_max; \
820 } \
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); \
826 while (i<n) { \
827 y_tex = y_max; \
828 y_max += dy_dx; \
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); \
834 y_tex = y_max; \
835 } \
836 nominator += vv; \
837 denominator -= dvdx; \
838 j = nominator/denominator; \
839 pos = COMP * TEX_COORD(x_m, y_tex); \
840 DRAW_LINE (DO_TEX); \
841 x_m ++; \
842 } \
843 }
844
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; \
849 GLint pos; \
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); \
855 y_tex = y_min; \
856 } \
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); \
862 while (i<n) { \
863 x_m --; \
864 y_tex = y_min; \
865 y_min -= dy_dx; \
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); \
871 y_tex = y_min; \
872 } \
873 nominator -= vv; \
874 denominator += dvdx; \
875 j = nominator/denominator; \
876 pos = COMP * TEX_COORD(x_m, y_tex); \
877 DRAW_LINE (DO_TEX); \
878 } \
879 }
880
881 #define SPAN4(DO_TEX, COMP, TEX_COORD) \
882 { \
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; \
886 GLint j; \
887 GLint pos; \
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); \
893 y_tex = y_min; \
894 } \
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); \
900 while (i<n) { \
901 x_m --; \
902 y_tex = y_min; \
903 y_min -= dy_dx; \
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); \
909 y_tex = y_min; \
910 } \
911 nominator -= vv; \
912 denominator += dvdx; \
913 j = nominator/denominator; \
914 pos = COMP * TEX_COORD(x_m, y_tex); \
915 DRAW_LINE (DO_TEX); \
916 } \
917 }
918
919 #define DRAW_LINE(DO_TEX) \
920 { \
921 GLchan *tex00 = texture + pos; \
922 if (j>n || j<-100000) \
923 j = n; \
924 while (i<j) { \
925 zspan[i] = FixedToDepth(ffz); \
926 fogspan[i] = fffog / 256; \
927 DO_TEX; \
928 fffog += fdfogdx; \
929 ffz += fdzdx; \
930 ffr += fdrdx; \
931 ffg += fdgdx; \
932 ffb += fdbdx; \
933 ffa += fdadx; \
934 dest += 4; \
935 i++; \
936 } \
937 }
938
939 #define INNER_LOOP( LEFT, RIGHT, Y ) \
940 { \
941 GLint i = 0; \
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 */ \
947 if (n > 0) { \
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; \
953 GLfloat x_tex; \
954 GLfloat y_tex; \
955 GLfloat dx_tex; \
956 GLfloat dy_tex; \
957 if (n<5) /* When line very short, setup-time > speed-gain. */ \
958 goto old_span; /* So: take old method */ \
959 x_tex = SS / vv, \
960 y_tex = TT / vv; \
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) { \
969 x_tex += BIAS; \
970 y_tex += BIAS; \
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; \
975 GLfloat dy_dx; \
976 GLfloat dx_dy; \
977 if (dy_tex != 0.0f) { \
978 dy_dx = dy_tex / dx_tex; \
979 dx_dy = 1.0f/dy_dx; \
980 } \
981 else \
982 dy_dx = 0.0f; \
983 if (dx_tex > 0.0f) { \
984 if (dy_tex > 0.0f) { \
985 switch (format) { \
986 case GL_RGB: \
987 switch (envmode) { \
988 case GL_MODULATE: \
989 SPAN1(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
990 break; \
991 case GL_DECAL: \
992 case GL_REPLACE: \
993 SPAN1(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
994 break; \
995 case GL_BLEND: \
996 SPAN1(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
997 break; \
998 case GL_ADD: \
999 SPAN1(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1000 break; \
1001 default: /* unexpected env mode */ \
1002 abort(); \
1003 } \
1004 break; \
1005 case GL_RGBA: \
1006 switch(envmode) { \
1007 case GL_MODULATE: \
1008 SPAN1(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1009 break; \
1010 case GL_DECAL: \
1011 SPAN1(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1012 break; \
1013 case GL_BLEND: \
1014 SPAN1(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1015 break; \
1016 case GL_ADD: \
1017 SPAN1(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1018 break; \
1019 case GL_REPLACE: \
1020 SPAN1(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1021 break; \
1022 default: /* unexpected env mode */ \
1023 abort(); \
1024 } \
1025 break; \
1026 } \
1027 } \
1028 else { /* dy_tex <= 0.0f */ \
1029 switch (format) { \
1030 case GL_RGB: \
1031 switch (envmode) { \
1032 case GL_MODULATE: \
1033 SPAN2(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1034 break; \
1035 case GL_DECAL: \
1036 case GL_REPLACE: \
1037 SPAN2(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1038 break; \
1039 case GL_BLEND: \
1040 SPAN2(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1041 break; \
1042 case GL_ADD: \
1043 SPAN2(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1044 break; \
1045 default: /* unexpected env mode */ \
1046 abort(); \
1047 } \
1048 break; \
1049 case GL_RGBA: \
1050 switch(envmode) { \
1051 case GL_MODULATE: \
1052 SPAN2(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1053 break; \
1054 case GL_DECAL: \
1055 SPAN2(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1056 break; \
1057 case GL_BLEND: \
1058 SPAN2(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1059 break; \
1060 case GL_ADD: \
1061 SPAN2(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1062 break; \
1063 case GL_REPLACE: \
1064 SPAN2(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1065 break; \
1066 default: /* unexpected env mode */ \
1067 abort(); \
1068 } \
1069 break; \
1070 } \
1071 } \
1072 } \
1073 else { /* dx_tex < 0.0f */ \
1074 if (dy_tex > 0.0f) { \
1075 switch (format) { \
1076 case GL_RGB: \
1077 switch (envmode) { \
1078 case GL_MODULATE: \
1079 SPAN3(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1080 break; \
1081 case GL_DECAL: \
1082 case GL_REPLACE: \
1083 SPAN3(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1084 break; \
1085 case GL_BLEND: \
1086 SPAN3(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1087 break; \
1088 case GL_ADD: \
1089 SPAN3(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1090 break; \
1091 default: /* unexpected env mode */ \
1092 abort(); \
1093 } \
1094 break; \
1095 case GL_RGBA: \
1096 switch(envmode) { \
1097 case GL_MODULATE: \
1098 SPAN3(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1099 break; \
1100 case GL_DECAL: \
1101 SPAN3(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1102 break; \
1103 case GL_BLEND: \
1104 SPAN3(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1105 break; \
1106 case GL_ADD: \
1107 SPAN3(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1108 break; \
1109 case GL_REPLACE: \
1110 SPAN3(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1111 break; \
1112 default: /* unexpected env mode */ \
1113 abort(); \
1114 } \
1115 break; \
1116 } \
1117 } \
1118 else { /* dy_tex <= 0.0f */ \
1119 switch (format) { \
1120 case GL_RGB: \
1121 switch (envmode) { \
1122 case GL_MODULATE: \
1123 SPAN4(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1124 break; \
1125 case GL_DECAL: \
1126 case GL_REPLACE: \
1127 SPAN4(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1128 break; \
1129 case GL_BLEND: \
1130 SPAN4(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1131 break; \
1132 case GL_ADD: \
1133 SPAN4(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1134 break; \
1135 default: \
1136 abort(); \
1137 } \
1138 break; \
1139 case GL_RGBA: \
1140 switch(envmode) { \
1141 case GL_MODULATE: \
1142 SPAN4(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1143 break; \
1144 case GL_DECAL: \
1145 SPAN4(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1146 break; \
1147 case GL_BLEND: \
1148 SPAN4(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1149 break; \
1150 case GL_ADD: \
1151 SPAN4(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1152 break; \
1153 case GL_REPLACE: \
1154 SPAN4(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1155 break; \
1156 default: /* unexpected env mode */ \
1157 abort(); \
1158 } \
1159 break; \
1160 } \
1161 } \
1162 } \
1163 } \
1164 else { /* FABSF(dx_tex) > FABSF(dy_tex) */ \
1165 GLfloat swap; \
1166 GLfloat dy_dx; \
1167 GLfloat dx_dy; \
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 */ \
1172 SS = TT; \
1173 dSdx = dTdx; \
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; \
1181 } \
1182 else \
1183 dy_dx = 0.0f; \
1184 if (dx_tex > 0.0f) { \
1185 if (dy_tex > 0.0f) { \
1186 switch (format) { \
1187 case GL_RGB: \
1188 switch (envmode) { \
1189 case GL_MODULATE: \
1190 SPAN1(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1191 break; \
1192 case GL_DECAL: \
1193 case GL_REPLACE: \
1194 SPAN1(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1195 break; \
1196 case GL_BLEND: \
1197 SPAN1(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1198 break; \
1199 case GL_ADD: \
1200 SPAN1(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1201 break; \
1202 default: /* unexpected env mode */ \
1203 abort(); \
1204 } \
1205 break; \
1206 case GL_RGBA: \
1207 switch(envmode) { \
1208 case GL_MODULATE: \
1209 SPAN1(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1210 break; \
1211 case GL_DECAL: \
1212 SPAN1(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1213 break; \
1214 case GL_BLEND: \
1215 SPAN1(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1216 break; \
1217 case GL_ADD: \
1218 SPAN1(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1219 break; \
1220 case GL_REPLACE: \
1221 SPAN1(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1222 break; \
1223 default: \
1224 abort(); \
1225 } \
1226 break; \
1227 } \
1228 } \
1229 else { /* dy_tex <= 0.0f */ \
1230 switch (format) { \
1231 case GL_RGB: \
1232 switch (envmode) { \
1233 case GL_MODULATE: \
1234 SPAN2(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1235 break; \
1236 case GL_DECAL: \
1237 case GL_REPLACE: \
1238 SPAN2(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1239 break; \
1240 case GL_BLEND: \
1241 SPAN2(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1242 break; \
1243 case GL_ADD: \
1244 SPAN2(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1245 break; \
1246 default: \
1247 abort(); \
1248 } \
1249 break; \
1250 case GL_RGBA: \
1251 switch(envmode) { \
1252 case GL_MODULATE: \
1253 SPAN2(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1254 break; \
1255 case GL_DECAL: \
1256 SPAN2(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1257 break; \
1258 case GL_BLEND: \
1259 SPAN2(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1260 break; \
1261 case GL_ADD: \
1262 SPAN2(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1263 break; \
1264 case GL_REPLACE: \
1265 SPAN2(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1266 break; \
1267 default: \
1268 abort(); \
1269 } \
1270 break; \
1271 } \
1272 } \
1273 } \
1274 else { /* dx_tex < 0.0f */ \
1275 if (dy_tex > 0.0f) { \
1276 switch (format) { \
1277 case GL_RGB: \
1278 switch (envmode) { \
1279 case GL_MODULATE: \
1280 SPAN3(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1281 break; \
1282 case GL_DECAL: \
1283 case GL_REPLACE: \
1284 SPAN3(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1285 break; \
1286 case GL_BLEND: \
1287 SPAN3(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1288 break; \
1289 case GL_ADD: \
1290 SPAN3(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1291 break; \
1292 default: \
1293 abort(); \
1294 } \
1295 break; \
1296 case GL_RGBA: \
1297 switch(envmode) { \
1298 case GL_MODULATE: \
1299 SPAN3(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1300 break; \
1301 case GL_DECAL: \
1302 SPAN3(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1303 break; \
1304 case GL_BLEND: \
1305 SPAN3(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1306 break; \
1307 case GL_ADD: \
1308 SPAN3(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1309 break; \
1310 case GL_REPLACE: \
1311 SPAN3(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1312 break; \
1313 default: \
1314 abort(); \
1315 } \
1316 break; \
1317 } \
1318 } \
1319 else { /* dy_tex <= 0.0f */ \
1320 switch (format) { \
1321 case GL_RGB: \
1322 switch (envmode) { \
1323 case GL_MODULATE: \
1324 SPAN4(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1325 break; \
1326 case GL_DECAL: \
1327 case GL_REPLACE: \
1328 SPAN4(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1329 break; \
1330 case GL_BLEND: \
1331 SPAN4(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1332 break; \
1333 case GL_ADD: \
1334 SPAN4(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1335 break; \
1336 default: \
1337 abort(); \
1338 } \
1339 break; \
1340 case GL_RGBA: \
1341 switch(envmode) { \
1342 case GL_MODULATE: \
1343 SPAN4(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1344 break; \
1345 case GL_DECAL: \
1346 SPAN4(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1347 break; \
1348 case GL_BLEND: \
1349 SPAN4(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1350 break; \
1351 case GL_ADD: \
1352 SPAN4(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1353 break; \
1354 case GL_REPLACE: \
1355 SPAN4(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1356 break; \
1357 default: \
1358 abort(); \
1359 } \
1360 break; \
1361 } \
1362 } \
1363 } \
1364 } \
1365 } \
1366 else { \
1367 old_span: \
1368 switch (format) { \
1369 case GL_RGB: \
1370 switch (envmode) { \
1371 case GL_MODULATE: \
1372 OLD_SPAN(NEAREST_RGB;MODULATE,3); \
1373 break; \
1374 case GL_DECAL: \
1375 case GL_REPLACE: \
1376 OLD_SPAN(NEAREST_RGB_REPLACE,3); \
1377 break; \
1378 case GL_BLEND: \
1379 OLD_SPAN(NEAREST_RGB;BLEND,3); \
1380 break; \
1381 case GL_ADD: \
1382 OLD_SPAN(NEAREST_RGB;ADD,3); \
1383 break; \
1384 default: \
1385 abort(); \
1386 } \
1387 break; \
1388 case GL_RGBA: \
1389 switch(envmode) { \
1390 case GL_MODULATE: \
1391 OLD_SPAN(NEAREST_RGBA;MODULATE,4); \
1392 break; \
1393 case GL_DECAL: \
1394 OLD_SPAN(NEAREST_RGBA;DECAL,4); \
1395 break; \
1396 case GL_BLEND: \
1397 OLD_SPAN(NEAREST_RGBA;BLEND,4); \
1398 break; \
1399 case GL_ADD: \
1400 OLD_SPAN(NEAREST_RGBA;ADD,4); \
1401 break; \
1402 case GL_REPLACE: \
1403 OLD_SPAN(NEAREST_RGBA_REPLACE,4); \
1404 break; \
1405 default: \
1406 abort(); \
1407 } \
1408 break; \
1409 } \
1410 } \
1411 gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1412 fogspan, rgba, GL_POLYGON); \
1413 ffr = ffg = ffb = ffa = 0; \
1414 } \
1415 } \
1416
1417 #include "s_tritemp.h"
1418 #undef OLD_SPAN
1419 #undef SPAN1
1420 #undef SPAN2
1421 #undef SPAN3
1422 #undef SPAN4
1423 #undef X_Y_TEX_COORD
1424 #undef Y_X_TEX_COORD
1425 #undef DRAW_LINE
1426 #undef BIAS
1427 }
1428
1429
1430
1431 /*
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.
1435 *
1436 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
1437 * Send all questions and bug reports to him.
1438 */
1439 static void lin_persp_textured_triangle( GLcontext *ctx,
1440 SWvertex *v0,
1441 SWvertex *v1,
1442 SWvertex *v2 )
1443 {
1444 #define INTERP_Z 1
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; \
1465 if (!texture) { \
1466 if (!_mesa_get_teximages_from_driver(ctx, obj)) \
1467 return; \
1468 texture = obj->Image[b]->Data; \
1469 ASSERT(texture); \
1470 } \
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]); \
1476 } \
1477 switch (format) { \
1478 case GL_ALPHA: \
1479 case GL_LUMINANCE: \
1480 case GL_INTENSITY: \
1481 comp = 1; \
1482 break; \
1483 case GL_LUMINANCE_ALPHA: \
1484 comp = 2; \
1485 break; \
1486 case GL_RGB: \
1487 comp = 3; \
1488 break; \
1489 case GL_RGBA: \
1490 comp = 4; \
1491 break; \
1492 default: \
1493 gl_problem(NULL, "Bad texture format in lin_persp_texture_triangle"); \
1494 return; \
1495 } \
1496 sscale = FIXED_SCALE * twidth; \
1497 tscale = FIXED_SCALE * theight; \
1498 tbytesline = obj->Image[b]->Width * comp; \
1499 tsize = theight * tbytesline;
1500
1501
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; \
1518 if (t == tmask) { \
1519 tex10 -= tsize; \
1520 tex11 -= tsize; \
1521 } \
1522 if (s == smask) { \
1523 tex01 -= tbytesline; \
1524 tex11 -= tbytesline; \
1525 } \
1526 zspan[i] = FixedToDepth(ffz); \
1527 fogspan[i] = fffog / 256; \
1528 DO_TEX; \
1529 fffog += fdfogdx; \
1530 ffz += fdzdx; \
1531 ffr += fdrdx; \
1532 ffg += fdgdx; \
1533 ffb += fdbdx; \
1534 ffa += fdadx; \
1535 SS += dSdx; \
1536 TT += dTdx; \
1537 vv += dvdx; \
1538 dest += 4; \
1539 }
1540
1541 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1542 { \
1543 GLint i; \
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 */ \
1549 if (n > 0) { \
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; \
1557 switch (format) { \
1558 case GL_RGB: \
1559 switch (envmode) { \
1560 case GL_MODULATE: \
1561 SPAN(LINEAR_RGB;MODULATE,3); \
1562 break; \
1563 case GL_DECAL: \
1564 case GL_REPLACE: \
1565 SPAN(LINEAR_RGB;REPLACE,3); \
1566 break; \
1567 case GL_BLEND: \
1568 SPAN(LINEAR_RGB;BLEND,3); \
1569 break; \
1570 case GL_ADD: \
1571 SPAN(LINEAR_RGB;ADD,3); \
1572 break; \
1573 default: \
1574 abort(); \
1575 } \
1576 break; \
1577 case GL_RGBA: \
1578 switch (envmode) { \
1579 case GL_MODULATE: \
1580 SPAN(LINEAR_RGBA;MODULATE,4); \
1581 break; \
1582 case GL_DECAL: \
1583 SPAN(LINEAR_RGBA;DECAL,4); \
1584 break; \
1585 case GL_BLEND: \
1586 SPAN(LINEAR_RGBA;BLEND,4); \
1587 break; \
1588 case GL_REPLACE: \
1589 SPAN(LINEAR_RGBA;REPLACE,4); \
1590 break; \
1591 case GL_ADD: \
1592 SPAN(LINEAR_RGBA;ADD,4); \
1593 break; \
1594 default: /* unexpected env mode */ \
1595 abort(); \
1596 } \
1597 } \
1598 gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1599 fogspan, \
1600 rgba, GL_POLYGON ); \
1601 ffr = ffg = ffb = ffa = 0; \
1602 } \
1603 }
1604
1605
1606 #include "s_tritemp.h"
1607 #undef SPAN
1608 }
1609
1610
1611
1612 /*
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.
1617 */
1618 static void general_textured_triangle( GLcontext *ctx,
1619 SWvertex *v0,
1620 SWvertex *v1,
1621 SWvertex *v2 )
1622 {
1623 #define INTERP_Z 1
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); \
1630 GLint r, g, b, a; \
1631 if (flat_shade) { \
1632 r = v0->color[0]; \
1633 g = v0->color[1]; \
1634 b = v0->color[2]; \
1635 a = v0->color[3]; \
1636 }
1637 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1638 { \
1639 GLint i; \
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]; \
1645 if (n>0) { \
1646 if (flat_shade) { \
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; \
1655 s[i] = ss*invQ; \
1656 t[i] = tt*invQ; \
1657 u[i] = uu*invQ; \
1658 fffog += fdfogdx; \
1659 ffz += fdzdx; \
1660 ss += dsdx; \
1661 tt += dtdx; \
1662 uu += dudx; \
1663 vv += dvdx; \
1664 } \
1665 } \
1666 else { \
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; \
1675 s[i] = ss*invQ; \
1676 t[i] = tt*invQ; \
1677 u[i] = uu*invQ; \
1678 fffog += fdfogdx; \
1679 ffz += fdzdx; \
1680 ffr += fdrdx; \
1681 ffg += fdgdx; \
1682 ffb += fdbdx; \
1683 ffa += fdadx; \
1684 ss += dsdx; \
1685 tt += dtdx; \
1686 uu += dudx; \
1687 vv += dvdx; \
1688 } \
1689 } \
1690 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1691 s, t, u, NULL, \
1692 rgba, \
1693 NULL, GL_POLYGON ); \
1694 } \
1695 }
1696
1697 #include "s_tritemp.h"
1698 }
1699
1700
1701 /*
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.
1707 */
1708 static void general_textured_spec_triangle1( GLcontext *ctx,
1709 SWvertex *v0,
1710 SWvertex *v1,
1711 SWvertex *v2,
1712 GLdepth zspan[MAX_WIDTH],
1713 GLfixed fogspan[MAX_WIDTH],
1714 GLchan rgba[MAX_WIDTH][4],
1715 GLchan spec[MAX_WIDTH][4] )
1716 {
1717 #define INTERP_Z 1
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; \
1726 if (flat_shade) { \
1727 r = v0->color[0]; \
1728 g = v0->color[1]; \
1729 b = v0->color[2]; \
1730 a = v0->color[3]; \
1731 sr = v0->specular[0]; \
1732 sg = v0->specular[1]; \
1733 sb = v0->specular[2]; \
1734 }
1735 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1736 { \
1737 GLint i; \
1738 const GLint n = RIGHT-LEFT; \
1739 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
1740 if (n>0) { \
1741 if (flat_shade) { \
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; \
1753 s[i] = ss*invQ; \
1754 t[i] = tt*invQ; \
1755 u[i] = uu*invQ; \
1756 fffog += fdfogdx; \
1757 ffz += fdzdx; \
1758 ss += dsdx; \
1759 tt += dtdx; \
1760 uu += dudx; \
1761 vv += dvdx; \
1762 } \
1763 } \
1764 else { \
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); \
1776 s[i] = ss*invQ; \
1777 t[i] = tt*invQ; \
1778 u[i] = uu*invQ; \
1779 fffog += fdfogdx; \
1780 ffz += fdzdx; \
1781 ffr += fdrdx; \
1782 ffg += fdgdx; \
1783 ffb += fdbdx; \
1784 ffa += fdadx; \
1785 ffsr += fdsrdx; \
1786 ffsg += fdsgdx; \
1787 ffsb += fdsbdx; \
1788 ss += dsdx; \
1789 tt += dtdx; \
1790 uu += dudx; \
1791 vv += dvdx; \
1792 } \
1793 } \
1794 gl_write_texture_span( ctx, n, LEFT, Y, zspan, \
1795 fogspan, \
1796 s, t, u, NULL, rgba, \
1797 (CONST GLchan (*)[4]) spec, \
1798 GL_POLYGON ); \
1799 } \
1800 }
1801
1802 #include "s_tritemp.h"
1803 }
1804
1805
1806
1807 /*
1808 * Compute the lambda value for a fragment. (texture level of detail)
1809 */
1810 static INLINE GLfloat
1811 compute_lambda( GLfloat dsdx, GLfloat dsdy, GLfloat dtdx, GLfloat dtdy,
1812 GLfloat invQ, GLfloat width, GLfloat height )
1813 {
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) */
1823 }
1824
1825
1826 /*
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.
1832 */
1833 static void lambda_textured_triangle1( GLcontext *ctx,
1834 SWvertex *v0,
1835 SWvertex *v1,
1836 SWvertex *v2,
1837 GLfloat s[MAX_WIDTH],
1838 GLfloat t[MAX_WIDTH],
1839 GLfloat u[MAX_WIDTH] )
1840 {
1841 #define INTERP_Z 1
1842 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1843 #define INTERP_RGB 1
1844 #define INTERP_ALPHA 1
1845 #define INTERP_TEX 1
1846
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); \
1854 GLint r, g, b, a; \
1855 if (flat_shade) { \
1856 r = v0->color[0]; \
1857 g = v0->color[1]; \
1858 b = v0->color[2]; \
1859 a = v0->color[3]; \
1860 }
1861
1862 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1863 { \
1864 GLint i; \
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]; \
1870 if (n>0) { \
1871 if (flat_shade) { \
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; \
1880 s[i] = ss*invQ; \
1881 t[i] = tt*invQ; \
1882 u[i] = uu*invQ; \
1883 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
1884 invQ, twidth, theight );\
1885 ffz += fdzdx; \
1886 fffog += fdfogdx; \
1887 ss += dsdx; \
1888 tt += dtdx; \
1889 uu += dudx; \
1890 vv += dvdx; \
1891 } \
1892 } \
1893 else { \
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); \
1902 s[i] = ss*invQ; \
1903 t[i] = tt*invQ; \
1904 u[i] = uu*invQ; \
1905 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
1906 invQ, twidth, theight );\
1907 ffz += fdzdx; \
1908 fffog += fdfogdx; \
1909 ffr += fdrdx; \
1910 ffg += fdgdx; \
1911 ffb += fdbdx; \
1912 ffa += fdadx; \
1913 ss += dsdx; \
1914 tt += dtdx; \
1915 uu += dudx; \
1916 vv += dvdx; \
1917 } \
1918 } \
1919 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1920 s, t, u, lambda, \
1921 rgba, NULL, GL_POLYGON ); \
1922 } \
1923 }
1924
1925 #include "s_tritemp.h"
1926 }
1927
1928
1929 /*
1930 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1931 * interpolation.
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.
1936 */
1937 static void lambda_textured_spec_triangle1( GLcontext *ctx,
1938 SWvertex *v0,
1939 SWvertex *v1,
1940 SWvertex *v2,
1941 GLfloat s[MAX_WIDTH],
1942 GLfloat t[MAX_WIDTH],
1943 GLfloat u[MAX_WIDTH] )
1944 {
1945 #define INTERP_Z 1
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
1951
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; \
1960 if (flat_shade) { \
1961 r = v0->color[0]; \
1962 g = v0->color[1]; \
1963 b = v0->color[2]; \
1964 a = v0->color[3]; \
1965 sr = v0->specular[0]; \
1966 sg = v0->specular[1]; \
1967 sb = v0->specular[2]; \
1968 }
1969
1970 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1971 { \
1972 GLint i; \
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]; \
1979 if (n>0) { \
1980 if (flat_shade) { \
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; \
1992 s[i] = ss*invQ; \
1993 t[i] = tt*invQ; \
1994 u[i] = uu*invQ; \
1995 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
1996 invQ, twidth, theight );\
1997 fffog += fdfogdx; \
1998 ffz += fdzdx; \
1999 ss += dsdx; \
2000 tt += dtdx; \
2001 uu += dudx; \
2002 vv += dvdx; \
2003 } \
2004 } \
2005 else { \
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); \
2017 s[i] = ss*invQ; \
2018 t[i] = tt*invQ; \
2019 u[i] = uu*invQ; \
2020 lambda[i] = compute_lambda( dsdx, dsdy, dtdx, dtdy, \
2021 invQ, twidth, theight );\
2022 fffog += fdfogdx; \
2023 ffz += fdzdx; \
2024 ffr += fdrdx; \
2025 ffg += fdgdx; \
2026 ffb += fdbdx; \
2027 ffa += fdadx; \
2028 ffsr += fdsrdx; \
2029 ffsg += fdsgdx; \
2030 ffsb += fdsbdx; \
2031 ss += dsdx; \
2032 tt += dtdx; \
2033 uu += dudx; \
2034 vv += dvdx; \
2035 } \
2036 } \
2037 gl_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
2038 s, t, u, lambda, \
2039 rgba, (CONST GLchan (*)[4]) spec, \
2040 GL_POLYGON ); \
2041 } \
2042 }
2043
2044 #include "s_tritemp.h"
2045 }
2046
2047
2048 /*
2049 * This is the big one!
2050 * Interpolate Z, RGB, Alpha, and two sets of texture coordinates.
2051 * Yup, it's slow.
2052 */
2053 static void
2054 lambda_multitextured_triangle1( GLcontext *ctx,
2055 SWvertex *v0,
2056 SWvertex *v1,
2057 SWvertex *v2,
2058 GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH],
2059 GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH],
2060 GLfloat u[MAX_TEXTURE_UNITS][MAX_WIDTH])
2061 {
2062 #define INTERP_Z 1
2063 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2064 #define INTERP_RGB 1
2065 #define INTERP_ALPHA 1
2066 #define INTERP_MULTITEX 1
2067
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]; \
2072 GLint r, g, b, a; \
2073 if (flat_shade) { \
2074 r = v0->color[0]; \
2075 g = v0->color[1]; \
2076 b = v0->color[2]; \
2077 a = v0->color[3]; \
2078 } \
2079 { \
2080 GLuint unit; \
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; \
2088 } \
2089 } \
2090 }
2091
2092
2093
2094 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2095 { \
2096 GLint i; \
2097 const GLint n = RIGHT-LEFT; \
2098 GLdepth zspan[MAX_WIDTH]; \
2099 GLfixed fogspan[MAX_WIDTH]; \
2100 GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; \
2101 if (n > 0) { \
2102 if (flat_shade) { \
2103 for (i=0;i<n;i++) { \
2104 zspan[i] = FixedToDepth(ffz); \
2105 fogspan[i] = fffog / 256; \
2106 fffog += fdfogdx; \
2107 ffz += fdzdx; \
2108 rgba[i][RCOMP] = r; \
2109 rgba[i][GCOMP] = g; \
2110 rgba[i][BCOMP] = b; \
2111 rgba[i][ACOMP] = a; \
2112 { \
2113 GLuint unit; \
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]; \
2127 } \
2128 } \
2129 } \
2130 } \
2131 } \
2132 else { /* smooth shade */ \
2133 for (i=0;i<n;i++) { \
2134 zspan[i] = FixedToDepth(ffz); \
2135 fogspan[i] = fffog / 256; \
2136 ffz += fdzdx; \
2137 fffog += fdfogdx; \
2138 rgba[i][RCOMP] = FixedToInt(ffr); \
2139 rgba[i][GCOMP] = FixedToInt(ffg); \
2140 rgba[i][BCOMP] = FixedToInt(ffb); \
2141 rgba[i][ACOMP] = FixedToInt(ffa); \
2142 ffr += fdrdx; \
2143 ffg += fdgdx; \
2144 ffb += fdbdx; \
2145 ffa += fdadx; \
2146 { \
2147 GLuint unit; \
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]; \
2161 } \
2162 } \
2163 } \
2164 } \
2165 } \
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 ); \
2172 } \
2173 }
2174 #include "s_tritemp.h"
2175 }
2176
2177
2178 /*
2179 * These wrappers are needed to deal with the 32KB / stack frame limit
2180 * on Mac / PowerPC systems.
2181 */
2182
2183 static void general_textured_spec_triangle(GLcontext *ctx,
2184 SWvertex *v0,
2185 SWvertex *v1,
2186 SWvertex *v2 )
2187 {
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);
2192 }
2193
2194 static void lambda_textured_triangle( GLcontext *ctx,
2195 SWvertex *v0,
2196 SWvertex *v1,
2197 SWvertex *v2 )
2198 {
2199 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];
2200 lambda_textured_triangle1(ctx,v0,v1,v2,s,t,u);
2201 }
2202
2203 static void lambda_textured_spec_triangle( GLcontext *ctx,
2204 SWvertex *v0,
2205 SWvertex *v1,
2206 SWvertex *v2 )
2207 {
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);
2212 }
2213
2214
2215 static void lambda_multitextured_triangle( GLcontext *ctx,
2216 SWvertex *v0,
2217 SWvertex *v1,
2218 SWvertex *v2 )
2219 {
2220
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);
2225
2226 lambda_multitextured_triangle1(ctx,v0,v1,v2,s,t,u);
2227
2228 UNDEFARRAY(u);
2229 }
2230
2231
2232
2233 static void occlusion_zless_triangle( GLcontext *ctx,
2234 SWvertex *v0,
2235 SWvertex *v1,
2236 SWvertex *v2 )
2237 {
2238 if (ctx->OcclusionResult) {
2239 return;
2240 }
2241
2242 #define DO_OCCLUSION_TEST
2243 #define INTERP_Z 1
2244 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2245 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2246 { \
2247 GLint i; \
2248 const GLint len = RIGHT-LEFT; \
2249 for (i=0;i<len;i++) { \
2250 GLdepth z = FixedToDepth(ffz); \
2251 (void) fffog; \
2252 if (z < zRow[i]) { \
2253 ctx->OcclusionResult = GL_TRUE; \
2254 return; \
2255 } \
2256 ffz += fdzdx; \
2257 } \
2258 }
2259 #include "s_tritemp.h"
2260 }
2261
2262
2263
2264
2265
2266 #if 0
2267 # define dputs(s) puts(s)
2268 #else
2269 # define dputs(s)
2270 #endif
2271
2272
2273
2274 /*
2275 * Determine which triangle rendering function to use given the current
2276 * rendering context.
2277 *
2278 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
2279 * remove tests to this code.
2280 */
2281 void
2282 _swrast_choose_triangle( GLcontext *ctx )
2283 {
2284 SWcontext *swrast = SWRAST_CONTEXT(ctx);
2285 const GLboolean rgbmode = ctx->Visual.RGBAflag;
2286
2287 if (ctx->RenderMode==GL_RENDER) {
2288
2289 if (ctx->Polygon.SmoothFlag) {
2290 _mesa_set_aa_triangle_function(ctx);
2291 ASSERT(swrast->Triangle);
2292 return;
2293 }
2294
2295 if (ctx->Depth.OcclusionTest &&
2296 ctx->Depth.Test &&
2297 ctx->Depth.Mask == GL_FALSE &&
2298 ctx->Depth.Func == GL_LESS &&
2299 !ctx->Stencil.Enabled) {
2300 if ((rgbmode &&
2301 ctx->Color.ColorMask[0] == 0 &&
2302 ctx->Color.ColorMask[1] == 0 &&
2303 ctx->Color.ColorMask[2] == 0 &&
2304 ctx->Color.ColorMask[3] == 0)
2305 ||
2306 (!rgbmode && ctx->Color.IndexMask == 0)) {
2307 dputs("occlusion_test_triangle");
2308 swrast->Triangle = occlusion_zless_triangle;
2309 return;
2310 }
2311 }
2312
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! */
2323 && image->Border==0
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) {
2328
2329 if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
2330
2331 if (filter==GL_NEAREST
2332 && format==GL_RGB
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) {
2340
2341 if (swrast->_RasterMask==DEPTH_BIT) {
2342 swrast->Triangle = simple_z_textured_triangle;
2343 dputs("simple_z_textured_triangle");
2344 }
2345 else {
2346 swrast->Triangle = simple_textured_triangle;
2347 dputs("simple_textured_triangle");
2348 }
2349 }
2350 else {
2351 if (ctx->Texture.Unit[0].EnvMode==GL_ADD) {
2352 swrast->Triangle = general_textured_triangle;
2353 dputs("general_textured_triangle");
2354 }
2355 else {
2356 swrast->Triangle = affine_textured_triangle;
2357 dputs("affine_textured_triangle");
2358 }
2359 }
2360 }
2361 else {
2362 if (filter==GL_NEAREST) {
2363 swrast->Triangle = near_persp_textured_triangle;
2364 dputs("near_persp_textured_triangle");
2365 }
2366 else {
2367 swrast->Triangle = lin_persp_textured_triangle;
2368 dputs("lin_persp_textured_triangle");
2369 }
2370 }
2371 }
2372 else {
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;
2379 else
2380 needLambda = GL_FALSE;
2381 if (swrast->_MultiTextureEnabled) {
2382 swrast->Triangle = lambda_multitextured_triangle;
2383 dputs("lambda_multitextured_triangle");
2384 }
2385 else if ((ctx->Light.Enabled &&
2386 ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR)
2387 || ctx->Fog.ColorSumEnabled) {
2388 /* separate specular color interpolation */
2389 if (needLambda) {
2390 swrast->Triangle = lambda_textured_spec_triangle;
2391 dputs("lambda_textured_spec_triangle");
2392 }
2393 else {
2394 swrast->Triangle = general_textured_spec_triangle;
2395 dputs("general_textured_spec_triangle");
2396 }
2397 }
2398 else {
2399 if (needLambda) {
2400 swrast->Triangle = lambda_textured_triangle;
2401 dputs("lambda_textured_triangle");
2402 }
2403 else {
2404 swrast->Triangle = general_textured_triangle;
2405 dputs("general_textured_triangle");
2406 }
2407 }
2408 }
2409 }
2410 else {
2411 if (ctx->Light.ShadeModel==GL_SMOOTH) {
2412 /* smooth shaded, no texturing, stippled or some raster ops */
2413 if (rgbmode) {
2414 dputs("smooth_rgba_triangle");
2415 swrast->Triangle = smooth_rgba_triangle;
2416 }
2417 else {
2418 dputs("smooth_ci_triangle");
2419 swrast->Triangle = smooth_ci_triangle;
2420 }
2421 }
2422 else {
2423 /* flat shaded, no texturing, stippled or some raster ops */
2424 if (rgbmode) {
2425 dputs("flat_rgba_triangle");
2426 swrast->Triangle = flat_rgba_triangle;
2427 }
2428 else {
2429 dputs("flat_ci_triangle");
2430 swrast->Triangle = flat_ci_triangle;
2431 }
2432 }
2433 }
2434 }
2435 else if (ctx->RenderMode==GL_FEEDBACK) {
2436 swrast->Triangle = gl_feedback_triangle;
2437 }
2438 else {
2439 /* GL_SELECT mode */
2440 swrast->Triangle = gl_select_triangle;
2441 }
2442 }