Fix typo
[mesa.git] / src / mesa / swrast / s_triangle.c
1 /* $Id: s_triangle.c,v 1.15 2001/03/03 20:33:30 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 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 "colormac.h"
38 #include "macros.h"
39 #include "mem.h"
40 #include "mmath.h"
41 #include "teximage.h"
42 #include "texstate.h"
43
44 #include "s_aatriangle.h"
45 #include "s_context.h"
46 #include "s_depth.h"
47 #include "s_feedback.h"
48 #include "s_span.h"
49 #include "s_triangle.h"
50
51 GLboolean _mesa_cull_triangle( GLcontext *ctx,
52 const SWvertex *v0,
53 const SWvertex *v1,
54 const SWvertex *v2 )
55 {
56 GLfloat ex = v1->win[0] - v0->win[0];
57 GLfloat ey = v1->win[1] - v0->win[1];
58 GLfloat fx = v2->win[0] - v0->win[0];
59 GLfloat fy = v2->win[1] - v0->win[1];
60 GLfloat c = ex*fy-ey*fx;
61
62 if (c * SWRAST_CONTEXT(ctx)->_backface_sign > 0)
63 return 0;
64
65 return 1;
66 }
67
68
69 /*
70 * Render a flat-shaded color index triangle.
71 */
72 static void flat_ci_triangle( GLcontext *ctx,
73 const SWvertex *v0,
74 const SWvertex *v1,
75 const SWvertex *v2 )
76 {
77 #define INTERP_Z 1
78
79 #define INNER_LOOP( LEFT, RIGHT, Y ) \
80 { \
81 const GLint n = RIGHT-LEFT; \
82 GLint i; \
83 GLdepth zspan[MAX_WIDTH]; \
84 GLfixed fogspan[MAX_WIDTH]; \
85 if (n>0) { \
86 for (i=0;i<n;i++) { \
87 zspan[i] = FixedToDepth(ffz); \
88 ffz += fdzdx; \
89 fogspan[i] = fffog / 256; \
90 fffog += fdfogdx; \
91 } \
92 _mesa_write_monoindex_span( ctx, n, LEFT, Y, zspan, \
93 fogspan, v0->index, GL_POLYGON ); \
94 } \
95 }
96
97 #include "s_tritemp.h"
98 }
99
100
101
102 /*
103 * Render a smooth-shaded color index triangle.
104 */
105 static void smooth_ci_triangle( GLcontext *ctx,
106 const SWvertex *v0,
107 const SWvertex *v1,
108 const SWvertex *v2 )
109 {
110 #define INTERP_Z 1
111 #define INTERP_INDEX 1
112
113 #define INNER_LOOP( LEFT, RIGHT, Y ) \
114 { \
115 const GLint n = RIGHT-LEFT; \
116 GLint i; \
117 GLdepth zspan[MAX_WIDTH]; \
118 GLfixed fogspan[MAX_WIDTH]; \
119 GLuint index[MAX_WIDTH]; \
120 if (n>0) { \
121 for (i=0;i<n;i++) { \
122 zspan[i] = FixedToDepth(ffz); \
123 ffz += fdzdx; \
124 index[i] = FixedToInt(ffi); \
125 ffi += fdidx; \
126 fogspan[i] = fffog / 256; \
127 fffog += fdfogdx; \
128 } \
129 _mesa_write_index_span( ctx, n, LEFT, Y, zspan, fogspan, \
130 index, GL_POLYGON ); \
131 } \
132 }
133
134 #include "s_tritemp.h"
135 }
136
137
138
139 /*
140 * Render a flat-shaded RGBA triangle.
141 */
142 static void flat_rgba_triangle( GLcontext *ctx,
143 const SWvertex *v0,
144 const SWvertex *v1,
145 const SWvertex *v2 )
146 {
147 #define INTERP_Z 1
148 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
149
150 #define INNER_LOOP( LEFT, RIGHT, Y ) \
151 { \
152 const GLint n = RIGHT-LEFT; \
153 GLint i; \
154 GLdepth zspan[MAX_WIDTH]; \
155 GLfixed fogspan[MAX_WIDTH]; \
156 if (n>0) { \
157 for (i=0;i<n;i++) { \
158 zspan[i] = FixedToDepth(ffz); \
159 ffz += fdzdx; \
160 fogspan[i] = fffog / 256; \
161 fffog += fdfogdx; \
162 } \
163 _mesa_write_monocolor_span( ctx, n, LEFT, Y, zspan, \
164 fogspan, v2->color, \
165 GL_POLYGON ); \
166 } \
167 }
168
169 #include "s_tritemp.h"
170
171 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */
172 ASSERT(ctx->Light.ShadeModel==GL_FLAT);
173 }
174
175
176
177 /*
178 * Render a smooth-shaded RGBA triangle.
179 */
180 static void smooth_rgba_triangle( GLcontext *ctx,
181 const SWvertex *v0,
182 const SWvertex *v1,
183 const SWvertex *v2 )
184 {
185
186 #define INTERP_Z 1
187 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
188 #define INTERP_RGB 1
189 #define INTERP_ALPHA 1
190
191 #define INNER_LOOP( LEFT, RIGHT, Y ) \
192 { \
193 const GLint n = RIGHT-LEFT; \
194 GLint i; \
195 GLdepth zspan[MAX_WIDTH]; \
196 GLchan rgba[MAX_WIDTH][4]; \
197 GLfixed fogspan[MAX_WIDTH]; \
198 if (n>0) { \
199 for (i=0;i<n;i++) { \
200 zspan[i] = FixedToDepth(ffz); \
201 rgba[i][RCOMP] = FixedToInt(ffr); \
202 rgba[i][GCOMP] = FixedToInt(ffg); \
203 rgba[i][BCOMP] = FixedToInt(ffb); \
204 rgba[i][ACOMP] = FixedToInt(ffa); \
205 fogspan[i] = fffog / 256; \
206 fffog += fdfogdx; \
207 ffz += fdzdx; \
208 ffr += fdrdx; \
209 ffg += fdgdx; \
210 ffb += fdbdx; \
211 ffa += fdadx; \
212 } \
213 _mesa_write_rgba_span( ctx, n, LEFT, Y, \
214 (CONST GLdepth *) zspan, \
215 fogspan, \
216 rgba, GL_POLYGON ); \
217 } \
218 }
219
220 #include "s_tritemp.h"
221
222 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */
223 ASSERT(ctx->Light.ShadeModel==GL_SMOOTH);
224 }
225
226
227 /*
228 * Render an RGB, GL_DECAL, textured triangle.
229 * Interpolate S,T only w/out mipmapping or perspective correction.
230 *
231 * No fog.
232 */
233 static void simple_textured_triangle( GLcontext *ctx,
234 const SWvertex *v0,
235 const SWvertex *v1,
236 const SWvertex *v2 )
237 {
238 #define INTERP_INT_TEX 1
239 #define S_SCALE twidth
240 #define T_SCALE theight
241 #define SETUP_CODE \
242 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
243 GLint b = obj->BaseLevel; \
244 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
245 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
246 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
247 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
248 GLint smask = obj->Image[b]->Width - 1; \
249 GLint tmask = obj->Image[b]->Height - 1; \
250 if (!texture) { \
251 /* this shouldn't happen */ \
252 return; \
253 }
254
255 #define INNER_LOOP( LEFT, RIGHT, Y ) \
256 { \
257 CONST GLint n = RIGHT-LEFT; \
258 GLint i; \
259 GLchan rgb[MAX_WIDTH][3]; \
260 if (n>0) { \
261 ffs -= FIXED_HALF; /* off-by-one error? */ \
262 fft -= FIXED_HALF; \
263 for (i=0;i<n;i++) { \
264 GLint s = FixedToInt(ffs) & smask; \
265 GLint t = FixedToInt(fft) & tmask; \
266 GLint pos = (t << twidth_log2) + s; \
267 pos = pos + pos + pos; /* multiply by 3 */ \
268 rgb[i][RCOMP] = texture[pos]; \
269 rgb[i][GCOMP] = texture[pos+1]; \
270 rgb[i][BCOMP] = texture[pos+2]; \
271 ffs += fdsdx; \
272 fft += fdtdx; \
273 } \
274 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
275 (CONST GLchan (*)[3]) rgb, NULL ); \
276 } \
277 }
278
279 #include "s_tritemp.h"
280 }
281
282
283 /*
284 * Render an RGB, GL_DECAL, textured triangle.
285 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
286 * perspective correction.
287 *
288 * No fog.
289 */
290 static void simple_z_textured_triangle( GLcontext *ctx,
291 const SWvertex *v0,
292 const SWvertex *v1,
293 const SWvertex *v2 )
294 {
295 #define INTERP_Z 1
296 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
297 #define INTERP_INT_TEX 1
298 #define S_SCALE twidth
299 #define T_SCALE theight
300 #define SETUP_CODE \
301 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
302 GLint b = obj->BaseLevel; \
303 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
304 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
305 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
306 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
307 GLint smask = obj->Image[b]->Width - 1; \
308 GLint tmask = obj->Image[b]->Height - 1; \
309 if (!texture) { \
310 /* this shouldn't happen */ \
311 return; \
312 }
313
314 #define INNER_LOOP( LEFT, RIGHT, Y ) \
315 { \
316 CONST GLint n = RIGHT-LEFT; \
317 GLint i; \
318 GLchan rgb[MAX_WIDTH][3]; \
319 GLubyte mask[MAX_WIDTH]; \
320 (void) fffog; \
321 if (n>0) { \
322 ffs -= FIXED_HALF; /* off-by-one error? */ \
323 fft -= FIXED_HALF; \
324 for (i=0;i<n;i++) { \
325 GLdepth z = FixedToDepth(ffz); \
326 if (z < zRow[i]) { \
327 GLint s = FixedToInt(ffs) & smask; \
328 GLint t = FixedToInt(fft) & tmask; \
329 GLint pos = (t << twidth_log2) + s; \
330 pos = pos + pos + pos; /* multiply by 3 */ \
331 rgb[i][RCOMP] = texture[pos]; \
332 rgb[i][GCOMP] = texture[pos+1]; \
333 rgb[i][BCOMP] = texture[pos+2]; \
334 zRow[i] = z; \
335 mask[i] = 1; \
336 } \
337 else { \
338 mask[i] = 0; \
339 } \
340 ffz += fdzdx; \
341 ffs += fdsdx; \
342 fft += fdtdx; \
343 } \
344 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
345 (CONST GLchan (*)[3]) rgb, mask ); \
346 } \
347 }
348
349 #include "s_tritemp.h"
350 }
351
352
353
354 /*
355 * Render an RGB/RGBA textured triangle without perspective correction.
356 */
357 static void affine_textured_triangle( GLcontext *ctx,
358 const SWvertex *v0,
359 const SWvertex *v1,
360 const SWvertex *v2 )
361 {
362 #define INTERP_Z 1
363 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
364 #define INTERP_RGB 1
365 #define INTERP_ALPHA 1
366 #define INTERP_INT_TEX 1
367 #define S_SCALE twidth
368 #define T_SCALE theight
369 #define SETUP_CODE \
370 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
371 struct gl_texture_object *obj = unit->Current2D; \
372 GLint b = obj->BaseLevel; \
373 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
374 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
375 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
376 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
377 GLint smask = obj->Image[b]->Width - 1; \
378 GLint tmask = obj->Image[b]->Height - 1; \
379 GLint format = obj->Image[b]->Format; \
380 GLint filter = obj->MinFilter; \
381 GLint envmode = unit->EnvMode; \
382 GLint comp, tbytesline, tsize; \
383 GLfixed er, eg, eb, ea; \
384 GLint tr, tg, tb, ta; \
385 if (!texture) { \
386 /* this shouldn't happen */ \
387 return; \
388 } \
389 if (envmode == GL_BLEND || envmode == GL_ADD) { \
390 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
391 er = FloatToFixed(unit->EnvColor[RCOMP]); \
392 eg = FloatToFixed(unit->EnvColor[GCOMP]); \
393 eb = FloatToFixed(unit->EnvColor[BCOMP]); \
394 ea = FloatToFixed(unit->EnvColor[ACOMP]); \
395 } \
396 switch (format) { \
397 case GL_ALPHA: \
398 case GL_LUMINANCE: \
399 case GL_INTENSITY: \
400 comp = 1; \
401 break; \
402 case GL_LUMINANCE_ALPHA: \
403 comp = 2; \
404 break; \
405 case GL_RGB: \
406 comp = 3; \
407 break; \
408 case GL_RGBA: \
409 comp = 4; \
410 break; \
411 default: \
412 _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
413 return; \
414 } \
415 tbytesline = obj->Image[b]->Width * comp; \
416 tsize = theight * tbytesline;
417
418
419 /* Instead of defining a function for each mode, a test is done
420 * between the outer and inner loops. This is to reduce code size
421 * and complexity. Observe that an optimizing compiler kills
422 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
423 */
424
425 #define NEAREST_RGB \
426 tr = tex00[RCOMP]; \
427 tg = tex00[GCOMP]; \
428 tb = tex00[BCOMP]; \
429 ta = 0xff
430
431 #define LINEAR_RGB \
432 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
433 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
434 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
435 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
436 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
437 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
438 ta = 0xff
439
440 #define NEAREST_RGBA \
441 tr = tex00[RCOMP]; \
442 tg = tex00[GCOMP]; \
443 tb = tex00[BCOMP]; \
444 ta = tex00[ACOMP]
445
446 #define LINEAR_RGBA \
447 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
448 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
449 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
450 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
451 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
452 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
453 ta = (ti * (si * tex00[3] + sf * tex01[3]) + \
454 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
455
456 #define MODULATE \
457 dest[RCOMP] = ffr * (tr + 1) >> (FIXED_SHIFT + 8); \
458 dest[GCOMP] = ffg * (tg + 1) >> (FIXED_SHIFT + 8); \
459 dest[BCOMP] = ffb * (tb + 1) >> (FIXED_SHIFT + 8); \
460 dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
461
462 #define DECAL \
463 dest[RCOMP] = ((0xff - ta) * ffr + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
464 dest[GCOMP] = ((0xff - ta) * ffg + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
465 dest[BCOMP] = ((0xff - ta) * ffb + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
466 dest[ACOMP] = FixedToInt(ffa)
467
468 #define BLEND \
469 dest[RCOMP] = ((0xff - tr) * ffr + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
470 dest[GCOMP] = ((0xff - tg) * ffg + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
471 dest[BCOMP] = ((0xff - tb) * ffb + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
472 dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
473
474 #define REPLACE \
475 dest[RCOMP] = tr; \
476 dest[GCOMP] = tg; \
477 dest[BCOMP] = tb; \
478 dest[ACOMP] = ta
479
480 #define ADD \
481 dest[RCOMP] = ((ffr << 8) + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
482 dest[GCOMP] = ((ffg << 8) + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
483 dest[BCOMP] = ((ffb << 8) + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
484 dest[ACOMP] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
485
486 /* shortcuts */
487
488 #define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE
489
490 #define NEAREST_RGBA_REPLACE *(GLint *)dest = *(GLint *)tex00
491
492 #define SPAN1(DO_TEX,COMP) \
493 for (i=0;i<n;i++) { \
494 GLint s = FixedToInt(ffs) & smask; \
495 GLint t = FixedToInt(fft) & tmask; \
496 GLint pos = (t << twidth_log2) + s; \
497 const GLchan *tex00 = texture + COMP * pos; \
498 zspan[i] = FixedToDepth(ffz); \
499 fogspan[i] = fffog / 256; \
500 DO_TEX; \
501 fffog += fdfogdx; \
502 ffz += fdzdx; \
503 ffr += fdrdx; \
504 ffg += fdgdx; \
505 ffb += fdbdx; \
506 ffa += fdadx; \
507 ffs += fdsdx; \
508 fft += fdtdx; \
509 dest += 4; \
510 }
511
512 #define SPAN2(DO_TEX,COMP) \
513 for (i=0;i<n;i++) { \
514 GLint s = FixedToInt(ffs) & smask; \
515 GLint t = FixedToInt(fft) & tmask; \
516 GLint sf = ffs & FIXED_FRAC_MASK; \
517 GLint tf = fft & FIXED_FRAC_MASK; \
518 GLint si = FIXED_FRAC_MASK - sf; \
519 GLint ti = FIXED_FRAC_MASK - tf; \
520 GLint pos = (t << twidth_log2) + s; \
521 const GLchan *tex00 = texture + COMP * pos; \
522 const GLchan *tex10 = tex00 + tbytesline; \
523 const GLchan *tex01 = tex00 + COMP; \
524 const GLchan *tex11 = tex10 + COMP; \
525 if (t == tmask) { \
526 tex10 -= tsize; \
527 tex11 -= tsize; \
528 } \
529 if (s == smask) { \
530 tex01 -= tbytesline; \
531 tex11 -= tbytesline; \
532 } \
533 zspan[i] = FixedToDepth(ffz); \
534 fogspan[i] = fffog / 256; \
535 DO_TEX; \
536 fffog += fdfogdx; \
537 ffz += fdzdx; \
538 ffr += fdrdx; \
539 ffg += fdgdx; \
540 ffb += fdbdx; \
541 ffa += fdadx; \
542 ffs += fdsdx; \
543 fft += fdtdx; \
544 dest += 4; \
545 }
546
547 /* here comes the heavy part.. (something for the compiler to chew on) */
548 #define INNER_LOOP( LEFT, RIGHT, Y ) \
549 { \
550 CONST GLint n = RIGHT-LEFT; \
551 GLint i; \
552 GLdepth zspan[MAX_WIDTH]; \
553 GLfixed fogspan[MAX_WIDTH]; \
554 GLchan rgba[MAX_WIDTH][4]; \
555 if (n>0) { \
556 GLchan *dest = rgba[0]; \
557 ffs -= FIXED_HALF; /* off-by-one error? */ \
558 fft -= FIXED_HALF; \
559 switch (filter) { \
560 case GL_NEAREST: \
561 switch (format) { \
562 case GL_RGB: \
563 switch (envmode) { \
564 case GL_MODULATE: \
565 SPAN1(NEAREST_RGB;MODULATE,3); \
566 break; \
567 case GL_DECAL: \
568 case GL_REPLACE: \
569 SPAN1(NEAREST_RGB_REPLACE,3); \
570 break; \
571 case GL_BLEND: \
572 SPAN1(NEAREST_RGB;BLEND,3); \
573 break; \
574 case GL_ADD: \
575 SPAN1(NEAREST_RGB;ADD,3); \
576 break; \
577 default: /* unexpected env mode */ \
578 abort(); \
579 } \
580 break; \
581 case GL_RGBA: \
582 switch(envmode) { \
583 case GL_MODULATE: \
584 SPAN1(NEAREST_RGBA;MODULATE,4); \
585 break; \
586 case GL_DECAL: \
587 SPAN1(NEAREST_RGBA;DECAL,4); \
588 break; \
589 case GL_BLEND: \
590 SPAN1(NEAREST_RGBA;BLEND,4); \
591 break; \
592 case GL_ADD: \
593 SPAN1(NEAREST_RGBA;ADD,4); \
594 break; \
595 case GL_REPLACE: \
596 SPAN1(NEAREST_RGBA_REPLACE,4); \
597 break; \
598 default: /* unexpected env mode */ \
599 abort(); \
600 } \
601 break; \
602 } \
603 break; \
604 case GL_LINEAR: \
605 ffs -= FIXED_HALF; \
606 fft -= FIXED_HALF; \
607 switch (format) { \
608 case GL_RGB: \
609 switch (envmode) { \
610 case GL_MODULATE: \
611 SPAN2(LINEAR_RGB;MODULATE,3); \
612 break; \
613 case GL_DECAL: \
614 case GL_REPLACE: \
615 SPAN2(LINEAR_RGB;REPLACE,3); \
616 break; \
617 case GL_BLEND: \
618 SPAN2(LINEAR_RGB;BLEND,3); \
619 break; \
620 case GL_ADD: \
621 SPAN2(LINEAR_RGB;ADD,3); \
622 break; \
623 default: /* unexpected env mode */ \
624 abort(); \
625 } \
626 break; \
627 case GL_RGBA: \
628 switch (envmode) { \
629 case GL_MODULATE: \
630 SPAN2(LINEAR_RGBA;MODULATE,4); \
631 break; \
632 case GL_DECAL: \
633 SPAN2(LINEAR_RGBA;DECAL,4); \
634 break; \
635 case GL_BLEND: \
636 SPAN2(LINEAR_RGBA;BLEND,4); \
637 break; \
638 case GL_ADD: \
639 SPAN2(LINEAR_RGBA;ADD,4); \
640 break; \
641 case GL_REPLACE: \
642 SPAN2(LINEAR_RGBA;REPLACE,4); \
643 break; \
644 default: /* unexpected env mode */ \
645 abort(); \
646 } \
647 break; \
648 } \
649 break; \
650 } \
651 _mesa_write_rgba_span(ctx, n, LEFT, Y, zspan, \
652 fogspan, \
653 rgba, GL_POLYGON); \
654 /* explicit kill of variables: */ \
655 ffr = ffg = ffb = ffa = 0; \
656 } \
657 }
658
659 #include "s_tritemp.h"
660 #undef SPAN1
661 #undef SPAN2
662 }
663
664
665
666 /*
667 * Render an perspective corrected RGB/RGBA textured triangle.
668 * The Q (aka V in Mesa) coordinate must be zero such that the divide
669 * by interpolated Q/W comes out right.
670 *
671 * This function only renders textured triangles that use GL_NEAREST.
672 * Perspective correction works right.
673 *
674 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
675 * Send all questions and bug reports to him.
676 */
677 #if 0 /* XXX disabled because of texcoord interpolation errors */
678 static void near_persp_textured_triangle(GLcontext *ctx,
679 const SWvertex *v0,
680 const SWvertex *v1,
681 const SWvertex *v2 )
682 {
683 /* The BIAS value is used to shift negative values into positive values.
684 * Without this, negative texture values don't GL_REPEAT correctly at just
685 * below zero, because (int)-0.5 = 0 = (int)0.5. We're not going to worry
686 * about texture coords less than -BIAS. This could be fixed by using
687 * FLOORF etc. instead, but this is slower...
688 */
689 #define BIAS 4096.0F
690
691 #define INTERP_Z 1
692 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
693 #define INTERP_RGB 1
694 #define INTERP_ALPHA 1
695 #define INTERP_TEX 1
696 #define SETUP_CODE \
697 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
698 struct gl_texture_object *obj = unit->Current2D; \
699 const GLint b = obj->BaseLevel; \
700 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
701 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
702 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
703 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
704 const GLint smask = (obj->Image[b]->Width - 1); \
705 const GLint tmask = (obj->Image[b]->Height - 1); \
706 const GLint format = obj->Image[b]->Format; \
707 const GLint envmode = unit->EnvMode; \
708 GLfloat sscale, tscale; \
709 GLfixed er, eg, eb, ea; \
710 GLint tr, tg, tb, ta; \
711 if (!texture) { \
712 /* this shouldn't happen */ \
713 return; \
714 } \
715 if (envmode == GL_BLEND || envmode == GL_ADD) { \
716 er = FloatToFixed(unit->EnvColor[RCOMP]); \
717 eg = FloatToFixed(unit->EnvColor[GCOMP]); \
718 eb = FloatToFixed(unit->EnvColor[BCOMP]); \
719 ea = FloatToFixed(unit->EnvColor[ACOMP]); \
720 } \
721 sscale = twidth; \
722 tscale = theight; \
723
724
725 #define OLD_SPAN(DO_TEX,COMP) \
726 for (i=0;i<n;i++) { \
727 GLfloat invQ = 1.0f / vv; \
728 GLint s = (int)(SS * invQ + BIAS) & smask; \
729 GLint t = (int)(TT * invQ + BIAS) & tmask; \
730 GLint pos = COMP * ((t << twidth_log2) + s); \
731 const GLchan *tex00 = texture + pos; \
732 zspan[i] = FixedToDepth(ffz); \
733 fogspan[i] = fffog / 256; \
734 DO_TEX; \
735 fffog += fdfogdx; \
736 ffz += fdzdx; \
737 ffr += fdrdx; \
738 ffg += fdgdx; \
739 ffb += fdbdx; \
740 ffa += fdadx; \
741 SS += dSdx; \
742 TT += dTdx; \
743 vv += dvdx; \
744 dest += 4; \
745 }
746
747 #define X_Y_TEX_COORD(X, Y) ((((int)(X) & tmask) << twidth_log2) + ((int)(Y) & smask))
748 #define Y_X_TEX_COORD(X, Y) ((((int)(Y) & tmask) << twidth_log2) + ((int)(X) & smask))
749
750 #define SPAN1(DO_TEX, COMP, TEX_COORD) { \
751 GLfloat x_max = CEILF(x_tex); \
752 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \
753 GLint j, x_m = (int)x_max; \
754 GLint pos; \
755 if ((int)y_max != (int)y_tex) { \
756 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \
757 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
758 pos = COMP * TEX_COORD(x_tex, y_tex); \
759 DRAW_LINE (DO_TEX); \
760 y_tex = y_max; \
761 } \
762 nominator += vv * x_max; \
763 denominator -= dvdx * x_max; \
764 j = nominator / denominator; \
765 pos = COMP * TEX_COORD(x_tex, y_tex); \
766 DRAW_LINE (DO_TEX); \
767 while (i<n) { \
768 y_tex = y_max; \
769 y_max += dy_dx; \
770 if ((int)y_max != (int)y_tex) { \
771 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \
772 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
773 pos = COMP * TEX_COORD(x_m, y_tex); \
774 DRAW_LINE (DO_TEX); \
775 y_tex = y_max; \
776 } \
777 nominator += vv; \
778 denominator -= dvdx; \
779 j = nominator/denominator; \
780 pos = COMP * TEX_COORD(x_m, y_tex); \
781 DRAW_LINE (DO_TEX); \
782 x_m ++; \
783 } \
784 }
785
786 #define SPAN2(DO_TEX, COMP, TEX_COORD) { \
787 GLfloat x_max = CEILF (x_tex); \
788 GLfloat y_max = y_tex + (x_max - x_tex) * dy_dx; \
789 GLint j, x_m = (int) x_max; \
790 GLint pos; \
791 if ((int)y_max != (int)y_tex) { \
792 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \
793 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
794 pos = COMP * TEX_COORD(x_tex, y_tex); \
795 DRAW_LINE (DO_TEX); \
796 y_tex = y_max; \
797 } \
798 nominator += vv * x_max; \
799 denominator -= dvdx * x_max; \
800 j = nominator / denominator; \
801 pos = COMP * TEX_COORD(x_tex, y_tex); \
802 DRAW_LINE (DO_TEX); \
803 while (i<n) { \
804 y_tex = y_max; \
805 y_max += dy_dx; \
806 if ((int)y_max != (int)y_tex) { \
807 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \
808 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid);\
809 pos = COMP * TEX_COORD(x_m, y_tex); \
810 DRAW_LINE (DO_TEX); \
811 y_tex = y_max; \
812 } \
813 nominator += vv; \
814 denominator -= dvdx; \
815 j = nominator/denominator; \
816 pos = COMP * TEX_COORD(x_m, y_tex); \
817 DRAW_LINE (DO_TEX); \
818 x_m ++; \
819 } \
820 }
821
822 #define SPAN3(DO_TEX, COMP, TEX_COORD) { \
823 GLfloat x_min = FLOORF (x_tex); \
824 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \
825 GLint j, x_m = (int)x_min; \
826 GLint pos; \
827 if ((int)y_min != (int)y_tex) { \
828 GLfloat x_mid = x_tex + (CEILF(y_tex)-y_tex) * dx_dy; \
829 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
830 pos = COMP * TEX_COORD(x_m, y_tex); \
831 DRAW_LINE (DO_TEX); \
832 y_tex = y_min; \
833 } \
834 nominator += vv*x_min; \
835 denominator -= dvdx*x_min; \
836 j = nominator / denominator; \
837 pos = COMP * TEX_COORD(x_m, y_tex); \
838 DRAW_LINE (DO_TEX); \
839 while (i<n) { \
840 x_m --; \
841 y_tex = y_min; \
842 y_min -= dy_dx; \
843 if ((int)y_min != (int)y_tex) { \
844 GLfloat x_mid = (CEILF(y_tex)-y_tex) * dx_dy; \
845 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
846 pos = COMP * TEX_COORD(x_m, y_tex); \
847 DRAW_LINE (DO_TEX); \
848 y_tex = y_min; \
849 } \
850 nominator -= vv; \
851 denominator += dvdx; \
852 j = nominator/denominator; \
853 pos = COMP * TEX_COORD(x_m, y_tex); \
854 DRAW_LINE (DO_TEX); \
855 } \
856 }
857
858 #define SPAN4(DO_TEX, COMP, TEX_COORD) \
859 { \
860 GLfloat x_min = FLOORF(x_tex); \
861 GLint x_m = (int)x_min; \
862 GLfloat y_min = y_tex + (x_min - x_tex) * dy_dx; \
863 GLint j; \
864 GLint pos; \
865 if ((int)y_min != (int)y_tex) { \
866 GLfloat x_mid = x_tex + (FLOORF(y_tex)-y_tex) * dx_dy; \
867 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
868 pos = COMP * TEX_COORD(x_m, y_tex); \
869 DRAW_LINE (DO_TEX); \
870 y_tex = y_min; \
871 } \
872 nominator += vv * x_min; \
873 denominator -= dvdx * x_min; \
874 j = nominator / denominator; \
875 pos = COMP * TEX_COORD(x_m, y_tex); \
876 DRAW_LINE (DO_TEX); \
877 while (i<n) { \
878 x_m --; \
879 y_tex = y_min; \
880 y_min -= dy_dx; \
881 if ((int)y_min != (int)y_tex) { \
882 GLfloat x_mid = (FLOORF(y_tex)-y_tex) * dx_dy; \
883 j = (nominator + vv * x_mid)/(denominator - dvdx*x_mid); \
884 pos = COMP * TEX_COORD(x_m, (y_tex)); \
885 DRAW_LINE (DO_TEX); \
886 y_tex = y_min; \
887 } \
888 nominator -= vv; \
889 denominator += dvdx; \
890 j = nominator/denominator; \
891 pos = COMP * TEX_COORD(x_m, y_tex); \
892 DRAW_LINE (DO_TEX); \
893 } \
894 }
895
896 #define DRAW_LINE(DO_TEX) \
897 { \
898 GLchan *tex00 = texture + pos; \
899 if (j>n || j<-100000) \
900 j = n; \
901 while (i<j) { \
902 zspan[i] = FixedToDepth(ffz); \
903 fogspan[i] = fffog / 256; \
904 DO_TEX; \
905 fffog += fdfogdx; \
906 ffz += fdzdx; \
907 ffr += fdrdx; \
908 ffg += fdgdx; \
909 ffb += fdbdx; \
910 ffa += fdadx; \
911 dest += 4; \
912 i++; \
913 } \
914 }
915
916 #define INNER_LOOP( LEFT, RIGHT, Y ) \
917 { \
918 GLint i = 0; \
919 const GLint n = RIGHT-LEFT; \
920 GLdepth zspan[MAX_WIDTH]; \
921 GLfixed fogspan[MAX_WIDTH]; \
922 GLchan rgba[MAX_WIDTH][4]; \
923 (void)uu; /* please GCC */ \
924 if (n > 0) { \
925 GLchan *dest = rgba[0]; \
926 GLfloat SS = ss * sscale; \
927 GLfloat TT = tt * tscale; \
928 GLfloat dSdx = dsdx * sscale; \
929 GLfloat dTdx = dtdx * tscale; \
930 GLfloat x_tex; \
931 GLfloat y_tex; \
932 GLfloat dx_tex; \
933 GLfloat dy_tex; \
934 if (n<5) /* When line very short, setup-time > speed-gain. */ \
935 goto old_span; /* So: take old method */ \
936 x_tex = SS / vv, \
937 y_tex = TT / vv; \
938 dx_tex = (SS + n * dSdx) / (vv + n * dvdx) - x_tex, \
939 dy_tex = (TT + n * dTdx) / (vv + n * dvdx) - y_tex; \
940 /* Choose between walking over texture or over pixelline: */ \
941 /* If there are few texels, walk over texture otherwise */ \
942 /* walk over pixelarray. The quotient on the right side */ \
943 /* should give the timeratio needed to draw one texel in */ \
944 /* comparison to one pixel. Depends on CPU. */ \
945 if (dx_tex*dx_tex + dy_tex*dy_tex < (n*n)/16) { \
946 x_tex += BIAS; \
947 y_tex += BIAS; \
948 if (dx_tex*dx_tex > dy_tex*dy_tex) { \
949 /* if (FABSF(dx_tex) > FABSF(dy_tex)) */ \
950 GLfloat nominator = - SS - vv * BIAS; \
951 GLfloat denominator = dvdx * BIAS + dSdx; \
952 GLfloat dy_dx; \
953 GLfloat dx_dy; \
954 if (dy_tex != 0.0f) { \
955 dy_dx = dy_tex / dx_tex; \
956 dx_dy = 1.0f/dy_dx; \
957 } \
958 else \
959 dy_dx = 0.0f; \
960 if (dx_tex > 0.0f) { \
961 if (dy_tex > 0.0f) { \
962 switch (format) { \
963 case GL_RGB: \
964 switch (envmode) { \
965 case GL_MODULATE: \
966 SPAN1(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
967 break; \
968 case GL_DECAL: \
969 case GL_REPLACE: \
970 SPAN1(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
971 break; \
972 case GL_BLEND: \
973 SPAN1(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
974 break; \
975 case GL_ADD: \
976 SPAN1(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
977 break; \
978 default: /* unexpected env mode */ \
979 abort(); \
980 } \
981 break; \
982 case GL_RGBA: \
983 switch(envmode) { \
984 case GL_MODULATE: \
985 SPAN1(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
986 break; \
987 case GL_DECAL: \
988 SPAN1(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
989 break; \
990 case GL_BLEND: \
991 SPAN1(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
992 break; \
993 case GL_ADD: \
994 SPAN1(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
995 break; \
996 case GL_REPLACE: \
997 SPAN1(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
998 break; \
999 default: /* unexpected env mode */ \
1000 abort(); \
1001 } \
1002 break; \
1003 } \
1004 } \
1005 else { /* dy_tex <= 0.0f */ \
1006 switch (format) { \
1007 case GL_RGB: \
1008 switch (envmode) { \
1009 case GL_MODULATE: \
1010 SPAN2(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1011 break; \
1012 case GL_DECAL: \
1013 case GL_REPLACE: \
1014 SPAN2(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1015 break; \
1016 case GL_BLEND: \
1017 SPAN2(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1018 break; \
1019 case GL_ADD: \
1020 SPAN2(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1021 break; \
1022 default: /* unexpected env mode */ \
1023 abort(); \
1024 } \
1025 break; \
1026 case GL_RGBA: \
1027 switch(envmode) { \
1028 case GL_MODULATE: \
1029 SPAN2(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1030 break; \
1031 case GL_DECAL: \
1032 SPAN2(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1033 break; \
1034 case GL_BLEND: \
1035 SPAN2(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1036 break; \
1037 case GL_ADD: \
1038 SPAN2(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1039 break; \
1040 case GL_REPLACE: \
1041 SPAN2(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1042 break; \
1043 default: /* unexpected env mode */ \
1044 abort(); \
1045 } \
1046 break; \
1047 } \
1048 } \
1049 } \
1050 else { /* dx_tex < 0.0f */ \
1051 if (dy_tex > 0.0f) { \
1052 switch (format) { \
1053 case GL_RGB: \
1054 switch (envmode) { \
1055 case GL_MODULATE: \
1056 SPAN3(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1057 break; \
1058 case GL_DECAL: \
1059 case GL_REPLACE: \
1060 SPAN3(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1061 break; \
1062 case GL_BLEND: \
1063 SPAN3(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1064 break; \
1065 case GL_ADD: \
1066 SPAN3(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1067 break; \
1068 default: /* unexpected env mode */ \
1069 abort(); \
1070 } \
1071 break; \
1072 case GL_RGBA: \
1073 switch(envmode) { \
1074 case GL_MODULATE: \
1075 SPAN3(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1076 break; \
1077 case GL_DECAL: \
1078 SPAN3(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1079 break; \
1080 case GL_BLEND: \
1081 SPAN3(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1082 break; \
1083 case GL_ADD: \
1084 SPAN3(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1085 break; \
1086 case GL_REPLACE: \
1087 SPAN3(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1088 break; \
1089 default: /* unexpected env mode */ \
1090 abort(); \
1091 } \
1092 break; \
1093 } \
1094 } \
1095 else { /* dy_tex <= 0.0f */ \
1096 switch (format) { \
1097 case GL_RGB: \
1098 switch (envmode) { \
1099 case GL_MODULATE: \
1100 SPAN4(NEAREST_RGB;MODULATE,3, Y_X_TEX_COORD);\
1101 break; \
1102 case GL_DECAL: \
1103 case GL_REPLACE: \
1104 SPAN4(NEAREST_RGB_REPLACE,3, Y_X_TEX_COORD); \
1105 break; \
1106 case GL_BLEND: \
1107 SPAN4(NEAREST_RGB;BLEND,3, Y_X_TEX_COORD); \
1108 break; \
1109 case GL_ADD: \
1110 SPAN4(NEAREST_RGB;ADD,3, Y_X_TEX_COORD); \
1111 break; \
1112 default: \
1113 abort(); \
1114 } \
1115 break; \
1116 case GL_RGBA: \
1117 switch(envmode) { \
1118 case GL_MODULATE: \
1119 SPAN4(NEAREST_RGBA;MODULATE,4, Y_X_TEX_COORD);\
1120 break; \
1121 case GL_DECAL: \
1122 SPAN4(NEAREST_RGBA;DECAL,4, Y_X_TEX_COORD); \
1123 break; \
1124 case GL_BLEND: \
1125 SPAN4(NEAREST_RGBA;BLEND,4, Y_X_TEX_COORD); \
1126 break; \
1127 case GL_ADD: \
1128 SPAN4(NEAREST_RGBA;ADD,4, Y_X_TEX_COORD); \
1129 break; \
1130 case GL_REPLACE: \
1131 SPAN4(NEAREST_RGBA_REPLACE,4, Y_X_TEX_COORD);\
1132 break; \
1133 default: /* unexpected env mode */ \
1134 abort(); \
1135 } \
1136 break; \
1137 } \
1138 } \
1139 } \
1140 } \
1141 else { /* FABSF(dx_tex) > FABSF(dy_tex) */ \
1142 GLfloat swap; \
1143 GLfloat dy_dx; \
1144 GLfloat dx_dy; \
1145 GLfloat nominator, denominator; \
1146 if (dx_tex == 0.0f /* && dy_tex == 0.0f*/) \
1147 goto old_span; /* case so special, that use old */ \
1148 /* swap some x-values and y-values */ \
1149 SS = TT; \
1150 dSdx = dTdx; \
1151 swap = x_tex, x_tex = y_tex, y_tex = swap; \
1152 swap = dx_tex, dx_tex = dy_tex, dy_tex = swap; \
1153 nominator = - SS - vv * BIAS; \
1154 denominator = dvdx * BIAS + dSdx; \
1155 if (dy_tex != 0.0f) { \
1156 dy_dx = dy_tex / dx_tex; \
1157 dx_dy = 1.0f/dy_dx; \
1158 } \
1159 else \
1160 dy_dx = 0.0f; \
1161 if (dx_tex > 0.0f) { \
1162 if (dy_tex > 0.0f) { \
1163 switch (format) { \
1164 case GL_RGB: \
1165 switch (envmode) { \
1166 case GL_MODULATE: \
1167 SPAN1(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1168 break; \
1169 case GL_DECAL: \
1170 case GL_REPLACE: \
1171 SPAN1(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1172 break; \
1173 case GL_BLEND: \
1174 SPAN1(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1175 break; \
1176 case GL_ADD: \
1177 SPAN1(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1178 break; \
1179 default: /* unexpected env mode */ \
1180 abort(); \
1181 } \
1182 break; \
1183 case GL_RGBA: \
1184 switch(envmode) { \
1185 case GL_MODULATE: \
1186 SPAN1(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1187 break; \
1188 case GL_DECAL: \
1189 SPAN1(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1190 break; \
1191 case GL_BLEND: \
1192 SPAN1(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1193 break; \
1194 case GL_ADD: \
1195 SPAN1(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1196 break; \
1197 case GL_REPLACE: \
1198 SPAN1(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1199 break; \
1200 default: \
1201 abort(); \
1202 } \
1203 break; \
1204 } \
1205 } \
1206 else { /* dy_tex <= 0.0f */ \
1207 switch (format) { \
1208 case GL_RGB: \
1209 switch (envmode) { \
1210 case GL_MODULATE: \
1211 SPAN2(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1212 break; \
1213 case GL_DECAL: \
1214 case GL_REPLACE: \
1215 SPAN2(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1216 break; \
1217 case GL_BLEND: \
1218 SPAN2(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1219 break; \
1220 case GL_ADD: \
1221 SPAN2(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1222 break; \
1223 default: \
1224 abort(); \
1225 } \
1226 break; \
1227 case GL_RGBA: \
1228 switch(envmode) { \
1229 case GL_MODULATE: \
1230 SPAN2(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1231 break; \
1232 case GL_DECAL: \
1233 SPAN2(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1234 break; \
1235 case GL_BLEND: \
1236 SPAN2(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1237 break; \
1238 case GL_ADD: \
1239 SPAN2(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1240 break; \
1241 case GL_REPLACE: \
1242 SPAN2(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1243 break; \
1244 default: \
1245 abort(); \
1246 } \
1247 break; \
1248 } \
1249 } \
1250 } \
1251 else { /* dx_tex < 0.0f */ \
1252 if (dy_tex > 0.0f) { \
1253 switch (format) { \
1254 case GL_RGB: \
1255 switch (envmode) { \
1256 case GL_MODULATE: \
1257 SPAN3(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1258 break; \
1259 case GL_DECAL: \
1260 case GL_REPLACE: \
1261 SPAN3(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1262 break; \
1263 case GL_BLEND: \
1264 SPAN3(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1265 break; \
1266 case GL_ADD: \
1267 SPAN3(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1268 break; \
1269 default: \
1270 abort(); \
1271 } \
1272 break; \
1273 case GL_RGBA: \
1274 switch(envmode) { \
1275 case GL_MODULATE: \
1276 SPAN3(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1277 break; \
1278 case GL_DECAL: \
1279 SPAN3(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1280 break; \
1281 case GL_BLEND: \
1282 SPAN3(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1283 break; \
1284 case GL_ADD: \
1285 SPAN3(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1286 break; \
1287 case GL_REPLACE: \
1288 SPAN3(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1289 break; \
1290 default: \
1291 abort(); \
1292 } \
1293 break; \
1294 } \
1295 } \
1296 else { /* dy_tex <= 0.0f */ \
1297 switch (format) { \
1298 case GL_RGB: \
1299 switch (envmode) { \
1300 case GL_MODULATE: \
1301 SPAN4(NEAREST_RGB;MODULATE,3, X_Y_TEX_COORD);\
1302 break; \
1303 case GL_DECAL: \
1304 case GL_REPLACE: \
1305 SPAN4(NEAREST_RGB_REPLACE,3, X_Y_TEX_COORD); \
1306 break; \
1307 case GL_BLEND: \
1308 SPAN4(NEAREST_RGB;BLEND,3, X_Y_TEX_COORD); \
1309 break; \
1310 case GL_ADD: \
1311 SPAN4(NEAREST_RGB;ADD,3, X_Y_TEX_COORD); \
1312 break; \
1313 default: \
1314 abort(); \
1315 } \
1316 break; \
1317 case GL_RGBA: \
1318 switch(envmode) { \
1319 case GL_MODULATE: \
1320 SPAN4(NEAREST_RGBA;MODULATE,4, X_Y_TEX_COORD);\
1321 break; \
1322 case GL_DECAL: \
1323 SPAN4(NEAREST_RGBA;DECAL,4, X_Y_TEX_COORD); \
1324 break; \
1325 case GL_BLEND: \
1326 SPAN4(NEAREST_RGBA;BLEND,4, X_Y_TEX_COORD); \
1327 break; \
1328 case GL_ADD: \
1329 SPAN4(NEAREST_RGBA;ADD,4, X_Y_TEX_COORD); \
1330 break; \
1331 case GL_REPLACE: \
1332 SPAN4(NEAREST_RGBA_REPLACE,4, X_Y_TEX_COORD);\
1333 break; \
1334 default: \
1335 abort(); \
1336 } \
1337 break; \
1338 } \
1339 } \
1340 } \
1341 } \
1342 } \
1343 else { \
1344 old_span: \
1345 switch (format) { \
1346 case GL_RGB: \
1347 switch (envmode) { \
1348 case GL_MODULATE: \
1349 OLD_SPAN(NEAREST_RGB;MODULATE,3); \
1350 break; \
1351 case GL_DECAL: \
1352 case GL_REPLACE: \
1353 OLD_SPAN(NEAREST_RGB_REPLACE,3); \
1354 break; \
1355 case GL_BLEND: \
1356 OLD_SPAN(NEAREST_RGB;BLEND,3); \
1357 break; \
1358 case GL_ADD: \
1359 OLD_SPAN(NEAREST_RGB;ADD,3); \
1360 break; \
1361 default: \
1362 abort(); \
1363 } \
1364 break; \
1365 case GL_RGBA: \
1366 switch(envmode) { \
1367 case GL_MODULATE: \
1368 OLD_SPAN(NEAREST_RGBA;MODULATE,4); \
1369 break; \
1370 case GL_DECAL: \
1371 OLD_SPAN(NEAREST_RGBA;DECAL,4); \
1372 break; \
1373 case GL_BLEND: \
1374 OLD_SPAN(NEAREST_RGBA;BLEND,4); \
1375 break; \
1376 case GL_ADD: \
1377 OLD_SPAN(NEAREST_RGBA;ADD,4); \
1378 break; \
1379 case GL_REPLACE: \
1380 OLD_SPAN(NEAREST_RGBA_REPLACE,4); \
1381 break; \
1382 default: \
1383 abort(); \
1384 } \
1385 break; \
1386 } \
1387 } \
1388 _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1389 fogspan, rgba, GL_POLYGON); \
1390 ffr = ffg = ffb = ffa = 0; \
1391 } \
1392 } \
1393
1394 #include "s_tritemp.h"
1395 #undef OLD_SPAN
1396 #undef SPAN1
1397 #undef SPAN2
1398 #undef SPAN3
1399 #undef SPAN4
1400 #undef X_Y_TEX_COORD
1401 #undef Y_X_TEX_COORD
1402 #undef DRAW_LINE
1403 #undef BIAS
1404 }
1405 #endif
1406
1407
1408 /*
1409 * Render an perspective corrected RGB/RGBA textured triangle.
1410 * The Q (aka V in Mesa) coordinate must be zero such that the divide
1411 * by interpolated Q/W comes out right.
1412 *
1413 * This function written by Klaus Niederkrueger <klaus@math.leidenuniv.nl>
1414 * Send all questions and bug reports to him.
1415 */
1416 #if 0 /* XXX disabled because of texcoord interpolation errors */
1417 static void lin_persp_textured_triangle( GLcontext *ctx,
1418 const SWvertex *v0,
1419 const SWvertex *v1,
1420 const SWvertex *v2 )
1421 {
1422 #define INTERP_Z 1
1423 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1424 #define INTERP_RGB 1
1425 #define INTERP_ALPHA 1
1426 #define INTERP_TEX 1
1427 #define SETUP_CODE \
1428 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
1429 struct gl_texture_object *obj = unit->Current2D; \
1430 const GLint b = obj->BaseLevel; \
1431 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
1432 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
1433 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
1434 GLchan *texture = obj->Image[b]->Data; \
1435 const GLint smask = (obj->Image[b]->Width - 1); \
1436 const GLint tmask = (obj->Image[b]->Height - 1); \
1437 const GLint format = obj->Image[b]->Format; \
1438 const GLint envmode = unit->EnvMode; \
1439 GLfloat sscale, tscale; \
1440 GLint comp, tbytesline, tsize; \
1441 GLfixed er, eg, eb, ea; \
1442 GLint tr, tg, tb, ta; \
1443 if (!texture) { \
1444 return; \
1445 } \
1446 if (envmode == GL_BLEND || envmode == GL_ADD) { \
1447 er = FloatToFixed(unit->EnvColor[RCOMP]); \
1448 eg = FloatToFixed(unit->EnvColor[GCOMP]); \
1449 eb = FloatToFixed(unit->EnvColor[BCOMP]); \
1450 ea = FloatToFixed(unit->EnvColor[ACOMP]); \
1451 } \
1452 switch (format) { \
1453 case GL_ALPHA: \
1454 case GL_LUMINANCE: \
1455 case GL_INTENSITY: \
1456 comp = 1; \
1457 break; \
1458 case GL_LUMINANCE_ALPHA: \
1459 comp = 2; \
1460 break; \
1461 case GL_RGB: \
1462 comp = 3; \
1463 break; \
1464 case GL_RGBA: \
1465 comp = 4; \
1466 break; \
1467 default: \
1468 _mesa_problem(NULL, "Bad texture format in lin_persp_texture_triangle"); \
1469 return; \
1470 } \
1471 sscale = FIXED_SCALE * twidth; \
1472 tscale = FIXED_SCALE * theight; \
1473 tbytesline = obj->Image[b]->Width * comp; \
1474 tsize = theight * tbytesline;
1475
1476
1477 #define SPAN(DO_TEX,COMP) \
1478 for (i=0;i<n;i++) { \
1479 GLfloat invQ = 1.0f / vv; \
1480 GLfixed ffs = (int)(SS * invQ); \
1481 GLfixed fft = (int)(TT * invQ); \
1482 GLint s = FixedToInt(ffs) & smask; \
1483 GLint t = FixedToInt(fft) & tmask; \
1484 GLint sf = ffs & FIXED_FRAC_MASK; \
1485 GLint tf = fft & FIXED_FRAC_MASK; \
1486 GLint si = FIXED_FRAC_MASK - sf; \
1487 GLint ti = FIXED_FRAC_MASK - tf; \
1488 GLint pos = COMP * ((t << twidth_log2) + s); \
1489 GLchan *tex00 = texture + pos; \
1490 GLchan *tex10 = tex00 + tbytesline; \
1491 GLchan *tex01 = tex00 + COMP; \
1492 GLchan *tex11 = tex10 + COMP; \
1493 if (t == tmask) { \
1494 tex10 -= tsize; \
1495 tex11 -= tsize; \
1496 } \
1497 if (s == smask) { \
1498 tex01 -= tbytesline; \
1499 tex11 -= tbytesline; \
1500 } \
1501 zspan[i] = FixedToDepth(ffz); \
1502 fogspan[i] = fffog / 256; \
1503 DO_TEX; \
1504 fffog += fdfogdx; \
1505 ffz += fdzdx; \
1506 ffr += fdrdx; \
1507 ffg += fdgdx; \
1508 ffb += fdbdx; \
1509 ffa += fdadx; \
1510 SS += dSdx; \
1511 TT += dTdx; \
1512 vv += dvdx; \
1513 dest += 4; \
1514 }
1515
1516 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1517 { \
1518 GLint i; \
1519 const GLint n = RIGHT-LEFT; \
1520 GLdepth zspan[MAX_WIDTH]; \
1521 GLfixed fogspan[MAX_WIDTH]; \
1522 GLchan rgba[MAX_WIDTH][4]; \
1523 (void) uu; /* please GCC */ \
1524 if (n > 0) { \
1525 GLfloat SS = ss * sscale; \
1526 GLfloat TT = tt * tscale; \
1527 GLfloat dSdx = dsdx * sscale; \
1528 GLfloat dTdx = dtdx * tscale; \
1529 GLchan *dest = rgba[0]; \
1530 SS -= 0.5f * FIXED_SCALE * vv; \
1531 TT -= 0.5f * FIXED_SCALE * vv; \
1532 switch (format) { \
1533 case GL_RGB: \
1534 switch (envmode) { \
1535 case GL_MODULATE: \
1536 SPAN(LINEAR_RGB;MODULATE,3); \
1537 break; \
1538 case GL_DECAL: \
1539 case GL_REPLACE: \
1540 SPAN(LINEAR_RGB;REPLACE,3); \
1541 break; \
1542 case GL_BLEND: \
1543 SPAN(LINEAR_RGB;BLEND,3); \
1544 break; \
1545 case GL_ADD: \
1546 SPAN(LINEAR_RGB;ADD,3); \
1547 break; \
1548 default: \
1549 abort(); \
1550 } \
1551 break; \
1552 case GL_RGBA: \
1553 switch (envmode) { \
1554 case GL_MODULATE: \
1555 SPAN(LINEAR_RGBA;MODULATE,4); \
1556 break; \
1557 case GL_DECAL: \
1558 SPAN(LINEAR_RGBA;DECAL,4); \
1559 break; \
1560 case GL_BLEND: \
1561 SPAN(LINEAR_RGBA;BLEND,4); \
1562 break; \
1563 case GL_REPLACE: \
1564 SPAN(LINEAR_RGBA;REPLACE,4); \
1565 break; \
1566 case GL_ADD: \
1567 SPAN(LINEAR_RGBA;ADD,4); \
1568 break; \
1569 default: /* unexpected env mode */ \
1570 abort(); \
1571 } \
1572 } \
1573 _mesa_write_rgba_span( ctx, n, LEFT, Y, zspan, \
1574 fogspan, \
1575 rgba, GL_POLYGON ); \
1576 ffr = ffg = ffb = ffa = 0; \
1577 } \
1578 }
1579
1580 #include "s_tritemp.h"
1581 #undef SPAN
1582 }
1583 #endif
1584
1585
1586 /*
1587 * Render a smooth-shaded, textured, RGBA triangle.
1588 * Interpolate S,T,U with perspective correction, w/out mipmapping.
1589 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
1590 * R is already used for red.
1591 */
1592 static void general_textured_triangle( GLcontext *ctx,
1593 const SWvertex *v0,
1594 const SWvertex *v1,
1595 const SWvertex *v2 )
1596 {
1597 #define INTERP_Z 1
1598 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1599 #define INTERP_RGB 1
1600 #define INTERP_ALPHA 1
1601 #define INTERP_TEX 1
1602 #define SETUP_CODE \
1603 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1604 GLint r, g, b, a; \
1605 if (flat_shade) { \
1606 r = v2->color[RCOMP]; \
1607 g = v2->color[GCOMP]; \
1608 b = v2->color[BCOMP]; \
1609 a = v2->color[ACOMP]; \
1610 }
1611 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1612 { \
1613 GLint i; \
1614 const GLint n = RIGHT-LEFT; \
1615 GLdepth zspan[MAX_WIDTH]; \
1616 GLfixed fogspan[MAX_WIDTH]; \
1617 GLchan rgba[MAX_WIDTH][4]; \
1618 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
1619 if (n>0) { \
1620 if (flat_shade) { \
1621 for (i=0;i<n;i++) { \
1622 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1623 zspan[i] = FixedToDepth(ffz); \
1624 fogspan[i] = fffog / 256; \
1625 rgba[i][RCOMP] = r; \
1626 rgba[i][GCOMP] = g; \
1627 rgba[i][BCOMP] = b; \
1628 rgba[i][ACOMP] = a; \
1629 s[i] = ss*invQ; \
1630 t[i] = tt*invQ; \
1631 u[i] = uu*invQ; \
1632 fffog += fdfogdx; \
1633 ffz += fdzdx; \
1634 ss += dsdx; \
1635 tt += dtdx; \
1636 uu += dudx; \
1637 vv += dvdx; \
1638 } \
1639 } \
1640 else { \
1641 for (i=0;i<n;i++) { \
1642 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1643 zspan[i] = FixedToDepth(ffz); \
1644 rgba[i][RCOMP] = FixedToInt(ffr); \
1645 rgba[i][GCOMP] = FixedToInt(ffg); \
1646 rgba[i][BCOMP] = FixedToInt(ffb); \
1647 rgba[i][ACOMP] = FixedToInt(ffa); \
1648 fogspan[i] = fffog / 256; \
1649 s[i] = ss*invQ; \
1650 t[i] = tt*invQ; \
1651 u[i] = uu*invQ; \
1652 fffog += fdfogdx; \
1653 ffz += fdzdx; \
1654 ffr += fdrdx; \
1655 ffg += fdgdx; \
1656 ffb += fdbdx; \
1657 ffa += fdadx; \
1658 ss += dsdx; \
1659 tt += dtdx; \
1660 uu += dudx; \
1661 vv += dvdx; \
1662 } \
1663 } \
1664 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1665 s, t, u, NULL, \
1666 rgba, \
1667 NULL, GL_POLYGON ); \
1668 } \
1669 }
1670
1671 #include "s_tritemp.h"
1672 }
1673
1674
1675 /*
1676 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1677 * color interpolation.
1678 * Interpolate S,T,U with perspective correction, w/out mipmapping.
1679 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
1680 * R is already used for red.
1681 */
1682 static void general_textured_spec_triangle1( GLcontext *ctx,
1683 const SWvertex *v0,
1684 const SWvertex *v1,
1685 const SWvertex *v2,
1686 GLdepth zspan[MAX_WIDTH],
1687 GLfixed fogspan[MAX_WIDTH],
1688 GLchan rgba[MAX_WIDTH][4],
1689 GLchan spec[MAX_WIDTH][4] )
1690 {
1691 #define INTERP_Z 1
1692 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1693 #define INTERP_RGB 1
1694 #define INTERP_SPEC 1
1695 #define INTERP_ALPHA 1
1696 #define INTERP_TEX 1
1697 #define SETUP_CODE \
1698 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1699 GLint r, g, b, a, sr, sg, sb; \
1700 if (flat_shade) { \
1701 r = v2->color[RCOMP]; \
1702 g = v2->color[GCOMP]; \
1703 b = v2->color[BCOMP]; \
1704 a = v2->color[ACOMP]; \
1705 sr = v2->specular[RCOMP]; \
1706 sg = v2->specular[GCOMP]; \
1707 sb = v2->specular[BCOMP]; \
1708 }
1709 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1710 { \
1711 GLint i; \
1712 const GLint n = RIGHT-LEFT; \
1713 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
1714 if (n>0) { \
1715 if (flat_shade) { \
1716 for (i=0;i<n;i++) { \
1717 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1718 zspan[i] = FixedToDepth(ffz); \
1719 fogspan[i] = fffog / 256; \
1720 rgba[i][RCOMP] = r; \
1721 rgba[i][GCOMP] = g; \
1722 rgba[i][BCOMP] = b; \
1723 rgba[i][ACOMP] = a; \
1724 spec[i][RCOMP] = sr; \
1725 spec[i][GCOMP] = sg; \
1726 spec[i][BCOMP] = sb; \
1727 s[i] = ss*invQ; \
1728 t[i] = tt*invQ; \
1729 u[i] = uu*invQ; \
1730 fffog += fdfogdx; \
1731 ffz += fdzdx; \
1732 ss += dsdx; \
1733 tt += dtdx; \
1734 uu += dudx; \
1735 vv += dvdx; \
1736 } \
1737 } \
1738 else { \
1739 for (i=0;i<n;i++) { \
1740 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1741 zspan[i] = FixedToDepth(ffz); \
1742 fogspan[i] = fffog / 256; \
1743 rgba[i][RCOMP] = FixedToInt(ffr); \
1744 rgba[i][GCOMP] = FixedToInt(ffg); \
1745 rgba[i][BCOMP] = FixedToInt(ffb); \
1746 rgba[i][ACOMP] = FixedToInt(ffa); \
1747 spec[i][RCOMP] = FixedToInt(ffsr); \
1748 spec[i][GCOMP] = FixedToInt(ffsg); \
1749 spec[i][BCOMP] = FixedToInt(ffsb); \
1750 s[i] = ss*invQ; \
1751 t[i] = tt*invQ; \
1752 u[i] = uu*invQ; \
1753 fffog += fdfogdx; \
1754 ffz += fdzdx; \
1755 ffr += fdrdx; \
1756 ffg += fdgdx; \
1757 ffb += fdbdx; \
1758 ffa += fdadx; \
1759 ffsr += fdsrdx; \
1760 ffsg += fdsgdx; \
1761 ffsb += fdsbdx; \
1762 ss += dsdx; \
1763 tt += dtdx; \
1764 uu += dudx; \
1765 vv += dvdx; \
1766 } \
1767 } \
1768 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, \
1769 fogspan, \
1770 s, t, u, NULL, rgba, \
1771 (CONST GLchan (*)[4]) spec, \
1772 GL_POLYGON ); \
1773 } \
1774 }
1775
1776 #include "s_tritemp.h"
1777 }
1778
1779
1780 /*
1781 * Render a smooth-shaded, textured, RGBA triangle.
1782 * Interpolate S,T,U with perspective correction and compute lambda for
1783 * each fragment. Lambda is used to determine whether to use the
1784 * minification or magnification filter. If minification and using
1785 * mipmaps, lambda is also used to select the texture level of detail.
1786 */
1787 static void lambda_textured_triangle1( GLcontext *ctx,
1788 const SWvertex *v0,
1789 const SWvertex *v1,
1790 const SWvertex *v2,
1791 GLfloat s[MAX_WIDTH],
1792 GLfloat t[MAX_WIDTH],
1793 GLfloat u[MAX_WIDTH] )
1794 {
1795 #define INTERP_Z 1
1796 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1797 #define INTERP_RGB 1
1798 #define INTERP_ALPHA 1
1799 #define INTERP_LAMBDA 1
1800 #define INTERP_TEX 1
1801
1802 #define SETUP_CODE \
1803 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1804 const GLint baseLevel = obj->BaseLevel; \
1805 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1806 const GLfloat twidth = (GLfloat) texImage->Width; \
1807 const GLfloat theight = (GLfloat) texImage->Height; \
1808 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1809 GLint r, g, b, a; \
1810 if (flat_shade) { \
1811 r = v2->color[RCOMP]; \
1812 g = v2->color[GCOMP]; \
1813 b = v2->color[BCOMP]; \
1814 a = v2->color[ACOMP]; \
1815 }
1816
1817 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1818 { \
1819 GLint i; \
1820 const GLint n = RIGHT-LEFT; \
1821 GLdepth zspan[MAX_WIDTH]; \
1822 GLfixed fogspan[MAX_WIDTH]; \
1823 GLchan rgba[MAX_WIDTH][4]; \
1824 GLfloat lambda[MAX_WIDTH]; \
1825 if (n>0) { \
1826 if (flat_shade) { \
1827 for (i=0;i<n;i++) { \
1828 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1829 zspan[i] = FixedToDepth(ffz); \
1830 fogspan[i] = fffog / 256; \
1831 rgba[i][RCOMP] = r; \
1832 rgba[i][GCOMP] = g; \
1833 rgba[i][BCOMP] = b; \
1834 rgba[i][ACOMP] = a; \
1835 s[i] = ss*invQ; \
1836 t[i] = tt*invQ; \
1837 u[i] = uu*invQ; \
1838 COMPUTE_LAMBDA(lambda[i], invQ); \
1839 ffz += fdzdx; \
1840 fffog += fdfogdx; \
1841 ss += dsdx; \
1842 tt += dtdx; \
1843 uu += dudx; \
1844 vv += dvdx; \
1845 } \
1846 } \
1847 else { \
1848 for (i=0;i<n;i++) { \
1849 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1850 zspan[i] = FixedToDepth(ffz); \
1851 fogspan[i] = fffog / 256; \
1852 rgba[i][RCOMP] = FixedToInt(ffr); \
1853 rgba[i][GCOMP] = FixedToInt(ffg); \
1854 rgba[i][BCOMP] = FixedToInt(ffb); \
1855 rgba[i][ACOMP] = FixedToInt(ffa); \
1856 s[i] = ss*invQ; \
1857 t[i] = tt*invQ; \
1858 u[i] = uu*invQ; \
1859 COMPUTE_LAMBDA(lambda[i], invQ); \
1860 ffz += fdzdx; \
1861 fffog += fdfogdx; \
1862 ffr += fdrdx; \
1863 ffg += fdgdx; \
1864 ffb += fdbdx; \
1865 ffa += fdadx; \
1866 ss += dsdx; \
1867 tt += dtdx; \
1868 uu += dudx; \
1869 vv += dvdx; \
1870 } \
1871 } \
1872 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1873 s, t, u, lambda, \
1874 rgba, NULL, GL_POLYGON ); \
1875 } \
1876 }
1877
1878 #include "s_tritemp.h"
1879 }
1880
1881
1882 /*
1883 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1884 * interpolation.
1885 * Interpolate S,T,U with perspective correction and compute lambda for
1886 * each fragment. Lambda is used to determine whether to use the
1887 * minification or magnification filter. If minification and using
1888 * mipmaps, lambda is also used to select the texture level of detail.
1889 */
1890 static void lambda_textured_spec_triangle1( GLcontext *ctx,
1891 const SWvertex *v0,
1892 const SWvertex *v1,
1893 const SWvertex *v2,
1894 GLfloat s[MAX_WIDTH],
1895 GLfloat t[MAX_WIDTH],
1896 GLfloat u[MAX_WIDTH] )
1897 {
1898 #define INTERP_Z 1
1899 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1900 #define INTERP_RGB 1
1901 #define INTERP_SPEC 1
1902 #define INTERP_ALPHA 1
1903 #define INTERP_TEX 1
1904 #define INTERP_LAMBDA 1
1905
1906 #define SETUP_CODE \
1907 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1908 const GLint baseLevel = obj->BaseLevel; \
1909 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1910 const GLfloat twidth = (GLfloat) texImage->Width; \
1911 const GLfloat theight = (GLfloat) texImage->Height; \
1912 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1913 GLint r, g, b, a, sr, sg, sb; \
1914 if (flat_shade) { \
1915 r = v2->color[RCOMP]; \
1916 g = v2->color[GCOMP]; \
1917 b = v2->color[BCOMP]; \
1918 a = v2->color[ACOMP]; \
1919 sr = v2->specular[RCOMP]; \
1920 sg = v2->specular[GCOMP]; \
1921 sb = v2->specular[BCOMP]; \
1922 }
1923
1924 #define INNER_LOOP( LEFT, RIGHT, Y ) \
1925 { \
1926 GLint i; \
1927 const GLint n = RIGHT-LEFT; \
1928 GLdepth zspan[MAX_WIDTH]; \
1929 GLfixed fogspan[MAX_WIDTH]; \
1930 GLchan spec[MAX_WIDTH][4]; \
1931 GLchan rgba[MAX_WIDTH][4]; \
1932 GLfloat lambda[MAX_WIDTH]; \
1933 if (n>0) { \
1934 if (flat_shade) { \
1935 for (i=0;i<n;i++) { \
1936 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1937 zspan[i] = FixedToDepth(ffz); \
1938 fogspan[i] = fffog / 256; \
1939 rgba[i][RCOMP] = r; \
1940 rgba[i][GCOMP] = g; \
1941 rgba[i][BCOMP] = b; \
1942 rgba[i][ACOMP] = a; \
1943 spec[i][RCOMP] = sr; \
1944 spec[i][GCOMP] = sg; \
1945 spec[i][BCOMP] = sb; \
1946 s[i] = ss*invQ; \
1947 t[i] = tt*invQ; \
1948 u[i] = uu*invQ; \
1949 COMPUTE_LAMBDA(lambda[i], invQ); \
1950 fffog += fdfogdx; \
1951 ffz += fdzdx; \
1952 ss += dsdx; \
1953 tt += dtdx; \
1954 uu += dudx; \
1955 vv += dvdx; \
1956 } \
1957 } \
1958 else { \
1959 for (i=0;i<n;i++) { \
1960 GLdouble invQ = vv ? (1.0 / vv) : 1.0; \
1961 zspan[i] = FixedToDepth(ffz); \
1962 fogspan[i] = fffog / 256; \
1963 rgba[i][RCOMP] = FixedToInt(ffr); \
1964 rgba[i][GCOMP] = FixedToInt(ffg); \
1965 rgba[i][BCOMP] = FixedToInt(ffb); \
1966 rgba[i][ACOMP] = FixedToInt(ffa); \
1967 spec[i][RCOMP] = FixedToInt(ffsr); \
1968 spec[i][GCOMP] = FixedToInt(ffsg); \
1969 spec[i][BCOMP] = FixedToInt(ffsb); \
1970 s[i] = ss*invQ; \
1971 t[i] = tt*invQ; \
1972 u[i] = uu*invQ; \
1973 COMPUTE_LAMBDA(lambda[i], invQ); \
1974 fffog += fdfogdx; \
1975 ffz += fdzdx; \
1976 ffr += fdrdx; \
1977 ffg += fdgdx; \
1978 ffb += fdbdx; \
1979 ffa += fdadx; \
1980 ffsr += fdsrdx; \
1981 ffsg += fdsgdx; \
1982 ffsb += fdsbdx; \
1983 ss += dsdx; \
1984 tt += dtdx; \
1985 uu += dudx; \
1986 vv += dvdx; \
1987 } \
1988 } \
1989 _mesa_write_texture_span( ctx, n, LEFT, Y, zspan, fogspan, \
1990 s, t, u, lambda, \
1991 rgba, (CONST GLchan (*)[4]) spec, \
1992 GL_POLYGON ); \
1993 } \
1994 }
1995
1996 #include "s_tritemp.h"
1997 }
1998
1999
2000 /*
2001 * This is the big one!
2002 * Interpolate Z, RGB, Alpha, and two sets of texture coordinates.
2003 * Yup, it's slow.
2004 */
2005 static void
2006 lambda_multitextured_triangle1( GLcontext *ctx,
2007 const SWvertex *v0,
2008 const SWvertex *v1,
2009 const SWvertex *v2,
2010 GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH],
2011 GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH],
2012 GLfloat u[MAX_TEXTURE_UNITS][MAX_WIDTH])
2013 {
2014 #define INTERP_Z 1
2015 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2016 #define INTERP_RGB 1
2017 #define INTERP_ALPHA 1
2018 #define INTERP_MULTITEX 1
2019 #define INTERP_MULTILAMBDA 1
2020
2021 #define SETUP_CODE \
2022 GLchan rgba[MAX_WIDTH][4]; \
2023 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
2024 GLfloat twidth[MAX_TEXTURE_UNITS], theight[MAX_TEXTURE_UNITS]; \
2025 GLint r, g, b, a; \
2026 if (flat_shade) { \
2027 r = v2->color[0]; \
2028 g = v2->color[1]; \
2029 b = v2->color[2]; \
2030 a = v2->color[3]; \
2031 } \
2032 { \
2033 GLuint unit; \
2034 for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { \
2035 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2036 const struct gl_texture_object *obj = ctx->Texture.Unit[unit]._Current; \
2037 const GLint baseLevel = obj->BaseLevel; \
2038 const struct gl_texture_image *texImage = obj->Image[baseLevel];\
2039 twidth[unit] = (GLfloat) texImage->Width; \
2040 theight[unit] = (GLfloat) texImage->Height; \
2041 } \
2042 } \
2043 }
2044
2045 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2046 { \
2047 GLint i; \
2048 const GLint n = RIGHT-LEFT; \
2049 GLdepth zspan[MAX_WIDTH]; \
2050 GLfixed fogspan[MAX_WIDTH]; \
2051 GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; \
2052 if (n > 0) { \
2053 if (flat_shade) { \
2054 for (i=0;i<n;i++) { \
2055 GLuint unit; \
2056 zspan[i] = FixedToDepth(ffz); \
2057 fogspan[i] = fffog / 256; \
2058 fffog += fdfogdx; \
2059 ffz += fdzdx; \
2060 rgba[i][RCOMP] = r; \
2061 rgba[i][GCOMP] = g; \
2062 rgba[i][BCOMP] = b; \
2063 rgba[i][ACOMP] = a; \
2064 for (unit=0; unit < ctx->Const.MaxTextureUnits; unit++) {\
2065 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2066 GLdouble invQ = 1.0 / vv[unit]; \
2067 s[unit][i] = ss[unit] * invQ; \
2068 t[unit][i] = tt[unit] * invQ; \
2069 u[unit][i] = uu[unit] * invQ; \
2070 COMPUTE_MULTILAMBDA(lambda[unit][i], invQ, unit); \
2071 ss[unit] += dsdx[unit]; \
2072 tt[unit] += dtdx[unit]; \
2073 uu[unit] += dudx[unit]; \
2074 vv[unit] += dvdx[unit]; \
2075 } \
2076 } \
2077 } \
2078 } \
2079 else { /* smooth shade */ \
2080 for (i=0;i<n;i++) { \
2081 GLuint unit; \
2082 zspan[i] = FixedToDepth(ffz); \
2083 fogspan[i] = fffog / 256; \
2084 ffz += fdzdx; \
2085 fffog += fdfogdx; \
2086 rgba[i][RCOMP] = FixedToInt(ffr); \
2087 rgba[i][GCOMP] = FixedToInt(ffg); \
2088 rgba[i][BCOMP] = FixedToInt(ffb); \
2089 rgba[i][ACOMP] = FixedToInt(ffa); \
2090 ffr += fdrdx; \
2091 ffg += fdgdx; \
2092 ffb += fdbdx; \
2093 ffa += fdadx; \
2094 for (unit=0; unit < ctx->Const.MaxTextureUnits; unit++) {\
2095 if (ctx->Texture.Unit[unit]._ReallyEnabled) { \
2096 GLdouble invQ = 1.0 / vv[unit]; \
2097 s[unit][i] = ss[unit] * invQ; \
2098 t[unit][i] = tt[unit] * invQ; \
2099 u[unit][i] = uu[unit] * invQ; \
2100 COMPUTE_MULTILAMBDA(lambda[unit][i], invQ, unit); \
2101 ss[unit] += dsdx[unit]; \
2102 tt[unit] += dtdx[unit]; \
2103 uu[unit] += dudx[unit]; \
2104 vv[unit] += dvdx[unit]; \
2105 } \
2106 } \
2107 } \
2108 } \
2109 _mesa_write_multitexture_span(ctx, n, LEFT, Y, zspan, fogspan, \
2110 (const GLfloat (*)[MAX_WIDTH]) s,\
2111 (const GLfloat (*)[MAX_WIDTH]) t,\
2112 (const GLfloat (*)[MAX_WIDTH]) u,\
2113 (GLfloat (*)[MAX_WIDTH]) lambda, \
2114 rgba, NULL, GL_POLYGON ); \
2115 } \
2116 }
2117
2118 #include "s_tritemp.h"
2119 }
2120
2121
2122 /*
2123 * These wrappers are needed to deal with the 32KB / stack frame limit
2124 * on Mac / PowerPC systems.
2125 */
2126
2127 static void general_textured_spec_triangle(GLcontext *ctx,
2128 const SWvertex *v0,
2129 const SWvertex *v1,
2130 const SWvertex *v2 )
2131 {
2132 GLdepth zspan[MAX_WIDTH];
2133 GLfixed fogspan[MAX_WIDTH];
2134 GLchan rgba[MAX_WIDTH][4], spec[MAX_WIDTH][4];
2135 general_textured_spec_triangle1(ctx,v0,v1,v2,zspan,fogspan,rgba,spec);
2136 }
2137
2138 static void lambda_textured_triangle( GLcontext *ctx,
2139 const SWvertex *v0,
2140 const SWvertex *v1,
2141 const SWvertex *v2 )
2142 {
2143 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];
2144 lambda_textured_triangle1(ctx,v0,v1,v2,s,t,u);
2145 }
2146
2147 static void lambda_textured_spec_triangle( GLcontext *ctx,
2148 const SWvertex *v0,
2149 const SWvertex *v1,
2150 const SWvertex *v2 )
2151 {
2152 GLfloat s[MAX_WIDTH];
2153 GLfloat t[MAX_WIDTH];
2154 GLfloat u[MAX_WIDTH];
2155 lambda_textured_spec_triangle1(ctx,v0,v1,v2,s,t,u);
2156 }
2157
2158
2159 static void lambda_multitextured_triangle( GLcontext *ctx,
2160 const SWvertex *v0,
2161 const SWvertex *v1,
2162 const SWvertex *v2 )
2163 {
2164
2165 GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH];
2166 GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH];
2167 DEFMARRAY(GLfloat,u,MAX_TEXTURE_UNITS,MAX_WIDTH);
2168 CHECKARRAY(u,return);
2169
2170 lambda_multitextured_triangle1(ctx,v0,v1,v2,s,t,u);
2171
2172 UNDEFARRAY(u);
2173 }
2174
2175
2176
2177 static void occlusion_zless_triangle( GLcontext *ctx,
2178 const SWvertex *v0,
2179 const SWvertex *v1,
2180 const SWvertex *v2 )
2181 {
2182 if (ctx->OcclusionResult) {
2183 return;
2184 }
2185
2186 #define DO_OCCLUSION_TEST
2187 #define INTERP_Z 1
2188 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
2189 #define INNER_LOOP( LEFT, RIGHT, Y ) \
2190 { \
2191 GLint i; \
2192 const GLint len = RIGHT-LEFT; \
2193 for (i=0;i<len;i++) { \
2194 GLdepth z = FixedToDepth(ffz); \
2195 (void) fffog; \
2196 if (z < zRow[i]) { \
2197 ctx->OcclusionResult = GL_TRUE; \
2198 return; \
2199 } \
2200 ffz += fdzdx; \
2201 } \
2202 }
2203 #include "s_tritemp.h"
2204 }
2205
2206
2207
2208 void _swrast_add_spec_terms_triangle( GLcontext *ctx,
2209 const SWvertex *v0,
2210 const SWvertex *v1,
2211 const SWvertex *v2 )
2212 {
2213 SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */
2214 SWvertex *ncv1 = (SWvertex *)v1;
2215 SWvertex *ncv2 = (SWvertex *)v2;
2216 GLchan c[3][4];
2217 COPY_CHAN4( c[0], ncv0->color );
2218 COPY_CHAN4( c[1], ncv1->color );
2219 COPY_CHAN4( c[2], ncv2->color );
2220 ACC_3V( ncv0->color, ncv0->specular );
2221 ACC_3V( ncv1->color, ncv1->specular );
2222 ACC_3V( ncv2->color, ncv2->specular );
2223 SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 );
2224 COPY_CHAN4( ncv0->color, c[0] );
2225 COPY_CHAN4( ncv1->color, c[1] );
2226 COPY_CHAN4( ncv2->color, c[2] );
2227 }
2228
2229
2230
2231 #if 0
2232 # define dputs(s) puts(s)
2233 #else
2234 # define dputs(s)
2235 #endif
2236
2237
2238
2239 /*
2240 * Determine which triangle rendering function to use given the current
2241 * rendering context.
2242 *
2243 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
2244 * remove tests to this code.
2245 */
2246 void
2247 _swrast_choose_triangle( GLcontext *ctx )
2248 {
2249 SWcontext *swrast = SWRAST_CONTEXT(ctx);
2250 const GLboolean rgbmode = ctx->Visual.rgbMode;
2251
2252 if (ctx->RenderMode==GL_RENDER) {
2253
2254 if (ctx->Polygon.SmoothFlag) {
2255 _mesa_set_aa_triangle_function(ctx);
2256 ASSERT(swrast->Triangle);
2257 return;
2258 }
2259
2260 if (ctx->Depth.OcclusionTest &&
2261 ctx->Depth.Test &&
2262 ctx->Depth.Mask == GL_FALSE &&
2263 ctx->Depth.Func == GL_LESS &&
2264 !ctx->Stencil.Enabled) {
2265 if ((rgbmode &&
2266 ctx->Color.ColorMask[0] == 0 &&
2267 ctx->Color.ColorMask[1] == 0 &&
2268 ctx->Color.ColorMask[2] == 0 &&
2269 ctx->Color.ColorMask[3] == 0)
2270 ||
2271 (!rgbmode && ctx->Color.IndexMask == 0)) {
2272 dputs("occlusion_test_triangle");
2273 swrast->Triangle = occlusion_zless_triangle;
2274 return;
2275 }
2276 }
2277
2278 if (ctx->Texture._ReallyEnabled) {
2279 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
2280 GLint format, filter;
2281 const struct gl_texture_object *current2Dtex = ctx->Texture.Unit[0].Current2D;
2282 const struct gl_texture_image *image;
2283 /* First see if we can used an optimized 2-D texture function */
2284 if (ctx->Texture._ReallyEnabled==TEXTURE0_2D
2285 && current2Dtex->WrapS==GL_REPEAT
2286 && current2Dtex->WrapT==GL_REPEAT
2287 && ((image = current2Dtex->Image[current2Dtex->BaseLevel]) != 0) /* correct! */
2288 && image->Border==0
2289 && ((format = image->Format)==GL_RGB || format==GL_RGBA)
2290 && image->Type == CHAN_TYPE
2291 && (filter = current2Dtex->MinFilter)==current2Dtex->MagFilter
2292 /* ==> current2Dtex->MinFilter != GL_XXX_MIPMAP_XXX */
2293 && ctx->Light.Model.ColorControl==GL_SINGLE_COLOR
2294 && ctx->Texture.Unit[0].EnvMode!=GL_COMBINE_EXT) {
2295
2296 if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
2297
2298 if (filter==GL_NEAREST
2299 && format==GL_RGB
2300 && (ctx->Texture.Unit[0].EnvMode==GL_REPLACE
2301 || ctx->Texture.Unit[0].EnvMode==GL_DECAL)
2302 && ((swrast->_RasterMask==DEPTH_BIT
2303 && ctx->Depth.Func==GL_LESS
2304 && ctx->Depth.Mask==GL_TRUE)
2305 || swrast->_RasterMask==0)
2306 && ctx->Polygon.StippleFlag==GL_FALSE) {
2307
2308 if (swrast->_RasterMask==DEPTH_BIT) {
2309 swrast->Triangle = simple_z_textured_triangle;
2310 dputs("simple_z_textured_triangle");
2311 }
2312 else {
2313 swrast->Triangle = simple_textured_triangle;
2314 dputs("simple_textured_triangle");
2315 }
2316 }
2317 else {
2318 if (ctx->Texture.Unit[0].EnvMode==GL_ADD) {
2319 swrast->Triangle = general_textured_triangle;
2320 dputs("general_textured_triangle");
2321 }
2322 else {
2323 swrast->Triangle = affine_textured_triangle;
2324 dputs("affine_textured_triangle");
2325 }
2326 }
2327 }
2328 else {
2329 #if 00 /* XXX these function have problems with texture coord interpolation */
2330 if (filter==GL_NEAREST) {
2331 swrast->Triangle = near_persp_textured_triangle;
2332 dputs("near_persp_textured_triangle");
2333 }
2334 else {
2335 swrast->Triangle = lin_persp_textured_triangle;
2336 dputs("lin_persp_textured_triangle");
2337 }
2338 #endif
2339 swrast->Triangle = general_textured_triangle;
2340 }
2341 }
2342 else {
2343 /* More complicated textures (mipmap, multi-tex, sep specular) */
2344 GLboolean needLambda;
2345 /* if mag filter != min filter we need to compute lambda */
2346 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
2347 if (obj && obj->MinFilter != obj->MagFilter)
2348 needLambda = GL_TRUE;
2349 else
2350 needLambda = GL_FALSE;
2351 if (swrast->_MultiTextureEnabled) {
2352 swrast->Triangle = lambda_multitextured_triangle;
2353 dputs("lambda_multitextured_triangle");
2354 }
2355 else if (ctx->_TriangleCaps & DD_SEPERATE_SPECULAR) {
2356 /* separate specular color interpolation */
2357 if (needLambda) {
2358 swrast->Triangle = lambda_textured_spec_triangle;
2359 dputs("lambda_textured_spec_triangle");
2360 }
2361 else {
2362 swrast->Triangle = general_textured_spec_triangle;
2363 dputs("general_textured_spec_triangle");
2364 }
2365 }
2366 else {
2367 if (needLambda) {
2368 swrast->Triangle = lambda_textured_triangle;
2369 dputs("lambda_textured_triangle");
2370 }
2371 else {
2372 swrast->Triangle = general_textured_triangle;
2373 dputs("general_textured_triangle");
2374 }
2375 }
2376 }
2377 }
2378 else {
2379 if (ctx->Light.ShadeModel==GL_SMOOTH) {
2380 /* smooth shaded, no texturing, stippled or some raster ops */
2381 if (rgbmode) {
2382 dputs("smooth_rgba_triangle");
2383 swrast->Triangle = smooth_rgba_triangle;
2384 }
2385 else {
2386 dputs("smooth_ci_triangle");
2387 swrast->Triangle = smooth_ci_triangle;
2388 }
2389 }
2390 else {
2391 /* flat shaded, no texturing, stippled or some raster ops */
2392 if (rgbmode) {
2393 dputs("flat_rgba_triangle");
2394 swrast->Triangle = flat_rgba_triangle;
2395 }
2396 else {
2397 dputs("flat_ci_triangle");
2398 swrast->Triangle = flat_ci_triangle;
2399 }
2400 }
2401 }
2402 }
2403 else if (ctx->RenderMode==GL_FEEDBACK) {
2404 swrast->Triangle = _mesa_feedback_triangle;
2405 }
2406 else {
2407 /* GL_SELECT mode */
2408 swrast->Triangle = _mesa_select_triangle;
2409 }
2410 }