Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / tdfx / tdfx_tris.c
1 /* -*- mode: c; c-basic-offset: 3 -*-
2  *
3  * Copyright 2000 VA Linux Systems Inc., Fremont, California.
4  *
5  * 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 (including the next
15  * paragraph) shall be included in all copies or substantial portions of the
16  * Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
21  * VA LINUX SYSTEMS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26
27 /* New fixes:
28  *      Daniel Borca <dborca@users.sourceforge.net>, 19 Jul 2004
29  *
30  * Authors:
31  *    Keith Whitwell <keith@tungstengraphics.com>
32  */
33
34 #include "main/glheader.h"
35 #include "main/mtypes.h"
36 #include "main/macros.h"
37 #include "main/colormac.h"
38
39 #include "swrast/swrast.h"
40 #include "swrast_setup/swrast_setup.h"
41 #include "swrast_setup/ss_context.h"
42 #include "tnl/t_context.h"
43 #include "tnl/t_pipeline.h"
44
45 #include "tdfx_tris.h"
46 #include "tdfx_state.h"
47 #include "tdfx_vb.h"
48 #include "tdfx_lock.h"
49 #include "tdfx_render.h"
50
51
52 static void tdfxRasterPrimitive( struct gl_context *ctx, GLenum prim );
53 static void tdfxRenderPrimitive( struct gl_context *ctx, GLenum prim );
54
55 static GLenum reduced_prim[GL_POLYGON+1] = {
56    GL_POINTS,
57    GL_LINES,
58    GL_LINES,
59    GL_LINES,
60    GL_TRIANGLES,
61    GL_TRIANGLES,
62    GL_TRIANGLES,
63    GL_TRIANGLES,
64    GL_TRIANGLES,
65    GL_TRIANGLES
66 };
67
68 /***********************************************************************
69  *          Macros for t_dd_tritmp.h to draw basic primitives          *
70  ***********************************************************************/
71
72 #define TRI( a, b, c )                          \
73 do {                                            \
74    if (DO_FALLBACK)                             \
75       fxMesa->draw_triangle( fxMesa, a, b, c ); \
76    else                                         \
77       fxMesa->Glide.grDrawTriangle( a, b, c );  \
78 } while (0)                                     \
79
80 #define QUAD( a, b, c, d )                      \
81 do {                                            \
82    if (DO_FALLBACK) {                           \
83       fxMesa->draw_triangle( fxMesa, a, b, d ); \
84       fxMesa->draw_triangle( fxMesa, b, c, d ); \
85    } else {                                     \
86       tdfxVertex *_v_[4];                       \
87       _v_[0] = d;                               \
88       _v_[1] = a;                               \
89       _v_[2] = b;                               \
90       _v_[3] = c;                               \
91       fxMesa->Glide.grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
92       /*fxMesa->Glide.grDrawTriangle( a, b, d );*/\
93       /*fxMesa->Glide.grDrawTriangle( b, c, d );*/\
94    }                                            \
95 } while (0)
96
97 #define LINE( v0, v1 )                          \
98 do {                                            \
99    if (DO_FALLBACK)                             \
100       fxMesa->draw_line( fxMesa, v0, v1 );      \
101    else {                                       \
102       v0->x += LINE_X_OFFSET - TRI_X_OFFSET;    \
103       v0->y += LINE_Y_OFFSET - TRI_Y_OFFSET;    \
104       v1->x += LINE_X_OFFSET - TRI_X_OFFSET;    \
105       v1->y += LINE_Y_OFFSET - TRI_Y_OFFSET;    \
106       fxMesa->Glide.grDrawLine( v0, v1 );       \
107       v0->x -= LINE_X_OFFSET - TRI_X_OFFSET;    \
108       v0->y -= LINE_Y_OFFSET - TRI_Y_OFFSET;    \
109       v1->x -= LINE_X_OFFSET - TRI_X_OFFSET;    \
110       v1->y -= LINE_Y_OFFSET - TRI_Y_OFFSET;    \
111    }                                            \
112 } while (0)
113
114 #define POINT( v0 )                             \
115 do {                                            \
116    if (DO_FALLBACK)                             \
117       fxMesa->draw_point( fxMesa, v0 );         \
118    else {                                       \
119       v0->x += PNT_X_OFFSET - TRI_X_OFFSET;     \
120       v0->y += PNT_Y_OFFSET - TRI_Y_OFFSET;     \
121       fxMesa->Glide.grDrawPoint( v0 );          \
122       v0->x -= PNT_X_OFFSET - TRI_X_OFFSET;     \
123       v0->y -= PNT_Y_OFFSET - TRI_Y_OFFSET;     \
124    }                                            \
125 } while (0)
126
127
128 /***********************************************************************
129  *              Fallback to swrast for basic primitives                *
130  ***********************************************************************/
131
132 /* Build an SWvertex from a hardware vertex. 
133  *
134  * This code is hit only when a mix of accelerated and unaccelerated
135  * primitives are being drawn, and only for the unaccelerated
136  * primitives.  
137  */
138 static void 
139 tdfx_translate_vertex( struct gl_context *ctx, const tdfxVertex *src, SWvertex *dst)
140 {
141    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
142
143    if (fxMesa->vertexFormat == TDFX_LAYOUT_TINY) {
144       dst->attrib[FRAG_ATTRIB_WPOS][0] = src->x - fxMesa->x_offset;
145       dst->attrib[FRAG_ATTRIB_WPOS][1] = src->y - (fxMesa->screen_height - fxMesa->height - fxMesa->y_offset);
146       dst->attrib[FRAG_ATTRIB_WPOS][2] = src->z;
147       dst->attrib[FRAG_ATTRIB_WPOS][3] = 1.0;
148
149       dst->color[0] = src->color[2];
150       dst->color[1] = src->color[1];
151       dst->color[2] = src->color[0];
152       dst->color[3] = src->color[3];
153    } 
154    else {
155       GLfloat w = 1.0 / src->rhw;
156
157       dst->attrib[FRAG_ATTRIB_WPOS][0] = src->x - fxMesa->x_offset;
158       dst->attrib[FRAG_ATTRIB_WPOS][1] = src->y - (fxMesa->screen_height - fxMesa->height - fxMesa->y_offset);
159       dst->attrib[FRAG_ATTRIB_WPOS][2] = src->z;
160       dst->attrib[FRAG_ATTRIB_WPOS][3] = src->rhw;
161
162       dst->color[0] = src->color[2];
163       dst->color[1] = src->color[1];
164       dst->color[2] = src->color[0];
165       dst->color[3] = src->color[3];
166
167       dst->attrib[FRAG_ATTRIB_TEX0][0] = 1.0 / fxMesa->sScale0 * w * src->tu0;
168       dst->attrib[FRAG_ATTRIB_TEX0][1] = 1.0 / fxMesa->tScale0 * w * src->tv0;
169       if (fxMesa->vertexFormat == TDFX_LAYOUT_PROJ1 || fxMesa->vertexFormat == TDFX_LAYOUT_PROJ2) {
170          dst->attrib[FRAG_ATTRIB_TEX0][3] = w * src->tq0;
171       } else {
172          dst->attrib[FRAG_ATTRIB_TEX0][3] = 1.0;
173       }
174
175       if (fxMesa->SetupIndex & TDFX_TEX1_BIT) {
176          dst->attrib[FRAG_ATTRIB_TEX1][0] = 1.0 / fxMesa->sScale1 * w * src->tu1;
177          dst->attrib[FRAG_ATTRIB_TEX1][1] = 1.0 / fxMesa->tScale1 * w * src->tv1;
178          if (fxMesa->vertexFormat == TDFX_LAYOUT_PROJ2) {
179             dst->attrib[FRAG_ATTRIB_TEX1][3] = w * src->tq1;
180          } else {
181             dst->attrib[FRAG_ATTRIB_TEX1][3] = 1.0;
182          }
183       }
184    }
185
186    dst->pointSize = ctx->Point.Size;
187 }
188
189
190 static void 
191 tdfx_fallback_tri( tdfxContextPtr fxMesa, 
192                    tdfxVertex *v0, 
193                    tdfxVertex *v1, 
194                    tdfxVertex *v2 )
195 {
196    struct gl_context *ctx = fxMesa->glCtx;
197    SWvertex v[3];
198    tdfx_translate_vertex( ctx, v0, &v[0] );
199    tdfx_translate_vertex( ctx, v1, &v[1] );
200    tdfx_translate_vertex( ctx, v2, &v[2] );
201    _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
202 }
203
204
205 static void 
206 tdfx_fallback_line( tdfxContextPtr fxMesa,
207                     tdfxVertex *v0,
208                     tdfxVertex *v1 )
209 {
210    struct gl_context *ctx = fxMesa->glCtx;
211    SWvertex v[2];
212    tdfx_translate_vertex( ctx, v0, &v[0] );
213    tdfx_translate_vertex( ctx, v1, &v[1] );
214    _swrast_Line( ctx, &v[0], &v[1] );
215 }
216
217
218 static void 
219 tdfx_fallback_point( tdfxContextPtr fxMesa, 
220                      tdfxVertex *v0 )
221 {
222    struct gl_context *ctx = fxMesa->glCtx;
223    SWvertex v[1];
224    tdfx_translate_vertex( ctx, v0, &v[0] );
225    _swrast_Point( ctx, &v[0] );
226 }
227
228 /***********************************************************************
229  *                 Functions to draw basic primitives                  *
230  ***********************************************************************/
231
232 static void tdfx_print_vertex( struct gl_context *ctx, const tdfxVertex *v )
233 {
234    tdfxContextPtr tmesa = TDFX_CONTEXT( ctx );
235
236    fprintf(stderr, "vertex at %p\n", (void *)v);
237
238    if (tmesa->vertexFormat == TDFX_LAYOUT_TINY) {
239       fprintf(stderr, "x %f y %f z %f\n", v->x, v->y, v->z);
240    } 
241    else {
242       fprintf(stderr, "x %f y %f z %f oow %f\n", 
243               v->x, v->y, v->z, v->rhw);
244    }
245    fprintf(stderr, "r %d g %d b %d a %d\n", 
246               v->color[0],
247               v->color[1],
248               v->color[2],
249               v->color[3]);
250    
251    fprintf(stderr, "\n");
252 }
253
254 #define DO_FALLBACK 0
255
256 /* Need to do clip loop at each triangle when mixing swrast and hw
257  * rendering.  These functions are only used when mixed-mode rendering
258  * is occurring.
259  */
260 static void tdfx_draw_triangle( tdfxContextPtr fxMesa,
261                                 tdfxVertexPtr v0,
262                                 tdfxVertexPtr v1,
263                                 tdfxVertexPtr v2 )
264 {
265 /*     fprintf(stderr, "%s\n", __FUNCTION__); */
266 /*     tdfx_print_vertex( fxMesa->glCtx, v0 ); */
267 /*     tdfx_print_vertex( fxMesa->glCtx, v1 ); */
268 /*     tdfx_print_vertex( fxMesa->glCtx, v2 ); */
269    BEGIN_CLIP_LOOP_LOCKED(fxMesa) {
270       TRI( v0, v1, v2 );
271    } END_CLIP_LOOP_LOCKED(fxMesa);
272 }
273
274 static void tdfx_draw_line( tdfxContextPtr fxMesa,
275                             tdfxVertexPtr v0,
276                             tdfxVertexPtr v1 )
277 {
278    /* No support for wide lines (avoid wide/aa line fallback).
279     */
280    BEGIN_CLIP_LOOP_LOCKED(fxMesa) {
281       LINE(v0, v1);
282    } END_CLIP_LOOP_LOCKED(fxMesa);
283 }
284
285 static void tdfx_draw_point( tdfxContextPtr fxMesa,
286                              tdfxVertexPtr v0 )
287 {
288    /* No support for wide points.
289     */
290    BEGIN_CLIP_LOOP_LOCKED(fxMesa) {
291       POINT( v0 );
292    } END_CLIP_LOOP_LOCKED(fxMesa);
293 }
294
295 #undef DO_FALLBACK
296
297
298 #define TDFX_UNFILLED_BIT    0x1
299 #define TDFX_OFFSET_BIT      0x2
300 #define TDFX_TWOSIDE_BIT     0x4
301 #define TDFX_FLAT_BIT        0x8
302 #define TDFX_FALLBACK_BIT    0x10
303 #define TDFX_MAX_TRIFUNC     0x20
304
305 static struct {
306    tnl_points_func              points;
307    tnl_line_func                line;
308    tnl_triangle_func    triangle;
309    tnl_quad_func                quad;
310 } rast_tab[TDFX_MAX_TRIFUNC];
311
312 #define DO_FALLBACK (IND & TDFX_FALLBACK_BIT)
313 #define DO_OFFSET   (IND & TDFX_OFFSET_BIT)
314 #define DO_UNFILLED (IND & TDFX_UNFILLED_BIT)
315 #define DO_TWOSIDE  (IND & TDFX_TWOSIDE_BIT)
316 #define DO_FLAT     (IND & TDFX_FLAT_BIT)
317 #define DO_TRI       1
318 #define DO_QUAD      1
319 #define DO_LINE      1
320 #define DO_POINTS    1
321 #define DO_FULL_QUAD 1
322
323 #define HAVE_SPEC   0
324 #define HAVE_HW_FLATSHADE 0
325 #define HAVE_BACK_COLORS  0
326 #define VERTEX tdfxVertex
327 #define TAB rast_tab
328
329 #define DEPTH_SCALE 1.0
330 #define UNFILLED_TRI unfilled_tri
331 #define UNFILLED_QUAD unfilled_quad
332 #define VERT_X(_v) _v->x
333 #define VERT_Y(_v) _v->y
334 #define VERT_Z(_v) _v->z
335 #define AREA_IS_CCW( a ) (a < 0)
336 #define GET_VERTEX(e) (fxMesa->verts + (e))
337
338 #define VERT_SET_RGBA( dst, f )                 \
339 do {                                            \
340    UNCLAMPED_FLOAT_TO_UBYTE(dst->color[2], f[0]);\
341    UNCLAMPED_FLOAT_TO_UBYTE(dst->color[1], f[1]);\
342    UNCLAMPED_FLOAT_TO_UBYTE(dst->color[0], f[2]);\
343    UNCLAMPED_FLOAT_TO_UBYTE(dst->color[3], f[3]);\
344 } while (0)
345
346 #define VERT_COPY_RGBA( v0, v1 )                \
347    *(GLuint *)&v0->color = *(GLuint *)&v1->color
348
349 #define VERT_SAVE_RGBA( idx )                   \
350    *(GLuint *)&color[idx] = *(GLuint *)&v[idx]->color
351
352 #define VERT_RESTORE_RGBA( idx )                \
353    *(GLuint *)&v[idx]->color = *(GLuint *)&color[idx]
354
355 #define LOCAL_VARS(n)                                   \
356    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);           \
357    GLubyte color[n][4];                                 \
358    (void) color;
359
360
361
362 /***********************************************************************
363  *            Functions to draw basic unfilled primitives              *
364  ***********************************************************************/
365
366 #define RASTERIZE(x) if (fxMesa->raster_primitive != reduced_prim[x]) \
367                         tdfxRasterPrimitive( ctx, reduced_prim[x] )
368 #define RENDER_PRIMITIVE fxMesa->render_primitive
369 #define IND TDFX_FALLBACK_BIT
370 #define TAG(x) x
371 #include "tnl_dd/t_dd_unfilled.h"
372 #undef IND
373
374 /***********************************************************************
375  *                 Functions to draw GL primitives                     *
376  ***********************************************************************/
377
378 #define IND (0)
379 #define TAG(x) x
380 #include "tnl_dd/t_dd_tritmp.h"
381
382 #define IND (TDFX_OFFSET_BIT)
383 #define TAG(x) x##_offset
384 #include "tnl_dd/t_dd_tritmp.h"
385
386 #define IND (TDFX_TWOSIDE_BIT)
387 #define TAG(x) x##_twoside
388 #include "tnl_dd/t_dd_tritmp.h"
389
390 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT)
391 #define TAG(x) x##_twoside_offset
392 #include "tnl_dd/t_dd_tritmp.h"
393
394 #define IND (TDFX_UNFILLED_BIT)
395 #define TAG(x) x##_unfilled
396 #include "tnl_dd/t_dd_tritmp.h"
397
398 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT)
399 #define TAG(x) x##_offset_unfilled
400 #include "tnl_dd/t_dd_tritmp.h"
401
402 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT)
403 #define TAG(x) x##_twoside_unfilled
404 #include "tnl_dd/t_dd_tritmp.h"
405
406 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT)
407 #define TAG(x) x##_twoside_offset_unfilled
408 #include "tnl_dd/t_dd_tritmp.h"
409
410 #define IND (TDFX_FALLBACK_BIT)
411 #define TAG(x) x##_fallback
412 #include "tnl_dd/t_dd_tritmp.h"
413
414 #define IND (TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT)
415 #define TAG(x) x##_offset_fallback
416 #include "tnl_dd/t_dd_tritmp.h"
417
418 #define IND (TDFX_TWOSIDE_BIT|TDFX_FALLBACK_BIT)
419 #define TAG(x) x##_twoside_fallback
420 #include "tnl_dd/t_dd_tritmp.h"
421
422 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT)
423 #define TAG(x) x##_twoside_offset_fallback
424 #include "tnl_dd/t_dd_tritmp.h"
425
426 #define IND (TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT)
427 #define TAG(x) x##_unfilled_fallback
428 #include "tnl_dd/t_dd_tritmp.h"
429
430 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT)
431 #define TAG(x) x##_offset_unfilled_fallback
432 #include "tnl_dd/t_dd_tritmp.h"
433
434 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT)
435 #define TAG(x) x##_twoside_unfilled_fallback
436 #include "tnl_dd/t_dd_tritmp.h"
437
438 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT| \
439              TDFX_FALLBACK_BIT)
440 #define TAG(x) x##_twoside_offset_unfilled_fallback
441 #include "tnl_dd/t_dd_tritmp.h"
442
443
444 /* Tdfx doesn't support provoking-vertex flat-shading?
445  */
446 #define IND (TDFX_FLAT_BIT)
447 #define TAG(x) x##_flat
448 #include "tnl_dd/t_dd_tritmp.h"
449
450 #define IND (TDFX_OFFSET_BIT|TDFX_FLAT_BIT)
451 #define TAG(x) x##_offset_flat
452 #include "tnl_dd/t_dd_tritmp.h"
453
454 #define IND (TDFX_TWOSIDE_BIT|TDFX_FLAT_BIT)
455 #define TAG(x) x##_twoside_flat
456 #include "tnl_dd/t_dd_tritmp.h"
457
458 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_FLAT_BIT)
459 #define TAG(x) x##_twoside_offset_flat
460 #include "tnl_dd/t_dd_tritmp.h"
461
462 #define IND (TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
463 #define TAG(x) x##_unfilled_flat
464 #include "tnl_dd/t_dd_tritmp.h"
465
466 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
467 #define TAG(x) x##_offset_unfilled_flat
468 #include "tnl_dd/t_dd_tritmp.h"
469
470 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
471 #define TAG(x) x##_twoside_unfilled_flat
472 #include "tnl_dd/t_dd_tritmp.h"
473
474 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FLAT_BIT)
475 #define TAG(x) x##_twoside_offset_unfilled_flat
476 #include "tnl_dd/t_dd_tritmp.h"
477
478 #define IND (TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
479 #define TAG(x) x##_fallback_flat
480 #include "tnl_dd/t_dd_tritmp.h"
481
482 #define IND (TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
483 #define TAG(x) x##_offset_fallback_flat
484 #include "tnl_dd/t_dd_tritmp.h"
485
486 #define IND (TDFX_TWOSIDE_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
487 #define TAG(x) x##_twoside_fallback_flat
488 #include "tnl_dd/t_dd_tritmp.h"
489
490 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
491 #define TAG(x) x##_twoside_offset_fallback_flat
492 #include "tnl_dd/t_dd_tritmp.h"
493
494 #define IND (TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
495 #define TAG(x) x##_unfilled_fallback_flat
496 #include "tnl_dd/t_dd_tritmp.h"
497
498 #define IND (TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
499 #define TAG(x) x##_offset_unfilled_fallback_flat
500 #include "tnl_dd/t_dd_tritmp.h"
501
502 #define IND (TDFX_TWOSIDE_BIT|TDFX_UNFILLED_BIT|TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
503 #define TAG(x) x##_twoside_unfilled_fallback_flat
504 #include "tnl_dd/t_dd_tritmp.h"
505
506 #define IND (TDFX_TWOSIDE_BIT|TDFX_OFFSET_BIT|TDFX_UNFILLED_BIT| \
507              TDFX_FALLBACK_BIT|TDFX_FLAT_BIT)
508 #define TAG(x) x##_twoside_offset_unfilled_fallback_flat
509 #include "tnl_dd/t_dd_tritmp.h"
510
511
512 static void init_rast_tab( void )
513 {
514    init();
515    init_offset();
516    init_twoside();
517    init_twoside_offset();
518    init_unfilled();
519    init_offset_unfilled();
520    init_twoside_unfilled();
521    init_twoside_offset_unfilled();
522    init_fallback();
523    init_offset_fallback();
524    init_twoside_fallback();
525    init_twoside_offset_fallback();
526    init_unfilled_fallback();
527    init_offset_unfilled_fallback();
528    init_twoside_unfilled_fallback();
529    init_twoside_offset_unfilled_fallback();
530
531    init_flat();
532    init_offset_flat();
533    init_twoside_flat();
534    init_twoside_offset_flat();
535    init_unfilled_flat();
536    init_offset_unfilled_flat();
537    init_twoside_unfilled_flat();
538    init_twoside_offset_unfilled_flat();
539    init_fallback_flat();
540    init_offset_fallback_flat();
541    init_twoside_fallback_flat();
542    init_twoside_offset_fallback_flat();
543    init_unfilled_fallback_flat();
544    init_offset_unfilled_fallback_flat();
545    init_twoside_unfilled_fallback_flat();
546    init_twoside_offset_unfilled_fallback_flat();
547 }
548
549
550 /**********************************************************************/
551 /*                 Render whole begin/end objects                     */
552 /**********************************************************************/
553
554
555 /* Accelerate vertex buffer rendering when renderindex == 0 and
556  * there is no clipping.
557  */
558 #define INIT(x) tdfxRenderPrimitive( ctx, x )
559
560 static void tdfx_render_vb_points( struct gl_context *ctx,
561                                       GLuint start,
562                                       GLuint count,
563                                       GLuint flags )
564 {
565    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
566    tdfxVertex *fxVB = fxMesa->verts;
567    GLint i;
568    (void) flags;
569
570    INIT(GL_POINTS);
571
572    /* Adjust point coords */
573    for (i = start; i < count; i++) {
574       fxVB[i].x += PNT_X_OFFSET - TRI_X_OFFSET;
575       fxVB[i].y += PNT_Y_OFFSET - TRI_Y_OFFSET;
576    }
577
578    fxMesa->Glide.grDrawVertexArrayContiguous( GR_POINTS, count-start,
579                                               fxVB + start, sizeof(tdfxVertex));
580    /* restore point coords */
581    for (i = start; i < count; i++) {
582       fxVB[i].x -= PNT_X_OFFSET - TRI_X_OFFSET;
583       fxVB[i].y -= PNT_Y_OFFSET - TRI_Y_OFFSET;
584    }
585 }
586
587 static void tdfx_render_vb_line_strip( struct gl_context *ctx,
588                                       GLuint start,
589                                       GLuint count,
590                                       GLuint flags )
591 {
592    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
593    tdfxVertex *fxVB = fxMesa->verts;
594    GLint i;
595    (void) flags;
596
597    INIT(GL_LINE_STRIP);
598
599    /* adjust line coords */
600    for (i = start; i < count; i++) {
601       fxVB[i].x += LINE_X_OFFSET - TRI_X_OFFSET;
602       fxVB[i].y += LINE_Y_OFFSET - TRI_Y_OFFSET;
603    }
604
605    fxMesa->Glide.grDrawVertexArrayContiguous( GR_LINE_STRIP, count-start,
606                                               fxVB + start, sizeof(tdfxVertex) );
607
608    /* restore line coords */
609    for (i = start; i < count; i++) {
610       fxVB[i].x -= LINE_X_OFFSET - TRI_X_OFFSET;
611       fxVB[i].y -= LINE_Y_OFFSET - TRI_Y_OFFSET;
612    }
613 }
614
615 static void tdfx_render_vb_line_loop( struct gl_context *ctx,
616                                       GLuint start,
617                                       GLuint count,
618                                       GLuint flags )
619 {
620    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
621    tdfxVertex *fxVB = fxMesa->verts;
622    GLint i;
623    GLint j = start;
624    (void) flags;
625
626    INIT(GL_LINE_LOOP);
627
628    if (!(flags & PRIM_BEGIN)) {
629       j++;
630    }
631
632    /* adjust line coords */
633    for (i = start; i < count; i++) {
634       fxVB[i].x += LINE_X_OFFSET - TRI_X_OFFSET;
635       fxVB[i].y += LINE_Y_OFFSET - TRI_Y_OFFSET;
636    }
637
638    fxMesa->Glide.grDrawVertexArrayContiguous( GR_LINE_STRIP, count-j,
639                                               fxVB + j, sizeof(tdfxVertex));
640
641    if (flags & PRIM_END) 
642       fxMesa->Glide.grDrawLine( fxVB + (count - 1), 
643                                 fxVB + start );
644
645    /* restore line coords */
646    for (i = start; i < count; i++) {
647       fxVB[i].x -= LINE_X_OFFSET - TRI_X_OFFSET;
648       fxVB[i].y -= LINE_Y_OFFSET - TRI_Y_OFFSET;
649    }
650 }
651
652 static void tdfx_render_vb_lines( struct gl_context *ctx,
653                                       GLuint start,
654                                       GLuint count,
655                                       GLuint flags )
656 {
657    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
658    tdfxVertex *fxVB = fxMesa->verts;
659    GLint i;
660    (void) flags;
661
662    INIT(GL_LINES);
663
664    /* adjust line coords */
665    for (i = start; i < count; i++) {
666       fxVB[i].x += LINE_X_OFFSET - TRI_X_OFFSET;
667       fxVB[i].y += LINE_Y_OFFSET - TRI_Y_OFFSET;
668    }
669
670    fxMesa->Glide.grDrawVertexArrayContiguous( GR_LINES, count-start,
671                                               fxVB + start, sizeof(tdfxVertex));
672
673    /* restore line coords */
674    for (i = start; i < count; i++) {
675       fxVB[i].x -= LINE_X_OFFSET - TRI_X_OFFSET;
676       fxVB[i].y -= LINE_Y_OFFSET - TRI_Y_OFFSET;
677    }
678 }
679
680 static void tdfx_render_vb_triangles( struct gl_context *ctx,
681                                       GLuint start,
682                                       GLuint count,
683                                       GLuint flags )
684 {
685    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
686    tdfxVertex *fxVB = fxMesa->verts;
687    (void) flags;
688
689    INIT(GL_TRIANGLES);
690
691 #if 0
692    /* [dBorca]
693     * apparently, this causes troubles with some programs (GLExcess);
694     * might be a bug in Glide... However, "grDrawVertexArrayContiguous"
695     * eventually calls "grDrawTriangle" for GR_TRIANGLES, so we're better
696     * off doing it by hand...
697     */
698    fxMesa->Glide.grDrawVertexArrayContiguous( GR_TRIANGLES, count-start,
699                                               fxVB + start, sizeof(tdfxVertex));
700 #else
701    {
702     GLuint j;
703     for (j=start+2; j<count; j+=3) {
704         fxMesa->Glide.grDrawTriangle(fxVB + (j-2), fxVB + (j-1), fxVB + j);
705     }
706    }
707 #endif
708 }
709
710
711 static void tdfx_render_vb_tri_strip( struct gl_context *ctx,
712                                       GLuint start,
713                                       GLuint count,
714                                       GLuint flags )
715 {
716    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
717    tdfxVertex *fxVB = fxMesa->verts;
718    int mode;
719    (void) flags;
720
721    INIT(GL_TRIANGLE_STRIP);
722
723 /*     fprintf(stderr, "%s/%d\n", __FUNCTION__, 1<<shift); */
724 /*     if(!prevLockLine) abort(); */
725
726    mode = GR_TRIANGLE_STRIP;
727
728    fxMesa->Glide.grDrawVertexArrayContiguous( mode, count-start,
729                                               fxVB + start, sizeof(tdfxVertex));
730 }
731
732
733 static void tdfx_render_vb_tri_fan( struct gl_context *ctx,
734                                     GLuint start,
735                                     GLuint count,
736                                     GLuint flags )
737 {
738    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
739    tdfxVertex *fxVB = fxMesa->verts;
740    (void) flags;
741
742    INIT(GL_TRIANGLE_FAN);
743
744    fxMesa->Glide.grDrawVertexArrayContiguous( GR_TRIANGLE_FAN, count-start,
745                                               fxVB + start, sizeof(tdfxVertex) );
746 }
747
748 static void tdfx_render_vb_quads( struct gl_context *ctx,
749                                        GLuint start,
750                                        GLuint count,
751                                        GLuint flags )
752 {
753    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
754    tdfxVertex *fxVB = fxMesa->verts;
755    GLuint i;
756    (void) flags;
757
758    INIT(GL_QUADS);
759    
760    for (i = start + 3 ; i < count ; i += 4 ) {
761 #define VERT(x) (fxVB + (x))
762       tdfxVertex *_v_[4];
763       _v_[0] = VERT(i);
764       _v_[1] = VERT(i-3);
765       _v_[2] = VERT(i-2);
766       _v_[3] = VERT(i-1);
767       fxMesa->Glide.grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);
768       /*fxMesa->Glide.grDrawTriangle( VERT(i-3), VERT(i-2), VERT(i) );*/
769       /*fxMesa->Glide.grDrawTriangle( VERT(i-2), VERT(i-1), VERT(i) );*/
770 #undef VERT
771    }
772 }
773
774 static void tdfx_render_vb_quad_strip( struct gl_context *ctx,
775                                        GLuint start,
776                                        GLuint count,
777                                        GLuint flags )
778 {
779    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
780    tdfxVertex *fxVB = fxMesa->verts;
781    (void) flags;
782
783    INIT(GL_QUAD_STRIP);
784
785    count -= (count-start)&1;
786
787    fxMesa->Glide.grDrawVertexArrayContiguous( GR_TRIANGLE_STRIP,
788                                               count-start, fxVB + start, sizeof(tdfxVertex));
789 }
790
791 static void tdfx_render_vb_poly( struct gl_context *ctx,
792                                  GLuint start,
793                                  GLuint count,
794                                  GLuint flags )
795 {
796    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
797    tdfxVertex *fxVB = fxMesa->verts;
798    (void) flags;
799
800    INIT(GL_POLYGON);
801    
802    fxMesa->Glide.grDrawVertexArrayContiguous( GR_POLYGON, count-start,
803                                               fxVB + start, sizeof(tdfxVertex));
804 }
805
806 static void tdfx_render_vb_noop( struct gl_context *ctx,
807                                  GLuint start,
808                                  GLuint count,
809                                  GLuint flags )
810 {
811    (void) (ctx && start && count && flags);
812 }
813
814 static void (*tdfx_render_tab_verts[GL_POLYGON+2])(struct gl_context *,
815                                                    GLuint,
816                                                    GLuint,
817                                                    GLuint) = 
818 {
819    tdfx_render_vb_points,
820    tdfx_render_vb_lines,
821    tdfx_render_vb_line_loop,
822    tdfx_render_vb_line_strip,
823    tdfx_render_vb_triangles,
824    tdfx_render_vb_tri_strip,
825    tdfx_render_vb_tri_fan,
826    tdfx_render_vb_quads,
827    tdfx_render_vb_quad_strip,
828    tdfx_render_vb_poly,
829    tdfx_render_vb_noop,
830 };
831 #undef INIT
832
833
834 /**********************************************************************/
835 /*            Render whole (indexed) begin/end objects                */
836 /**********************************************************************/
837
838
839 #define VERT(x) (tdfxVertex *)(vertptr + (x))
840
841 #define RENDER_POINTS( start, count )           \
842    for ( ; start < count ; start++)             \
843       fxMesa->Glide.grDrawPoint( VERT(ELT(start)) );
844
845 #define RENDER_LINE( v0, v1 ) \
846    fxMesa->Glide.grDrawLine( VERT(v0), VERT(v1) )
847
848 #define RENDER_TRI( v0, v1, v2 )  \
849    fxMesa->Glide.grDrawTriangle( VERT(v0), VERT(v1), VERT(v2) )
850
851 #define RENDER_QUAD( v0, v1, v2, v3 ) \
852    do {                                 \
853       tdfxVertex *_v_[4];               \
854       _v_[0] = VERT(v3);                \
855       _v_[1] = VERT(v0);                \
856       _v_[2] = VERT(v1);                \
857       _v_[3] = VERT(v2);                \
858       fxMesa->Glide.grDrawVertexArray(GR_TRIANGLE_FAN, 4, _v_);\
859       /*fxMesa->Glide.grDrawTriangle( VERT(v0), VERT(v1), VERT(v3) );*/\
860       /*fxMesa->Glide.grDrawTriangle( VERT(v1), VERT(v2), VERT(v3) );*/\
861    } while (0)
862
863 #define INIT(x) tdfxRenderPrimitive( ctx, x )
864
865 #undef LOCAL_VARS
866 #define LOCAL_VARS                                              \
867     tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);                  \
868     tdfxVertex *vertptr = fxMesa->verts;                        \
869     const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;       \
870     (void) elt;
871
872 #define RESET_STIPPLE 
873 #define RESET_OCCLUSION 
874 #define PRESERVE_VB_DEFS
875
876 /* Elts, no clipping.
877  */
878 #undef ELT
879 #undef TAG
880 #define TAG(x) tdfx_##x##_elts
881 #define ELT(x) elt[x]
882 #include "tnl_dd/t_dd_rendertmp.h"
883
884 /* Verts, no clipping.
885  */
886 #undef ELT
887 #undef TAG
888 #define TAG(x) tdfx_##x##_verts
889 #define ELT(x) x
890 /*#include "tnl_dd/t_dd_rendertmp.h"*/
891
892
893
894 /**********************************************************************/
895 /*                   Render clipped primitives                        */
896 /**********************************************************************/
897
898
899
900 static void tdfxRenderClippedPoly( struct gl_context *ctx, const GLuint *elts, 
901                                    GLuint n )
902 {
903    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
904    TNLcontext *tnl = TNL_CONTEXT(ctx);
905    struct vertex_buffer *VB = &tnl->vb;
906    GLuint prim = fxMesa->render_primitive;
907
908    /* Render the new vertices as an unclipped polygon. 
909     */
910    {
911       GLuint *tmp = VB->Elts;
912       VB->Elts = (GLuint *)elts;
913       tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
914       VB->Elts = tmp;
915    }
916
917    /* Restore the render primitive
918     */
919    if (prim != GL_POLYGON)
920       tnl->Driver.Render.PrimitiveNotify( ctx, prim );
921 }
922
923 static void tdfxRenderClippedLine( struct gl_context *ctx, GLuint ii, GLuint jj )
924 {
925    TNLcontext *tnl = TNL_CONTEXT(ctx);
926    tnl->Driver.Render.Line( ctx, ii, jj );
927 }
928
929 static void tdfxFastRenderClippedPoly( struct gl_context *ctx, const GLuint *elts, 
930                                        GLuint n )
931 {
932    int i;
933    tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
934    tdfxVertex *vertptr = fxMesa->verts;
935    if (n == 3) {
936       fxMesa->Glide.grDrawTriangle( VERT(elts[0]), VERT(elts[1]), VERT(elts[2]) );
937    } else if (n <= 32) {
938       tdfxVertex *newvptr[32];
939       for (i = 0 ; i < n ; i++) {
940          newvptr[i] = VERT(elts[i]);
941       }
942       fxMesa->Glide.grDrawVertexArray(GR_TRIANGLE_FAN, n, newvptr);
943    } else {
944       const tdfxVertex *start = VERT(elts[0]);
945       for (i = 2 ; i < n ; i++) {
946          fxMesa->Glide.grDrawTriangle( start, VERT(elts[i-1]), VERT(elts[i]) );
947       }
948    }
949 }
950
951 /**********************************************************************/
952 /*                    Choose render functions                         */
953 /**********************************************************************/
954
955
956 #define POINT_FALLBACK (DD_POINT_SMOOTH)
957 #define LINE_FALLBACK (DD_LINE_STIPPLE)
958 #define TRI_FALLBACK (DD_TRI_SMOOTH)
959 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|DD_TRI_STIPPLE)
960 #define ANY_RASTER_FLAGS (DD_FLATSHADE|DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET| \
961                           DD_TRI_UNFILLED)
962
963
964 /* All state referenced below:
965  */
966 #define _TDFX_NEW_RENDERSTATE (_DD_NEW_POINT_SMOOTH |           \
967                                _DD_NEW_LINE_STIPPLE |           \
968                                _DD_NEW_TRI_SMOOTH |             \
969                                _DD_NEW_FLATSHADE |              \
970                                _DD_NEW_TRI_UNFILLED |           \
971                                _DD_NEW_TRI_LIGHT_TWOSIDE |      \
972                                _DD_NEW_TRI_OFFSET |             \
973                                _DD_NEW_TRI_STIPPLE |            \
974                                _NEW_POLYGONSTIPPLE)
975
976
977 static void tdfxChooseRenderState(struct gl_context *ctx)
978 {
979    TNLcontext *tnl = TNL_CONTEXT(ctx);
980    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
981    GLuint flags = ctx->_TriangleCaps;
982    GLuint index = 0;
983
984    if (0) {
985       fxMesa->draw_point = tdfx_draw_point;
986       fxMesa->draw_line = tdfx_draw_line;
987       fxMesa->draw_triangle = tdfx_draw_triangle;
988       index |= TDFX_FALLBACK_BIT;
989    }
990
991    if (flags & (ANY_FALLBACK_FLAGS|ANY_RASTER_FLAGS)) {
992       if (flags & ANY_RASTER_FLAGS) {
993          if (flags & DD_TRI_LIGHT_TWOSIDE)    index |= TDFX_TWOSIDE_BIT;
994          if (flags & DD_TRI_OFFSET)           index |= TDFX_OFFSET_BIT;
995          if (flags & DD_TRI_UNFILLED)         index |= TDFX_UNFILLED_BIT;
996          if (flags & DD_FLATSHADE)            index |= TDFX_FLAT_BIT;
997       }
998
999       fxMesa->draw_point = tdfx_draw_point;
1000       fxMesa->draw_line = tdfx_draw_line;
1001       fxMesa->draw_triangle = tdfx_draw_triangle;
1002
1003       /* Hook in fallbacks for specific primitives.
1004        *
1005        * DD_TRI_UNFILLED is here because the unfilled_tri functions use
1006        * fxMesa->draw_tri *always*, and thus can't use the multipass
1007        * approach to cliprects.
1008        *
1009        */
1010       if (flags & (POINT_FALLBACK|
1011                    LINE_FALLBACK|
1012                    TRI_FALLBACK|
1013                    DD_TRI_STIPPLE|
1014                    DD_TRI_UNFILLED))
1015       {
1016          if (flags & POINT_FALLBACK)
1017             fxMesa->draw_point = tdfx_fallback_point;
1018
1019          if (flags & LINE_FALLBACK)
1020             fxMesa->draw_line = tdfx_fallback_line;
1021
1022          if (flags & TRI_FALLBACK)
1023             fxMesa->draw_triangle = tdfx_fallback_tri;
1024
1025          if ((flags & DD_TRI_STIPPLE) && !fxMesa->haveHwStipple)
1026             fxMesa->draw_triangle = tdfx_fallback_tri;
1027
1028          index |= TDFX_FALLBACK_BIT;
1029       }
1030    }
1031
1032    if (fxMesa->RenderIndex != index) {
1033       fxMesa->RenderIndex = index;
1034
1035       tnl->Driver.Render.Points = rast_tab[index].points;
1036       tnl->Driver.Render.Line = rast_tab[index].line;
1037       tnl->Driver.Render.Triangle = rast_tab[index].triangle;
1038       tnl->Driver.Render.Quad = rast_tab[index].quad;
1039
1040       if (index == 0) {
1041          tnl->Driver.Render.PrimTabVerts = tdfx_render_tab_verts;
1042          tnl->Driver.Render.PrimTabElts = tdfx_render_tab_elts;
1043          tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
1044          tnl->Driver.Render.ClippedPolygon = tdfxFastRenderClippedPoly;
1045       } else {
1046          tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
1047          tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
1048          tnl->Driver.Render.ClippedLine = tdfxRenderClippedLine;
1049          tnl->Driver.Render.ClippedPolygon = tdfxRenderClippedPoly;
1050       }
1051    }
1052 }
1053
1054 /**********************************************************************/
1055 /*                Use multipass rendering for cliprects               */
1056 /**********************************************************************/
1057
1058
1059
1060 /* TODO: Benchmark this.
1061  * TODO: Use single back-buffer cliprect where possible.  
1062  * NOTE: <pass> starts at 1, not zero!
1063  */
1064 static GLboolean multipass_cliprect( struct gl_context *ctx, GLuint pass )
1065 {
1066    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1067    if (pass >= fxMesa->numClipRects)
1068       return GL_FALSE;
1069    else {   
1070       fxMesa->Glide.grClipWindow(fxMesa->pClipRects[pass].x1,
1071                    fxMesa->screen_height - fxMesa->pClipRects[pass].y2,
1072                    fxMesa->pClipRects[pass].x2,
1073                    fxMesa->screen_height - fxMesa->pClipRects[pass].y1);
1074       
1075       return GL_TRUE;
1076    }
1077 }
1078
1079
1080 /**********************************************************************/
1081 /*                Runtime render state and callbacks                  */
1082 /**********************************************************************/
1083
1084 static void tdfxRunPipeline( struct gl_context *ctx )
1085 {
1086    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1087
1088    if (fxMesa->new_state) {
1089       tdfxDDUpdateHwState( ctx );
1090    }
1091
1092    if (!fxMesa->Fallback && fxMesa->new_gl_state) {
1093       if (fxMesa->new_gl_state & _TDFX_NEW_RASTERSETUP)
1094          tdfxChooseVertexState( ctx );
1095       
1096       if (fxMesa->new_gl_state & _TDFX_NEW_RENDERSTATE)
1097          tdfxChooseRenderState( ctx );
1098       
1099       fxMesa->new_gl_state = 0;
1100    }
1101
1102    _tnl_run_pipeline( ctx );
1103 }
1104
1105
1106 static void tdfxRenderStart( struct gl_context *ctx )
1107 {
1108    TNLcontext *tnl = TNL_CONTEXT(ctx);
1109    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1110
1111    tdfxCheckTexSizes( ctx );
1112
1113    LOCK_HARDWARE(fxMesa);
1114
1115    /* Make sure vertex format changes get uploaded before we start
1116     * sending triangles.  
1117     */
1118    if (fxMesa->dirty) {
1119       tdfxEmitHwStateLocked( fxMesa );
1120    }
1121
1122    if (fxMesa->numClipRects && !(fxMesa->RenderIndex & TDFX_FALLBACK_BIT)) {
1123       fxMesa->Glide.grClipWindow(fxMesa->pClipRects[0].x1,
1124                    fxMesa->screen_height - fxMesa->pClipRects[0].y2,
1125                    fxMesa->pClipRects[0].x2,
1126                    fxMesa->screen_height - fxMesa->pClipRects[0].y1);
1127       if (fxMesa->numClipRects > 1)
1128          tnl->Driver.Render.Multipass = multipass_cliprect;
1129       else
1130          tnl->Driver.Render.Multipass = NULL;
1131    }
1132    else
1133       tnl->Driver.Render.Multipass = NULL;
1134 }
1135
1136
1137
1138 /* Always called between RenderStart and RenderFinish --> We already
1139  * hold the lock.
1140  */
1141 static void tdfxRasterPrimitive( struct gl_context *ctx, GLenum prim )
1142 {
1143    tdfxContextPtr fxMesa = TDFX_CONTEXT( ctx );
1144
1145    FLUSH_BATCH( fxMesa );
1146
1147    fxMesa->raster_primitive = prim;
1148
1149    tdfxUpdateCull(ctx);
1150    if ( fxMesa->dirty & TDFX_UPLOAD_CULL ) {
1151       fxMesa->Glide.grCullMode( fxMesa->CullMode );
1152       fxMesa->dirty &= ~TDFX_UPLOAD_CULL;
1153    }
1154
1155    tdfxUpdateStipple(ctx);
1156    if ( fxMesa->dirty & TDFX_UPLOAD_STIPPLE ) {
1157       fxMesa->Glide.grStipplePattern ( fxMesa->Stipple.Pattern );
1158       fxMesa->Glide.grStippleMode ( fxMesa->Stipple.Mode );
1159       fxMesa->dirty &= ~TDFX_UPLOAD_STIPPLE;
1160    }
1161 }
1162
1163
1164
1165 /* Determine the rasterized primitive when not drawing unfilled 
1166  * polygons.
1167  *
1168  * Used only for the default render stage which always decomposes
1169  * primitives to trianges/lines/points.  For the accelerated stage,
1170  * which renders strips as strips, the equivalent calculations are
1171  * performed in tdfx_render.c.
1172  */
1173 static void tdfxRenderPrimitive( struct gl_context *ctx, GLenum prim )
1174 {
1175    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1176    GLuint rprim = reduced_prim[prim];
1177
1178    fxMesa->render_primitive = prim;
1179
1180    if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
1181       return;
1182        
1183    if (fxMesa->raster_primitive != rprim) {
1184       tdfxRasterPrimitive( ctx, rprim );
1185    }
1186 }
1187
1188 static void tdfxRenderFinish( struct gl_context *ctx )
1189 {
1190    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1191
1192    if (fxMesa->RenderIndex & TDFX_FALLBACK_BIT)
1193       _swrast_flush( ctx );
1194
1195    UNLOCK_HARDWARE(fxMesa);
1196 }
1197
1198
1199 /**********************************************************************/
1200 /*               Manage total rasterization fallbacks                 */
1201 /**********************************************************************/
1202
1203 static char *fallbackStrings[] = {
1204    "3D/Rect/Cube Texture map",
1205    "glDrawBuffer(GL_FRONT_AND_BACK)",
1206    "Separate specular color",
1207    "glEnable/Disable(GL_STENCIL_TEST)",
1208    "glRenderMode(selection or feedback)",
1209    "glLogicOp()",
1210    "Texture env mode",
1211    "Texture border",
1212    "glColorMask",
1213    "blend mode",
1214    "line stipple",
1215    "Rasterization disable"
1216 };
1217
1218
1219 static char *getFallbackString(GLuint bit)
1220 {
1221    int i = 0;
1222    while (bit > 1) {
1223       i++;
1224       bit >>= 1;
1225    }
1226    return fallbackStrings[i];
1227 }
1228
1229
1230 void tdfxFallback( struct gl_context *ctx, GLuint bit, GLboolean mode )
1231 {
1232    TNLcontext *tnl = TNL_CONTEXT(ctx);
1233    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1234    GLuint oldfallback = fxMesa->Fallback;
1235
1236    if (mode) {
1237       fxMesa->Fallback |= bit;
1238       if (oldfallback == 0) {
1239          /*printf("Go to software rendering, bit = 0x%x\n", bit);*/
1240          FLUSH_BATCH(fxMesa);
1241          _swsetup_Wakeup( ctx );
1242          fxMesa->RenderIndex = ~0;
1243          if (TDFX_DEBUG & DEBUG_VERBOSE_FALL) {
1244             fprintf(stderr, "Tdfx begin software fallback: 0x%x %s\n",
1245                     bit, getFallbackString(bit));
1246          }
1247       }
1248    }
1249    else {
1250       fxMesa->Fallback &= ~bit;
1251       if (oldfallback == bit) {
1252          /*printf("Go to hardware rendering, bit = 0x%x\n", bit);*/
1253          _swrast_flush( ctx );
1254          tnl->Driver.Render.Start = tdfxRenderStart;
1255          tnl->Driver.Render.PrimitiveNotify = tdfxRenderPrimitive;
1256          tnl->Driver.Render.Finish = tdfxRenderFinish;
1257          tnl->Driver.Render.BuildVertices = tdfxBuildVertices;
1258          fxMesa->new_gl_state |= (_TDFX_NEW_RENDERSTATE|
1259                                   _TDFX_NEW_RASTERSETUP);
1260          if (TDFX_DEBUG & DEBUG_VERBOSE_FALL) {
1261             fprintf(stderr, "Tdfx end software fallback: 0x%x %s\n",
1262                     bit, getFallbackString(bit));
1263          }
1264       }
1265    }
1266 }
1267
1268
1269 void tdfxDDInitTriFuncs( struct gl_context *ctx )
1270 {
1271    TNLcontext *tnl = TNL_CONTEXT(ctx);
1272    tdfxContextPtr fxMesa = TDFX_CONTEXT(ctx);
1273    static int firsttime = 1;
1274
1275    if (firsttime) {
1276       init_rast_tab();
1277       firsttime = 0;
1278    }
1279
1280    fxMesa->RenderIndex = ~0;
1281         
1282    tnl->Driver.RunPipeline              = tdfxRunPipeline;
1283    tnl->Driver.Render.Start             = tdfxRenderStart;
1284    tnl->Driver.Render.Finish            = tdfxRenderFinish; 
1285    tnl->Driver.Render.PrimitiveNotify   = tdfxRenderPrimitive;
1286    tnl->Driver.Render.ResetLineStipple  = _swrast_ResetLineStipple;
1287    tnl->Driver.Render.BuildVertices     = tdfxBuildVertices;
1288    tnl->Driver.Render.Multipass         = NULL;
1289
1290    (void) tdfx_print_vertex;
1291 }