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