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