More span rendering optimizations from Klaus Niederkrueger
[mesa.git] / src / mesa / swrast / s_triangle.c
1 /* $Id: s_triangle.c,v 1.40 2001/11/19 01:18:28 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 #include "s_trispan.h"
51
52
53
54 GLboolean _mesa_cull_triangle( GLcontext *ctx,
55 const SWvertex *v0,
56 const SWvertex *v1,
57 const SWvertex *v2 )
58 {
59 GLfloat ex = v1->win[0] - v0->win[0];
60 GLfloat ey = v1->win[1] - v0->win[1];
61 GLfloat fx = v2->win[0] - v0->win[0];
62 GLfloat fy = v2->win[1] - v0->win[1];
63 GLfloat c = ex*fy-ey*fx;
64
65 if (c * SWRAST_CONTEXT(ctx)->_backface_sign > 0)
66 return 0;
67
68 return 1;
69 }
70
71
72
73 /*
74 * Render a flat-shaded color index triangle.
75 */
76 static void flat_ci_triangle( GLcontext *ctx,
77 const SWvertex *v0,
78 const SWvertex *v1,
79 const SWvertex *v2 )
80 {
81 #define INTERP_Z 1
82 #define INTERP_FOG 1
83
84 #define RENDER_SPAN( span ) \
85 GLdepth zSpan[MAX_WIDTH]; \
86 GLfloat fogSpan[MAX_WIDTH]; \
87 GLuint i; \
88 for (i = 0; i < span.count; i++) { \
89 zSpan[i] = FixedToDepth(span.z); \
90 span.z += span.zStep; \
91 fogSpan[i] = span.fog; \
92 span.fog += span.fogStep; \
93 } \
94 _mesa_write_monoindex_span(ctx, span.count, span.x, span.y, \
95 zSpan, fogSpan, v0->index, NULL, GL_POLYGON );
96
97 #include "s_tritemp.h"
98 }
99
100
101
102 /*
103 * Render a smooth-shaded color index triangle.
104 */
105 static void smooth_ci_triangle( GLcontext *ctx,
106 const SWvertex *v0,
107 const SWvertex *v1,
108 const SWvertex *v2 )
109 {
110 #define INTERP_Z 1
111 #define INTERP_FOG 1
112 #define INTERP_INDEX 1
113
114 #define RENDER_SPAN( span ) \
115 GLdepth zSpan[MAX_WIDTH]; \
116 GLfloat fogSpan[MAX_WIDTH]; \
117 GLuint indexSpan[MAX_WIDTH]; \
118 GLuint i; \
119 for (i = 0; i < span.count; i++) { \
120 zSpan[i] = FixedToDepth(span.z); \
121 span.z += span.zStep; \
122 indexSpan[i] = FixedToInt(span.index); \
123 span.index += span.indexStep; \
124 fogSpan[i] = span.fog; \
125 span.fog += span.fogStep; \
126 } \
127 _mesa_write_index_span(ctx, span.count, span.x, span.y, \
128 zSpan, fogSpan, indexSpan, NULL, GL_POLYGON);
129
130 #include "s_tritemp.h"
131 }
132
133
134
135 /*
136 * Render a flat-shaded RGBA triangle.
137 */
138 static void flat_rgba_triangle( GLcontext *ctx,
139 const SWvertex *v0,
140 const SWvertex *v1,
141 const SWvertex *v2 )
142 {
143 #define INTERP_Z 1
144 #define INTERP_FOG 1
145 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
146
147 #define RENDER_SPAN( span ) \
148 GLdepth zSpan[MAX_WIDTH]; \
149 GLfloat fogSpan[MAX_WIDTH]; \
150 GLuint i; \
151 for (i = 0; i < span.count; i++) { \
152 zSpan[i] = FixedToDepth(span.z); \
153 span.z += span.zStep; \
154 fogSpan[i] = span.fog; \
155 span.fog += span.fogStep; \
156 } \
157 _mesa_write_monocolor_span(ctx, span.count, span.x, span.y, zSpan, \
158 fogSpan, v2->color, NULL, GL_POLYGON );
159
160 #include "s_tritemp.h"
161
162 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */
163 ASSERT(ctx->Light.ShadeModel==GL_FLAT);
164 }
165
166
167
168 /*
169 * Render a smooth-shaded RGBA triangle.
170 */
171 static void smooth_rgba_triangle( GLcontext *ctx,
172 const SWvertex *v0,
173 const SWvertex *v1,
174 const SWvertex *v2 )
175 {
176
177 #define INTERP_Z 1
178 #define INTERP_FOG 1
179 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
180 #define INTERP_RGB 1
181 #define INTERP_ALPHA 1
182
183 #define RENDER_SPAN( span ) \
184 GLdepth zSpan[MAX_WIDTH]; \
185 GLchan rgbaSpan[MAX_WIDTH][4]; \
186 GLfloat fogSpan[MAX_WIDTH]; \
187 GLuint i; \
188 for (i = 0; i < span.count; i++) { \
189 rgbaSpan[i][RCOMP] = FixedToChan(span.red); \
190 rgbaSpan[i][GCOMP] = FixedToChan(span.green); \
191 rgbaSpan[i][BCOMP] = FixedToChan(span.blue); \
192 rgbaSpan[i][ACOMP] = FixedToChan(span.alpha); \
193 span.red += span.redStep; \
194 span.green += span.greenStep; \
195 span.blue += span.blueStep; \
196 span.alpha += span.alphaStep; \
197 zSpan[i] = FixedToDepth(span.z); \
198 span.z += span.zStep; \
199 fogSpan[i] = span.fog; \
200 span.fog += span.fogStep; \
201 } \
202 _mesa_write_rgba_span(ctx, span.count, span.x, span.y, \
203 (CONST GLdepth *) zSpan, \
204 fogSpan, rgbaSpan, NULL, GL_POLYGON);
205
206 #include "s_tritemp.h"
207
208 ASSERT(!ctx->Texture._ReallyEnabled); /* texturing must be off */
209 ASSERT(ctx->Light.ShadeModel==GL_SMOOTH);
210 }
211
212
213 /*
214 * Render an RGB, GL_DECAL, textured triangle.
215 * Interpolate S,T only w/out mipmapping or perspective correction.
216 *
217 * No fog.
218 */
219 static void simple_textured_triangle( GLcontext *ctx,
220 const SWvertex *v0,
221 const SWvertex *v1,
222 const SWvertex *v2 )
223 {
224 #define INTERP_INT_TEX 1
225 #define S_SCALE twidth
226 #define T_SCALE theight
227
228 #define SETUP_CODE \
229 SWcontext *swrast = SWRAST_CONTEXT(ctx); \
230 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
231 GLint b = obj->BaseLevel; \
232 const GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
233 const GLfloat theight = (GLfloat) obj->Image[b]->Height; \
234 const GLint twidth_log2 = obj->Image[b]->WidthLog2; \
235 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
236 const GLint smask = obj->Image[b]->Width - 1; \
237 const GLint tmask = obj->Image[b]->Height - 1; \
238 if (!texture) { \
239 /* this shouldn't happen */ \
240 return; \
241 }
242
243 #define RENDER_SPAN( span ) \
244 GLchan rgbSpan[MAX_WIDTH][3]; \
245 GLuint i; \
246 span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \
247 span.intTex[1] -= FIXED_HALF; \
248 for (i = 0; i < span.count; i++) { \
249 GLint s = FixedToInt(span.intTex[0]) & smask; \
250 GLint t = FixedToInt(span.intTex[1]) & tmask; \
251 GLint pos = (t << twidth_log2) + s; \
252 pos = pos + pos + pos; /* multiply by 3 */ \
253 rgbSpan[i][RCOMP] = texture[pos]; \
254 rgbSpan[i][GCOMP] = texture[pos+1]; \
255 rgbSpan[i][BCOMP] = texture[pos+2]; \
256 span.intTex[0] += span.intTexStep[0]; \
257 span.intTex[1] += span.intTexStep[1]; \
258 } \
259 (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y, \
260 (CONST GLchan (*)[3]) rgbSpan, NULL );
261
262 #include "s_tritemp.h"
263 }
264
265
266 /*
267 * Render an RGB, GL_DECAL, textured triangle.
268 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
269 * perspective correction.
270 *
271 * No fog.
272 */
273 static void simple_z_textured_triangle( GLcontext *ctx,
274 const SWvertex *v0,
275 const SWvertex *v1,
276 const SWvertex *v2 )
277 {
278 #define INTERP_Z 1
279 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
280 #define INTERP_INT_TEX 1
281 #define S_SCALE twidth
282 #define T_SCALE theight
283
284 #define SETUP_CODE \
285 SWcontext *swrast = SWRAST_CONTEXT(ctx); \
286 struct gl_texture_object *obj = ctx->Texture.Unit[0].Current2D; \
287 GLint b = obj->BaseLevel; \
288 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
289 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
290 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
291 const GLchan *texture = (const GLchan *) obj->Image[b]->Data; \
292 GLint smask = obj->Image[b]->Width - 1; \
293 GLint tmask = obj->Image[b]->Height - 1; \
294 if (!texture) { \
295 /* this shouldn't happen */ \
296 return; \
297 }
298
299 #define RENDER_SPAN( span ) \
300 GLchan rgbSpan[MAX_WIDTH][3]; \
301 GLubyte mask[MAX_WIDTH]; \
302 GLuint i; \
303 span.intTex[0] -= FIXED_HALF; /* off-by-one error? */ \
304 span.intTex[1] -= FIXED_HALF; \
305 for (i = 0; i < span.count; i++) { \
306 const GLdepth z = FixedToDepth(span.z); \
307 if (z < zRow[i]) { \
308 GLint s = FixedToInt(span.intTex[0]) & smask; \
309 GLint t = FixedToInt(span.intTex[1]) & tmask; \
310 GLint pos = (t << twidth_log2) + s; \
311 pos = pos + pos + pos; /* multiply by 3 */ \
312 rgbSpan[i][RCOMP] = texture[pos]; \
313 rgbSpan[i][GCOMP] = texture[pos+1]; \
314 rgbSpan[i][BCOMP] = texture[pos+2]; \
315 zRow[i] = z; \
316 mask[i] = 1; \
317 } \
318 else { \
319 mask[i] = 0; \
320 } \
321 span.intTex[0] += span.intTexStep[0]; \
322 span.intTex[1] += span.intTexStep[1]; \
323 span.z += span.zStep; \
324 } \
325 (*swrast->Driver.WriteRGBSpan)(ctx, span.count, span.x, span.y, \
326 (CONST GLchan (*)[3]) rgbSpan, mask );
327
328 #include "s_tritemp.h"
329 }
330
331
332 #if CHAN_TYPE != GL_FLOAT
333
334 struct affine_info
335 {
336 GLenum filter;
337 GLenum format;
338 GLenum envmode;
339 GLint smask, tmask;
340 GLint twidth_log2;
341 const GLchan *texture;
342 GLchan er, eg, eb, ea;
343 GLint tbytesline, tsize;
344 GLint fixedToDepthShift;
345 };
346
347
348 /* This function can handle GL_NEAREST or GL_LINEAR sampling of 2D RGB or RGBA
349 * textures with GL_REPLACE, GL_MODULATE, GL_BLEND, GL_DECAL or GL_ADD
350 * texture env modes.
351 */
352 static INLINE void
353 affine_span(GLcontext *ctx, struct triangle_span *span,
354 struct affine_info *info)
355 {
356 GLchan sample[4]; /* the filtered texture sample */
357
358 /* Instead of defining a function for each mode, a test is done
359 * between the outer and inner loops. This is to reduce code size
360 * and complexity. Observe that an optimizing compiler kills
361 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
362 */
363
364 #define NEAREST_RGB \
365 sample[RCOMP] = tex00[RCOMP]; \
366 sample[GCOMP] = tex00[GCOMP]; \
367 sample[BCOMP] = tex00[BCOMP]; \
368 sample[ACOMP] = CHAN_MAX
369
370 #define LINEAR_RGB \
371 sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \
372 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
373 sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \
374 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
375 sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \
376 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
377 sample[ACOMP] = CHAN_MAX
378
379 #define NEAREST_RGBA COPY_CHAN4(sample, tex00)
380
381 #define LINEAR_RGBA \
382 sample[RCOMP] = (ti * (si * tex00[0] + sf * tex01[0]) + \
383 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT;\
384 sample[GCOMP] = (ti * (si * tex00[1] + sf * tex01[1]) + \
385 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT;\
386 sample[BCOMP] = (ti * (si * tex00[2] + sf * tex01[2]) + \
387 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT;\
388 sample[ACOMP] = (ti * (si * tex00[3] + sf * tex01[3]) + \
389 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
390
391 #define MODULATE \
392 dest[RCOMP] = span->red * (sample[RCOMP] + 1u) >> (FIXED_SHIFT + 8); \
393 dest[GCOMP] = span->green * (sample[GCOMP] + 1u) >> (FIXED_SHIFT + 8); \
394 dest[BCOMP] = span->blue * (sample[BCOMP] + 1u) >> (FIXED_SHIFT + 8); \
395 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1u) >> (FIXED_SHIFT + 8)
396
397 #define DECAL \
398 dest[RCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->red + \
399 ((sample[ACOMP] + 1) * sample[RCOMP] << FIXED_SHIFT)) \
400 >> (FIXED_SHIFT + 8); \
401 dest[GCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->green + \
402 ((sample[ACOMP] + 1) * sample[GCOMP] << FIXED_SHIFT)) \
403 >> (FIXED_SHIFT + 8); \
404 dest[BCOMP] = ((CHAN_MAX - sample[ACOMP]) * span->blue + \
405 ((sample[ACOMP] + 1) * sample[BCOMP] << FIXED_SHIFT)) \
406 >> (FIXED_SHIFT + 8); \
407 dest[ACOMP] = FixedToInt(span->alpha)
408
409 #define BLEND \
410 dest[RCOMP] = ((CHAN_MAX - sample[RCOMP]) * span->red \
411 + (sample[RCOMP] + 1) * info->er) >> (FIXED_SHIFT + 8); \
412 dest[GCOMP] = ((CHAN_MAX - sample[GCOMP]) * span->green \
413 + (sample[GCOMP] + 1) * info->eg) >> (FIXED_SHIFT + 8); \
414 dest[BCOMP] = ((CHAN_MAX - sample[BCOMP]) * span->blue \
415 + (sample[BCOMP] + 1) * info->eb) >> (FIXED_SHIFT + 8); \
416 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8)
417
418 #define REPLACE COPY_CHAN4(dest, sample)
419
420 #define ADD \
421 { \
422 GLint rSum = FixedToInt(span->red) + (GLint) sample[RCOMP]; \
423 GLint gSum = FixedToInt(span->green) + (GLint) sample[GCOMP]; \
424 GLint bSum = FixedToInt(span->blue) + (GLint) sample[BCOMP]; \
425 dest[RCOMP] = MIN2(rSum, CHAN_MAX); \
426 dest[GCOMP] = MIN2(gSum, CHAN_MAX); \
427 dest[BCOMP] = MIN2(bSum, CHAN_MAX); \
428 dest[ACOMP] = span->alpha * (sample[ACOMP] + 1) >> (FIXED_SHIFT + 8); \
429 }
430
431 /* shortcuts */
432
433 #define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE
434
435 #define NEAREST_RGBA_REPLACE COPY_CHAN4(dest, tex00)
436
437 #define SPAN_NEAREST(DO_TEX,COMP) \
438 for (i = 0; i < span->count; i++) { \
439 /* Isn't it necessary to use FixedFloor below?? */ \
440 GLint s = FixedToInt(span->intTex[0]) & info->smask; \
441 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \
442 GLint pos = (t << info->twidth_log2) + s; \
443 const GLchan *tex00 = info->texture + COMP * pos; \
444 zspan[i] = FixedToDepth(span->z); \
445 fogspan[i] = span->fog; \
446 DO_TEX; \
447 span->fog += span->fogStep; \
448 span->z += span->zStep; \
449 span->red += span->redStep; \
450 span->green += span->greenStep; \
451 span->blue += span->blueStep; \
452 span->alpha += span->alphaStep; \
453 span->intTex[0] += span->intTexStep[0]; \
454 span->intTex[1] += span->intTexStep[1]; \
455 dest += 4; \
456 }
457
458 #define SPAN_LINEAR(DO_TEX,COMP) \
459 for (i = 0; i < span->count; i++) { \
460 /* Isn't it necessary to use FixedFloor below?? */ \
461 GLint s = FixedToInt(span->intTex[0]) & info->smask; \
462 GLint t = FixedToInt(span->intTex[1]) & info->tmask; \
463 GLfixed sf = span->intTex[0] & FIXED_FRAC_MASK; \
464 GLfixed tf = span->intTex[1] & FIXED_FRAC_MASK; \
465 GLfixed si = FIXED_FRAC_MASK - sf; \
466 GLfixed ti = FIXED_FRAC_MASK - tf; \
467 GLint pos = (t << info->twidth_log2) + s; \
468 const GLchan *tex00 = info->texture + COMP * pos; \
469 const GLchan *tex10 = tex00 + info->tbytesline; \
470 const GLchan *tex01 = tex00 + COMP; \
471 const GLchan *tex11 = tex10 + COMP; \
472 (void) ti; \
473 (void) si; \
474 if (t == info->tmask) { \
475 tex10 -= info->tsize; \
476 tex11 -= info->tsize; \
477 } \
478 if (s == info->smask) { \
479 tex01 -= info->tbytesline; \
480 tex11 -= info->tbytesline; \
481 } \
482 zspan[i] = FixedToDepth(span->z); \
483 fogspan[i] = span->fog; \
484 DO_TEX; \
485 span->fog += span->fogStep; \
486 span->z += span->zStep; \
487 span->red += span->redStep; \
488 span->green += span->greenStep; \
489 span->blue += span->blueStep; \
490 span->alpha += span->alphaStep; \
491 span->intTex[0] += span->intTexStep[0]; \
492 span->intTex[1] += span->intTexStep[1]; \
493 dest += 4; \
494 }
495
496 #define FixedToDepth(F) ((F) >> fixedToDepthShift)
497
498 GLuint i;
499 GLdepth zspan[MAX_WIDTH];
500 GLfloat fogspan[MAX_WIDTH];
501 GLchan rgba[MAX_WIDTH][4];
502 GLchan *dest = rgba[0];
503 const GLint fixedToDepthShift = info->fixedToDepthShift;
504
505 span->intTex[0] -= FIXED_HALF;
506 span->intTex[1] -= FIXED_HALF;
507 switch (info->filter) {
508 case GL_NEAREST:
509 switch (info->format) {
510 case GL_RGB:
511 switch (info->envmode) {
512 case GL_MODULATE:
513 SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
514 break;
515 case GL_DECAL:
516 case GL_REPLACE:
517 SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
518 break;
519 case GL_BLEND:
520 SPAN_NEAREST(NEAREST_RGB;BLEND,3);
521 break;
522 case GL_ADD:
523 SPAN_NEAREST(NEAREST_RGB;ADD,3);
524 break;
525 default:
526 abort();
527 }
528 break;
529 case GL_RGBA:
530 switch(info->envmode) {
531 case GL_MODULATE:
532 SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
533 break;
534 case GL_DECAL:
535 SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
536 break;
537 case GL_BLEND:
538 SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
539 break;
540 case GL_ADD:
541 SPAN_NEAREST(NEAREST_RGBA;ADD,4);
542 break;
543 case GL_REPLACE:
544 SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
545 break;
546 default:
547 abort();
548 }
549 break;
550 }
551 break;
552
553 case GL_LINEAR:
554 span->intTex[0] -= FIXED_HALF;
555 span->intTex[1] -= FIXED_HALF;
556 switch (info->format) {
557 case GL_RGB:
558 switch (info->envmode) {
559 case GL_MODULATE:
560 SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
561 break;
562 case GL_DECAL:
563 case GL_REPLACE:
564 SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
565 break;
566 case GL_BLEND:
567 SPAN_LINEAR(LINEAR_RGB;BLEND,3);
568 break;
569 case GL_ADD:
570 SPAN_LINEAR(LINEAR_RGB;ADD,3);
571 break;
572 default:
573 abort();
574 }
575 break;
576 case GL_RGBA:
577 switch (info->envmode) {
578 case GL_MODULATE:
579 SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
580 break;
581 case GL_DECAL:
582 SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
583 break;
584 case GL_BLEND:
585 SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
586 break;
587 case GL_ADD:
588 SPAN_LINEAR(LINEAR_RGBA;ADD,4);
589 break;
590 case GL_REPLACE:
591 SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
592 break;
593 default:
594 abort();
595 } break;
596 }
597 break;
598 }
599 _mesa_write_rgba_span(ctx, span->count, span->x, span->y,
600 zspan, fogspan, rgba, NULL, GL_POLYGON);
601
602 #undef SPAN_NEAREST
603 #undef SPAN_LINEAR
604 #undef FixedToDepth
605 }
606
607
608
609 /*
610 * Render an RGB/RGBA textured triangle without perspective correction.
611 */
612 static void affine_textured_triangle( GLcontext *ctx,
613 const SWvertex *v0,
614 const SWvertex *v1,
615 const SWvertex *v2 )
616 {
617 #define INTERP_Z 1
618 #define INTERP_FOG 1
619 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
620 #define INTERP_RGB 1
621 #define INTERP_ALPHA 1
622 #define INTERP_INT_TEX 1
623 #define S_SCALE twidth
624 #define T_SCALE theight
625
626 #define SETUP_CODE \
627 struct affine_info info; \
628 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
629 struct gl_texture_object *obj = unit->Current2D; \
630 GLint b = obj->BaseLevel; \
631 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
632 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
633 info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\
634 info.texture = (const GLchan *) obj->Image[b]->Data; \
635 info.twidth_log2 = obj->Image[b]->WidthLog2; \
636 info.smask = obj->Image[b]->Width - 1; \
637 info.tmask = obj->Image[b]->Height - 1; \
638 info.format = obj->Image[b]->Format; \
639 info.filter = obj->MinFilter; \
640 info.envmode = unit->EnvMode; \
641 \
642 if (info.envmode == GL_BLEND) { \
643 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
644 info.er = FloatToFixed(unit->EnvColor[RCOMP]); \
645 info.eg = FloatToFixed(unit->EnvColor[GCOMP]); \
646 info.eb = FloatToFixed(unit->EnvColor[BCOMP]); \
647 info.ea = FloatToFixed(unit->EnvColor[ACOMP]); \
648 } \
649 if (!info.texture) { \
650 /* this shouldn't happen */ \
651 return; \
652 } \
653 \
654 switch (info.format) { \
655 case GL_ALPHA: \
656 case GL_LUMINANCE: \
657 case GL_INTENSITY: \
658 info.tbytesline = obj->Image[b]->Width; \
659 break; \
660 case GL_LUMINANCE_ALPHA: \
661 info.tbytesline = obj->Image[b]->Width * 2; \
662 break; \
663 case GL_RGB: \
664 info.tbytesline = obj->Image[b]->Width * 3; \
665 break; \
666 case GL_RGBA: \
667 info.tbytesline = obj->Image[b]->Width * 4; \
668 break; \
669 default: \
670 _mesa_problem(NULL, "Bad texture format in affine_texture_triangle");\
671 return; \
672 } \
673 info.tsize = obj->Image[b]->Height * info.tbytesline;
674
675 #define RENDER_SPAN( span ) affine_span(ctx, &span, &info);
676
677 #include "s_tritemp.h"
678
679 }
680
681
682
683 struct persp_info
684 {
685 GLenum filter;
686 GLenum format;
687 GLenum envmode;
688 GLint smask, tmask;
689 GLint twidth_log2;
690 const GLchan *texture;
691 GLchan er, eg, eb, ea; /* texture env color */
692 GLint tbytesline, tsize;
693 GLint fixedToDepthShift;
694 };
695
696
697 static INLINE void
698 fast_persp_span(GLcontext *ctx, struct triangle_span *span,
699 struct persp_info *info)
700 {
701 GLchan sample[4]; /* the filtered texture sample */
702
703 /* Instead of defining a function for each mode, a test is done
704 * between the outer and inner loops. This is to reduce code size
705 * and complexity. Observe that an optimizing compiler kills
706 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
707 */
708 #define SPAN_NEAREST(DO_TEX,COMP) \
709 for (i = 0; i < span->count; i++) { \
710 GLdouble invQ = tex_coord[2] ? \
711 (1.0 / tex_coord[2]) : 1.0; \
712 GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \
713 GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \
714 GLint s = IFLOOR(s_tmp) & info->smask; \
715 GLint t = IFLOOR(t_tmp) & info->tmask; \
716 GLint pos = (t << info->twidth_log2) + s; \
717 const GLchan *tex00 = info->texture + COMP * pos; \
718 zspan[i] = FixedToDepth(span->z); \
719 fogspan[i] = span->fog; \
720 DO_TEX; \
721 span->fog += span->fogStep; \
722 span->z += span->zStep; \
723 span->red += span->redStep; \
724 span->green += span->greenStep; \
725 span->blue += span->blueStep; \
726 span->alpha += span->alphaStep; \
727 tex_coord[0] += tex_step[0]; \
728 tex_coord[1] += tex_step[1]; \
729 tex_coord[2] += tex_step[2]; \
730 dest += 4; \
731 }
732
733 #define SPAN_LINEAR(DO_TEX,COMP) \
734 for (i = 0; i < span->count; i++) { \
735 GLdouble invQ = tex_coord[2] ? \
736 (1.0 / tex_coord[2]) : 1.0; \
737 GLfloat s_tmp = (GLfloat) (tex_coord[0] * invQ); \
738 GLfloat t_tmp = (GLfloat) (tex_coord[1] * invQ); \
739 GLfixed s_fix = FloatToFixed(s_tmp) - FIXED_HALF; \
740 GLfixed t_fix = FloatToFixed(t_tmp) - FIXED_HALF; \
741 GLint s = FixedToInt(FixedFloor(s_fix)) & info->smask; \
742 GLint t = FixedToInt(FixedFloor(t_fix)) & info->tmask; \
743 GLfixed sf = s_fix & FIXED_FRAC_MASK; \
744 GLfixed tf = t_fix & FIXED_FRAC_MASK; \
745 GLfixed si = FIXED_FRAC_MASK - sf; \
746 GLfixed ti = FIXED_FRAC_MASK - tf; \
747 GLint pos = (t << info->twidth_log2) + s; \
748 const GLchan *tex00 = info->texture + COMP * pos; \
749 const GLchan *tex10 = tex00 + info->tbytesline; \
750 const GLchan *tex01 = tex00 + COMP; \
751 const GLchan *tex11 = tex10 + COMP; \
752 (void) ti; \
753 (void) si; \
754 if (t == info->tmask) { \
755 tex10 -= info->tsize; \
756 tex11 -= info->tsize; \
757 } \
758 if (s == info->smask) { \
759 tex01 -= info->tbytesline; \
760 tex11 -= info->tbytesline; \
761 } \
762 zspan[i] = FixedToDepth(span->z); \
763 fogspan[i] = span->fog; \
764 DO_TEX; \
765 span->fog += span->fogStep; \
766 span->z += span->zStep; \
767 span->red += span->redStep; \
768 span->green += span->greenStep; \
769 span->blue += span->blueStep; \
770 span->alpha += span->alphaStep; \
771 tex_coord[0] += tex_step[0]; \
772 tex_coord[1] += tex_step[1]; \
773 tex_coord[2] += tex_step[2]; \
774 dest += 4; \
775 }
776
777 #define FixedToDepth(F) ((F) >> fixedToDepthShift)
778
779 GLuint i;
780 GLdepth zspan[MAX_WIDTH];
781 GLfloat tex_coord[3], tex_step[3];
782 GLfloat fogspan[MAX_WIDTH];
783 GLchan rgba[MAX_WIDTH][4];
784 GLchan *dest = rgba[0];
785 const GLint fixedToDepthShift = info->fixedToDepthShift;
786
787 tex_coord[0] = span->tex[0][0] * (info->smask + 1),
788 tex_step[0] = span->texStep[0][0] * (info->smask + 1);
789 tex_coord[1] = span->tex[0][1] * (info->tmask + 1),
790 tex_step[1] = span->texStep[0][1] * (info->tmask + 1);
791 /* span->tex[0][2] only if 3D-texturing, here only 2D */
792 tex_coord[2] = span->tex[0][3],
793 tex_step[2] = span->texStep[0][3];
794
795 switch (info->filter) {
796 case GL_NEAREST:
797 switch (info->format) {
798 case GL_RGB:
799 switch (info->envmode) {
800 case GL_MODULATE:
801 SPAN_NEAREST(NEAREST_RGB;MODULATE,3);
802 break;
803 case GL_DECAL:
804 case GL_REPLACE:
805 SPAN_NEAREST(NEAREST_RGB_REPLACE,3);
806 break;
807 case GL_BLEND:
808 SPAN_NEAREST(NEAREST_RGB;BLEND,3);
809 break;
810 case GL_ADD:
811 SPAN_NEAREST(NEAREST_RGB;ADD,3);
812 break;
813 default:
814 abort();
815 }
816 break;
817 case GL_RGBA:
818 switch(info->envmode) {
819 case GL_MODULATE:
820 SPAN_NEAREST(NEAREST_RGBA;MODULATE,4);
821 break;
822 case GL_DECAL:
823 SPAN_NEAREST(NEAREST_RGBA;DECAL,4);
824 break;
825 case GL_BLEND:
826 SPAN_NEAREST(NEAREST_RGBA;BLEND,4);
827 break;
828 case GL_ADD:
829 SPAN_NEAREST(NEAREST_RGBA;ADD,4);
830 break;
831 case GL_REPLACE:
832 SPAN_NEAREST(NEAREST_RGBA_REPLACE,4);
833 break;
834 default:
835 abort();
836 }
837 break;
838 }
839 break;
840
841 case GL_LINEAR:
842 switch (info->format) {
843 case GL_RGB:
844 switch (info->envmode) {
845 case GL_MODULATE:
846 SPAN_LINEAR(LINEAR_RGB;MODULATE,3);
847 break;
848 case GL_DECAL:
849 case GL_REPLACE:
850 SPAN_LINEAR(LINEAR_RGB;REPLACE,3);
851 break;
852 case GL_BLEND:
853 SPAN_LINEAR(LINEAR_RGB;BLEND,3);
854 break;
855 case GL_ADD:
856 SPAN_LINEAR(LINEAR_RGB;ADD,3);
857 break;
858 default:
859 abort();
860 }
861 break;
862 case GL_RGBA:
863 switch (info->envmode) {
864 case GL_MODULATE:
865 SPAN_LINEAR(LINEAR_RGBA;MODULATE,4);
866 break;
867 case GL_DECAL:
868 SPAN_LINEAR(LINEAR_RGBA;DECAL,4);
869 break;
870 case GL_BLEND:
871 SPAN_LINEAR(LINEAR_RGBA;BLEND,4);
872 break;
873 case GL_ADD:
874 SPAN_LINEAR(LINEAR_RGBA;ADD,4);
875 break;
876 case GL_REPLACE:
877 SPAN_LINEAR(LINEAR_RGBA;REPLACE,4);
878 break;
879 default:
880 abort();
881 }
882 break;
883 }
884 break;
885 }
886 /* This does not seem to be necessary, but I don't know !! */
887 /* span->tex[0][0] = tex_coord[0] / (info->smask + 1),
888 span->tex[0][1] = tex_coord[1] / (info->tmask + 1),*/
889 /* span->tex[0][2] only if 3D-texturing, here only 2D */
890 /* span->tex[0][3] = tex_coord[2]; */
891
892 _mesa_write_rgba_span(ctx, span->count, span->x, span->y,
893 zspan, fogspan, rgba, NULL, GL_POLYGON);
894
895
896 #undef SPAN_NEAREST
897 #undef SPAN_LINEAR
898 #undef FixedToDepth
899 }
900
901
902 /*
903 * Render an perspective corrected RGB/RGBA textured triangle.
904 * The Q (aka V in Mesa) coordinate must be zero such that the divide
905 * by interpolated Q/W comes out right.
906 *
907 */
908 static void persp_textured_triangle( GLcontext *ctx,
909 const SWvertex *v0,
910 const SWvertex *v1,
911 const SWvertex *v2 )
912 {
913 #define INTERP_Z 1
914 #define INTERP_FOG 1
915 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
916 #define INTERP_RGB 1
917 #define INTERP_ALPHA 1
918 #define INTERP_TEX 1
919
920 #define SETUP_CODE \
921 struct persp_info info; \
922 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
923 struct gl_texture_object *obj = unit->Current2D; \
924 GLint b = obj->BaseLevel; \
925 info.fixedToDepthShift = ctx->Visual.depthBits <= 16 ? FIXED_SHIFT : 0;\
926 info.texture = (const GLchan *) obj->Image[b]->Data; \
927 info.twidth_log2 = obj->Image[b]->WidthLog2; \
928 info.smask = obj->Image[b]->Width - 1; \
929 info.tmask = obj->Image[b]->Height - 1; \
930 info.format = obj->Image[b]->Format; \
931 info.filter = obj->MinFilter; \
932 info.envmode = unit->EnvMode; \
933 \
934 if (info.envmode == GL_BLEND) { \
935 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
936 info.er = FloatToFixed(unit->EnvColor[RCOMP]); \
937 info.eg = FloatToFixed(unit->EnvColor[GCOMP]); \
938 info.eb = FloatToFixed(unit->EnvColor[BCOMP]); \
939 info.ea = FloatToFixed(unit->EnvColor[ACOMP]); \
940 } \
941 if (!info.texture) { \
942 /* this shouldn't happen */ \
943 return; \
944 } \
945 \
946 switch (info.format) { \
947 case GL_ALPHA: \
948 case GL_LUMINANCE: \
949 case GL_INTENSITY: \
950 info.tbytesline = obj->Image[b]->Width; \
951 break; \
952 case GL_LUMINANCE_ALPHA: \
953 info.tbytesline = obj->Image[b]->Width * 2; \
954 break; \
955 case GL_RGB: \
956 info.tbytesline = obj->Image[b]->Width * 3; \
957 break; \
958 case GL_RGBA: \
959 info.tbytesline = obj->Image[b]->Width * 4; \
960 break; \
961 default: \
962 _mesa_problem(NULL, "Bad texture format in persp_textured_triangle");\
963 return; \
964 } \
965 info.tsize = obj->Image[b]->Height * info.tbytesline;
966
967 #define RENDER_SPAN( span ) fast_persp_span(ctx, &span, &info);
968
969 #include "s_tritemp.h"
970
971 }
972
973
974 #endif /* CHAN_BITS != GL_FLOAT */
975
976
977
978
979 /*
980 * Render a smooth-shaded, textured, RGBA triangle.
981 * Interpolate S,T,R with perspective correction, w/out mipmapping.
982 */
983 static void general_textured_triangle( GLcontext *ctx,
984 const SWvertex *v0,
985 const SWvertex *v1,
986 const SWvertex *v2 )
987 {
988 #define INTERP_Z 1
989 #define INTERP_FOG 1
990 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
991 #define INTERP_RGB 1
992 #define INTERP_ALPHA 1
993 #define INTERP_TEX 1
994
995 #define SETUP_CODE \
996 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
997 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
998 DEFARRAY(GLfloat, sSpan, MAX_WIDTH); /* mac 32k limitation */ \
999 DEFARRAY(GLfloat, tSpan, MAX_WIDTH); /* mac 32k limitation */ \
1000 DEFARRAY(GLfloat, uSpan, MAX_WIDTH); /* mac 32k limitation */ \
1001 CHECKARRAY(sSpan, return); /* mac 32k limitation */ \
1002 CHECKARRAY(tSpan, return); /* mac 32k limitation */ \
1003 CHECKARRAY(uSpan, return); /* mac 32k limitation */ \
1004 span.texWidth[0] = (GLfloat) texImage->Width; \
1005 span.texHeight[0] = (GLfloat) texImage->Height; \
1006 (void) fixedToDepthShift;
1007
1008 #define RENDER_SPAN( span ) \
1009 GLdepth zSpan[MAX_WIDTH]; \
1010 GLfloat fogSpan[MAX_WIDTH]; \
1011 GLchan rgbaSpan[MAX_WIDTH][4]; \
1012 GLuint i; \
1013 /* NOTE: we could just call rasterize_span() here instead */ \
1014 for (i = 0; i < span.count; i++) { \
1015 GLdouble invQ = span.tex[0][3] ? (1.0 / span.tex[0][3]) : 1.0; \
1016 zSpan[i] = FixedToDepth(span.z); \
1017 span.z += span.zStep; \
1018 fogSpan[i] = span.fog; \
1019 span.fog += span.fogStep; \
1020 rgbaSpan[i][RCOMP] = FixedToChan(span.red); \
1021 rgbaSpan[i][GCOMP] = FixedToChan(span.green); \
1022 rgbaSpan[i][BCOMP] = FixedToChan(span.blue); \
1023 rgbaSpan[i][ACOMP] = FixedToChan(span.alpha); \
1024 span.red += span.redStep; \
1025 span.green += span.greenStep; \
1026 span.blue += span.blueStep; \
1027 span.alpha += span.alphaStep; \
1028 sSpan[i] = (GLfloat) (span.tex[0][0] * invQ); \
1029 tSpan[i] = (GLfloat) (span.tex[0][1] * invQ); \
1030 uSpan[i] = (GLfloat) (span.tex[0][2] * invQ); \
1031 span.tex[0][0] += span.texStep[0][0]; \
1032 span.tex[0][1] += span.texStep[0][1]; \
1033 span.tex[0][2] += span.texStep[0][2]; \
1034 span.tex[0][3] += span.texStep[0][3]; \
1035 } \
1036 _mesa_write_texture_span(ctx, span.count, span.x, span.y, \
1037 zSpan, fogSpan, sSpan, tSpan, uSpan, \
1038 NULL, rgbaSpan, NULL, NULL, GL_POLYGON );
1039
1040 #define CLEANUP_CODE \
1041 UNDEFARRAY(sSpan); /* mac 32k limitation */ \
1042 UNDEFARRAY(tSpan); \
1043 UNDEFARRAY(uSpan);
1044
1045 #include "s_tritemp.h"
1046 }
1047
1048
1049 /*
1050 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1051 * color interpolation.
1052 * Interpolate texcoords with perspective correction, w/out mipmapping.
1053 */
1054 static void general_textured_spec_triangle( GLcontext *ctx,
1055 const SWvertex *v0,
1056 const SWvertex *v1,
1057 const SWvertex *v2 )
1058 {
1059 #define INTERP_Z 1
1060 #define INTERP_FOG 1
1061 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1062 #define INTERP_RGB 1
1063 #define INTERP_SPEC 1
1064 #define INTERP_ALPHA 1
1065 #define INTERP_TEX 1
1066
1067 #define SETUP_CODE \
1068 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1069 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1070 span.texWidth[0] = (GLfloat) texImage->Width; \
1071 span.texHeight[0] = (GLfloat) texImage->Height; \
1072 (void) fixedToDepthShift;
1073
1074 #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
1075
1076 #include "s_tritemp.h"
1077 }
1078
1079
1080 /*
1081 * Render a smooth-shaded, textured, RGBA triangle.
1082 * Interpolate S,T,R with perspective correction and compute lambda for
1083 * each fragment. Lambda is used to determine whether to use the
1084 * minification or magnification filter. If minification and using
1085 * mipmaps, lambda is also used to select the texture level of detail.
1086 */
1087 static void lambda_textured_triangle( GLcontext *ctx,
1088 const SWvertex *v0,
1089 const SWvertex *v1,
1090 const SWvertex *v2 )
1091 {
1092 #define INTERP_Z 1
1093 #define INTERP_FOG 1
1094 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1095 #define INTERP_RGB 1
1096 #define INTERP_ALPHA 1
1097 #define INTERP_TEX 1
1098 #define INTERP_LAMBDA 1
1099
1100 #define SETUP_CODE \
1101 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1102 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1103 span.texWidth[0] = (GLfloat) texImage->Width; \
1104 span.texHeight[0] = (GLfloat) texImage->Height; \
1105 (void) fixedToDepthShift;
1106
1107 #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
1108
1109 #include "s_tritemp.h"
1110 }
1111
1112
1113 /*
1114 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1115 * interpolation.
1116 * Interpolate S,T,R with perspective correction and compute lambda for
1117 * each fragment. Lambda is used to determine whether to use the
1118 * minification or magnification filter. If minification and using
1119 * mipmaps, lambda is also used to select the texture level of detail.
1120 */
1121 static void lambda_textured_spec_triangle( GLcontext *ctx,
1122 const SWvertex *v0,
1123 const SWvertex *v1,
1124 const SWvertex *v2 )
1125 {
1126 #define INTERP_Z 1
1127 #define INTERP_FOG 1
1128 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1129 #define INTERP_RGB 1
1130 #define INTERP_SPEC 1
1131 #define INTERP_ALPHA 1
1132 #define INTERP_TEX 1
1133 #define INTERP_LAMBDA 1
1134
1135 #define SETUP_CODE \
1136 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current; \
1137 const struct gl_texture_image *texImage = obj->Image[obj->BaseLevel];\
1138 span.texWidth[0] = (GLfloat) texImage->Width; \
1139 span.texHeight[0] = (GLfloat) texImage->Height; \
1140 (void) fixedToDepthShift;
1141
1142 #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
1143
1144 #include "s_tritemp.h"
1145 }
1146
1147
1148 /*
1149 * This is the big one!
1150 * Interpolate Z, RGB, Alpha, specular, fog, and N sets of texture coordinates
1151 * with lambda (LOD).
1152 * Yup, it's slow.
1153 */
1154 static void
1155 lambda_multitextured_triangle( GLcontext *ctx,
1156 const SWvertex *v0,
1157 const SWvertex *v1,
1158 const SWvertex *v2 )
1159 {
1160
1161 #define INTERP_Z 1
1162 #define INTERP_FOG 1
1163 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1164 #define INTERP_RGB 1
1165 #define INTERP_ALPHA 1
1166 #define INTERP_SPEC 1
1167 #define INTERP_MULTITEX 1
1168 #define INTERP_LAMBDA 1
1169
1170 #define SETUP_CODE \
1171 GLuint u; \
1172 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { \
1173 if (ctx->Texture.Unit[u]._ReallyEnabled) { \
1174 const struct gl_texture_object *texObj; \
1175 const struct gl_texture_image *texImage; \
1176 texObj = ctx->Texture.Unit[u]._Current; \
1177 texImage = texObj->Image[texObj->BaseLevel]; \
1178 span.texWidth[u] = (GLfloat) texImage->Width; \
1179 span.texHeight[u] = (GLfloat) texImage->Height; \
1180 } \
1181 } \
1182 (void) fixedToDepthShift;
1183
1184 #define RENDER_SPAN( span ) _mesa_rasterize_span(ctx, &span);
1185
1186 #include "s_tritemp.h"
1187
1188 }
1189
1190
1191 static void occlusion_zless_triangle( GLcontext *ctx,
1192 const SWvertex *v0,
1193 const SWvertex *v1,
1194 const SWvertex *v2 )
1195 {
1196 if (ctx->OcclusionResult) {
1197 return;
1198 }
1199
1200 #define DO_OCCLUSION_TEST
1201 #define INTERP_Z 1
1202 #define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
1203
1204 #define RENDER_SPAN( span ) \
1205 GLuint i; \
1206 for (i = 0; i < span.count; i++) { \
1207 GLdepth z = FixedToDepth(span.z); \
1208 if (z < zRow[i]) { \
1209 ctx->OcclusionResult = GL_TRUE; \
1210 return; \
1211 } \
1212 span.z += span.zStep; \
1213 }
1214
1215 #include "s_tritemp.h"
1216 }
1217
1218 static void nodraw_triangle( GLcontext *ctx,
1219 const SWvertex *v0,
1220 const SWvertex *v1,
1221 const SWvertex *v2 )
1222 {
1223 (void) (ctx && v0 && v1 && v2);
1224 }
1225
1226 void _swrast_add_spec_terms_triangle( GLcontext *ctx,
1227 const SWvertex *v0,
1228 const SWvertex *v1,
1229 const SWvertex *v2 )
1230 {
1231 SWvertex *ncv0 = (SWvertex *)v0; /* drop const qualifier */
1232 SWvertex *ncv1 = (SWvertex *)v1;
1233 SWvertex *ncv2 = (SWvertex *)v2;
1234 GLchan c[3][4];
1235 COPY_CHAN4( c[0], ncv0->color );
1236 COPY_CHAN4( c[1], ncv1->color );
1237 COPY_CHAN4( c[2], ncv2->color );
1238 ACC_3V( ncv0->color, ncv0->specular );
1239 ACC_3V( ncv1->color, ncv1->specular );
1240 ACC_3V( ncv2->color, ncv2->specular );
1241 SWRAST_CONTEXT(ctx)->SpecTriangle( ctx, ncv0, ncv1, ncv2 );
1242 COPY_CHAN4( ncv0->color, c[0] );
1243 COPY_CHAN4( ncv1->color, c[1] );
1244 COPY_CHAN4( ncv2->color, c[2] );
1245 }
1246
1247
1248
1249 #ifdef DEBUG
1250
1251 /* record the current triangle function name */
1252 static const char *triFuncName = NULL;
1253
1254 #define USE(triFunc) \
1255 do { \
1256 triFuncName = #triFunc; \
1257 /*printf("%s\n", triFuncName);*/ \
1258 swrast->Triangle = triFunc; \
1259 } while (0)
1260
1261 #else
1262
1263 #define USE(triFunc) swrast->Triangle = triFunc;
1264
1265 #endif
1266
1267
1268
1269
1270 /*
1271 * Determine which triangle rendering function to use given the current
1272 * rendering context.
1273 *
1274 * Please update the summary flag _SWRAST_NEW_TRIANGLE if you add or
1275 * remove tests to this code.
1276 */
1277 void
1278 _swrast_choose_triangle( GLcontext *ctx )
1279 {
1280 SWcontext *swrast = SWRAST_CONTEXT(ctx);
1281 const GLboolean rgbmode = ctx->Visual.rgbMode;
1282
1283 if (ctx->Polygon.CullFlag &&
1284 ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) {
1285 USE(nodraw_triangle);
1286 return;
1287 }
1288
1289 if (ctx->RenderMode==GL_RENDER) {
1290
1291 if (ctx->Polygon.SmoothFlag) {
1292 _mesa_set_aa_triangle_function(ctx);
1293 ASSERT(swrast->Triangle);
1294 return;
1295 }
1296
1297 if (ctx->Depth.OcclusionTest &&
1298 ctx->Depth.Test &&
1299 ctx->Depth.Mask == GL_FALSE &&
1300 ctx->Depth.Func == GL_LESS &&
1301 !ctx->Stencil.Enabled) {
1302 if ((rgbmode &&
1303 ctx->Color.ColorMask[0] == 0 &&
1304 ctx->Color.ColorMask[1] == 0 &&
1305 ctx->Color.ColorMask[2] == 0 &&
1306 ctx->Color.ColorMask[3] == 0)
1307 ||
1308 (!rgbmode && ctx->Color.IndexMask == 0)) {
1309 USE(occlusion_zless_triangle);
1310 return;
1311 }
1312 }
1313
1314 if (ctx->Texture._ReallyEnabled) {
1315 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
1316 const struct gl_texture_object *texObj2D;
1317 const struct gl_texture_image *texImg;
1318 GLenum minFilter, magFilter, envMode;
1319 GLint format;
1320 texObj2D = ctx->Texture.Unit[0].Current2D;
1321 texImg = texObj2D ? texObj2D->Image[texObj2D->BaseLevel] : NULL;
1322 format = texImg ? texImg->TexFormat->MesaFormat : -1;
1323 minFilter = texObj2D ? texObj2D->MinFilter : (GLenum) 0;
1324 magFilter = texObj2D ? texObj2D->MagFilter : (GLenum) 0;
1325 envMode = ctx->Texture.Unit[0].EnvMode;
1326
1327 /* First see if we can used an optimized 2-D texture function */
1328 if (ctx->Texture._ReallyEnabled==TEXTURE0_2D
1329 && texObj2D->WrapS==GL_REPEAT
1330 && texObj2D->WrapT==GL_REPEAT
1331 && texImg->Border==0
1332 && (format == MESA_FORMAT_RGB || format == MESA_FORMAT_RGBA)
1333 && minFilter == magFilter
1334 && ctx->Light.Model.ColorControl == GL_SINGLE_COLOR
1335 && ctx->Texture.Unit[0].EnvMode != GL_COMBINE_EXT) {
1336 if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
1337 if (minFilter == GL_NEAREST
1338 && format == MESA_FORMAT_RGB
1339 && (envMode == GL_REPLACE || envMode == GL_DECAL)
1340 && ((swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)
1341 && ctx->Depth.Func == GL_LESS
1342 && ctx->Depth.Mask == GL_TRUE)
1343 || swrast->_RasterMask == TEXTURE_BIT)
1344 && ctx->Polygon.StippleFlag == GL_FALSE) {
1345 if (swrast->_RasterMask == (DEPTH_BIT | TEXTURE_BIT)) {
1346 USE(simple_z_textured_triangle);
1347 }
1348 else {
1349 USE(simple_textured_triangle);
1350 }
1351 }
1352 else {
1353 #if CHAN_TYPE == GL_FLOAT
1354 USE(general_textured_triangle);
1355 #else
1356 USE(affine_textured_triangle);
1357 #endif
1358 }
1359 }
1360 else {
1361 #if CHAN_TYPE == GL_FLOAT
1362 USE(general_textured_triangle);
1363 #else
1364 USE(persp_textured_triangle);
1365 #endif
1366 }
1367 }
1368 else {
1369 /* More complicated textures (mipmap, multi-tex, sep specular) */
1370 GLboolean needLambda;
1371 /* if mag filter != min filter we need to compute lambda */
1372 const struct gl_texture_object *obj = ctx->Texture.Unit[0]._Current;
1373 if (obj && obj->MinFilter != obj->MagFilter)
1374 needLambda = GL_TRUE;
1375 else
1376 needLambda = GL_FALSE;
1377 if (ctx->Texture._ReallyEnabled > TEXTURE0_ANY) {
1378 USE(lambda_multitextured_triangle);
1379 }
1380 else if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
1381 /* separate specular color interpolation */
1382 if (needLambda) {
1383 USE(lambda_textured_spec_triangle);
1384 }
1385 else {
1386 USE(general_textured_spec_triangle);
1387 }
1388 }
1389 else {
1390 if (needLambda) {
1391 USE(lambda_textured_triangle);
1392 }
1393 else {
1394 USE(general_textured_triangle);
1395 }
1396 }
1397 }
1398 }
1399 else {
1400 ASSERT(!ctx->Texture._ReallyEnabled);
1401 if (ctx->Light.ShadeModel==GL_SMOOTH) {
1402 /* smooth shaded, no texturing, stippled or some raster ops */
1403 if (rgbmode) {
1404 USE(smooth_rgba_triangle);
1405 }
1406 else {
1407 USE(smooth_ci_triangle);
1408 }
1409 }
1410 else {
1411 /* flat shaded, no texturing, stippled or some raster ops */
1412 if (rgbmode) {
1413 USE(flat_rgba_triangle);
1414 }
1415 else {
1416 USE(flat_ci_triangle);
1417 }
1418 }
1419 }
1420 }
1421 else if (ctx->RenderMode==GL_FEEDBACK) {
1422 USE(_mesa_feedback_triangle);
1423 }
1424 else {
1425 /* GL_SELECT mode */
1426 USE(_mesa_select_triangle);
1427 }
1428 }