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