source: trunk/src/opengl/mesa/triangle.c@ 3597

Last change on this file since 3597 was 2962, checked in by jeroen, 25 years ago

* empty log message *

File size: 60.3 KB
Line 
1/* $Id: triangle.c,v 1.2 2000-03-01 18:49:38 jeroen Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version: 3.1
6 *
7 * Copyright (C) 1999 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
30/*
31 * Triangle rasterizers
32 * When the device driver doesn't implement triangle rasterization Mesa
33 * will use these functions to draw triangles.
34 */
35
36
37#ifdef PC_HEADER
38#include "all.h"
39#else
40#ifndef XFree86Server
41#include <assert.h>
42#include <math.h>
43#include <stdio.h>
44#else
45#include "GL/xf86glx.h"
46#endif
47#include "types.h"
48#include "context.h"
49#include "depth.h"
50#include "feedback.h"
51#include "macros.h"
52#include "mmath.h"
53#include "span.h"
54#include "texstate.h"
55#include "triangle.h"
56#include "vb.h"
57#endif
58
59
60GLboolean gl_cull_triangle( GLcontext *ctx,
61 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
62{
63 struct vertex_buffer *VB = ctx->VB;
64 GLfloat (*win)[4] = VB->Win.data;
65 GLfloat ex = win[v1][0] - win[v0][0];
66 GLfloat ey = win[v1][1] - win[v0][1];
67 GLfloat fx = win[v2][0] - win[v0][0];
68 GLfloat fy = win[v2][1] - win[v0][1];
69 GLfloat c = ex*fy-ey*fx;
70
71 if (c * ctx->backface_sign > 0)
72 return 0;
73
74 return 1;
75}
76
77
78
79
80
81
82/*
83 * Render a flat-shaded color index triangle.
84 */
85static void flat_ci_triangle( GLcontext *ctx,
86 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
87{
88#define INTERP_Z 1
89
90#define SETUP_CODE \
91 GLuint index = VB->IndexPtr->data[pv]; \
92 if (1) { \
93 /* set the color index */ \
94 (*ctx->Driver.Index)( ctx, index ); \
95 }
96
97#define INNER_LOOP( LEFT, RIGHT, Y ) \
98 { \
99 GLint i, n = RIGHT-LEFT; \
100 GLdepth zspan[MAX_WIDTH]; \
101 if (n>0) { \
102 for (i=0;i<n;i++) { \
103 zspan[i] = FixedToDepth(ffz); \
104 ffz += fdzdx; \
105 } \
106 gl_write_monoindex_span( ctx, n, LEFT, Y, \
107 zspan, index, GL_POLYGON ); \
108 } \
109 }
110
111#include "tritemp.h"
112}
113
114
115
116/*
117 * Render a smooth-shaded color index triangle.
118 */
119static void smooth_ci_triangle( GLcontext *ctx,
120 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
121{
122 (void) pv;
123#define INTERP_Z 1
124#define INTERP_INDEX 1
125
126#define INNER_LOOP( LEFT, RIGHT, Y ) \
127 { \
128 GLint i, n = RIGHT-LEFT; \
129 GLdepth zspan[MAX_WIDTH]; \
130 GLuint index[MAX_WIDTH]; \
131 if (n>0) { \
132 for (i=0;i<n;i++) { \
133 zspan[i] = FixedToDepth(ffz); \
134 index[i] = FixedToInt(ffi); \
135 ffz += fdzdx; \
136 ffi += fdidx; \
137 } \
138 gl_write_index_span( ctx, n, LEFT, Y, zspan, \
139 index, GL_POLYGON ); \
140 } \
141 }
142
143#include "tritemp.h"
144}
145
146
147
148/*
149 * Render a flat-shaded RGBA triangle.
150 */
151static void flat_rgba_triangle( GLcontext *ctx,
152 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
153{
154#define INTERP_Z 1
155
156#define SETUP_CODE \
157 if (1) { \
158 /* set the color */ \
159 GLubyte r = VB->ColorPtr->data[pv][0]; \
160 GLubyte g = VB->ColorPtr->data[pv][1]; \
161 GLubyte b = VB->ColorPtr->data[pv][2]; \
162 GLubyte a = VB->ColorPtr->data[pv][3]; \
163 (*ctx->Driver.Color)( ctx, r, g, b, a ); \
164 }
165
166#define INNER_LOOP( LEFT, RIGHT, Y ) \
167 { \
168 GLint i, n = RIGHT-LEFT; \
169 GLdepth zspan[MAX_WIDTH]; \
170 if (n>0) { \
171 for (i=0;i<n;i++) { \
172 zspan[i] = FixedToDepth(ffz); \
173 ffz += fdzdx; \
174 } \
175 gl_write_monocolor_span( ctx, n, LEFT, Y, zspan, \
176 VB->ColorPtr->data[pv], \
177 GL_POLYGON ); \
178 } \
179 }
180
181#include "tritemp.h"
182
183 ASSERT(!ctx->Texture.ReallyEnabled); /* texturing must be off */
184 ASSERT(ctx->Light.ShadeModel==GL_FLAT);
185}
186
187
188
189/*
190 * Render a smooth-shaded RGBA triangle.
191 */
192static void smooth_rgba_triangle( GLcontext *ctx,
193 GLuint v0, GLuint v1, GLuint v2, GLuint pv )
194{
195 (void) pv;
196#define INTERP_Z 1
197#define INTERP_RGB 1
198#define INTERP_ALPHA 1
199
200#define INNER_LOOP( LEFT, RIGHT, Y ) \
201 { \
202 GLint i, n = RIGHT-LEFT; \
203 GLdepth zspan[MAX_WIDTH]; \
204 GLubyte rgba[MAX_WIDTH][4]; \
205 if (n>0) { \
206 for (i=0;i<n;i++) { \
207 zspan[i] = FixedToDepth(ffz); \
208 rgba[i][RCOMP] = FixedToInt(ffr); \
209 rgba[i][GCOMP] = FixedToInt(ffg); \
210 rgba[i][BCOMP] = FixedToInt(ffb); \
211 rgba[i][ACOMP] = FixedToInt(ffa); \
212 ffz += fdzdx; \
213 ffr += fdrdx; \
214 ffg += fdgdx; \
215 ffb += fdbdx; \
216 ffa += fdadx; \
217 } \
218 gl_write_rgba_span( ctx, n, LEFT, Y, \
219 (const GLdepth *) zspan, \
220 rgba, GL_POLYGON ); \
221 } \
222 }
223
224#include "tritemp.h"
225
226 ASSERT(!ctx->Texture.ReallyEnabled); /* texturing must be off */
227 ASSERT(ctx->Light.ShadeModel==GL_SMOOTH);
228}
229
230
231/*
232 * Render an RGB, GL_DECAL, textured triangle.
233 * Interpolate S,T only w/out mipmapping or perspective correction.
234 */
235static void simple_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
236 GLuint v2, GLuint pv )
237{
238#define INTERP_INT_ST 1
239#define S_SCALE twidth
240#define T_SCALE theight
241#define SETUP_CODE \
242 struct gl_texture_object *obj = ctx->Texture.Unit[0].CurrentD[2]; \
243 GLint b = obj->BaseLevel; \
244 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
245 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
246 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
247 GLubyte *texture = obj->Image[b]->Data; \
248 GLint smask = obj->Image[b]->Width - 1; \
249 GLint tmask = obj->Image[b]->Height - 1;
250 (void) pv;
251
252#define INNER_LOOP( LEFT, RIGHT, Y ) \
253 { \
254 GLint i, n = RIGHT-LEFT; \
255 GLubyte rgb[MAX_WIDTH][3]; \
256 if (n>0) { \
257 ffs -= FIXED_HALF; /* off-by-one error? */ \
258 fft -= FIXED_HALF; \
259 for (i=0;i<n;i++) { \
260 GLint s = FixedToInt(ffs) & smask; \
261 GLint t = FixedToInt(fft) & tmask; \
262 GLint pos = (t << twidth_log2) + s; \
263 pos = pos + pos + pos; /* multiply by 3 */ \
264 rgb[i][RCOMP] = texture[pos]; \
265 rgb[i][GCOMP] = texture[pos+1]; \
266 rgb[i][BCOMP] = texture[pos+2]; \
267 ffs += fdsdx; \
268 fft += fdtdx; \
269 } \
270 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
271 (const GLubyte (*)[3]) rgb, NULL ); \
272 } \
273 }
274
275#include "tritemp.h"
276}
277
278
279/*
280 * Render an RGB, GL_DECAL, textured triangle.
281 * Interpolate S,T, GL_LESS depth test, w/out mipmapping or
282 * perspective correction.
283 */
284static void simple_z_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
285 GLuint v2, GLuint pv )
286{
287#define INTERP_Z 1
288#define INTERP_INT_ST 1
289#define S_SCALE twidth
290#define T_SCALE theight
291#define SETUP_CODE \
292 struct gl_texture_object *obj = ctx->Texture.Unit[0].CurrentD[2]; \
293 GLint b = obj->BaseLevel; \
294 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
295 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
296 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
297 GLubyte *texture = obj->Image[b]->Data; \
298 GLint smask = obj->Image[b]->Width - 1; \
299 GLint tmask = obj->Image[b]->Height - 1;
300 (void) pv;
301
302#define INNER_LOOP( LEFT, RIGHT, Y ) \
303 { \
304 GLint i, n = RIGHT-LEFT; \
305 GLubyte rgb[MAX_WIDTH][3]; \
306 GLubyte mask[MAX_WIDTH]; \
307 if (n>0) { \
308 ffs -= FIXED_HALF; /* off-by-one error? */ \
309 fft -= FIXED_HALF; \
310 for (i=0;i<n;i++) { \
311 GLdepth z = FixedToDepth(ffz); \
312 if (z < zRow[i]) { \
313 GLint s = FixedToInt(ffs) & smask; \
314 GLint t = FixedToInt(fft) & tmask; \
315 GLint pos = (t << twidth_log2) + s; \
316 pos = pos + pos + pos; /* multiply by 3 */ \
317 rgb[i][RCOMP] = texture[pos]; \
318 rgb[i][GCOMP] = texture[pos+1]; \
319 rgb[i][BCOMP] = texture[pos+2]; \
320 zRow[i] = z; \
321 mask[i] = 1; \
322 } \
323 else { \
324 mask[i] = 0; \
325 } \
326 ffz += fdzdx; \
327 ffs += fdsdx; \
328 fft += fdtdx; \
329 } \
330 (*ctx->Driver.WriteRGBSpan)( ctx, n, LEFT, Y, \
331 (const GLubyte (*)[3]) rgb, mask ); \
332 } \
333 }
334
335#include "tritemp.h"
336}
337
338
339
340/*
341 * Render an RGB/RGBA textured triangle without perspective correction.
342 */
343static void affine_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
344 GLuint v2, GLuint pv )
345{
346#define INTERP_Z 1
347#define INTERP_RGB 1
348#define INTERP_ALPHA 1
349#define INTERP_INT_ST 1
350#define S_SCALE twidth
351#define T_SCALE theight
352#define SETUP_CODE \
353 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
354 struct gl_texture_object *obj = unit->CurrentD[2]; \
355 GLint b = obj->BaseLevel; \
356 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
357 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
358 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
359 GLubyte *texture = obj->Image[b]->Data; \
360 GLint smask = obj->Image[b]->Width - 1; \
361 GLint tmask = obj->Image[b]->Height - 1; \
362 GLint format = obj->Image[b]->Format; \
363 GLint filter = obj->MinFilter; \
364 GLint envmode = unit->EnvMode; \
365 GLint comp, tbytesline, tsize; \
366 GLfixed er, eg, eb, ea; \
367 GLint tr, tg, tb, ta; \
368 if (envmode == GL_BLEND || envmode == GL_ADD) { \
369 /* potential off-by-one error here? (1.0f -> 2048 -> 0) */ \
370 er = FloatToFixed(unit->EnvColor[0]); \
371 eg = FloatToFixed(unit->EnvColor[1]); \
372 eb = FloatToFixed(unit->EnvColor[2]); \
373 ea = FloatToFixed(unit->EnvColor[3]); \
374 } \
375 switch (format) { \
376 case GL_ALPHA: \
377 case GL_LUMINANCE: \
378 case GL_INTENSITY: \
379 comp = 1; \
380 break; \
381 case GL_LUMINANCE_ALPHA: \
382 comp = 2; \
383 break; \
384 case GL_RGB: \
385 comp = 3; \
386 break; \
387 case GL_RGBA: \
388 comp = 4; \
389 break; \
390 default: \
391 gl_problem(NULL, "Bad texture format in affine_texture_triangle");\
392 return; \
393 } \
394 tbytesline = obj->Image[b]->Width * comp; \
395 tsize = theight * tbytesline;
396 (void) pv;
397
398 /* Instead of defining a function for each mode, a test is done
399 * between the outer and inner loops. This is to reduce code size
400 * and complexity. Observe that an optimizing compiler kills
401 * unused variables (for instance tf,sf,ti,si in case of GL_NEAREST).
402 */
403
404#define NEAREST_RGB \
405 tr = tex00[0]; \
406 tg = tex00[1]; \
407 tb = tex00[2]; \
408 ta = 0xff
409
410#define LINEAR_RGB \
411 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
412 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
413 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
414 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
415 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
416 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
417 ta = 0xff
418
419#define NEAREST_RGBA \
420 tr = tex00[0]; \
421 tg = tex00[1]; \
422 tb = tex00[2]; \
423 ta = tex00[3]
424
425#define LINEAR_RGBA \
426 tr = (ti * (si * tex00[0] + sf * tex01[0]) + \
427 tf * (si * tex10[0] + sf * tex11[0])) >> 2 * FIXED_SHIFT; \
428 tg = (ti * (si * tex00[1] + sf * tex01[1]) + \
429 tf * (si * tex10[1] + sf * tex11[1])) >> 2 * FIXED_SHIFT; \
430 tb = (ti * (si * tex00[2] + sf * tex01[2]) + \
431 tf * (si * tex10[2] + sf * tex11[2])) >> 2 * FIXED_SHIFT; \
432 ta = (ti * (si * tex00[3] + sf * tex01[3]) + \
433 tf * (si * tex10[3] + sf * tex11[3])) >> 2 * FIXED_SHIFT
434
435#define MODULATE \
436 dest[0] = ffr * (tr + 1) >> (FIXED_SHIFT + 8); \
437 dest[1] = ffg * (tg + 1) >> (FIXED_SHIFT + 8); \
438 dest[2] = ffb * (tb + 1) >> (FIXED_SHIFT + 8); \
439 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
440
441#define DECAL \
442 dest[0] = ((0xff - ta) * ffr + ((ta + 1) * tr << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
443 dest[1] = ((0xff - ta) * ffg + ((ta + 1) * tg << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
444 dest[2] = ((0xff - ta) * ffb + ((ta + 1) * tb << FIXED_SHIFT)) >> (FIXED_SHIFT + 8); \
445 dest[3] = FixedToInt(ffa)
446
447#define BLEND \
448 dest[0] = ((0xff - tr) * ffr + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
449 dest[1] = ((0xff - tg) * ffg + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
450 dest[2] = ((0xff - tb) * ffb + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
451 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
452
453#define REPLACE \
454 dest[0] = tr; \
455 dest[1] = tg; \
456 dest[2] = tb; \
457 dest[3] = ta
458
459#define ADD \
460 dest[0] = ((ffr << 8) + (tr + 1) * er) >> (FIXED_SHIFT + 8); \
461 dest[1] = ((ffg << 8) + (tg + 1) * eg) >> (FIXED_SHIFT + 8); \
462 dest[2] = ((ffb << 8) + (tb + 1) * eb) >> (FIXED_SHIFT + 8); \
463 dest[3] = ffa * (ta + 1) >> (FIXED_SHIFT + 8)
464
465/* shortcuts */
466
467#define NEAREST_RGB_REPLACE NEAREST_RGB;REPLACE
468
469#define NEAREST_RGBA_REPLACE *(GLint *)dest = *(GLint *)tex00
470
471#define SPAN1(DO_TEX,COMP) \
472 for (i=0;i<n;i++) { \
473 GLint s = FixedToInt(ffs) & smask; \
474 GLint t = FixedToInt(fft) & tmask; \
475 GLint pos = (t << twidth_log2) + s; \
476 GLubyte *tex00 = texture + COMP * pos; \
477 zspan[i] = FixedToDepth(ffz); \
478 DO_TEX; \
479 ffz += fdzdx; \
480 ffr += fdrdx; \
481 ffg += fdgdx; \
482 ffb += fdbdx; \
483 ffa += fdadx; \
484 ffs += fdsdx; \
485 fft += fdtdx; \
486 dest += 4; \
487 }
488
489#define SPAN2(DO_TEX,COMP) \
490 for (i=0;i<n;i++) { \
491 GLint s = FixedToInt(ffs) & smask; \
492 GLint t = FixedToInt(fft) & tmask; \
493 GLint sf = ffs & FIXED_FRAC_MASK; \
494 GLint tf = fft & FIXED_FRAC_MASK; \
495 GLint si = FIXED_FRAC_MASK - sf; \
496 GLint ti = FIXED_FRAC_MASK - tf; \
497 GLint pos = (t << twidth_log2) + s; \
498 GLubyte *tex00 = texture + COMP * pos; \
499 GLubyte *tex10 = tex00 + tbytesline; \
500 GLubyte *tex01 = tex00 + COMP; \
501 GLubyte *tex11 = tex10 + COMP; \
502 if (t == tmask) { \
503 tex10 -= tsize; \
504 tex11 -= tsize; \
505 } \
506 if (s == smask) { \
507 tex01 -= tbytesline; \
508 tex11 -= tbytesline; \
509 } \
510 zspan[i] = FixedToDepth(ffz); \
511 DO_TEX; \
512 ffz += fdzdx; \
513 ffr += fdrdx; \
514 ffg += fdgdx; \
515 ffb += fdbdx; \
516 ffa += fdadx; \
517 ffs += fdsdx; \
518 fft += fdtdx; \
519 dest += 4; \
520 }
521
522/* here comes the heavy part.. (something for the compiler to chew on) */
523#define INNER_LOOP( LEFT, RIGHT, Y ) \
524 { \
525 GLint i, n = RIGHT-LEFT; \
526 GLdepth zspan[MAX_WIDTH]; \
527 GLubyte rgba[MAX_WIDTH][4]; \
528 if (n>0) { \
529 GLubyte *dest = rgba[0]; \
530 ffs -= FIXED_HALF; /* off-by-one error? */ \
531 fft -= FIXED_HALF; \
532 switch (filter) { \
533 case GL_NEAREST: \
534 switch (format) { \
535 case GL_RGB: \
536 switch (envmode) { \
537 case GL_MODULATE: \
538 SPAN1(NEAREST_RGB;MODULATE,3); \
539 break; \
540 case GL_DECAL: \
541 case GL_REPLACE: \
542 SPAN1(NEAREST_RGB_REPLACE,3); \
543 break; \
544 case GL_BLEND: \
545 SPAN1(NEAREST_RGB;BLEND,3); \
546 break; \
547 case GL_ADD: \
548 SPAN1(NEAREST_RGB;ADD,3); \
549 break; \
550 } \
551 break; \
552 case GL_RGBA: \
553 switch(envmode) { \
554 case GL_MODULATE: \
555 SPAN1(NEAREST_RGBA;MODULATE,4); \
556 break; \
557 case GL_DECAL: \
558 SPAN1(NEAREST_RGBA;DECAL,4); \
559 break; \
560 case GL_BLEND: \
561 SPAN1(NEAREST_RGBA;BLEND,4); \
562 break; \
563 case GL_REPLACE: \
564 SPAN1(NEAREST_RGBA_REPLACE,4); \
565 break; \
566 case GL_ADD: \
567 SPAN1(NEAREST_RGBA;ADD,4); \
568 break; \
569 } \
570 break; \
571 } \
572 break; \
573 case GL_LINEAR: \
574 ffs -= FIXED_HALF; \
575 fft -= FIXED_HALF; \
576 switch (format) { \
577 case GL_RGB: \
578 switch (envmode) { \
579 case GL_MODULATE: \
580 SPAN2(LINEAR_RGB;MODULATE,3); \
581 break; \
582 case GL_DECAL: \
583 case GL_REPLACE: \
584 SPAN2(LINEAR_RGB;REPLACE,3); \
585 break; \
586 case GL_BLEND: \
587 SPAN2(LINEAR_RGB;BLEND,3); \
588 break; \
589 case GL_ADD: \
590 SPAN2(LINEAR_RGB;ADD,3); \
591 break; \
592 } \
593 break; \
594 case GL_RGBA: \
595 switch (envmode) { \
596 case GL_MODULATE: \
597 SPAN2(LINEAR_RGBA;MODULATE,4); \
598 break; \
599 case GL_DECAL: \
600 SPAN2(LINEAR_RGBA;DECAL,4); \
601 break; \
602 case GL_BLEND: \
603 SPAN2(LINEAR_RGBA;BLEND,4); \
604 break; \
605 case GL_REPLACE: \
606 SPAN2(LINEAR_RGBA;REPLACE,4); \
607 break; \
608 case GL_ADD: \
609 SPAN2(LINEAR_RGBA;ADD,4); \
610 break; \
611 } \
612 break; \
613 } \
614 break; \
615 } \
616 gl_write_rgba_span(ctx, n, LEFT, Y, zspan, \
617 rgba, GL_POLYGON); \
618 /* explicit kill of variables: */ \
619 ffr = ffg = ffb = ffa = 0; \
620 } \
621 }
622
623#include "tritemp.h"
624#undef SPAN1
625#undef SPAN2
626}
627
628
629/*
630 * Render an perspective corrected RGB/RGBA textured triangle.
631 * The Q (aka V in Mesa) coordinate must be zero such that the divide
632 * by interpolated Q/W comes out right.
633 *
634 * XXX (May 15, 1999) this function not used for now because repeating
635 * of negative texture coords not handled correctly!!!
636 */
637#if 000
638static void persp_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
639 GLuint v2, GLuint pv )
640{
641
642#define INTERP_Z 1
643#define INTERP_RGB 1
644#define INTERP_ALPHA 1
645#define INTERP_STUV 1
646#define SETUP_CODE \
647 struct gl_texture_unit *unit = ctx->Texture.Unit+0; \
648 struct gl_texture_object *obj = unit->CurrentD[2]; \
649 GLint b = obj->BaseLevel; \
650 GLfloat twidth = (GLfloat) obj->Image[b]->Width; \
651 GLfloat theight = (GLfloat) obj->Image[b]->Height; \
652 GLint twidth_log2 = obj->Image[b]->WidthLog2; \
653 GLubyte *texture = obj->Image[b]->Data; \
654 GLint smask = (obj->Image[b]->Width - 1); \
655 GLint tmask = (obj->Image[b]->Height - 1); \
656 GLint format = obj->Image[b]->Format; \
657 GLint filter = obj->MinFilter; \
658 GLint envmode = unit->EnvMode; \
659 GLfloat sscale, tscale; \
660 GLint comp, tbytesline, tsize; \
661 GLfixed er, eg, eb, ea; \
662 GLint tr, tg, tb, ta; \
663 if (envmode == GL_BLEND || envmode == GL_ADD) { \
664 er = FloatToFixed(unit->EnvColor[0]); \
665 eg = FloatToFixed(unit->EnvColor[1]); \
666 eb = FloatToFixed(unit->EnvColor[2]); \
667 ea = FloatToFixed(unit->EnvColor[3]); \
668 } \
669 switch (format) { \
670 case GL_ALPHA: \
671 case GL_LUMINANCE: \
672 case GL_INTENSITY: \
673 comp = 1; \
674 break; \
675 case GL_LUMINANCE_ALPHA: \
676 comp = 2; \
677 break; \
678 case GL_RGB: \
679 comp = 3; \
680 break; \
681 case GL_RGBA: \
682 comp = 4; \
683 break; \
684 default: \
685 gl_problem(NULL, "Bad texture format in persp_texture_triangle"); \
686 return; \
687 } \
688 if (filter == GL_NEAREST) { \
689 sscale = twidth; \
690 tscale = theight; \
691 } \
692 else { \
693 sscale = FIXED_SCALE * twidth; \
694 tscale = FIXED_SCALE * theight; \
695 } \
696 tbytesline = obj->Image[b]->Width * comp; \
697 tsize = theight * tbytesline;
698 (void) pv;
699
700#define SPAN1(DO_TEX,COMP) \
701 for (i=0;i<n;i++) { \
702 GLfloat invQ = 1.0f / vv; \
703 GLint s = (int)(SS * invQ) & smask; \
704 GLint t = (int)(TT * invQ) & tmask; \
705 GLint pos = COMP * ((t << twidth_log2) + s); \
706 GLubyte *tex00 = texture + pos; \
707 zspan[i] = FixedToDepth(ffz); \
708 DO_TEX; \
709 ffz += fdzdx; \
710 ffr += fdrdx; \
711 ffg += fdgdx; \
712 ffb += fdbdx; \
713 ffa += fdadx; \
714 SS += dSdx; \
715 TT += dTdx; \
716 vv += dvdx; \
717 dest += 4; \
718 }
719
720#define SPAN2(DO_TEX,COMP) \
721 for (i=0;i<n;i++) { \
722 GLfloat invQ = 1.0f / vv; \
723 GLfixed ffs = (int)(SS * invQ); \
724 GLfixed fft = (int)(TT * invQ); \
725 GLint s = FixedToInt(ffs) & smask; \
726 GLint t = FixedToInt(fft) & tmask; \
727 GLint sf = ffs & FIXED_FRAC_MASK; \
728 GLint tf = fft & FIXED_FRAC_MASK; \
729 GLint si = FIXED_FRAC_MASK - sf; \
730 GLint ti = FIXED_FRAC_MASK - tf; \
731 GLint pos = COMP * ((t << twidth_log2) + s); \
732 GLubyte *tex00 = texture + pos; \
733 GLubyte *tex10 = tex00 + tbytesline; \
734 GLubyte *tex01 = tex00 + COMP; \
735 GLubyte *tex11 = tex10 + COMP; \
736 if (t == tmask) { \
737 tex10 -= tsize; \
738 tex11 -= tsize; \
739 } \
740 if (s == smask) { \
741 tex01 -= tbytesline; \
742 tex11 -= tbytesline; \
743 } \
744 zspan[i] = FixedToDepth(ffz); \
745 DO_TEX; \
746 ffz += fdzdx; \
747 ffr += fdrdx; \
748 ffg += fdgdx; \
749 ffb += fdbdx; \
750 ffa += fdadx; \
751 SS += dSdx; \
752 TT += dTdx; \
753 vv += dvdx; \
754 dest += 4; \
755 }
756
757#define INNER_LOOP( LEFT, RIGHT, Y ) \
758 { \
759 GLint i, n = RIGHT-LEFT; \
760 GLdepth zspan[MAX_WIDTH]; \
761 GLubyte rgba[MAX_WIDTH][4]; \
762 (void)uu; /* please GCC */ \
763 if (n>0) { \
764 GLfloat SS = ss * sscale; \
765 GLfloat TT = tt * tscale; \
766 GLfloat dSdx = dsdx * sscale; \
767 GLfloat dTdx = dtdx * tscale; \
768 GLubyte *dest = rgba[0]; \
769 switch (filter) { \
770 case GL_NEAREST: \
771 switch (format) { \
772 case GL_RGB: \
773 switch (envmode) { \
774 case GL_MODULATE: \
775 SPAN1(NEAREST_RGB;MODULATE,3); \
776 break; \
777 case GL_DECAL: \
778 case GL_REPLACE: \
779 SPAN1(NEAREST_RGB_REPLACE,3); \
780 break; \
781 case GL_BLEND: \
782 SPAN1(NEAREST_RGB;BLEND,3); \
783 break; \
784 case GL_ADD: \
785 SPAN1(NEAREST_RGB;ADD,3); \
786 break; \
787 } \
788 break; \
789 case GL_RGBA: \
790 switch(envmode) { \
791 case GL_MODULATE: \
792 SPAN1(NEAREST_RGBA;MODULATE,4); \
793 break; \
794 case GL_DECAL: \
795 SPAN1(NEAREST_RGBA;DECAL,4); \
796 break; \
797 case GL_BLEND: \
798 SPAN1(NEAREST_RGBA;BLEND,4); \
799 break; \
800 case GL_REPLACE: \
801 SPAN1(NEAREST_RGBA_REPLACE,4); \
802 break; \
803 case GL_ADD: \
804 SPAN1(NEAREST_RGBA;ADD,4); \
805 break; \
806 } \
807 break; \
808 } \
809 break; \
810 case GL_LINEAR: \
811 SS -= 0.5f * FIXED_SCALE * vv; \
812 TT -= 0.5f * FIXED_SCALE * vv; \
813 switch (format) { \
814 case GL_RGB: \
815 switch (envmode) { \
816 case GL_MODULATE: \
817 SPAN2(LINEAR_RGB;MODULATE,3); \
818 break; \
819 case GL_DECAL: \
820 case GL_REPLACE: \
821 SPAN2(LINEAR_RGB;REPLACE,3); \
822 break; \
823 case GL_BLEND: \
824 SPAN2(LINEAR_RGB;BLEND,3); \
825 break; \
826 case GL_ADD: \
827 SPAN2(LINEAR_RGB;ADD,3); \
828 break; \
829 } \
830 break; \
831 case GL_RGBA: \
832 switch (envmode) { \
833 case GL_MODULATE: \
834 SPAN2(LINEAR_RGBA;MODULATE,4); \
835 break; \
836 case GL_DECAL: \
837 SPAN2(LINEAR_RGBA;DECAL,4); \
838 break; \
839 case GL_BLEND: \
840 SPAN2(LINEAR_RGBA;BLEND,4); \
841 break; \
842 case GL_REPLACE: \
843 SPAN2(LINEAR_RGBA;REPLACE,4); \
844 break; \
845 case GL_ADD: \
846 SPAN2(LINEAR_RGBA;ADD,4); \
847 break; \
848 } \
849 break; \
850 } \
851 break; \
852 } \
853 gl_write_rgba_span( ctx, n, LEFT, Y, zspan, \
854 rgba, GL_POLYGON ); \
855 ffr = ffg = ffb = ffa = 0; \
856 } \
857 }
858
859
860#include "tritemp.h"
861#undef SPAN1
862#undef SPAN2
863}
864#endif
865
866
867
868/*
869 * Render a smooth-shaded, textured, RGBA triangle.
870 * Interpolate S,T,U with perspective correction, w/out mipmapping.
871 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
872 * R is already used for red.
873 */
874static void general_textured_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
875 GLuint v2, GLuint pv )
876{
877#define INTERP_Z 1
878#define INTERP_RGB 1
879#define INTERP_ALPHA 1
880#define INTERP_STUV 1
881#define SETUP_CODE \
882 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
883 GLint r, g, b, a; \
884 if (flat_shade) { \
885 r = VB->ColorPtr->data[pv][0]; \
886 g = VB->ColorPtr->data[pv][1]; \
887 b = VB->ColorPtr->data[pv][2]; \
888 a = VB->ColorPtr->data[pv][3]; \
889 }
890#define INNER_LOOP( LEFT, RIGHT, Y ) \
891 { \
892 GLint i, n = RIGHT-LEFT; \
893 GLdepth zspan[MAX_WIDTH]; \
894 GLubyte rgba[MAX_WIDTH][4]; \
895 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
896 if (n>0) { \
897 if (flat_shade) { \
898 for (i=0;i<n;i++) { \
899 GLdouble invQ = 1.0 / vv; \
900 zspan[i] = FixedToDepth(ffz); \
901 rgba[i][RCOMP] = r; \
902 rgba[i][GCOMP] = g; \
903 rgba[i][BCOMP] = b; \
904 rgba[i][ACOMP] = a; \
905 s[i] = ss*invQ; \
906 t[i] = tt*invQ; \
907 u[i] = uu*invQ; \
908 ffz += fdzdx; \
909 ss += dsdx; \
910 tt += dtdx; \
911 uu += dudx; \
912 vv += dvdx; \
913 } \
914 } \
915 else { \
916 for (i=0;i<n;i++) { \
917 GLdouble invQ = 1.0 / vv; \
918 zspan[i] = FixedToDepth(ffz); \
919 rgba[i][RCOMP] = FixedToInt(ffr); \
920 rgba[i][GCOMP] = FixedToInt(ffg); \
921 rgba[i][BCOMP] = FixedToInt(ffb); \
922 rgba[i][ACOMP] = FixedToInt(ffa); \
923 s[i] = ss*invQ; \
924 t[i] = tt*invQ; \
925 u[i] = uu*invQ; \
926 ffz += fdzdx; \
927 ffr += fdrdx; \
928 ffg += fdgdx; \
929 ffb += fdbdx; \
930 ffa += fdadx; \
931 ss += dsdx; \
932 tt += dtdx; \
933 uu += dudx; \
934 vv += dvdx; \
935 } \
936 } \
937 gl_write_texture_span( ctx, n, LEFT, Y, zspan, \
938 s, t, u, NULL, \
939 rgba, \
940 NULL, GL_POLYGON ); \
941 } \
942 }
943
944#include "tritemp.h"
945}
946
947
948/*
949 * Render a smooth-shaded, textured, RGBA triangle with separate specular
950 * color interpolation.
951 * Interpolate S,T,U with perspective correction, w/out mipmapping.
952 * Note: we use texture coordinates S,T,U,V instead of S,T,R,Q because
953 * R is already used for red.
954 */
955static void general_textured_spec_triangle1( GLcontext *ctx, GLuint v0,
956 GLuint v1, GLuint v2, GLuint pv,
957 GLdepth zspan[MAX_WIDTH],
958 GLubyte rgba[MAX_WIDTH][4],
959 GLubyte spec[MAX_WIDTH][4] )
960{
961#define INTERP_Z 1
962#define INTERP_RGB 1
963#define INTERP_SPEC 1
964#define INTERP_ALPHA 1
965#define INTERP_STUV 1
966#define SETUP_CODE \
967 GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
968 GLint r, g, b, a, sr, sg, sb; \
969 if (flat_shade) { \
970 r = VB->ColorPtr->data[pv][0]; \
971 g = VB->ColorPtr->data[pv][1]; \
972 b = VB->ColorPtr->data[pv][2]; \
973 a = VB->ColorPtr->data[pv][3]; \
974 sr = VB->Specular[pv][0]; \
975 sg = VB->Specular[pv][1]; \
976 sb = VB->Specular[pv][2]; \
977 }
978#define INNER_LOOP( LEFT, RIGHT, Y ) \
979 { \
980 GLint i, n = RIGHT-LEFT; \
981 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH]; \
982 if (n>0) { \
983 if (flat_shade) { \
984 for (i=0;i<n;i++) { \
985 GLdouble invQ = 1.0 / vv; \
986 zspan[i] = FixedToDepth(ffz); \
987 rgba[i][RCOMP] = r; \
988 rgba[i][GCOMP] = g; \
989 rgba[i][BCOMP] = b; \
990 rgba[i][ACOMP] = a; \
991 spec[i][RCOMP] = sr; \
992 spec[i][GCOMP] = sg; \
993 spec[i][BCOMP] = sb; \
994 s[i] = ss*invQ; \
995 t[i] = tt*invQ; \
996 u[i] = uu*invQ; \
997 ffz += fdzdx; \
998 ss += dsdx; \
999 tt += dtdx; \
1000 uu += dudx; \
1001 vv += dvdx; \
1002 } \
1003 } \
1004 else { \
1005 for (i=0;i<n;i++) { \
1006 GLdouble invQ = 1.0 / vv; \
1007 zspan[i] = FixedToDepth(ffz); \
1008 rgba[i][RCOMP] = FixedToInt(ffr); \
1009 rgba[i][GCOMP] = FixedToInt(ffg); \
1010 rgba[i][BCOMP] = FixedToInt(ffb); \
1011 rgba[i][ACOMP] = FixedToInt(ffa); \
1012 spec[i][RCOMP] = FixedToInt(ffsr); \
1013 spec[i][GCOMP] = FixedToInt(ffsg); \
1014 spec[i][BCOMP] = FixedToInt(ffsb); \
1015 s[i] = ss*invQ; \
1016 t[i] = tt*invQ; \
1017 u[i] = uu*invQ; \
1018 ffz += fdzdx; \
1019 ffr += fdrdx; \
1020 ffg += fdgdx; \
1021 ffb += fdbdx; \
1022 ffa += fdadx; \
1023 ffsr += fdsrdx; \
1024 ffsg += fdsgdx; \
1025 ffsb += fdsbdx; \
1026 ss += dsdx; \
1027 tt += dtdx; \
1028 uu += dudx; \
1029 vv += dvdx; \
1030 } \
1031 } \
1032 gl_write_texture_span( ctx, n, LEFT, Y, zspan, \
1033 s, t, u, NULL, rgba, \
1034 (const GLubyte (*)[4]) spec, \
1035 GL_POLYGON ); \
1036 } \
1037 }
1038
1039#include "tritemp.h"
1040}
1041
1042
1043
1044/*
1045 * Compute the lambda value (texture level value) for a fragment.
1046 */
1047static GLfloat compute_lambda( GLfloat s, GLfloat dsdx, GLfloat dsdy,
1048 GLfloat t, GLfloat dtdx, GLfloat dtdy,
1049 GLfloat invQ, GLfloat dqdx, GLfloat dqdy,
1050 GLfloat width, GLfloat height )
1051{
1052 GLfloat dudx, dudy, dvdx, dvdy;
1053 GLfloat r1, r2, rho2;
1054 GLfloat invQ_width = invQ * width;
1055 GLfloat invQ_height = invQ * height;
1056
1057 dudx = (dsdx - s*dqdx) * invQ_width;
1058 dudy = (dsdy - s*dqdy) * invQ_width;
1059 dvdx = (dtdx - t*dqdx) * invQ_height;
1060 dvdy = (dtdy - t*dqdy) * invQ_height;
1061
1062 r1 = dudx * dudx + dudy * dudy;
1063 r2 = dvdx * dvdx + dvdy * dvdy;
1064
1065 rho2 = r1 + r2; /* used to be: rho2 = MAX2(r1,r2); */
1066 ASSERT( rho2 >= 0.0 );
1067
1068 /* return log base 2 of rho */
1069 return log(rho2) * 1.442695 * 0.5; /* 1.442695 = 1/log(2) */
1070}
1071
1072
1073/*
1074 * Render a smooth-shaded, textured, RGBA triangle.
1075 * Interpolate S,T,U with perspective correction and compute lambda for
1076 * each fragment. Lambda is used to determine whether to use the
1077 * minification or magnification filter. If minification and using
1078 * mipmaps, lambda is also used to select the texture level of detail.
1079 */
1080static void lambda_textured_triangle1( GLcontext *ctx, GLuint v0, GLuint v1,
1081 GLuint v2, GLuint pv,
1082 GLfloat s[MAX_WIDTH],
1083 GLfloat t[MAX_WIDTH],
1084 GLfloat u[MAX_WIDTH] )
1085{
1086#define INTERP_Z 1
1087#define INTERP_RGB 1
1088#define INTERP_ALPHA 1
1089#define INTERP_STUV 1
1090
1091#define SETUP_CODE \
1092 const struct gl_texture_object *obj = ctx->Texture.Unit[0].Current; \
1093 const GLint baseLevel = obj->BaseLevel; \
1094 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1095 const GLfloat twidth = (GLfloat) texImage->Width; \
1096 const GLfloat theight = (GLfloat) texImage->Height; \
1097 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1098 GLint r, g, b, a; \
1099 if (flat_shade) { \
1100 r = VB->ColorPtr->data[pv][0]; \
1101 g = VB->ColorPtr->data[pv][1]; \
1102 b = VB->ColorPtr->data[pv][2]; \
1103 a = VB->ColorPtr->data[pv][3]; \
1104 }
1105
1106#define INNER_LOOP( LEFT, RIGHT, Y ) \
1107 { \
1108 GLint i, n = RIGHT-LEFT; \
1109 GLdepth zspan[MAX_WIDTH]; \
1110 GLubyte rgba[MAX_WIDTH][4]; \
1111 GLfloat lambda[MAX_WIDTH]; \
1112 if (n>0) { \
1113 if (flat_shade) { \
1114 for (i=0;i<n;i++) { \
1115 GLdouble invQ = 1.0 / vv; \
1116 zspan[i] = FixedToDepth(ffz); \
1117 rgba[i][RCOMP] = r; \
1118 rgba[i][GCOMP] = g; \
1119 rgba[i][BCOMP] = b; \
1120 rgba[i][ACOMP] = a; \
1121 s[i] = ss*invQ; \
1122 t[i] = tt*invQ; \
1123 u[i] = uu*invQ; \
1124 lambda[i] = compute_lambda( s[i], dsdx, dsdy, \
1125 t[i], dtdx, dtdy, \
1126 invQ, dvdx, dvdy, \
1127 twidth, theight ); \
1128 ffz += fdzdx; \
1129 ss += dsdx; \
1130 tt += dtdx; \
1131 uu += dudx; \
1132 vv += dvdx; \
1133 } \
1134 } \
1135 else { \
1136 for (i=0;i<n;i++) { \
1137 GLdouble invQ = 1.0 / vv; \
1138 zspan[i] = FixedToDepth(ffz); \
1139 rgba[i][RCOMP] = FixedToInt(ffr); \
1140 rgba[i][GCOMP] = FixedToInt(ffg); \
1141 rgba[i][BCOMP] = FixedToInt(ffb); \
1142 rgba[i][ACOMP] = FixedToInt(ffa); \
1143 s[i] = ss*invQ; \
1144 t[i] = tt*invQ; \
1145 u[i] = uu*invQ; \
1146 lambda[i] = compute_lambda( s[i], dsdx, dsdy, \
1147 t[i], dtdx, dtdy, \
1148 invQ, dvdx, dvdy, \
1149 twidth, theight ); \
1150 ffz += fdzdx; \
1151 ffr += fdrdx; \
1152 ffg += fdgdx; \
1153 ffb += fdbdx; \
1154 ffa += fdadx; \
1155 ss += dsdx; \
1156 tt += dtdx; \
1157 uu += dudx; \
1158 vv += dvdx; \
1159 } \
1160 } \
1161 gl_write_texture_span( ctx, n, LEFT, Y, zspan, \
1162 s, t, u, lambda, \
1163 rgba, NULL, GL_POLYGON ); \
1164 } \
1165 }
1166
1167#include "tritemp.h"
1168}
1169
1170
1171/*
1172 * Render a smooth-shaded, textured, RGBA triangle with separate specular
1173 * interpolation.
1174 * Interpolate S,T,U with perspective correction and compute lambda for
1175 * each fragment. Lambda is used to determine whether to use the
1176 * minification or magnification filter. If minification and using
1177 * mipmaps, lambda is also used to select the texture level of detail.
1178 */
1179static void lambda_textured_spec_triangle1( GLcontext *ctx, GLuint v0,
1180 GLuint v1, GLuint v2, GLuint pv,
1181 GLfloat s[MAX_WIDTH],
1182 GLfloat t[MAX_WIDTH],
1183 GLfloat u[MAX_WIDTH] )
1184{
1185#define INTERP_Z 1
1186#define INTERP_RGB 1
1187#define INTERP_SPEC 1
1188#define INTERP_ALPHA 1
1189#define INTERP_STUV 1
1190
1191#define SETUP_CODE \
1192 const struct gl_texture_object *obj = ctx->Texture.Unit[0].Current; \
1193 const GLint baseLevel = obj->BaseLevel; \
1194 const struct gl_texture_image *texImage = obj->Image[baseLevel]; \
1195 const GLfloat twidth = (GLfloat) texImage->Width; \
1196 const GLfloat theight = (GLfloat) texImage->Height; \
1197 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1198 GLint r, g, b, a, sr, sg, sb; \
1199 if (flat_shade) { \
1200 r = VB->ColorPtr->data[pv][0]; \
1201 g = VB->ColorPtr->data[pv][1]; \
1202 b = VB->ColorPtr->data[pv][2]; \
1203 a = VB->ColorPtr->data[pv][3]; \
1204 sr = VB->Specular[pv][0]; \
1205 sg = VB->Specular[pv][1]; \
1206 sb = VB->Specular[pv][2]; \
1207 }
1208
1209#define INNER_LOOP( LEFT, RIGHT, Y ) \
1210 { \
1211 GLint i, n = RIGHT-LEFT; \
1212 GLdepth zspan[MAX_WIDTH]; \
1213 GLubyte spec[MAX_WIDTH][4]; \
1214 GLubyte rgba[MAX_WIDTH][4]; \
1215 GLfloat lambda[MAX_WIDTH]; \
1216 if (n>0) { \
1217 if (flat_shade) { \
1218 for (i=0;i<n;i++) { \
1219 GLdouble invQ = 1.0 / vv; \
1220 zspan[i] = FixedToDepth(ffz); \
1221 rgba[i][RCOMP] = r; \
1222 rgba[i][GCOMP] = g; \
1223 rgba[i][BCOMP] = b; \
1224 rgba[i][ACOMP] = a; \
1225 spec[i][RCOMP] = sr; \
1226 spec[i][GCOMP] = sg; \
1227 spec[i][BCOMP] = sb; \
1228 s[i] = ss*invQ; \
1229 t[i] = tt*invQ; \
1230 u[i] = uu*invQ; \
1231 lambda[i] = compute_lambda( s[i], dsdx, dsdy, \
1232 t[i], dtdx, dtdy, \
1233 invQ, dvdx, dvdy, \
1234 twidth, theight ); \
1235 ffz += fdzdx; \
1236 ss += dsdx; \
1237 tt += dtdx; \
1238 uu += dudx; \
1239 vv += dvdx; \
1240 } \
1241 } \
1242 else { \
1243 for (i=0;i<n;i++) { \
1244 GLdouble invQ = 1.0 / vv; \
1245 zspan[i] = FixedToDepth(ffz); \
1246 rgba[i][RCOMP] = FixedToInt(ffr); \
1247 rgba[i][GCOMP] = FixedToInt(ffg); \
1248 rgba[i][BCOMP] = FixedToInt(ffb); \
1249 rgba[i][ACOMP] = FixedToInt(ffa); \
1250 spec[i][RCOMP] = FixedToInt(ffsr); \
1251 spec[i][GCOMP] = FixedToInt(ffsg); \
1252 spec[i][BCOMP] = FixedToInt(ffsb); \
1253 s[i] = ss*invQ; \
1254 t[i] = tt*invQ; \
1255 u[i] = uu*invQ; \
1256 lambda[i] = compute_lambda( s[i], dsdx, dsdy, \
1257 t[i], dtdx, dtdy, \
1258 invQ, dvdx, dvdy, \
1259 twidth, theight ); \
1260 ffz += fdzdx; \
1261 ffr += fdrdx; \
1262 ffg += fdgdx; \
1263 ffb += fdbdx; \
1264 ffa += fdadx; \
1265 ffsr += fdsrdx; \
1266 ffsg += fdsgdx; \
1267 ffsb += fdsbdx; \
1268 ss += dsdx; \
1269 tt += dtdx; \
1270 uu += dudx; \
1271 vv += dvdx; \
1272 } \
1273 } \
1274 gl_write_texture_span( ctx, n, LEFT, Y, zspan, \
1275 s, t, u, lambda, \
1276 rgba, (const GLubyte (*)[4]) spec, \
1277 GL_POLYGON ); \
1278 } \
1279 }
1280
1281#include "tritemp.h"
1282}
1283
1284
1285/*
1286 * This is the big one!
1287 * Interpolate Z, RGB, Alpha, and two sets of texture coordinates.
1288 * Yup, it's slow.
1289 */
1290static void lambda_multitextured_triangle1( GLcontext *ctx, GLuint v0,
1291 GLuint v1, GLuint v2, GLuint pv,
1292 GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH],
1293 GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH],
1294 GLfloat u[MAX_TEXTURE_UNITS][MAX_WIDTH]
1295 )
1296{
1297 GLubyte rgba[MAX_WIDTH][4];
1298#define INTERP_Z 1
1299#define INTERP_RGB 1
1300#define INTERP_ALPHA 1
1301#define INTERP_STUV 1
1302#define INTERP_STUV1 1
1303
1304#define SETUP_CODE \
1305 const struct gl_texture_object *obj0 = ctx->Texture.Unit[0].Current; \
1306 const GLint baseLevel0 = obj0->BaseLevel; \
1307 const struct gl_texture_image *texImage0 = obj0->Image[baseLevel0]; \
1308 const GLfloat twidth0 = (GLfloat) texImage0->Width; \
1309 const GLfloat theight0 = (GLfloat) texImage0->Height; \
1310 const struct gl_texture_object *obj1 = ctx->Texture.Unit[1].Current; \
1311 const GLint baseLevel1 = obj1->BaseLevel; \
1312 const struct gl_texture_image *texImage1 = obj1->Image[baseLevel1]; \
1313 const GLfloat twidth1 = (GLfloat) texImage1->Width; \
1314 const GLfloat theight1 = (GLfloat) texImage1->Height; \
1315 const GLboolean flat_shade = (ctx->Light.ShadeModel==GL_FLAT); \
1316 GLint r, g, b, a; \
1317 if (flat_shade) { \
1318 r = VB->ColorPtr->data[pv][0]; \
1319 g = VB->ColorPtr->data[pv][1]; \
1320 b = VB->ColorPtr->data[pv][2]; \
1321 a = VB->ColorPtr->data[pv][3]; \
1322 }
1323
1324#define INNER_LOOP( LEFT, RIGHT, Y ) \
1325 { \
1326 GLint i, n = RIGHT-LEFT; \
1327 GLdepth zspan[MAX_WIDTH]; \
1328 GLfloat lambda[MAX_TEXTURE_UNITS][MAX_WIDTH]; \
1329 if (n>0) { \
1330 if (flat_shade) { \
1331 for (i=0;i<n;i++) { \
1332 GLdouble invQ = 1.0 / vv; \
1333 GLdouble invQ1 = 1.0 / vv1; \
1334 zspan[i] = FixedToDepth(ffz); \
1335 rgba[i][RCOMP] = r; \
1336 rgba[i][GCOMP] = g; \
1337 rgba[i][BCOMP] = b; \
1338 rgba[i][ACOMP] = a; \
1339 s[0][i] = ss*invQ; \
1340 t[0][i] = tt*invQ; \
1341 u[0][i] = uu*invQ; \
1342 lambda[0][i] = compute_lambda( s[0][i], dsdx, dsdy, \
1343 t[0][i], dtdx, dtdy, \
1344 invQ, dvdx, dvdy, \
1345 twidth0, theight0 ); \
1346 s[1][i] = ss1*invQ1; \
1347 t[1][i] = tt1*invQ1; \
1348 u[1][i] = uu1*invQ1; \
1349 lambda[1][i] = compute_lambda( s[1][i], ds1dx, ds1dy, \
1350 t[1][i], dt1dx, dt1dy, \
1351 invQ1, dvdx, dvdy, \
1352 twidth1, theight1 ); \
1353 ffz += fdzdx; \
1354 ss += dsdx; \
1355 tt += dtdx; \
1356 uu += dudx; \
1357 vv += dvdx; \
1358 ss1 += ds1dx; \
1359 tt1 += dt1dx; \
1360 uu1 += du1dx; \
1361 vv1 += dv1dx; \
1362 } \
1363 } \
1364 else { \
1365 for (i=0;i<n;i++) { \
1366 GLdouble invQ = 1.0 / vv; \
1367 GLdouble invQ1 = 1.0 / vv1; \
1368 zspan[i] = FixedToDepth(ffz); \
1369 rgba[i][RCOMP] = FixedToInt(ffr); \
1370 rgba[i][GCOMP] = FixedToInt(ffg); \
1371 rgba[i][BCOMP] = FixedToInt(ffb); \
1372 rgba[i][ACOMP] = FixedToInt(ffa); \
1373 s[0][i] = ss*invQ; \
1374 t[0][i] = tt*invQ; \
1375 u[0][i] = uu*invQ; \
1376 lambda[0][i] = compute_lambda( s[0][i], dsdx, dsdy, \
1377 t[0][i], dtdx, dtdy, \
1378 invQ, dvdx, dvdy, \
1379 twidth0, theight0 ); \
1380 s[1][i] = ss1*invQ1; \
1381 t[1][i] = tt1*invQ1; \
1382 u[1][i] = uu1*invQ1; \
1383 lambda[1][i] = compute_lambda( s[1][i], ds1dx, ds1dy, \
1384 t[1][i], dt1dx, dt1dy, \
1385 invQ1, dvdx, dvdy, \
1386 twidth1, theight1 ); \
1387 ffz += fdzdx; \
1388 ffr += fdrdx; \
1389 ffg += fdgdx; \
1390 ffb += fdbdx; \
1391 ffa += fdadx; \
1392 ss += dsdx; \
1393 tt += dtdx; \
1394 uu += dudx; \
1395 vv += dvdx; \
1396 ss1 += ds1dx; \
1397 tt1 += dt1dx; \
1398 uu1 += du1dx; \
1399 vv1 += dv1dx; \
1400 } \
1401 } \
1402 gl_write_multitexture_span( ctx, 2, n, LEFT, Y, zspan, \
1403 (const GLfloat (*)[MAX_WIDTH]) s, \
1404 (const GLfloat (*)[MAX_WIDTH]) t, \
1405 (const GLfloat (*)[MAX_WIDTH]) u, \
1406 (GLfloat (*)[MAX_WIDTH]) lambda, \
1407 rgba, NULL, GL_POLYGON ); \
1408 } \
1409 }
1410
1411#include "tritemp.h"
1412}
1413
1414
1415/*
1416 * These wrappers are needed to deal with the 32KB / stack frame limit
1417 * on Mac / PowerPC systems.
1418 */
1419
1420static void general_textured_spec_triangle(GLcontext *ctx, GLuint v0,
1421 GLuint v1, GLuint v2, GLuint pv)
1422{
1423 GLdepth zspan[MAX_WIDTH];
1424 GLubyte rgba[MAX_WIDTH][4], spec[MAX_WIDTH][4];
1425 general_textured_spec_triangle1(ctx,v0,v1,v2,pv,zspan,rgba,spec);
1426}
1427
1428static void lambda_textured_triangle( GLcontext *ctx, GLuint v0,
1429 GLuint v1, GLuint v2, GLuint pv )
1430{
1431 GLfloat s[MAX_WIDTH], t[MAX_WIDTH], u[MAX_WIDTH];
1432 lambda_textured_triangle1(ctx,v0,v1,v2,pv,s,t,u);
1433}
1434
1435static void lambda_textured_spec_triangle( GLcontext *ctx, GLuint v0,
1436 GLuint v1, GLuint v2, GLuint pv )
1437{
1438 GLfloat s[MAX_WIDTH];
1439 GLfloat t[MAX_WIDTH];
1440 GLfloat u[MAX_WIDTH];
1441 lambda_textured_spec_triangle1(ctx,v0,v1,v2,pv,s,t,u);
1442}
1443
1444
1445static void lambda_multitextured_triangle( GLcontext *ctx, GLuint v0,
1446 GLuint v1, GLuint v2, GLuint pv)
1447{
1448
1449 GLfloat s[MAX_TEXTURE_UNITS][MAX_WIDTH];
1450 GLfloat t[MAX_TEXTURE_UNITS][MAX_WIDTH];
1451 DEFMARRAY(GLfloat,u,MAX_TEXTURE_UNITS,MAX_WIDTH);
1452 CHECKARRAY(u,return);
1453
1454 lambda_multitextured_triangle1(ctx,v0,v1,v2,pv,s,t,u);
1455
1456 UNDEFARRAY(u);
1457}
1458
1459
1460/*
1461 * Null rasterizer for measuring transformation speed.
1462 */
1463static void null_triangle( GLcontext *ctx, GLuint v0, GLuint v1,
1464 GLuint v2, GLuint pv )
1465{
1466 (void) ctx;
1467 (void) v0;
1468 (void) v1;
1469 (void) v2;
1470 (void) pv;
1471}
1472
1473
1474#if 0
1475# define dputs(s) puts(s)
1476#else
1477# define dputs(s)
1478#endif
1479
1480/*
1481 * Determine which triangle rendering function to use given the current
1482 * rendering context.
1483 */
1484void gl_set_triangle_function( GLcontext *ctx )
1485{
1486 GLboolean rgbmode = ctx->Visual->RGBAflag;
1487
1488 if (ctx->RenderMode==GL_RENDER) {
1489 if (ctx->NoRaster) {
1490 ctx->Driver.TriangleFunc = null_triangle;
1491 return;
1492 }
1493 if (ctx->Driver.TriangleFunc) {
1494 /* Device driver will draw triangles. */
1495 return;
1496 }
1497
1498 if (ctx->Texture.ReallyEnabled) {
1499 /* Ugh, we do a _lot_ of tests to pick the best textured tri func */
1500 int format, filter;
1501 const struct gl_texture_object *current2Dtex = ctx->Texture.Unit[0].CurrentD[2];
1502 const struct gl_texture_image *image;
1503 /* First see if we can used an optimized 2-D texture function */
1504 if (ctx->Texture.ReallyEnabled==TEXTURE0_2D
1505 && current2Dtex->WrapS==GL_REPEAT
1506 && current2Dtex->WrapT==GL_REPEAT
1507 && ((image = current2Dtex->Image[current2Dtex->BaseLevel]) != 0) /* correct! */
1508 && image->Border==0
1509 && ((format = image->Format)==GL_RGB || format==GL_RGBA)
1510 && (filter = current2Dtex->MinFilter)==current2Dtex->MagFilter
1511 && ctx->Light.Model.ColorControl==GL_SINGLE_COLOR) {
1512
1513 if (ctx->Hint.PerspectiveCorrection==GL_FASTEST) {
1514
1515 if (filter==GL_NEAREST
1516 && format==GL_RGB
1517 && (ctx->Texture.Unit[0].EnvMode==GL_REPLACE
1518 || ctx->Texture.Unit[0].EnvMode==GL_DECAL)
1519 && ((ctx->RasterMask==DEPTH_BIT
1520 && ctx->Depth.Func==GL_LESS
1521 && ctx->Depth.Mask==GL_TRUE)
1522 || ctx->RasterMask==0)
1523 && ctx->Polygon.StippleFlag==GL_FALSE) {
1524
1525 if (ctx->RasterMask==DEPTH_BIT) {
1526 ctx->Driver.TriangleFunc = simple_z_textured_triangle;
1527 dputs("simple_z_textured_triangle");
1528 }
1529 else {
1530 ctx->Driver.TriangleFunc = simple_textured_triangle;
1531 dputs("simple_textured_triangle");
1532 }
1533 }
1534 else {
1535 ctx->Driver.TriangleFunc = affine_textured_triangle;
1536 dputs("affine_textured_triangle");
1537 }
1538 }
1539 else {
1540 /*ctx->Driver.TriangleFunc = persp_textured_triangle;*/
1541 ctx->Driver.TriangleFunc = general_textured_triangle;
1542 dputs("persp_textured_triangle");
1543 }
1544 }
1545 else {
1546 /* More complicated textures (mipmap, multi-tex, sep specular) */
1547 GLboolean needLambda;
1548 /* if mag filter != min filter we need to compute lambda */
1549 const struct gl_texture_object *obj0 = ctx->Texture.Unit[0].Current;
1550 const struct gl_texture_object *obj1 = ctx->Texture.Unit[1].Current;
1551 if (obj0 && obj0->MinFilter != obj0->MagFilter)
1552 needLambda = GL_TRUE;
1553 else if (obj1 && obj1->MinFilter != obj1->MagFilter)
1554 needLambda = GL_TRUE;
1555 else
1556 needLambda = GL_FALSE;
1557 if (ctx->Texture.ReallyEnabled >= TEXTURE1_1D) {
1558 /* multi-texture! */
1559 ctx->Driver.TriangleFunc = lambda_multitextured_triangle;
1560 dputs("lambda_multitextured_triangle");
1561 }
1562 else if (ctx->Light.Enabled &&
1563 ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) {
1564 /* separate specular color interpolation */
1565 if (needLambda) {
1566 ctx->Driver.TriangleFunc = lambda_textured_spec_triangle;
1567 dputs("lambda_textured_spec_triangle");
1568 }
1569 else {
1570 ctx->Driver.TriangleFunc = general_textured_spec_triangle;
1571 dputs("general_textured_spec_triangle");
1572 }
1573 }
1574 else {
1575 if (needLambda) {
1576 ctx->Driver.TriangleFunc = lambda_textured_triangle;
1577 dputs("lambda_textured_triangle");
1578 }
1579 else {
1580 ctx->Driver.TriangleFunc = general_textured_triangle;
1581 dputs("general_textured_triangle");
1582 }
1583 }
1584 }
1585 }
1586 else {
1587 if (ctx->Light.ShadeModel==GL_SMOOTH) {
1588 /* smooth shaded, no texturing, stippled or some raster ops */
1589 if (rgbmode)
1590 ctx->Driver.TriangleFunc = smooth_rgba_triangle;
1591 else
1592 ctx->Driver.TriangleFunc = smooth_ci_triangle;
1593 }
1594 else {
1595 /* flat shaded, no texturing, stippled or some raster ops */
1596 if (rgbmode)
1597 ctx->Driver.TriangleFunc = flat_rgba_triangle;
1598 else
1599 ctx->Driver.TriangleFunc = flat_ci_triangle;
1600 }
1601 }
1602 }
1603 else if (ctx->RenderMode==GL_FEEDBACK) {
1604 ctx->Driver.TriangleFunc = gl_feedback_triangle;
1605 }
1606 else {
1607 /* GL_SELECT mode */
1608 ctx->Driver.TriangleFunc = gl_select_triangle;
1609 }
1610}
Note: See TracBrowser for help on using the repository browser.