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

Last change on this file was 3598, checked in by jeroen, 25 years ago

* empty log message *

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