small cleanup, remove some warnings
[mesa.git] / src / mesa / drivers / glide / fxtris.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 4.0
4 *
5 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /* Authors:
26 * Keith Whitwell <keith@tungstengraphics.com>
27 * Daniel Borca <dborca@users.sourceforge.net>
28 */
29
30 #include "glheader.h"
31
32 #ifdef FX
33
34 #include "imports.h"
35 #include "mtypes.h"
36 #include "macros.h"
37 #include "colormac.h"
38 #include "nvfragprog.h"
39
40 #include "swrast/swrast.h"
41 #include "swrast_setup/swrast_setup.h"
42 #include "tnl/t_context.h"
43 #include "tnl/t_pipeline.h"
44
45 #include "fxdrv.h"
46
47
48 static GLboolean fxMultipass_ColorSum (GLcontext *ctx, GLuint pass);
49
50
51 /*
52 * Subpixel offsets to adjust Mesa's (true) window coordinates to
53 * Glide coordinates. We need these to ensure precise rasterization.
54 * Otherwise, we'll fail a bunch of conformance tests.
55 */
56 #define TRI_X_OFFSET ( 0.0F)
57 #define TRI_Y_OFFSET ( 0.0F)
58 #define LINE_X_OFFSET ( 0.0F)
59 #define LINE_Y_OFFSET ( 0.125F)
60 #define PNT_X_OFFSET ( 0.375F)
61 #define PNT_Y_OFFSET ( 0.375F)
62
63 static void fxRasterPrimitive( GLcontext *ctx, GLenum prim );
64 static void fxRenderPrimitive( GLcontext *ctx, GLenum prim );
65
66 static GLenum reduced_prim[GL_POLYGON+1] = {
67 GL_POINTS,
68 GL_LINES,
69 GL_LINES,
70 GL_LINES,
71 GL_TRIANGLES,
72 GL_TRIANGLES,
73 GL_TRIANGLES,
74 GL_TRIANGLES,
75 GL_TRIANGLES,
76 GL_TRIANGLES
77 };
78
79 /***********************************************************************
80 * Macros for t_dd_tritmp.h to draw basic primitives *
81 ***********************************************************************/
82
83 #define TRI( a, b, c ) \
84 do { \
85 if (DO_FALLBACK) \
86 fxMesa->draw_tri( fxMesa, a, b, c ); \
87 else \
88 grDrawTriangle( a, b, c ); \
89 } while (0) \
90
91 #define QUAD( a, b, c, d ) \
92 do { \
93 if (DO_FALLBACK) { \
94 fxMesa->draw_tri( fxMesa, a, b, d ); \
95 fxMesa->draw_tri( fxMesa, b, c, d ); \
96 } else { \
97 GrVertex *_v_[4]; \
98 _v_[0] = d; \
99 _v_[1] = a; \
100 _v_[2] = b; \
101 _v_[3] = c; \
102 grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
103 /*grDrawTriangle( a, b, d );*/ \
104 /*grDrawTriangle( b, c, d );*/ \
105 } \
106 } while (0)
107
108 #define LINE( v0, v1 ) \
109 do { \
110 if (DO_FALLBACK) \
111 fxMesa->draw_line( fxMesa, v0, v1 ); \
112 else { \
113 v0->x += LINE_X_OFFSET - TRI_X_OFFSET; \
114 v0->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
115 v1->x += LINE_X_OFFSET - TRI_X_OFFSET; \
116 v1->y += LINE_Y_OFFSET - TRI_Y_OFFSET; \
117 grDrawLine( v0, v1 ); \
118 v0->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
119 v0->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
120 v1->x -= LINE_X_OFFSET - TRI_X_OFFSET; \
121 v1->y -= LINE_Y_OFFSET - TRI_Y_OFFSET; \
122 } \
123 } while (0)
124
125 #define POINT( v0 ) \
126 do { \
127 if (DO_FALLBACK) \
128 fxMesa->draw_point( fxMesa, v0 ); \
129 else { \
130 v0->x += PNT_X_OFFSET - TRI_X_OFFSET; \
131 v0->y += PNT_Y_OFFSET - TRI_Y_OFFSET; \
132 grDrawPoint( v0 ); \
133 v0->x -= PNT_X_OFFSET - TRI_X_OFFSET; \
134 v0->y -= PNT_Y_OFFSET - TRI_Y_OFFSET; \
135 } \
136 } while (0)
137
138
139 /***********************************************************************
140 * Fallback to swrast for basic primitives *
141 ***********************************************************************/
142
143 /* Build an SWvertex from a hardware vertex.
144 *
145 * This code is hit only when a mix of accelerated and unaccelerated
146 * primitives are being drawn, and only for the unaccelerated
147 * primitives.
148 */
149 static void
150 fx_translate_vertex( GLcontext *ctx, const GrVertex *src, SWvertex *dst)
151 {
152 fxMesaContext fxMesa = FX_CONTEXT(ctx);
153 GLuint ts0 = fxMesa->tmu_source[0];
154 GLuint ts1 = fxMesa->tmu_source[1];
155 GLfloat w = 1.0F / src->oow;
156
157 dst->win[0] = src->x;
158 dst->win[1] = src->y;
159 dst->win[2] = src->ooz;
160 dst->win[3] = src->oow;
161
162 #if FX_PACKEDCOLOR
163 dst->color[0] = src->pargb[2];
164 dst->color[1] = src->pargb[1];
165 dst->color[2] = src->pargb[0];
166 dst->color[3] = src->pargb[3];
167
168 dst->specular[0] = src->pspec[2];
169 dst->specular[1] = src->pspec[1];
170 dst->specular[2] = src->pspec[0];
171 #else /* !FX_PACKEDCOLOR */
172 dst->color[0] = src->r;
173 dst->color[1] = src->g;
174 dst->color[2] = src->b;
175 dst->color[3] = src->a;
176
177 dst->specular[0] = src->r1;
178 dst->specular[1] = src->g1;
179 dst->specular[2] = src->g1;
180 #endif /* !FX_PACKEDCOLOR */
181
182 dst->texcoord[ts0][0] = fxMesa->inv_s0scale * src->tmuvtx[0].sow * w;
183 dst->texcoord[ts0][1] = fxMesa->inv_t0scale * src->tmuvtx[0].tow * w;
184
185 if (fxMesa->stw_hint_state & GR_STWHINT_W_DIFF_TMU0)
186 dst->texcoord[ts0][3] = src->tmuvtx[0].oow * w;
187 else
188 dst->texcoord[ts0][3] = 1.0F;
189
190 if (fxMesa->SetupIndex & SETUP_TMU1) {
191 dst->texcoord[ts1][0] = fxMesa->inv_s1scale * src->tmuvtx[1].sow * w;
192 dst->texcoord[ts1][1] = fxMesa->inv_t1scale * src->tmuvtx[1].tow * w;
193
194 if (fxMesa->stw_hint_state & GR_STWHINT_W_DIFF_TMU1)
195 dst->texcoord[ts1][3] = src->tmuvtx[1].oow * w;
196 else
197 dst->texcoord[ts1][3] = 1.0F;
198 }
199
200 dst->pointSize = src->psize;
201 }
202
203
204 static void
205 fx_fallback_tri( fxMesaContext fxMesa,
206 GrVertex *v0,
207 GrVertex *v1,
208 GrVertex *v2 )
209 {
210 GLcontext *ctx = fxMesa->glCtx;
211 SWvertex v[3];
212
213 fx_translate_vertex( ctx, v0, &v[0] );
214 fx_translate_vertex( ctx, v1, &v[1] );
215 fx_translate_vertex( ctx, v2, &v[2] );
216 _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
217 }
218
219
220 static void
221 fx_fallback_line( fxMesaContext fxMesa,
222 GrVertex *v0,
223 GrVertex *v1 )
224 {
225 GLcontext *ctx = fxMesa->glCtx;
226 SWvertex v[2];
227 fx_translate_vertex( ctx, v0, &v[0] );
228 fx_translate_vertex( ctx, v1, &v[1] );
229 _swrast_Line( ctx, &v[0], &v[1] );
230 }
231
232
233 static void
234 fx_fallback_point( fxMesaContext fxMesa,
235 GrVertex *v0 )
236 {
237 GLcontext *ctx = fxMesa->glCtx;
238 SWvertex v[1];
239 fx_translate_vertex( ctx, v0, &v[0] );
240 _swrast_Point( ctx, &v[0] );
241 }
242
243 /***********************************************************************
244 * Functions to draw basic primitives *
245 ***********************************************************************/
246
247 static void fx_print_vertex( GLcontext *ctx, const GrVertex *v )
248 {
249 fprintf(stderr, "fx_print_vertex:\n");
250
251 fprintf(stderr, "\tvertex at %p\n", (void *) v);
252
253 fprintf(stderr, "\tx %f y %f z %f oow %f\n", v->x, v->y, v->ooz, v->oow);
254 #if FX_PACKEDCOLOR
255 fprintf(stderr, "\tr %d g %d b %d a %d\n", v->pargb[2], v->pargb[1], v->pargb[0], v->pargb[3]);
256 #else /* !FX_PACKEDCOLOR */
257 fprintf(stderr, "\tr %f g %f b %f a %f\n", v->r, v->g, v->b, v->a);
258 #endif /* !FX_PACKEDCOLOR */
259
260 fprintf(stderr, "\n");
261 }
262
263 #define DO_FALLBACK 0
264
265 /* Need to do clip loop at each triangle when mixing swrast and hw
266 * rendering. These functions are only used when mixed-mode rendering
267 * is occurring.
268 */
269 static void fx_draw_triangle( fxMesaContext fxMesa,
270 GrVertex *v0,
271 GrVertex *v1,
272 GrVertex *v2 )
273 {
274 BEGIN_CLIP_LOOP();
275 TRI( v0, v1, v2 );
276 END_CLIP_LOOP();
277 }
278
279 static void fx_draw_line( fxMesaContext fxMesa,
280 GrVertex *v0,
281 GrVertex *v1 )
282 {
283 /* No support for wide lines (avoid wide/aa line fallback).
284 */
285 BEGIN_CLIP_LOOP();
286 LINE(v0, v1);
287 END_CLIP_LOOP();
288 }
289
290 static void fx_draw_point( fxMesaContext fxMesa,
291 GrVertex *v0 )
292 {
293 /* No support for wide points.
294 */
295 BEGIN_CLIP_LOOP();
296 POINT( v0 );
297 END_CLIP_LOOP();
298 }
299
300 #ifndef M_2PI
301 #define M_2PI 6.28318530717958647692528676655901
302 #endif
303 #define __GL_COSF cos
304 #define __GL_SINF sin
305 static void fx_draw_point_sprite ( fxMesaContext fxMesa,
306 GrVertex *v0, GLfloat psize )
307 {
308 const GLcontext *ctx = fxMesa->glCtx;
309
310 GLfloat radius;
311 GrVertex _v_[4];
312 GLuint ts0 = fxMesa->tmu_source[0];
313 GLuint ts1 = fxMesa->tmu_source[1];
314 GLfloat w = v0->oow;
315 GLfloat u0scale = fxMesa->s0scale * w;
316 GLfloat v0scale = fxMesa->t0scale * w;
317 GLfloat u1scale = fxMesa->s1scale * w;
318 GLfloat v1scale = fxMesa->t1scale * w;
319
320 radius = psize / 2.0F;
321 _v_[0] = *v0;
322 _v_[1] = *v0;
323 _v_[2] = *v0;
324 _v_[3] = *v0;
325 /* CLIP_LOOP ?!? */
326 /* point coverage? */
327 /* we don't care about culling here (see fxSetupCull) */
328
329 if (ctx->Point.SpriteOrigin == GL_UPPER_LEFT) {
330 _v_[0].x -= radius;
331 _v_[0].y += radius;
332 _v_[1].x += radius;
333 _v_[1].y += radius;
334 _v_[2].x += radius;
335 _v_[2].y -= radius;
336 _v_[3].x -= radius;
337 _v_[3].y -= radius;
338 } else {
339 _v_[0].x -= radius;
340 _v_[0].y -= radius;
341 _v_[1].x += radius;
342 _v_[1].y -= radius;
343 _v_[2].x += radius;
344 _v_[2].y += radius;
345 _v_[3].x -= radius;
346 _v_[3].y += radius;
347 }
348
349 if (ctx->Point.CoordReplace[ts0]) {
350 _v_[0].tmuvtx[0].sow = 0;
351 _v_[0].tmuvtx[0].tow = 0;
352 _v_[1].tmuvtx[0].sow = u0scale;
353 _v_[1].tmuvtx[0].tow = 0;
354 _v_[2].tmuvtx[0].sow = u0scale;
355 _v_[2].tmuvtx[0].tow = v0scale;
356 _v_[3].tmuvtx[0].sow = 0;
357 _v_[3].tmuvtx[0].tow = v0scale;
358 }
359 if (ctx->Point.CoordReplace[ts1]) {
360 _v_[0].tmuvtx[1].sow = 0;
361 _v_[0].tmuvtx[1].tow = 0;
362 _v_[1].tmuvtx[1].sow = u1scale;
363 _v_[1].tmuvtx[1].tow = 0;
364 _v_[2].tmuvtx[1].sow = u1scale;
365 _v_[2].tmuvtx[1].tow = v1scale;
366 _v_[3].tmuvtx[1].sow = 0;
367 _v_[3].tmuvtx[1].tow = v1scale;
368 }
369
370 grDrawVertexArrayContiguous(GR_TRIANGLE_FAN, 4, _v_, sizeof(GrVertex));
371 }
372
373 static void fx_draw_point_wide ( fxMesaContext fxMesa,
374 GrVertex *v0 )
375 {
376 GLint i, n;
377 GLfloat ang, radius, oon;
378 GrVertex vtxB, vtxC;
379 GrVertex *_v_[3];
380
381 const GLcontext *ctx = fxMesa->glCtx;
382 const GLfloat psize = (ctx->_TriangleCaps & DD_POINT_ATTEN)
383 ? CLAMP(v0->psize, ctx->Point.MinSize, ctx->Point.MaxSize)
384 : ctx->Point._Size; /* clamped */
385
386 if (ctx->Point.PointSprite) {
387 fx_draw_point_sprite(fxMesa, v0, psize);
388 return;
389 }
390
391 _v_[0] = v0;
392 _v_[1] = &vtxB;
393 _v_[2] = &vtxC;
394
395 radius = psize / 2.0F;
396 n = IROUND(psize * 2); /* radius x 4 */
397 if (n < 4) n = 4;
398 oon = 1.0F / (GLfloat)n;
399
400 /* CLIP_LOOP ?!? */
401 /* point coverage? */
402 /* we don't care about culling here (see fxSetupCull) */
403
404 vtxB = *v0;
405 vtxC = *v0;
406
407 vtxB.x += radius;
408 ang = M_2PI * oon;
409 vtxC.x += radius * __GL_COSF(ang);
410 vtxC.y += radius * __GL_SINF(ang);
411 grDrawVertexArray(GR_TRIANGLE_FAN, 3, _v_);
412 for (i = 2; i <= n; i++) {
413 ang = M_2PI * i * oon;
414 vtxC.x = v0->x + radius * __GL_COSF(ang);
415 vtxC.y = v0->y + radius * __GL_SINF(ang);
416 grDrawVertexArray(GR_TRIANGLE_FAN_CONTINUE, 1, &_v_[2]);
417 }
418 }
419
420 static void fx_render_pw_verts( GLcontext *ctx,
421 GLuint start,
422 GLuint count,
423 GLuint flags )
424 {
425 fxMesaContext fxMesa = FX_CONTEXT(ctx);
426 GrVertex *fxVB = fxMesa->verts;
427 (void) flags;
428
429 fxRenderPrimitive( ctx, GL_POINTS );
430
431 for ( ; start < count ; start++)
432 fx_draw_point_wide(fxMesa, fxVB + start);
433 }
434
435 static void fx_render_pw_elts ( GLcontext *ctx,
436 GLuint start,
437 GLuint count,
438 GLuint flags )
439 {
440 fxMesaContext fxMesa = FX_CONTEXT(ctx);
441 GrVertex *fxVB = fxMesa->verts;
442 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;
443 (void) flags;
444
445 fxRenderPrimitive( ctx, GL_POINTS );
446
447 for ( ; start < count ; start++)
448 fx_draw_point_wide(fxMesa, fxVB + elt[start]);
449 }
450
451 static void fx_draw_point_wide_aa ( fxMesaContext fxMesa,
452 GrVertex *v0 )
453 {
454 GLint i, n;
455 GLfloat ang, radius, oon;
456 GrVertex vtxB, vtxC;
457
458 const GLcontext *ctx = fxMesa->glCtx;
459 const GLfloat psize = (ctx->_TriangleCaps & DD_POINT_ATTEN)
460 ? CLAMP(v0->psize, ctx->Point.MinSize, ctx->Point.MaxSize)
461 : ctx->Point._Size; /* clamped */
462
463 if (ctx->Point.PointSprite) {
464 fx_draw_point_sprite(fxMesa, v0, psize);
465 return;
466 }
467
468 radius = psize / 2.0F;
469 n = IROUND(psize * 2); /* radius x 4 */
470 if (n < 4) n = 4;
471 oon = 1.0F / (GLfloat)n;
472
473 /* CLIP_LOOP ?!? */
474 /* point coverage? */
475 /* we don't care about culling here (see fxSetupCull) */
476
477 vtxB = *v0;
478 vtxC = *v0;
479
480 vtxB.x += radius;
481 for (i = 1; i <= n; i++) {
482 ang = M_2PI * i * oon;
483 vtxC.x = v0->x + radius * __GL_COSF(ang);
484 vtxC.y = v0->y + radius * __GL_SINF(ang);
485 grAADrawTriangle( v0, &vtxB, &vtxC, FXFALSE, FXTRUE, FXFALSE);
486 /*grDrawTriangle( v0, &vtxB, &vtxC);*/
487 vtxB.x = vtxC.x;
488 vtxB.y = vtxC.y;
489 }
490 }
491 #undef __GLCOSF
492 #undef __GLSINF
493 #undef M_2PI
494
495 #undef DO_FALLBACK
496
497
498 #define FX_UNFILLED_BIT 0x1
499 #define FX_OFFSET_BIT 0x2
500 #define FX_TWOSIDE_BIT 0x4
501 #define FX_FLAT_BIT 0x8
502 #define FX_TWOSTENCIL_BIT 0x10
503 #define FX_FALLBACK_BIT 0x20
504 #define FX_MAX_TRIFUNC 0x40
505
506 static struct {
507 tnl_points_func points;
508 tnl_line_func line;
509 tnl_triangle_func triangle;
510 tnl_quad_func quad;
511 } rast_tab[FX_MAX_TRIFUNC];
512
513 #define DO_FALLBACK (IND & FX_FALLBACK_BIT)
514 #define DO_OFFSET (IND & FX_OFFSET_BIT)
515 #define DO_UNFILLED (IND & FX_UNFILLED_BIT)
516 #define DO_TWOSIDE (IND & FX_TWOSIDE_BIT)
517 #define DO_FLAT (IND & FX_FLAT_BIT)
518 #define DO_TWOSTENCIL (IND & FX_TWOSTENCIL_BIT)
519 #define DO_TRI 1
520 #define DO_QUAD 1
521 #define DO_LINE 1
522 #define DO_POINTS 1
523 #define DO_FULL_QUAD 1
524
525 #define HAVE_RGBA 1
526 #define HAVE_SPEC 1
527 #define HAVE_HW_FLATSHADE 0
528 #define HAVE_BACK_COLORS 0
529 #define VERTEX GrVertex
530 #define TAB rast_tab
531
532 #define DEPTH_SCALE 1.0
533 #define UNFILLED_TRI unfilled_tri
534 #define UNFILLED_QUAD unfilled_quad
535 #define VERT_X(_v) _v->x
536 #define VERT_Y(_v) _v->y
537 #define VERT_Z(_v) _v->ooz
538 #define AREA_IS_CCW( a ) IS_NEGATIVE( a )
539 #define GET_VERTEX(e) (fxMesa->verts + e)
540
541
542 #if FX_PACKEDCOLOR
543 #define VERT_SET_RGBA( dst, f ) \
544 do { \
545 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[2], f[0]);\
546 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[1], f[1]);\
547 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[0], f[2]);\
548 UNCLAMPED_FLOAT_TO_UBYTE(dst->pargb[3], f[3]);\
549 } while (0)
550
551 #define VERT_COPY_RGBA( v0, v1 ) \
552 *(GLuint *)&v0->pargb = *(GLuint *)&v1->pargb
553
554 #define VERT_SAVE_RGBA( idx ) \
555 *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->pargb
556
557 #define VERT_RESTORE_RGBA( idx ) \
558 *(GLuint *)&v[idx]->pargb = *(GLuint *)&color[idx]
559
560
561 #define VERT_SET_SPEC( dst, f ) \
562 do { \
563 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[2], f[0]);\
564 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[1], f[1]);\
565 UNCLAMPED_FLOAT_TO_UBYTE(dst->pspec[0], f[2]);\
566 } while (0)
567
568 #define VERT_COPY_SPEC( v0, v1 ) \
569 *(GLuint *)&v0->pspec = *(GLuint *)&v1->pspec
570
571 #define VERT_SAVE_SPEC( idx ) \
572 *(GLuint *)&spec[idx] = *(GLuint *)&v[idx]->pspec
573
574 #define VERT_RESTORE_SPEC( idx ) \
575 *(GLuint *)&v[idx]->pspec = *(GLuint *)&spec[idx]
576
577
578 #define LOCAL_VARS(n) \
579 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
580 GLubyte color[n][4], spec[n][4]; \
581 (void) color; (void) spec;
582 #else /* !FX_PACKEDCOLOR */
583 #define VERT_SET_RGBA( dst, f ) \
584 do { \
585 CNORM(dst->r, f[0]); \
586 CNORM(dst->g, f[1]); \
587 CNORM(dst->b, f[2]); \
588 CNORM(dst->a, f[3]); \
589 } while (0)
590
591 #define VERT_COPY_RGBA( v0, v1 ) \
592 do { \
593 COPY_FLOAT(v0->r, v1->r); \
594 COPY_FLOAT(v0->g, v1->g); \
595 COPY_FLOAT(v0->b, v1->b); \
596 COPY_FLOAT(v0->a, v1->a); \
597 } while (0)
598
599 #define VERT_SAVE_RGBA( idx ) \
600 do { \
601 COPY_FLOAT(color[idx][0], v[idx]->r); \
602 COPY_FLOAT(color[idx][1], v[idx]->g); \
603 COPY_FLOAT(color[idx][2], v[idx]->b); \
604 COPY_FLOAT(color[idx][3], v[idx]->a); \
605 } while (0)
606
607 #define VERT_RESTORE_RGBA( idx ) \
608 do { \
609 COPY_FLOAT(v[idx]->r, color[idx][0]); \
610 COPY_FLOAT(v[idx]->g, color[idx][1]); \
611 COPY_FLOAT(v[idx]->b, color[idx][2]); \
612 COPY_FLOAT(v[idx]->a, color[idx][3]); \
613 } while (0)
614
615
616 #define VERT_SET_SPEC( dst, f ) \
617 do { \
618 CNORM(dst->r1, f[0]); \
619 CNORM(dst->g1, f[1]); \
620 CNORM(dst->b1, f[2]); \
621 } while (0)
622
623 #define VERT_COPY_SPEC( v0, v1 ) \
624 do { \
625 COPY_FLOAT(v0->r1, v1->r1); \
626 COPY_FLOAT(v0->g1, v1->g1); \
627 COPY_FLOAT(v0->b1, v1->b1); \
628 } while (0)
629
630 #define VERT_SAVE_SPEC( idx ) \
631 do { \
632 COPY_FLOAT(spec[idx][0], v[idx]->r1); \
633 COPY_FLOAT(spec[idx][1], v[idx]->g1); \
634 COPY_FLOAT(spec[idx][2], v[idx]->b1); \
635 } while (0)
636
637 #define VERT_RESTORE_SPEC( idx ) \
638 do { \
639 COPY_FLOAT(v[idx]->r1, spec[idx][0]); \
640 COPY_FLOAT(v[idx]->g1, spec[idx][1]); \
641 COPY_FLOAT(v[idx]->b1, spec[idx][2]); \
642 } while (0)
643
644
645 #define LOCAL_VARS(n) \
646 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
647 GLfloat color[n][4], spec[n][4]; \
648 (void) color; (void) spec;
649 #endif /* !FX_PACKEDCOLOR */
650
651
652 /***********************************************************************
653 * Twoside stencil *
654 ***********************************************************************/
655 #define SETUP_STENCIL(f) if (f) fxSetupStencilFace(ctx, f)
656 #define UNSET_STENCIL(f) if (f) fxSetupStencil(ctx)
657
658
659 /***********************************************************************
660 * Functions to draw basic unfilled primitives *
661 ***********************************************************************/
662
663 #define RASTERIZE(x) if (fxMesa->raster_primitive != reduced_prim[x]) \
664 fxRasterPrimitive( ctx, reduced_prim[x] )
665 #define RENDER_PRIMITIVE fxMesa->render_primitive
666 #define IND FX_FALLBACK_BIT
667 #define TAG(x) x
668 #include "tnl_dd/t_dd_unfilled.h"
669 #undef IND
670
671 /***********************************************************************
672 * Functions to draw GL primitives *
673 ***********************************************************************/
674
675 #define IND (0)
676 #define TAG(x) x
677 #include "tnl_dd/t_dd_tritmp.h"
678
679 #define IND (FX_OFFSET_BIT)
680 #define TAG(x) x##_offset
681 #include "tnl_dd/t_dd_tritmp.h"
682
683 #define IND (FX_TWOSIDE_BIT)
684 #define TAG(x) x##_twoside
685 #include "tnl_dd/t_dd_tritmp.h"
686
687 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT)
688 #define TAG(x) x##_twoside_offset
689 #include "tnl_dd/t_dd_tritmp.h"
690
691 #define IND (FX_UNFILLED_BIT)
692 #define TAG(x) x##_unfilled
693 #include "tnl_dd/t_dd_tritmp.h"
694
695 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT)
696 #define TAG(x) x##_offset_unfilled
697 #include "tnl_dd/t_dd_tritmp.h"
698
699 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT)
700 #define TAG(x) x##_twoside_unfilled
701 #include "tnl_dd/t_dd_tritmp.h"
702
703 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT)
704 #define TAG(x) x##_twoside_offset_unfilled
705 #include "tnl_dd/t_dd_tritmp.h"
706
707 #define IND (FX_FALLBACK_BIT)
708 #define TAG(x) x##_fallback
709 #include "tnl_dd/t_dd_tritmp.h"
710
711 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT)
712 #define TAG(x) x##_offset_fallback
713 #include "tnl_dd/t_dd_tritmp.h"
714
715 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT)
716 #define TAG(x) x##_twoside_fallback
717 #include "tnl_dd/t_dd_tritmp.h"
718
719 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT)
720 #define TAG(x) x##_twoside_offset_fallback
721 #include "tnl_dd/t_dd_tritmp.h"
722
723 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT)
724 #define TAG(x) x##_unfilled_fallback
725 #include "tnl_dd/t_dd_tritmp.h"
726
727 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
728 #define TAG(x) x##_offset_unfilled_fallback
729 #include "tnl_dd/t_dd_tritmp.h"
730
731 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT)
732 #define TAG(x) x##_twoside_unfilled_fallback
733 #include "tnl_dd/t_dd_tritmp.h"
734
735 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
736 FX_FALLBACK_BIT)
737 #define TAG(x) x##_twoside_offset_unfilled_fallback
738 #include "tnl_dd/t_dd_tritmp.h"
739
740
741 /* Fx doesn't support provoking-vertex flat-shading?
742 */
743 #define IND (FX_FLAT_BIT)
744 #define TAG(x) x##_flat
745 #include "tnl_dd/t_dd_tritmp.h"
746
747 #define IND (FX_OFFSET_BIT|FX_FLAT_BIT)
748 #define TAG(x) x##_offset_flat
749 #include "tnl_dd/t_dd_tritmp.h"
750
751 #define IND (FX_TWOSIDE_BIT|FX_FLAT_BIT)
752 #define TAG(x) x##_twoside_flat
753 #include "tnl_dd/t_dd_tritmp.h"
754
755 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FLAT_BIT)
756 #define TAG(x) x##_twoside_offset_flat
757 #include "tnl_dd/t_dd_tritmp.h"
758
759 #define IND (FX_UNFILLED_BIT|FX_FLAT_BIT)
760 #define TAG(x) x##_unfilled_flat
761 #include "tnl_dd/t_dd_tritmp.h"
762
763 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
764 #define TAG(x) x##_offset_unfilled_flat
765 #include "tnl_dd/t_dd_tritmp.h"
766
767 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
768 #define TAG(x) x##_twoside_unfilled_flat
769 #include "tnl_dd/t_dd_tritmp.h"
770
771 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT)
772 #define TAG(x) x##_twoside_offset_unfilled_flat
773 #include "tnl_dd/t_dd_tritmp.h"
774
775 #define IND (FX_FALLBACK_BIT|FX_FLAT_BIT)
776 #define TAG(x) x##_fallback_flat
777 #include "tnl_dd/t_dd_tritmp.h"
778
779 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
780 #define TAG(x) x##_offset_fallback_flat
781 #include "tnl_dd/t_dd_tritmp.h"
782
783 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
784 #define TAG(x) x##_twoside_fallback_flat
785 #include "tnl_dd/t_dd_tritmp.h"
786
787 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
788 #define TAG(x) x##_twoside_offset_fallback_flat
789 #include "tnl_dd/t_dd_tritmp.h"
790
791 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
792 #define TAG(x) x##_unfilled_fallback_flat
793 #include "tnl_dd/t_dd_tritmp.h"
794
795 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
796 #define TAG(x) x##_offset_unfilled_fallback_flat
797 #include "tnl_dd/t_dd_tritmp.h"
798
799 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT)
800 #define TAG(x) x##_twoside_unfilled_fallback_flat
801 #include "tnl_dd/t_dd_tritmp.h"
802
803 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
804 FX_FALLBACK_BIT|FX_FLAT_BIT)
805 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat
806 #include "tnl_dd/t_dd_tritmp.h"
807
808
809 /* 2-sided stencil begin */
810 #define IND (FX_TWOSTENCIL_BIT)
811 #define TAG(x) x##_twostencil
812 #include "tnl_dd/t_dd_tritmp.h"
813
814 #define IND (FX_OFFSET_BIT|FX_TWOSTENCIL_BIT)
815 #define TAG(x) x##_offset_twostencil
816 #include "tnl_dd/t_dd_tritmp.h"
817
818 #define IND (FX_TWOSIDE_BIT|FX_TWOSTENCIL_BIT)
819 #define TAG(x) x##_twoside_twostencil
820 #include "tnl_dd/t_dd_tritmp.h"
821
822 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_TWOSTENCIL_BIT)
823 #define TAG(x) x##_twoside_offset_twostencil
824 #include "tnl_dd/t_dd_tritmp.h"
825
826 #define IND (FX_UNFILLED_BIT|FX_TWOSTENCIL_BIT)
827 #define TAG(x) x##_unfilled_twostencil
828 #include "tnl_dd/t_dd_tritmp.h"
829
830 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_TWOSTENCIL_BIT)
831 #define TAG(x) x##_offset_unfilled_twostencil
832 #include "tnl_dd/t_dd_tritmp.h"
833
834 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_TWOSTENCIL_BIT)
835 #define TAG(x) x##_twoside_unfilled_twostencil
836 #include "tnl_dd/t_dd_tritmp.h"
837
838 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_TWOSTENCIL_BIT)
839 #define TAG(x) x##_twoside_offset_unfilled_twostencil
840 #include "tnl_dd/t_dd_tritmp.h"
841
842 #define IND (FX_FALLBACK_BIT|FX_TWOSTENCIL_BIT)
843 #define TAG(x) x##_fallback_twostencil
844 #include "tnl_dd/t_dd_tritmp.h"
845
846 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_TWOSTENCIL_BIT)
847 #define TAG(x) x##_offset_fallback_twostencil
848 #include "tnl_dd/t_dd_tritmp.h"
849
850 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT|FX_TWOSTENCIL_BIT)
851 #define TAG(x) x##_twoside_fallback_twostencil
852 #include "tnl_dd/t_dd_tritmp.h"
853
854 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_TWOSTENCIL_BIT)
855 #define TAG(x) x##_twoside_offset_fallback_twostencil
856 #include "tnl_dd/t_dd_tritmp.h"
857
858 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_TWOSTENCIL_BIT)
859 #define TAG(x) x##_unfilled_fallback_twostencil
860 #include "tnl_dd/t_dd_tritmp.h"
861
862 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_TWOSTENCIL_BIT)
863 #define TAG(x) x##_offset_unfilled_fallback_twostencil
864 #include "tnl_dd/t_dd_tritmp.h"
865
866 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_TWOSTENCIL_BIT)
867 #define TAG(x) x##_twoside_unfilled_fallback_twostencil
868 #include "tnl_dd/t_dd_tritmp.h"
869
870 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
871 FX_FALLBACK_BIT|FX_TWOSTENCIL_BIT)
872 #define TAG(x) x##_twoside_offset_unfilled_fallback_twostencil
873 #include "tnl_dd/t_dd_tritmp.h"
874
875
876 /* Fx doesn't support provoking-vertex flat-shading?
877 */
878 #define IND (FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
879 #define TAG(x) x##_flat_twostencil
880 #include "tnl_dd/t_dd_tritmp.h"
881
882 #define IND (FX_OFFSET_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
883 #define TAG(x) x##_offset_flat_twostencil
884 #include "tnl_dd/t_dd_tritmp.h"
885
886 #define IND (FX_TWOSIDE_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
887 #define TAG(x) x##_twoside_flat_twostencil
888 #include "tnl_dd/t_dd_tritmp.h"
889
890 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
891 #define TAG(x) x##_twoside_offset_flat_twostencil
892 #include "tnl_dd/t_dd_tritmp.h"
893
894 #define IND (FX_UNFILLED_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
895 #define TAG(x) x##_unfilled_flat_twostencil
896 #include "tnl_dd/t_dd_tritmp.h"
897
898 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
899 #define TAG(x) x##_offset_unfilled_flat_twostencil
900 #include "tnl_dd/t_dd_tritmp.h"
901
902 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
903 #define TAG(x) x##_twoside_unfilled_flat_twostencil
904 #include "tnl_dd/t_dd_tritmp.h"
905
906 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
907 #define TAG(x) x##_twoside_offset_unfilled_flat_twostencil
908 #include "tnl_dd/t_dd_tritmp.h"
909
910 #define IND (FX_FALLBACK_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
911 #define TAG(x) x##_fallback_flat_twostencil
912 #include "tnl_dd/t_dd_tritmp.h"
913
914 #define IND (FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
915 #define TAG(x) x##_offset_fallback_flat_twostencil
916 #include "tnl_dd/t_dd_tritmp.h"
917
918 #define IND (FX_TWOSIDE_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
919 #define TAG(x) x##_twoside_fallback_flat_twostencil
920 #include "tnl_dd/t_dd_tritmp.h"
921
922 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
923 #define TAG(x) x##_twoside_offset_fallback_flat_twostencil
924 #include "tnl_dd/t_dd_tritmp.h"
925
926 #define IND (FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
927 #define TAG(x) x##_unfilled_fallback_flat_twostencil
928 #include "tnl_dd/t_dd_tritmp.h"
929
930 #define IND (FX_OFFSET_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
931 #define TAG(x) x##_offset_unfilled_fallback_flat_twostencil
932 #include "tnl_dd/t_dd_tritmp.h"
933
934 #define IND (FX_TWOSIDE_BIT|FX_UNFILLED_BIT|FX_FALLBACK_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
935 #define TAG(x) x##_twoside_unfilled_fallback_flat_twostencil
936 #include "tnl_dd/t_dd_tritmp.h"
937
938 #define IND (FX_TWOSIDE_BIT|FX_OFFSET_BIT|FX_UNFILLED_BIT| \
939 FX_FALLBACK_BIT|FX_FLAT_BIT|FX_TWOSTENCIL_BIT)
940 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat_twostencil
941 #include "tnl_dd/t_dd_tritmp.h"
942 /* 2-sided stencil end */
943
944
945 static void init_rast_tab( void )
946 {
947 init();
948 init_offset();
949 init_twoside();
950 init_twoside_offset();
951 init_unfilled();
952 init_offset_unfilled();
953 init_twoside_unfilled();
954 init_twoside_offset_unfilled();
955 init_fallback();
956 init_offset_fallback();
957 init_twoside_fallback();
958 init_twoside_offset_fallback();
959 init_unfilled_fallback();
960 init_offset_unfilled_fallback();
961 init_twoside_unfilled_fallback();
962 init_twoside_offset_unfilled_fallback();
963
964 init_flat();
965 init_offset_flat();
966 init_twoside_flat();
967 init_twoside_offset_flat();
968 init_unfilled_flat();
969 init_offset_unfilled_flat();
970 init_twoside_unfilled_flat();
971 init_twoside_offset_unfilled_flat();
972 init_fallback_flat();
973 init_offset_fallback_flat();
974 init_twoside_fallback_flat();
975 init_twoside_offset_fallback_flat();
976 init_unfilled_fallback_flat();
977 init_offset_unfilled_fallback_flat();
978 init_twoside_unfilled_fallback_flat();
979 init_twoside_offset_unfilled_fallback_flat();
980
981 /* 2-sided stencil begin */
982 init_twostencil();
983 init_offset_twostencil();
984 init_twoside_twostencil();
985 init_twoside_offset_twostencil();
986 init_unfilled_twostencil();
987 init_offset_unfilled_twostencil();
988 init_twoside_unfilled_twostencil();
989 init_twoside_offset_unfilled_twostencil();
990 init_fallback_twostencil();
991 init_offset_fallback_twostencil();
992 init_twoside_fallback_twostencil();
993 init_twoside_offset_fallback_twostencil();
994 init_unfilled_fallback_twostencil();
995 init_offset_unfilled_fallback_twostencil();
996 init_twoside_unfilled_fallback_twostencil();
997 init_twoside_offset_unfilled_fallback_twostencil();
998
999 init_flat_twostencil();
1000 init_offset_flat_twostencil();
1001 init_twoside_flat_twostencil();
1002 init_twoside_offset_flat_twostencil();
1003 init_unfilled_flat_twostencil();
1004 init_offset_unfilled_flat_twostencil();
1005 init_twoside_unfilled_flat_twostencil();
1006 init_twoside_offset_unfilled_flat_twostencil();
1007 init_fallback_flat_twostencil();
1008 init_offset_fallback_flat_twostencil();
1009 init_twoside_fallback_flat_twostencil();
1010 init_twoside_offset_fallback_flat_twostencil();
1011 init_unfilled_fallback_flat_twostencil();
1012 init_offset_unfilled_fallback_flat_twostencil();
1013 init_twoside_unfilled_fallback_flat_twostencil();
1014 init_twoside_offset_unfilled_fallback_flat_twostencil();
1015 /* 2-sided stencil end */
1016 }
1017
1018
1019 /**********************************************************************/
1020 /* Render whole begin/end objects */
1021 /**********************************************************************/
1022
1023
1024 /* Accelerate vertex buffer rendering when renderindex == 0 and
1025 * there is no clipping.
1026 */
1027 #define INIT(x) fxRenderPrimitive( ctx, x )
1028
1029 static void fx_render_vb_points( GLcontext *ctx,
1030 GLuint start,
1031 GLuint count,
1032 GLuint flags )
1033 {
1034 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1035 GrVertex *fxVB = fxMesa->verts;
1036 GLint i;
1037 (void) flags;
1038
1039 if (TDFX_DEBUG & VERBOSE_VARRAY) {
1040 fprintf(stderr, "fx_render_vb_points\n");
1041 }
1042
1043 INIT(GL_POINTS);
1044
1045 /* Adjust point coords */
1046 for (i = start; i < count; i++) {
1047 fxVB[i].x += PNT_X_OFFSET - TRI_X_OFFSET;
1048 fxVB[i].y += PNT_Y_OFFSET - TRI_Y_OFFSET;
1049 }
1050
1051 grDrawVertexArrayContiguous( GR_POINTS, count-start,
1052 fxVB + start, sizeof(GrVertex));
1053 /* restore point coords */
1054 for (i = start; i < count; i++) {
1055 fxVB[i].x -= PNT_X_OFFSET - TRI_X_OFFSET;
1056 fxVB[i].y -= PNT_Y_OFFSET - TRI_Y_OFFSET;
1057 }
1058 }
1059
1060 static void fx_render_vb_line_strip( GLcontext *ctx,
1061 GLuint start,
1062 GLuint count,
1063 GLuint flags )
1064 {
1065 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1066 GrVertex *fxVB = fxMesa->verts;
1067 GLint i;
1068 (void) flags;
1069
1070 if (TDFX_DEBUG & VERBOSE_VARRAY) {
1071 fprintf(stderr, "fx_render_vb_line_strip\n");
1072 }
1073
1074 INIT(GL_LINE_STRIP);
1075
1076 /* adjust line coords */
1077 for (i = start; i < count; i++) {
1078 fxVB[i].x += LINE_X_OFFSET - TRI_X_OFFSET;
1079 fxVB[i].y += LINE_Y_OFFSET - TRI_Y_OFFSET;
1080 }
1081
1082 grDrawVertexArrayContiguous( GR_LINE_STRIP, count-start,
1083 fxVB + start, sizeof(GrVertex));
1084
1085 /* restore line coords */
1086 for (i = start; i < count; i++) {
1087 fxVB[i].x -= LINE_X_OFFSET - TRI_X_OFFSET;
1088 fxVB[i].y -= LINE_Y_OFFSET - TRI_Y_OFFSET;
1089 }
1090 }
1091
1092 static void fx_render_vb_line_loop( GLcontext *ctx,
1093 GLuint start,
1094 GLuint count,
1095 GLuint flags )
1096 {
1097 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1098 GrVertex *fxVB = fxMesa->verts;
1099 GLint i;
1100 GLint j = start;
1101 (void) flags;
1102
1103 if (TDFX_DEBUG & VERBOSE_VARRAY) {
1104 fprintf(stderr, "fx_render_vb_line_loop\n");
1105 }
1106
1107 INIT(GL_LINE_LOOP);
1108
1109 if (!(flags & PRIM_BEGIN)) {
1110 j++;
1111 }
1112
1113 /* adjust line coords */
1114 for (i = start; i < count; i++) {
1115 fxVB[i].x += LINE_X_OFFSET - TRI_X_OFFSET;
1116 fxVB[i].y += LINE_Y_OFFSET - TRI_Y_OFFSET;
1117 }
1118
1119 grDrawVertexArrayContiguous( GR_LINE_STRIP, count-j,
1120 fxVB + j, sizeof(GrVertex));
1121
1122 if (flags & PRIM_END)
1123 grDrawLine( fxVB + (count - 1),
1124 fxVB + start );
1125
1126 /* restore line coords */
1127 for (i = start; i < count; i++) {
1128 fxVB[i].x -= LINE_X_OFFSET - TRI_X_OFFSET;
1129 fxVB[i].y -= LINE_Y_OFFSET - TRI_Y_OFFSET;
1130 }
1131 }
1132
1133 static void fx_render_vb_lines( GLcontext *ctx,
1134 GLuint start,
1135 GLuint count,
1136 GLuint flags )
1137 {
1138 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1139 GrVertex *fxVB = fxMesa->verts;
1140 GLint i;
1141 (void) flags;
1142
1143 if (TDFX_DEBUG & VERBOSE_VARRAY) {
1144 fprintf(stderr, "fx_render_vb_lines\n");
1145 }
1146
1147 INIT(GL_LINES);
1148
1149 /* adjust line coords */
1150 for (i = start; i < count; i++) {
1151 fxVB[i].x += LINE_X_OFFSET - TRI_X_OFFSET;
1152 fxVB[i].y += LINE_Y_OFFSET - TRI_Y_OFFSET;
1153 }
1154
1155 grDrawVertexArrayContiguous( GR_LINES, count-start,
1156 fxVB + start, sizeof(GrVertex));
1157
1158 /* restore line coords */
1159 for (i = start; i < count; i++) {
1160 fxVB[i].x -= LINE_X_OFFSET - TRI_X_OFFSET;
1161 fxVB[i].y -= LINE_Y_OFFSET - TRI_Y_OFFSET;
1162 }
1163 }
1164
1165 static void fx_render_vb_triangles( GLcontext *ctx,
1166 GLuint start,
1167 GLuint count,
1168 GLuint flags )
1169 {
1170 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1171 GrVertex *fxVB = fxMesa->verts;
1172 GLuint j;
1173 (void) flags;
1174
1175 if (TDFX_DEBUG & VERBOSE_VARRAY) {
1176 fprintf(stderr, "fx_render_vb_triangles\n");
1177 }
1178
1179 INIT(GL_TRIANGLES);
1180
1181 for (j=start+2; j<count; j+=3) {
1182 grDrawTriangle(fxVB + (j-2), fxVB + (j-1), fxVB + j);
1183 }
1184 }
1185
1186
1187 static void fx_render_vb_tri_strip( GLcontext *ctx,
1188 GLuint start,
1189 GLuint count,
1190 GLuint flags )
1191 {
1192 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1193 GrVertex *fxVB = fxMesa->verts;
1194 (void) flags;
1195
1196 if (TDFX_DEBUG & VERBOSE_VARRAY) {
1197 fprintf(stderr, "fx_render_vb_tri_strip\n");
1198 }
1199
1200 INIT(GL_TRIANGLE_STRIP);
1201
1202 /* no GR_TRIANGLE_STRIP_CONTINUE?!? */
1203
1204 grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP, count-start,
1205 fxVB + start, sizeof(GrVertex));
1206 }
1207
1208
1209 static void fx_render_vb_tri_fan( GLcontext *ctx,
1210 GLuint start,
1211 GLuint count,
1212 GLuint flags )
1213 {
1214 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1215 GrVertex *fxVB = fxMesa->verts;
1216 (void) flags;
1217
1218 if (TDFX_DEBUG & VERBOSE_VARRAY) {
1219 fprintf(stderr, "fx_render_vb_tri_fan\n");
1220 }
1221
1222 INIT(GL_TRIANGLE_FAN);
1223
1224 grDrawVertexArrayContiguous( GR_TRIANGLE_FAN, count-start,
1225 fxVB + start, sizeof(GrVertex) );
1226 }
1227
1228 static void fx_render_vb_quads( GLcontext *ctx,
1229 GLuint start,
1230 GLuint count,
1231 GLuint flags )
1232 {
1233 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1234 GrVertex *fxVB = fxMesa->verts;
1235 GLuint i;
1236 (void) flags;
1237
1238 if (TDFX_DEBUG & VERBOSE_VARRAY) {
1239 fprintf(stderr, "fx_render_vb_quads\n");
1240 }
1241
1242 INIT(GL_QUADS);
1243
1244 for (i = start + 3 ; i < count ; i += 4 ) {
1245 #define VERT(x) (fxVB + (x))
1246 GrVertex *_v_[4];
1247 _v_[0] = VERT(i);
1248 _v_[1] = VERT(i-3);
1249 _v_[2] = VERT(i-2);
1250 _v_[3] = VERT(i-1);
1251 grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);
1252 /*grDrawTriangle( VERT(i-3), VERT(i-2), VERT(i) );*/
1253 /*grDrawTriangle( VERT(i-2), VERT(i-1), VERT(i) );*/
1254 #undef VERT
1255 }
1256 }
1257
1258 static void fx_render_vb_quad_strip( GLcontext *ctx,
1259 GLuint start,
1260 GLuint count,
1261 GLuint flags )
1262 {
1263 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1264 GrVertex *fxVB = fxMesa->verts;
1265 (void) flags;
1266
1267 if (TDFX_DEBUG & VERBOSE_VARRAY) {
1268 fprintf(stderr, "fx_render_vb_quad_strip\n");
1269 }
1270
1271 INIT(GL_QUAD_STRIP);
1272
1273 count -= (count-start)&1;
1274
1275 grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP,
1276 count-start, fxVB + start, sizeof(GrVertex));
1277 }
1278
1279 static void fx_render_vb_poly( GLcontext *ctx,
1280 GLuint start,
1281 GLuint count,
1282 GLuint flags )
1283 {
1284 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1285 GrVertex *fxVB = fxMesa->verts;
1286 (void) flags;
1287
1288 if (TDFX_DEBUG & VERBOSE_VARRAY) {
1289 fprintf(stderr, "fx_render_vb_poly\n");
1290 }
1291
1292 INIT(GL_POLYGON);
1293
1294 grDrawVertexArrayContiguous( GR_POLYGON, count-start,
1295 fxVB + start, sizeof(GrVertex));
1296 }
1297
1298 static void fx_render_vb_noop( GLcontext *ctx,
1299 GLuint start,
1300 GLuint count,
1301 GLuint flags )
1302 {
1303 (void) (ctx && start && count && flags);
1304 }
1305
1306 static void (*fx_render_tab_verts[GL_POLYGON+2])(GLcontext *,
1307 GLuint,
1308 GLuint,
1309 GLuint) =
1310 {
1311 fx_render_vb_points,
1312 fx_render_vb_lines,
1313 fx_render_vb_line_loop,
1314 fx_render_vb_line_strip,
1315 fx_render_vb_triangles,
1316 fx_render_vb_tri_strip,
1317 fx_render_vb_tri_fan,
1318 fx_render_vb_quads,
1319 fx_render_vb_quad_strip,
1320 fx_render_vb_poly,
1321 fx_render_vb_noop,
1322 };
1323 #undef INIT
1324
1325
1326 /**********************************************************************/
1327 /* Render whole (indexed) begin/end objects */
1328 /**********************************************************************/
1329
1330
1331 #define VERT(x) (vertptr + x)
1332
1333 #define RENDER_POINTS( start, count ) \
1334 for ( ; start < count ; start++) \
1335 grDrawPoint( VERT(ELT(start)) );
1336
1337 #define RENDER_LINE( v0, v1 ) \
1338 grDrawLine( VERT(v0), VERT(v1) )
1339
1340 #define RENDER_TRI( v0, v1, v2 ) \
1341 grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
1342
1343 #define RENDER_QUAD( v0, v1, v2, v3 ) \
1344 do { \
1345 GrVertex *_v_[4]; \
1346 _v_[0] = VERT(v3);\
1347 _v_[1] = VERT(v0);\
1348 _v_[2] = VERT(v1);\
1349 _v_[3] = VERT(v2);\
1350 grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
1351 /*grDrawTriangle( VERT(v0), VERT(v1), VERT(v3) );*/\
1352 /*grDrawTriangle( VERT(v1), VERT(v2), VERT(v3) );*/\
1353 } while (0)
1354
1355 #define INIT(x) fxRenderPrimitive( ctx, x )
1356
1357 #undef LOCAL_VARS
1358 #define LOCAL_VARS \
1359 fxMesaContext fxMesa = FX_CONTEXT(ctx); \
1360 GrVertex *vertptr = fxMesa->verts; \
1361 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
1362 (void) elt;
1363
1364 #define RESET_STIPPLE
1365 #define RESET_OCCLUSION
1366 #define PRESERVE_VB_DEFS
1367
1368 /* Elts, no clipping.
1369 */
1370 #undef ELT
1371 #undef TAG
1372 #define TAG(x) fx_##x##_elts
1373 #define ELT(x) elt[x]
1374 #include "tnl_dd/t_dd_rendertmp.h"
1375
1376 /* Verts, no clipping.
1377 */
1378 #undef ELT
1379 #undef TAG
1380 #define TAG(x) fx_##x##_verts
1381 #define ELT(x) x
1382 /*#include "tnl_dd/t_dd_rendertmp.h"*/ /* we have fx_render_vb_* now */
1383
1384
1385
1386 /**********************************************************************/
1387 /* Render clipped primitives */
1388 /**********************************************************************/
1389
1390
1391
1392 static void fxRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
1393 GLuint n )
1394 {
1395 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1396 TNLcontext *tnl = TNL_CONTEXT(ctx);
1397 struct vertex_buffer *VB = &tnl->vb;
1398 GLuint prim = fxMesa->render_primitive;
1399
1400 /* Render the new vertices as an unclipped polygon.
1401 */
1402 {
1403 GLuint *tmp = VB->Elts;
1404 VB->Elts = (GLuint *)elts;
1405 tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n,
1406 PRIM_BEGIN|PRIM_END );
1407 VB->Elts = tmp;
1408 }
1409
1410 /* Restore the render primitive
1411 */
1412 if (prim != GL_POLYGON)
1413 tnl->Driver.Render.PrimitiveNotify( ctx, prim );
1414 }
1415
1416
1417 static void fxFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
1418 GLuint n )
1419 {
1420 int i;
1421 fxMesaContext fxMesa = FX_CONTEXT( ctx );
1422 GrVertex *vertptr = fxMesa->verts;
1423 if (n == 3) {
1424 grDrawTriangle( VERT(elts[0]), VERT(elts[1]), VERT(elts[2]) );
1425 } else if (n <= 32) {
1426 GrVertex *newvptr[32];
1427 for (i = 0 ; i < n ; i++) {
1428 newvptr[i] = VERT(elts[i]);
1429 }
1430 grDrawVertexArray(GR_TRIANGLE_FAN, n, newvptr);
1431 } else {
1432 const GrVertex *start = VERT(elts[0]);
1433 for (i = 2 ; i < n ; i++) {
1434 grDrawTriangle( start, VERT(elts[i-1]), VERT(elts[i]) );
1435 }
1436 }
1437 }
1438
1439 /**********************************************************************/
1440 /* Choose render functions */
1441 /**********************************************************************/
1442
1443
1444 #define POINT_FALLBACK (DD_POINT_SMOOTH)
1445 #define LINE_FALLBACK (DD_LINE_STIPPLE)
1446 #define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_STIPPLE)
1447 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK | LINE_FALLBACK | TRI_FALLBACK)
1448 #define ANY_RASTER_FLAGS (DD_FLATSHADE | DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET \
1449 | DD_TRI_UNFILLED | DD_TRI_TWOSTENCIL)
1450
1451
1452
1453 void fxDDChooseRenderState(GLcontext *ctx)
1454 {
1455 TNLcontext *tnl = TNL_CONTEXT(ctx);
1456 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1457 GLuint flags = ctx->_TriangleCaps;
1458 GLuint index = 0;
1459
1460 if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) {
1461 if (flags & ANY_RASTER_FLAGS) {
1462 if (flags & DD_TRI_TWOSTENCIL) index |= FX_TWOSTENCIL_BIT;
1463 if (flags & DD_TRI_LIGHT_TWOSIDE) index |= FX_TWOSIDE_BIT;
1464 if (flags & DD_TRI_OFFSET) index |= FX_OFFSET_BIT;
1465 if (flags & DD_TRI_UNFILLED) index |= FX_UNFILLED_BIT;
1466 if (flags & DD_FLATSHADE) index |= FX_FLAT_BIT;
1467 }
1468
1469 fxMesa->draw_point = fx_draw_point;
1470 fxMesa->draw_line = fx_draw_line;
1471 fxMesa->draw_tri = fx_draw_triangle;
1472
1473 /* Hook in fallbacks for specific primitives. */
1474 if (flags & (POINT_FALLBACK|
1475 LINE_FALLBACK|
1476 TRI_FALLBACK))
1477 {
1478 if (fxMesa->verbose) {
1479 fprintf(stderr, "Voodoo ! fallback (%x), raster (%x)\n",
1480 flags & ANY_FALLBACK_FLAGS, flags & ANY_RASTER_FLAGS);
1481 }
1482
1483 if (flags & POINT_FALLBACK)
1484 fxMesa->draw_point = fx_fallback_point;
1485
1486 if (flags & LINE_FALLBACK)
1487 fxMesa->draw_line = fx_fallback_line;
1488
1489 if (flags & TRI_FALLBACK)
1490 fxMesa->draw_tri = fx_fallback_tri;
1491
1492 index |= FX_FALLBACK_BIT;
1493 }
1494 }
1495
1496 tnl->Driver.Render.Points = rast_tab[index].points;
1497 tnl->Driver.Render.Line = rast_tab[index].line;
1498 tnl->Driver.Render.ClippedLine = rast_tab[index].line;
1499 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
1500 tnl->Driver.Render.Quad = rast_tab[index].quad;
1501
1502 if (index == 0) {
1503 tnl->Driver.Render.PrimTabVerts = fx_render_tab_verts;
1504 tnl->Driver.Render.PrimTabElts = fx_render_tab_elts;
1505 tnl->Driver.Render.ClippedPolygon = fxFastRenderClippedPoly;
1506 } else {
1507 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
1508 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
1509 tnl->Driver.Render.ClippedPolygon = fxRenderClippedPoly;
1510 }
1511
1512 fxMesa->render_index = index;
1513
1514 /* [dBorca] Hack alert: more a trick than a real plug-in!!! */
1515 if (flags & (DD_POINT_SIZE | DD_POINT_ATTEN)) {
1516 /* We need to set the point primitive to go through "rast_tab",
1517 * to make sure "POINT" calls "fxMesa->draw_point" instead of
1518 * "grDrawPoint". We can achieve this by using FX_FALLBACK_BIT
1519 * (not really a total rasterization fallback, so we don't alter
1520 * "fxMesa->render_index"). If we get here with DD_POINT_SMOOTH,
1521 * we're done, cos we've already set _tnl_render_tab_{verts|elts}
1522 * above. Otherwise, the T&L engine can optimize point rendering
1523 * by using fx_render_tab_{verts|elts} hence the extra work.
1524 */
1525 if (flags & DD_POINT_SMOOTH) {
1526 fxMesa->draw_point = fx_draw_point_wide_aa;
1527 } else {
1528 fxMesa->draw_point = fx_draw_point_wide;
1529 fx_render_tab_verts[0] = fx_render_pw_verts;
1530 fx_render_tab_elts[0] = fx_render_pw_elts;
1531 }
1532 tnl->Driver.Render.Points = rast_tab[index|FX_FALLBACK_BIT].points;
1533 } else {
1534 fx_render_tab_verts[0] = fx_render_vb_points;
1535 fx_render_tab_elts[0] = fx_render_points_elts;
1536 }
1537 }
1538
1539
1540 /**********************************************************************/
1541 /* Runtime render state and callbacks */
1542 /**********************************************************************/
1543
1544 static void fxRunPipeline( GLcontext *ctx )
1545 {
1546 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1547 GLuint new_gl_state = fxMesa->new_gl_state;
1548
1549 if (TDFX_DEBUG & VERBOSE_PIPELINE) {
1550 fprintf(stderr, "fxRunPipeline()\n");
1551 }
1552
1553 #if 0
1554 /* Recalculate fog table on projection matrix changes. This used to
1555 * be triggered by the NearFar callback.
1556 */
1557 if (new_gl_state & _NEW_PROJECTION)
1558 fxMesa->new_state |= FX_NEW_FOG;
1559 #endif
1560
1561 if (new_gl_state & _FX_NEW_IS_IN_HARDWARE)
1562 fxCheckIsInHardware(ctx);
1563
1564 if (fxMesa->new_state)
1565 fxSetupFXUnits(ctx);
1566
1567 if (!fxMesa->fallback) {
1568 if (new_gl_state & _FX_NEW_RENDERSTATE)
1569 fxDDChooseRenderState(ctx);
1570
1571 if (new_gl_state & _FX_NEW_SETUP_FUNCTION)
1572 fxChooseVertexState(ctx);
1573 }
1574
1575 if (new_gl_state & _NEW_TEXTURE) {
1576 struct gl_texture_unit *t0 = &ctx->Texture.Unit[fxMesa->tmu_source[0]];
1577 struct gl_texture_unit *t1 = &ctx->Texture.Unit[fxMesa->tmu_source[1]];
1578
1579 if (t0->_Current && FX_TEXTURE_DATA(t0)) {
1580 fxMesa->s0scale = FX_TEXTURE_DATA(t0)->sScale;
1581 fxMesa->t0scale = FX_TEXTURE_DATA(t0)->tScale;
1582 fxMesa->inv_s0scale = 1.0F / fxMesa->s0scale;
1583 fxMesa->inv_t0scale = 1.0F / fxMesa->t0scale;
1584 }
1585
1586 if (t1->_Current && FX_TEXTURE_DATA(t1)) {
1587 fxMesa->s1scale = FX_TEXTURE_DATA(t1)->sScale;
1588 fxMesa->t1scale = FX_TEXTURE_DATA(t1)->tScale;
1589 fxMesa->inv_s1scale = 1.0F / fxMesa->s1scale;
1590 fxMesa->inv_t1scale = 1.0F / fxMesa->t1scale;
1591 }
1592 }
1593
1594 fxMesa->new_gl_state = 0;
1595
1596 _tnl_run_pipeline( ctx );
1597 }
1598
1599
1600
1601 /* Always called between RenderStart and RenderFinish --> We already
1602 * hold the lock.
1603 */
1604 static void fxRasterPrimitive( GLcontext *ctx, GLenum prim )
1605 {
1606 fxMesaContext fxMesa = FX_CONTEXT( ctx );
1607
1608 fxMesa->raster_primitive = prim;
1609
1610 fxSetupCull(ctx);
1611 }
1612
1613
1614
1615 /* Determine the rasterized primitive when not drawing unfilled
1616 * polygons.
1617 */
1618 static void fxRenderPrimitive( GLcontext *ctx, GLenum prim )
1619 {
1620 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1621 GLuint rprim = reduced_prim[prim];
1622
1623 fxMesa->render_primitive = prim;
1624
1625 if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
1626 return;
1627
1628 if (fxMesa->raster_primitive != rprim) {
1629 fxRasterPrimitive( ctx, rprim );
1630 }
1631 }
1632
1633 static void fxRenderFinish( GLcontext *ctx )
1634 {
1635 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1636
1637 if (fxMesa->render_index & FX_FALLBACK_BIT)
1638 _swrast_flush( ctx );
1639 }
1640
1641
1642
1643 /**********************************************************************/
1644 /* Manage total rasterization fallbacks */
1645 /**********************************************************************/
1646
1647 static char *fallbackStrings[] = {
1648 "3D/Rect/Cube Texture map",
1649 "glDrawBuffer(GL_FRONT_AND_BACK)",
1650 "Separate specular color",
1651 "glEnable/Disable(GL_STENCIL_TEST)",
1652 "glRenderMode(selection or feedback)",
1653 "glLogicOp()",
1654 "Texture env mode",
1655 "Texture border",
1656 "glColorMask",
1657 "blend mode",
1658 "multitex"
1659 };
1660
1661
1662 static char *getFallbackString(GLuint bit)
1663 {
1664 int i = 0;
1665 while (bit > 1) {
1666 i++;
1667 bit >>= 1;
1668 }
1669 return fallbackStrings[i];
1670 }
1671
1672
1673 void fxCheckIsInHardware( GLcontext *ctx )
1674 {
1675 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1676 TNLcontext *tnl = TNL_CONTEXT(ctx);
1677 GLuint oldfallback = fxMesa->fallback;
1678 GLuint newfallback = fxMesa->fallback = fx_check_IsInHardware( ctx );
1679
1680 if (newfallback) {
1681 if (oldfallback == 0) {
1682 if (fxMesa->verbose) {
1683 fprintf(stderr, "Voodoo ! enter SW 0x%08x %s\n", newfallback, getFallbackString(newfallback));
1684 }
1685 _swsetup_Wakeup( ctx );
1686 }
1687 }
1688 else {
1689 if (oldfallback) {
1690 _swrast_flush( ctx );
1691 tnl->Driver.Render.Start = fxCheckTexSizes;
1692 tnl->Driver.Render.Finish = fxRenderFinish;
1693 tnl->Driver.Render.PrimitiveNotify = fxRenderPrimitive;
1694 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
1695 tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
1696 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
1697 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
1698 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
1699 tnl->Driver.Render.BuildVertices = fxBuildVertices;
1700 fxChooseVertexState(ctx);
1701 fxDDChooseRenderState(ctx);
1702 if (fxMesa->verbose) {
1703 fprintf(stderr, "Voodoo ! leave SW 0x%08x %s\n", oldfallback, getFallbackString(oldfallback));
1704 }
1705 }
1706 tnl->Driver.Render.Multipass = NULL;
1707 if (HAVE_SPEC && NEED_SECONDARY_COLOR(ctx)) {
1708 tnl->Driver.Render.Multipass = fxMultipass_ColorSum;
1709 /* obey stencil, but do not change it */
1710 fxMesa->multipass = GL_TRUE;
1711 if (fxMesa->unitsState.stencilEnabled) {
1712 fxMesa->new_state |= FX_NEW_STENCIL;
1713 }
1714 }
1715 }
1716 }
1717
1718 void fxDDInitTriFuncs( GLcontext *ctx )
1719 {
1720 TNLcontext *tnl = TNL_CONTEXT(ctx);
1721 static int firsttime = 1;
1722
1723 if (firsttime) {
1724 init_rast_tab();
1725 firsttime = 0;
1726 }
1727
1728 tnl->Driver.RunPipeline = fxRunPipeline;
1729 tnl->Driver.Render.Start = fxCheckTexSizes;
1730 tnl->Driver.Render.Finish = fxRenderFinish;
1731 tnl->Driver.Render.PrimitiveNotify = fxRenderPrimitive;
1732 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
1733 tnl->Driver.Render.ClippedLine = _tnl_RenderClippedLine;
1734 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
1735 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
1736 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
1737 tnl->Driver.Render.BuildVertices = fxBuildVertices;
1738 tnl->Driver.Render.Multipass = NULL;
1739
1740 (void) fx_print_vertex;
1741 }
1742
1743
1744 /* [dBorca] Hack alert:
1745 * doesn't work with blending.
1746 */
1747 static GLboolean
1748 fxMultipass_ColorSum (GLcontext *ctx, GLuint pass)
1749 {
1750 fxMesaContext fxMesa = FX_CONTEXT(ctx);
1751 tfxUnitsState *us = &fxMesa->unitsState;
1752
1753 static int t0 = 0;
1754 static int t1 = 0;
1755
1756 switch (pass) {
1757 case 1: /* first pass: the TEXTURED triangles are drawn */
1758 /* set stencil's real values */
1759 fxMesa->multipass = GL_FALSE;
1760 if (us->stencilEnabled) {
1761 fxSetupStencil(ctx);
1762 }
1763 /* save per-pass data */
1764 fxMesa->restoreUnitsState = *us;
1765 /* turn off texturing */
1766 t0 = ctx->Texture.Unit[0]._ReallyEnabled;
1767 t1 = ctx->Texture.Unit[1]._ReallyEnabled;
1768 ctx->Texture.Unit[0]._ReallyEnabled = 0;
1769 ctx->Texture.Unit[1]._ReallyEnabled = 0;
1770 /* SUM the colors */
1771 fxDDBlendEquationSeparate(ctx, GL_FUNC_ADD, GL_FUNC_ADD);
1772 fxDDBlendFuncSeparate(ctx, GL_ONE, GL_ONE, GL_ZERO, GL_ONE);
1773 fxDDEnable(ctx, GL_BLEND, GL_TRUE);
1774 /* make sure we draw only where we want to */
1775 if (us->depthTestEnabled) {
1776 switch (us->depthTestFunc) {
1777 default:
1778 fxDDDepthFunc(ctx, GL_EQUAL);
1779 case GL_NEVER:
1780 case GL_ALWAYS:
1781 ;
1782 }
1783 fxDDDepthMask(ctx, GL_FALSE);
1784 }
1785 /* switch to secondary colors */
1786 #if FX_PACKEDCOLOR
1787 grVertexLayout(GR_PARAM_PARGB, GR_VERTEX_PSPEC_OFFSET << 2, GR_PARAM_ENABLE);
1788 #else /* !FX_PACKEDCOLOR */
1789 grVertexLayout(GR_PARAM_RGB, GR_VERTEX_SPEC_OFFSET << 2, GR_PARAM_ENABLE);
1790 #endif /* !FX_PACKEDCOLOR */
1791 /* don't advertise new state */
1792 fxMesa->new_state = 0;
1793 break;
1794 case 2: /* 2nd pass (last): the secondary color is summed over texture */
1795 /* restore original state */
1796 *us = fxMesa->restoreUnitsState;
1797 /* restore texturing */
1798 ctx->Texture.Unit[0]._ReallyEnabled = t0;
1799 ctx->Texture.Unit[1]._ReallyEnabled = t1;
1800 /* revert to primary colors */
1801 #if FX_PACKEDCOLOR
1802 grVertexLayout(GR_PARAM_PARGB, GR_VERTEX_PARGB_OFFSET << 2, GR_PARAM_ENABLE);
1803 #else /* !FX_PACKEDCOLOR */
1804 grVertexLayout(GR_PARAM_RGB, GR_VERTEX_RGB_OFFSET << 2, GR_PARAM_ENABLE);
1805 #endif /* !FX_PACKEDCOLOR */
1806 break;
1807 default:
1808 assert(0); /* NOTREACHED */
1809 }
1810
1811 /* update HW state */
1812 fxSetupBlend(ctx);
1813 fxSetupDepthTest(ctx);
1814 fxSetupTexture(ctx);
1815
1816 return (pass == 1);
1817 }
1818
1819
1820 #else
1821
1822
1823 /*
1824 * Need this to provide at least one external definition.
1825 */
1826
1827 extern int gl_fx_dummy_function_tris(void);
1828 int
1829 gl_fx_dummy_function_tris(void)
1830 {
1831 return 0;
1832 }
1833
1834 #endif /* FX */