Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / savage / savagetris.c
1 /* -*- c-basic-offset: 3 -*- */
2 /**************************************************************************
3
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5                      VA Linux Systems Inc., Fremont, California.
6
7 All Rights Reserved.
8
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the "Software"),
11 to deal in the Software without restriction, including without limitation
12 on the rights to use, copy, modify, merge, publish, distribute, sub
13 license, and/or sell copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the following conditions:
15
16 The above copyright notice and this permission notice (including the next
17 paragraph) shall be included in all copies or substantial portions of the
18 Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
23 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
24 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
25 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
26 USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /*
31  * Authors:
32  *   Keith Whitwell <keithw@valinux.com>
33  *   Felix Kuehling <fxkuehl@gmx.de>
34  *
35  */
36
37 #include <stdio.h>
38 #include <math.h>
39
40 #include "main/glheader.h"
41 #include "main/mtypes.h"
42 #include "main/colormac.h"
43 #include "main/macros.h"
44
45 #include "swrast/swrast.h"
46 #include "swrast_setup/swrast_setup.h"
47 #include "tnl/tnl.h"
48 #include "tnl/t_context.h"
49 #include "tnl/t_pipeline.h"
50
51 #include "savagetris.h"
52 #include "savagestate.h"
53 #include "savagetex.h"
54 #include "savageioctl.h"
55
56 static void savageRasterPrimitive( struct gl_context *ctx, GLuint prim );
57 static void savageRenderPrimitive( struct gl_context *ctx, GLenum prim );
58
59
60 static GLenum reduced_prim[GL_POLYGON+1] = {
61    GL_POINTS,
62    GL_LINES,
63    GL_LINES,
64    GL_LINES,
65    GL_TRIANGLES,
66    GL_TRIANGLES,
67    GL_TRIANGLES,
68    GL_TRIANGLES,
69    GL_TRIANGLES,
70    GL_TRIANGLES
71 };
72
73  
74 /***********************************************************************
75  *                    Emit primitives                                  *
76  ***********************************************************************/
77
78 #if defined (USE_X86_ASM)
79 #define EMIT_VERT( j, vb, vertex_size, start, v )               \
80 do {    int __tmp;                                              \
81          vb += start;                                           \
82         __asm__ __volatile__( "rep ; movsl"                     \
83                          : "=%c" (j), "=D" (vb), "=S" (__tmp)   \
84                          : "0" (vertex_size-start),             \
85                            "D" ((long)vb),                      \
86                            "S" ((long)&(v)->ui[start]));        \
87 } while (0)
88 #else
89 #define EMIT_VERT( j, vb, vertex_size, start, v )       \
90 do {                                            \
91    for ( j = start ; j < vertex_size ; j++ )    \
92       vb[j] = (v)->ui[j];                       \
93    vb += vertex_size;                           \
94 } while (0)
95 #endif
96
97 static void INLINE savage_draw_triangle (savageContextPtr imesa,
98                                              savageVertexPtr v0,
99                                              savageVertexPtr v1,
100                                              savageVertexPtr v2) {
101    GLuint vertsize = imesa->HwVertexSize;
102    uint32_t *vb = savageAllocVtxBuf (imesa, 3*vertsize);
103    GLuint j;
104
105    EMIT_VERT (j, vb, vertsize, 0, v0);
106    EMIT_VERT (j, vb, vertsize, 0, v1);
107    EMIT_VERT (j, vb, vertsize, 0, v2);
108 }
109
110 static void INLINE savage_draw_quad (savageContextPtr imesa,
111                                          savageVertexPtr v0,
112                                          savageVertexPtr v1,
113                                          savageVertexPtr v2,
114                                          savageVertexPtr v3) {
115    GLuint vertsize = imesa->HwVertexSize;
116    uint32_t *vb = savageAllocVtxBuf (imesa, 6*vertsize);
117    GLuint j;
118
119    EMIT_VERT (j, vb, vertsize, 0, v0);
120    EMIT_VERT (j, vb, vertsize, 0, v1);
121    EMIT_VERT (j, vb, vertsize, 0, v3);
122    EMIT_VERT (j, vb, vertsize, 0, v1);
123    EMIT_VERT (j, vb, vertsize, 0, v2);
124    EMIT_VERT (j, vb, vertsize, 0, v3);
125 }
126
127 static INLINE void savage_draw_point (savageContextPtr imesa,
128                                           savageVertexPtr tmp) {
129    GLuint vertsize = imesa->HwVertexSize;
130    uint32_t *vb = savageAllocVtxBuf (imesa, 6*vertsize);
131    const GLfloat x = tmp->v.x;
132    const GLfloat y = tmp->v.y;
133    const GLfloat sz = 0.5 * CLAMP(imesa->glCtx->Point.Size,
134                                   imesa->glCtx->Const.MinPointSize,
135                                   imesa->glCtx->Const.MaxPointSize);
136    GLuint j;
137
138    *(float *)&vb[0] = x - sz;
139    *(float *)&vb[1] = y - sz;
140    EMIT_VERT (j, vb, vertsize, 2, tmp);
141
142    *(float *)&vb[0] = x + sz;
143    *(float *)&vb[1] = y - sz;
144    EMIT_VERT (j, vb, vertsize, 2, tmp);
145
146    *(float *)&vb[0] = x + sz;
147    *(float *)&vb[1] = y + sz;
148    EMIT_VERT (j, vb, vertsize, 2, tmp);
149
150    *(float *)&vb[0] = x + sz;
151    *(float *)&vb[1] = y + sz;
152    EMIT_VERT (j, vb, vertsize, 2, tmp);
153
154    *(float *)&vb[0] = x - sz;
155    *(float *)&vb[1] = y + sz;
156    EMIT_VERT (j, vb, vertsize, 2, tmp);
157
158    *(float *)&vb[0] = x - sz;
159    *(float *)&vb[1] = y - sz;
160    EMIT_VERT (j, vb, vertsize, 2, tmp);
161 }
162
163 static INLINE void savage_draw_line (savageContextPtr imesa,
164                                          savageVertexPtr v0,
165                                          savageVertexPtr v1 ) {
166    GLuint vertsize = imesa->HwVertexSize;
167    uint32_t *vb = savageAllocVtxBuf (imesa, 6*vertsize);
168    const GLfloat width = CLAMP(imesa->glCtx->Line.Width,
169                                imesa->glCtx->Const.MinLineWidth,
170                                imesa->glCtx->Const.MaxLineWidth);
171    GLfloat dx, dy, ix, iy;
172    GLuint j;
173
174    dx = v0->v.x - v1->v.x;
175    dy = v0->v.y - v1->v.y;
176
177    ix = width * .5; iy = 0;
178    if (dx * dx > dy * dy) {
179       iy = ix; ix = 0;
180    }
181
182    *(float *)&vb[0] = v0->v.x - ix;
183    *(float *)&vb[1] = v0->v.y - iy;
184    EMIT_VERT (j, vb, vertsize, 2, v0);
185
186    *(float *)&vb[0] = v1->v.x + ix;
187    *(float *)&vb[1] = v1->v.y + iy;
188    EMIT_VERT (j, vb, vertsize, 2, v1);
189
190    *(float *)&vb[0] = v0->v.x + ix;
191    *(float *)&vb[1] = v0->v.y + iy;
192    EMIT_VERT (j, vb, vertsize, 2, v0);
193
194    *(float *)&vb[0] = v0->v.x - ix;
195    *(float *)&vb[1] = v0->v.y - iy;
196    EMIT_VERT (j, vb, vertsize, 2, v0);
197
198    *(float *)&vb[0] = v1->v.x - ix;
199    *(float *)&vb[1] = v1->v.y - iy;
200    EMIT_VERT (j, vb, vertsize, 2, v1);
201
202    *(float *)&vb[0] = v1->v.x + ix;
203    *(float *)&vb[1] = v1->v.y + iy;
204    EMIT_VERT (j, vb, vertsize, 2, v1);
205
206
207 /* Fallback drawing functions for the ptex hack. Code duplication
208  * (especially lines and points) isn't beautiful, but I didn't feel
209  * like inventing yet another template. :-/
210  */
211 #define PTEX_VERTEX( j, tmp, vertex_size, start, v)     \
212 do {                                                    \
213    GLfloat rhw = 1.0 / v->f[vertex_size];               \
214    for ( j = start ; j < vertex_size ; j++ )            \
215       tmp.f[j] = v->f[j];                               \
216    tmp.f[3] *= v->f[vertex_size];                       \
217    tmp.f[vertex_size-2] *= rhw;                         \
218    tmp.f[vertex_size-1] *= rhw;                         \
219 } while (0)
220
221 static void INLINE savage_ptex_tri (savageContextPtr imesa,
222                                         savageVertexPtr v0,
223                                         savageVertexPtr v1,
224                                         savageVertexPtr v2) {
225    GLuint vertsize = imesa->HwVertexSize;
226    uint32_t *vb = savageAllocVtxBuf (imesa, 3*vertsize);
227    savageVertex tmp;
228    GLuint j;
229
230    PTEX_VERTEX (j, tmp, vertsize, 0, v0); EMIT_VERT (j, vb, vertsize, 0, &tmp);
231    PTEX_VERTEX (j, tmp, vertsize, 0, v1); EMIT_VERT (j, vb, vertsize, 0, &tmp);
232    PTEX_VERTEX (j, tmp, vertsize, 0, v2); EMIT_VERT (j, vb, vertsize, 0, &tmp);
233 }
234
235 static INLINE void savage_ptex_line (savageContextPtr imesa,
236                                          savageVertexPtr v0,
237                                          savageVertexPtr v1 ) {
238    GLuint vertsize = imesa->HwVertexSize;
239    uint32_t *vb = savageAllocVtxBuf (imesa, 6*vertsize);
240    const GLfloat width = CLAMP(imesa->glCtx->Line.Width,
241                                imesa->glCtx->Const.MinLineWidth,
242                                imesa->glCtx->Const.MaxLineWidth);
243    GLfloat dx, dy, ix, iy;
244    savageVertex tmp0, tmp1;
245    GLuint j;
246
247    PTEX_VERTEX (j, tmp0, vertsize, 2, v0);
248    PTEX_VERTEX (j, tmp1, vertsize, 2, v1);
249
250    dx = v0->v.x - v1->v.x;
251    dy = v0->v.y - v1->v.y;
252
253    ix = width * .5; iy = 0;
254    if (dx * dx > dy * dy) {
255       iy = ix; ix = 0;
256    }
257
258    *(float *)&vb[0] = v0->v.x - ix;
259    *(float *)&vb[1] = v0->v.y - iy;
260    EMIT_VERT (j, vb, vertsize, 2, &tmp0);
261
262    *(float *)&vb[0] = v1->v.x + ix;
263    *(float *)&vb[1] = v1->v.y + iy;
264    EMIT_VERT (j, vb, vertsize, 2, &tmp1);
265
266    *(float *)&vb[0] = v0->v.x + ix;
267    *(float *)&vb[1] = v0->v.y + iy;
268    EMIT_VERT (j, vb, vertsize, 2, &tmp0);
269
270    *(float *)&vb[0] = v0->v.x - ix;
271    *(float *)&vb[1] = v0->v.y - iy;
272    EMIT_VERT (j, vb, vertsize, 2, &tmp0);
273
274    *(float *)&vb[0] = v1->v.x - ix;
275    *(float *)&vb[1] = v1->v.y - iy;
276    EMIT_VERT (j, vb, vertsize, 2, &tmp1);
277
278    *(float *)&vb[0] = v1->v.x + ix;
279    *(float *)&vb[1] = v1->v.y + iy;
280    EMIT_VERT (j, vb, vertsize, 2, &tmp1);
281
282
283 static INLINE void savage_ptex_point (savageContextPtr imesa,
284                                           savageVertexPtr v0) {
285    GLuint vertsize = imesa->HwVertexSize;
286    uint32_t *vb = savageAllocVtxBuf (imesa, 6*vertsize);
287    const GLfloat x = v0->v.x;
288    const GLfloat y = v0->v.y;
289    const GLfloat sz = 0.5 * CLAMP(imesa->glCtx->Point.Size,
290                                   imesa->glCtx->Const.MinPointSize,
291                                   imesa->glCtx->Const.MaxPointSize);
292    savageVertex tmp;
293    GLuint j;
294
295    PTEX_VERTEX (j, tmp, vertsize, 2, v0);
296
297    *(float *)&vb[0] = x - sz;
298    *(float *)&vb[1] = y - sz;
299    EMIT_VERT (j, vb, vertsize, 2, &tmp);
300
301    *(float *)&vb[0] = x + sz;
302    *(float *)&vb[1] = y - sz;
303    EMIT_VERT (j, vb, vertsize, 2, &tmp);
304
305    *(float *)&vb[0] = x + sz;
306    *(float *)&vb[1] = y + sz;
307    EMIT_VERT (j, vb, vertsize, 2, &tmp);
308
309    *(float *)&vb[0] = x + sz;
310    *(float *)&vb[1] = y + sz;
311    EMIT_VERT (j, vb, vertsize, 2, &tmp);
312
313    *(float *)&vb[0] = x - sz;
314    *(float *)&vb[1] = y + sz;
315    EMIT_VERT (j, vb, vertsize, 2, &tmp);
316
317    *(float *)&vb[0] = x - sz;
318    *(float *)&vb[1] = y - sz;
319    EMIT_VERT (j, vb, vertsize, 2, &tmp);
320 }
321  
322 /***********************************************************************
323  *          Macros for t_dd_tritmp.h to draw basic primitives          *
324  ***********************************************************************/
325
326 #define TRI( a, b, c )                          \
327 do {                                            \
328    if (DO_FALLBACK)                             \
329       imesa->draw_tri( imesa, a, b, c );        \
330    else                                         \
331       savage_draw_triangle( imesa, a, b, c );   \
332 } while (0)
333
334 #define QUAD( a, b, c, d )                      \
335 do {                                            \
336    if (DO_FALLBACK) {                           \
337       imesa->draw_tri( imesa, a, b, d );        \
338       imesa->draw_tri( imesa, b, c, d );        \
339    } else                                       \
340       savage_draw_quad( imesa, a, b, c, d );    \
341 } while (0)
342
343 #define LINE( v0, v1 )                          \
344 do {                                            \
345    if (DO_FALLBACK)                             \
346       imesa->draw_line( imesa, v0, v1 );        \
347    else                                         \
348       savage_draw_line( imesa, v0, v1 );        \
349 } while (0)
350
351 #define POINT( v0 )                             \
352 do {                                            \
353    if (DO_FALLBACK)                             \
354       imesa->draw_point( imesa, v0 );           \
355    else                                         \
356       savage_draw_point( imesa, v0 );           \
357 } while (0)
358
359
360 /***********************************************************************
361  *              Build render functions from dd templates               *
362  ***********************************************************************/
363
364 #define SAVAGE_OFFSET_BIT        0x1
365 #define SAVAGE_TWOSIDE_BIT       0x2
366 #define SAVAGE_UNFILLED_BIT      0x4
367 #define SAVAGE_FALLBACK_BIT      0x8
368 #define SAVAGE_MAX_TRIFUNC       0x10
369
370
371 static struct {
372    tnl_points_func              points;
373    tnl_line_func                line;
374    tnl_triangle_func    triangle;
375    tnl_quad_func                quad;
376 } rast_tab[SAVAGE_MAX_TRIFUNC];
377
378
379 #define DO_FALLBACK (IND & SAVAGE_FALLBACK_BIT)
380 #define DO_OFFSET   (IND & SAVAGE_OFFSET_BIT)
381 #define DO_UNFILLED (IND & SAVAGE_UNFILLED_BIT)
382 #define DO_TWOSIDE  (IND & SAVAGE_TWOSIDE_BIT)
383 #define DO_FLAT      0
384 #define DO_TRI       1
385 #define DO_QUAD      1
386 #define DO_LINE      1
387 #define DO_POINTS    1
388 #define DO_FULL_QUAD 1
389
390 #define HAVE_SPEC   1
391 #define HAVE_BACK_COLORS  0
392 #define HAVE_HW_FLATSHADE 1
393 #define VERTEX savageVertex
394 #define TAB rast_tab
395
396 #define DEPTH_SCALE imesa->depth_scale
397 #define REVERSE_DEPTH 1
398 #define UNFILLED_TRI unfilled_tri
399 #define UNFILLED_QUAD unfilled_quad
400 #define VERT_X(_v) _v->v.x
401 #define VERT_Y(_v) _v->v.y
402 #define VERT_Z(_v) _v->v.z
403 #define AREA_IS_CCW( a ) (a > 0)
404 #define GET_VERTEX(e) (imesa->verts + (e * imesa->vertex_size * sizeof(int)))
405
406 #define VERT_SET_RGBA( v, c )                                   \
407 do {                                                            \
408    savage_color_t *color = (savage_color_t *)&((v)->ub4[coloroffset]);  \
409    UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]);                \
410    UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]);              \
411    UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]);               \
412    UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]);              \
413 } while (0)
414 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
415 #define VERT_SAVE_RGBA( idx )    color[idx] = v[idx]->ui[coloroffset]
416 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
417
418 #define VERT_SET_SPEC( v, c )                                   \
419 do {                                                            \
420    if (specoffset) {                                            \
421       savage_color_t *spec = (savage_color_t *)&((v)->ub4[specoffset]); \
422       UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]);              \
423       UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]);            \
424       UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]);             \
425    }                                                            \
426 } while (0)
427 #define VERT_COPY_SPEC( v0, v1 )                                        \
428    if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset])
429 #define VERT_SAVE_SPEC( idx )                                           \
430    if (specoffset) spec[idx] = v[idx]->ui[specoffset]
431 #define VERT_RESTORE_SPEC( idx )                                        \
432    if (specoffset) v[idx]->ui[specoffset] = spec[idx]
433
434 #define LOCAL_VARS(n)                                           \
435    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);                \
436    GLuint color[n] = { 0 };                                     \
437    GLuint spec[n] = { 0 };                                      \
438    GLuint coloroffset =                                         \
439       ((imesa->skip & SAVAGE_SKIP_W) ? 3 : 4);                  \
440    GLboolean specoffset =                                       \
441       ((imesa->skip & SAVAGE_SKIP_C1) ? 0 : coloroffset+1);     \
442    (void) color; (void) spec; (void) coloroffset; (void) specoffset;
443
444 /***********************************************************************
445  *                Helpers for rendering unfilled primitives            *
446  ***********************************************************************/
447
448 #define RASTERIZE(x) if (imesa->raster_primitive != reduced_prim[x]) \
449                         savageRasterPrimitive( ctx, x )
450 #define RENDER_PRIMITIVE imesa->render_primitive
451 #define IND SAVAGE_FALLBACK_BIT
452 #define TAG(x) x
453 #include "tnl_dd/t_dd_unfilled.h"
454 #undef IND
455
456
457 /***********************************************************************
458  *                      Generate GL render functions                   *
459  ***********************************************************************/
460
461
462 #define IND (0)
463 #define TAG(x) x
464 #include "tnl_dd/t_dd_tritmp.h"
465
466 #define IND (SAVAGE_OFFSET_BIT)
467 #define TAG(x) x##_offset
468 #include "tnl_dd/t_dd_tritmp.h"
469
470 #define IND (SAVAGE_TWOSIDE_BIT)
471 #define TAG(x) x##_twoside
472 #include "tnl_dd/t_dd_tritmp.h"
473
474 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT)
475 #define TAG(x) x##_twoside_offset
476 #include "tnl_dd/t_dd_tritmp.h"
477
478 #define IND (SAVAGE_UNFILLED_BIT)
479 #define TAG(x) x##_unfilled
480 #include "tnl_dd/t_dd_tritmp.h"
481
482 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
483 #define TAG(x) x##_offset_unfilled
484 #include "tnl_dd/t_dd_tritmp.h"
485
486 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT)
487 #define TAG(x) x##_twoside_unfilled
488 #include "tnl_dd/t_dd_tritmp.h"
489
490 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
491 #define TAG(x) x##_twoside_offset_unfilled
492 #include "tnl_dd/t_dd_tritmp.h"
493
494 #define IND (SAVAGE_FALLBACK_BIT)
495 #define TAG(x) x##_fallback
496 #include "tnl_dd/t_dd_tritmp.h"
497
498 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
499 #define TAG(x) x##_offset_fallback
500 #include "tnl_dd/t_dd_tritmp.h"
501
502 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_FALLBACK_BIT)
503 #define TAG(x) x##_twoside_fallback
504 #include "tnl_dd/t_dd_tritmp.h"
505
506 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
507 #define TAG(x) x##_twoside_offset_fallback
508 #include "tnl_dd/t_dd_tritmp.h"
509
510 #define IND (SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
511 #define TAG(x) x##_unfilled_fallback
512 #include "tnl_dd/t_dd_tritmp.h"
513
514 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
515 #define TAG(x) x##_offset_unfilled_fallback
516 #include "tnl_dd/t_dd_tritmp.h"
517
518 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
519 #define TAG(x) x##_twoside_unfilled_fallback
520 #include "tnl_dd/t_dd_tritmp.h"
521
522 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT| \
523              SAVAGE_FALLBACK_BIT)
524 #define TAG(x) x##_twoside_offset_unfilled_fallback
525 #include "tnl_dd/t_dd_tritmp.h"
526
527
528 static void init_rast_tab( void )
529 {
530    init();
531    init_offset();
532    init_twoside();
533    init_twoside_offset();
534    init_unfilled();
535    init_offset_unfilled();
536    init_twoside_unfilled();
537    init_twoside_offset_unfilled();
538    init_fallback();
539    init_offset_fallback();
540    init_twoside_fallback();
541    init_twoside_offset_fallback();
542    init_unfilled_fallback();
543    init_offset_unfilled_fallback();
544    init_twoside_unfilled_fallback();
545    init_twoside_offset_unfilled_fallback();
546 }
547
548
549
550 /***********************************************************************
551  *                    Rasterization fallback helpers                   *
552  ***********************************************************************/
553
554
555 /* This code is hit only when a mix of accelerated and unaccelerated
556  * primitives are being drawn, and only for the unaccelerated
557  * primitives.
558  */
559 static void
560 savage_fallback_tri( savageContextPtr imesa,
561                      savageVertexPtr v0,
562                      savageVertexPtr v1,
563                      savageVertexPtr v2 )
564 {
565    struct gl_context *ctx = imesa->glCtx;
566    SWvertex v[3];
567    FLUSH_BATCH(imesa);
568    WAIT_IDLE_EMPTY(imesa);
569    _swsetup_Translate( ctx, v0, &v[0] );
570    _swsetup_Translate( ctx, v1, &v[1] );
571    _swsetup_Translate( ctx, v2, &v[2] );
572    _swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
573 }
574
575
576 static void
577 savage_fallback_line( savageContextPtr imesa,
578                       savageVertexPtr v0,
579                       savageVertexPtr v1 )
580 {
581    struct gl_context *ctx = imesa->glCtx;
582    SWvertex v[2];
583    FLUSH_BATCH(imesa);
584    WAIT_IDLE_EMPTY(imesa);
585    _swsetup_Translate( ctx, v0, &v[0] );
586    _swsetup_Translate( ctx, v1, &v[1] );
587    _swrast_Line( ctx, &v[0], &v[1] );
588 }
589
590
591 static void
592 savage_fallback_point( savageContextPtr imesa,
593                        savageVertexPtr v0 )
594 {
595    struct gl_context *ctx = imesa->glCtx;
596    SWvertex v[1];
597    FLUSH_BATCH(imesa);
598    WAIT_IDLE_EMPTY(imesa);
599    _swsetup_Translate( ctx, v0, &v[0] );
600    _swrast_Point( ctx, &v[0] );
601 }
602
603
604
605 /**********************************************************************/
606 /*               Render unclipped begin/end objects                   */
607 /**********************************************************************/
608
609 #define VERT(x) (savageVertexPtr)(savageVerts + (x * vertsize * sizeof(int)))
610 #define RENDER_POINTS( start, count )           \
611    for ( ; start < count ; start++)             \
612       savage_draw_point( imesa, VERT(start) )
613 #define RENDER_LINE( v0, v1 ) \
614    savage_draw_line( imesa, VERT(v0), VERT(v1) )
615 #define RENDER_TRI( v0, v1, v2 )  \
616    savage_draw_triangle( imesa, VERT(v0), VERT(v1), VERT(v2) )
617 #define RENDER_QUAD( v0, v1, v2, v3 ) \
618    savage_draw_quad( imesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
619 #define INIT(x) do {                                    \
620    if (0) fprintf(stderr, "%s\n", __FUNCTION__);        \
621    savageRenderPrimitive( ctx, x );                     \
622    /*SAVAGE_CONTEXT(ctx)->render_primitive = x;*/       \
623 } while (0)
624 #undef LOCAL_VARS
625 #define LOCAL_VARS                                              \
626     savageContextPtr imesa = SAVAGE_CONTEXT(ctx);               \
627     const GLuint vertsize = imesa->vertex_size;                 \
628     const char *savageVerts = (char *)imesa->verts;             \
629     const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;       \
630     (void) elt;
631 #define RESET_STIPPLE
632 #define RESET_OCCLUSION
633 #define PRESERVE_VB_DEFS
634 #define ELT(x) (x)
635 #define TAG(x) savage_##x##_verts
636 #include "tnl/t_vb_rendertmp.h"
637 #undef ELT
638 #undef TAG
639 #define TAG(x) savage_##x##_elts
640 #define ELT(x) elt[x]
641 #include "tnl/t_vb_rendertmp.h"
642
643
644 /**********************************************************************/
645 /*                    Render clipped primitives                       */
646 /**********************************************************************/
647
648 static void savageRenderClippedPoly( struct gl_context *ctx, const GLuint *elts,
649                                      GLuint n )
650 {
651    TNLcontext *tnl = TNL_CONTEXT(ctx);
652    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
653
654    /* Render the new vertices as an unclipped polygon.
655     */
656    {
657       GLuint *tmp = VB->Elts;
658       VB->Elts = (GLuint *)elts;
659       tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
660       VB->Elts = tmp;
661    }
662 }
663
664 static void savageRenderClippedLine( struct gl_context *ctx, GLuint ii, GLuint jj )
665 {
666    TNLcontext *tnl = TNL_CONTEXT(ctx);
667    tnl->Driver.Render.Line( ctx, ii, jj );
668 }
669 /*
670 static void savageFastRenderClippedPoly( struct gl_context *ctx, const GLuint *elts,
671                                          GLuint n )
672 {
673    r128ContextPtr rmesa = R128_CONTEXT( ctx );
674    GLuint vertsize = rmesa->vertex_size;
675    GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
676    GLubyte *r128verts = (GLubyte *)rmesa->verts;
677    const GLuint shift = rmesa->vertex_stride_shift;
678    const GLuint *start = (const GLuint *)VERT(elts[0]);
679    int i,j;
680
681    rmesa->num_verts += (n-2) * 3;
682
683    for (i = 2 ; i < n ; i++) {
684       COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
685       COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
686       COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
687    }
688 }
689 */
690
691
692
693 /**********************************************************************/
694 /*                    Choose render functions                         */
695 /**********************************************************************/
696
697 #define _SAVAGE_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE |        \
698                                   _DD_NEW_LINE_SMOOTH |         \
699                                   _DD_NEW_POINT_SMOOTH |        \
700                                   _DD_NEW_TRI_STIPPLE |         \
701                                   _DD_NEW_TRI_SMOOTH |          \
702                                   _DD_NEW_TRI_UNFILLED |        \
703                                   _DD_NEW_TRI_LIGHT_TWOSIDE |   \
704                                   _DD_NEW_TRI_OFFSET)           \
705
706 /* original driver didn't have DD_POINT_SMOOTH. really needed? */
707 #define POINT_FALLBACK (DD_POINT_SMOOTH)
708 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
709 #define TRI_FALLBACK (DD_TRI_STIPPLE|DD_TRI_SMOOTH)
710 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
711 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
712
713
714 static void savageChooseRenderState(struct gl_context *ctx)
715 {
716    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
717    GLuint flags = ctx->_TriangleCaps;
718    GLuint index = 0;
719
720    /* Hook in fallback functions for the ptex hack. Do this first, so
721     * that a real fallback will overwrite them with the respective
722     * savage_fallback_... function.
723     */
724    if (imesa->ptexHack) {
725       /* Do textures make sense with points? */
726       imesa->draw_point = savage_ptex_point;
727       imesa->draw_line = savage_ptex_line;
728       imesa->draw_tri = savage_ptex_tri;
729       index |= SAVAGE_FALLBACK_BIT;
730    } else {
731       imesa->draw_point = savage_draw_point;
732       imesa->draw_line = savage_draw_line;
733       imesa->draw_tri = savage_draw_triangle;
734    }
735
736    if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
737       if (flags & ANY_RASTER_FLAGS) {
738          if (flags & DD_TRI_LIGHT_TWOSIDE) index |= SAVAGE_TWOSIDE_BIT;
739          if (flags & DD_TRI_OFFSET)        index |= SAVAGE_OFFSET_BIT;
740          if (flags & DD_TRI_UNFILLED)      index |= SAVAGE_UNFILLED_BIT;
741       }
742
743       /* Hook in fallbacks for specific primitives.
744        */
745       if (flags & ANY_FALLBACK_FLAGS) {
746          if (flags & POINT_FALLBACK) imesa->draw_point = savage_fallback_point;
747          if (flags & LINE_FALLBACK)  imesa->draw_line = savage_fallback_line;
748          if (flags & TRI_FALLBACK)   imesa->draw_tri = savage_fallback_tri;
749          index |= SAVAGE_FALLBACK_BIT;
750          if (SAVAGE_DEBUG & DEBUG_FALLBACKS) {
751             fprintf (stderr, "Per-primitive fallback, TriangleCaps=0x%x\n",
752                      ctx->_TriangleCaps);
753          }
754       }
755    }
756
757    if (index != imesa->RenderIndex) {
758       TNLcontext *tnl = TNL_CONTEXT(ctx);
759       tnl->Driver.Render.Points = rast_tab[index].points;
760       tnl->Driver.Render.Line = rast_tab[index].line;
761       tnl->Driver.Render.Triangle = rast_tab[index].triangle;
762       tnl->Driver.Render.Quad = rast_tab[index].quad;
763
764       if (index == 0) {
765          tnl->Driver.Render.PrimTabVerts = savage_render_tab_verts;
766          tnl->Driver.Render.PrimTabElts = savage_render_tab_elts;
767          tnl->Driver.Render.ClippedLine = rast_tab[index].line;
768          tnl->Driver.Render.ClippedPolygon = savageRenderClippedPoly/*r128FastRenderClippedPoly*/;
769       } else {
770          tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
771          tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
772          tnl->Driver.Render.ClippedLine = savageRenderClippedLine;
773          tnl->Driver.Render.ClippedPolygon = savageRenderClippedPoly;
774       }
775
776       imesa->RenderIndex = index;
777    }
778 }
779
780 /**********************************************************************/
781 /*                 Validate state at pipeline start                   */
782 /**********************************************************************/
783
784 static void savageRunPipeline( struct gl_context *ctx )
785 {
786    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
787
788    if (imesa->no_rast)
789       FALLBACK(ctx, SAVAGE_FALLBACK_NORAST, GL_TRUE);
790
791    if (imesa->new_state)
792       savageDDUpdateHwState( ctx );
793
794    if (!imesa->Fallback) {
795       if (imesa->new_gl_state & _SAVAGE_NEW_RENDER_STATE)
796          savageChooseRenderState( ctx );
797
798       /* choose the correct primitive type for tnl rendering */
799       if (imesa->savageScreen->chipset < S3_SAVAGE4 &&
800           (ctx->_TriangleCaps & DD_FLATSHADE)) {
801          if (imesa->HwPrim != SAVAGE_PRIM_TRILIST_201)
802             savageFlushVertices(imesa);
803          imesa->HwPrim = SAVAGE_PRIM_TRILIST_201;
804       } else {
805          if (imesa->HwPrim != SAVAGE_PRIM_TRILIST)
806             savageFlushVertices(imesa);
807          imesa->HwPrim = SAVAGE_PRIM_TRILIST;
808       }
809
810       imesa->new_gl_state = 0;
811    }
812
813    _tnl_run_pipeline( ctx );
814
815    if (imesa->no_rast)
816       FALLBACK(ctx, SAVAGE_FALLBACK_NORAST, GL_FALSE);
817 }
818
819 /**********************************************************************/
820 /*                 High level hooks for t_vb_render.c                 */
821 /**********************************************************************/
822
823 /* This is called when Mesa switches between rendering triangle
824  * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
825  * and lines, points and bitmaps.
826  *
827  * As the r128 uses triangles to render lines and points, it is
828  * necessary to turn off hardware culling when rendering these
829  * primitives.
830  */
831
832 static void savageRasterPrimitive( struct gl_context *ctx, GLuint prim )
833 {
834    savageContextPtr imesa = SAVAGE_CONTEXT( ctx );
835
836    /* Update culling */
837    if (imesa->raster_primitive != prim) {
838       imesa->raster_primitive = prim;
839       imesa->new_state |= SAVAGE_NEW_CULL;
840       savageDDUpdateHwState (ctx);
841    }
842
843 #if 0
844    if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple)
845    {
846       mmesa->dirty |= MGA_UPLOAD_CONTEXT;
847       mmesa->setup.dwgctl &= ~(0xf<<20);
848       if (mmesa->raster_primitive == GL_TRIANGLES)
849          mmesa->setup.dwgctl |= mmesa->poly_stipple;
850    }
851 #endif
852 }
853
854 static void savageRenderPrimitive( struct gl_context *ctx, GLenum prim )
855 {
856    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
857    GLuint rprim = reduced_prim[prim];
858
859    imesa->render_primitive = prim;
860
861    if (rprim == GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
862       return;
863        
864    if (imesa->raster_primitive != rprim) {
865       savageRasterPrimitive( ctx, rprim );
866    }
867 }
868
869 /* Check if projective texture coordinates are used and if we can fake
870  * them. Fallback to swrast we can't. Returns GL_TRUE if projective
871  * texture coordinates must be faked, GL_FALSE otherwise.
872  */
873 static GLboolean savageCheckPTexHack( struct gl_context *ctx )
874 {
875    TNLcontext *tnl = TNL_CONTEXT(ctx);
876    struct vertex_buffer *VB = &tnl->vb;
877    DECLARE_RENDERINPUTS(index_bitset);
878
879    RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
880
881    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 ) && VB->AttribPtr[_TNL_ATTRIB_TEX0]->size == 4) {
882       if (!RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_ATTRIB_TEX1, _TNL_LAST_TEX ))
883          return GL_TRUE; /* apply ptex hack */
884       else
885          FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
886    }
887    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 ) && VB->AttribPtr[_TNL_ATTRIB_TEX1]->size == 4)
888       FALLBACK(ctx, SAVAGE_FALLBACK_PROJ_TEXTURE, GL_TRUE);
889
890    return GL_FALSE; /* don't apply ptex hack */
891 }
892
893
894 #define DO_EMIT_ATTR( ATTR, STYLE )                                     \
895 do {                                                                    \
896    imesa->vertex_attrs[imesa->vertex_attr_count].attrib = (ATTR);       \
897    imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE);      \
898    imesa->vertex_attr_count++;                                          \
899 } while (0)
900
901 #define NEED_ATTR( INDEX, SKIP )                                        \
902 do {                                                                    \
903    setupIndex |= (INDEX);                                               \
904    skip &= ~(SKIP);                                                     \
905 } while (0)
906
907 #define EMIT_ATTR( ATTR, STYLE, INDEX, SKIP )                           \
908 do {                                                                    \
909    NEED_ATTR( INDEX, SKIP );                                            \
910    DO_EMIT_ATTR( ATTR, STYLE );                                         \
911 } while (0)
912
913 #define EMIT_PAD( N )                                                   \
914 do {                                                                    \
915    imesa->vertex_attrs[imesa->vertex_attr_count].attrib = 0;            \
916    imesa->vertex_attrs[imesa->vertex_attr_count].format = EMIT_PAD;     \
917    imesa->vertex_attrs[imesa->vertex_attr_count].offset = (N);          \
918    imesa->vertex_attr_count++;                                          \
919 } while (0)
920
921 #define SAVAGE_EMIT_XYZ  0x0001
922 #define SAVAGE_EMIT_W    0x0002
923 #define SAVAGE_EMIT_C0   0x0004
924 #define SAVAGE_EMIT_C1   0x0008
925 #define SAVAGE_EMIT_FOG  0x0010
926 #define SAVAGE_EMIT_S0   0x0020
927 #define SAVAGE_EMIT_T0   0x0040
928 #define SAVAGE_EMIT_Q0   0x0080
929 #define SAVAGE_EMIT_ST0  0x0060
930 #define SAVAGE_EMIT_STQ0 0x00e0
931 #define SAVAGE_EMIT_S1   0x0100
932 #define SAVAGE_EMIT_T1   0x0200
933 #define SAVAGE_EMIT_ST1  0x0300
934
935
936 static INLINE GLuint savageChooseVertexFormat_s3d( struct gl_context *ctx )
937 {
938    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
939    TNLcontext *tnl = TNL_CONTEXT(ctx);
940    struct vertex_buffer *VB = &tnl->vb;
941    DECLARE_RENDERINPUTS(index_bitset);
942    GLuint setupIndex = SAVAGE_EMIT_XYZ;
943    GLubyte skip;
944
945    RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
946    imesa->vertex_attr_count = 0;
947
948    skip = SAVAGE_SKIP_ALL_S3D;
949    skip &= ~SAVAGE_SKIP_Z; /* all mesa vertices have a z coordinate */
950
951    /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
952     * build up a hardware vertex.
953     */
954    if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) || !(ctx->_TriangleCaps & DD_FLATSHADE))
955       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, SAVAGE_EMIT_W, SAVAGE_SKIP_W );
956    else {
957       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
958       EMIT_PAD( 4 );
959       skip &= ~SAVAGE_SKIP_W;
960    }
961
962    /* t_context.c always includes a diffuse color */
963    EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 );
964
965    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ))
966       EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 );
967    else
968       EMIT_PAD( 3 );
969    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
970       EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
971    else
972       EMIT_PAD( 1 );
973    skip &= ~SAVAGE_SKIP_C1;
974
975    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
976       if (imesa->ptexHack)
977          EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0);
978       else if (VB->AttribPtr[_TNL_ATTRIB_TEX0]->size == 4)
979          assert (0); /* should be caught by savageCheckPTexHack */
980       else if (VB->AttribPtr[_TNL_ATTRIB_TEX0]->size >= 2)
981          /* The chromium menu emits some 3D tex coords even though no
982           * 3D texture is enabled. Ignore the 3rd coordinate. */
983          EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, SAVAGE_EMIT_ST0, SAVAGE_SKIP_ST0 );
984       else if (VB->AttribPtr[_TNL_ATTRIB_TEX0]->size == 1) {
985          EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F, SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 );
986          EMIT_PAD( 4 );
987       } else
988          EMIT_PAD( 8 );
989    } else
990       EMIT_PAD( 8 );
991    skip &= ~SAVAGE_SKIP_ST0;
992
993    assert (skip == 0);
994    imesa->skip = skip;
995    return setupIndex;
996 }
997
998
999 static INLINE GLuint savageChooseVertexFormat_s4( struct gl_context *ctx )
1000 {
1001    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1002    TNLcontext *tnl = TNL_CONTEXT(ctx);
1003    struct vertex_buffer *VB = &tnl->vb;
1004    DECLARE_RENDERINPUTS(index_bitset);
1005    GLuint setupIndex = SAVAGE_EMIT_XYZ;
1006    GLubyte skip;
1007    GLuint size, mask;
1008
1009    RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
1010    skip = SAVAGE_SKIP_ALL_S4;
1011    skip &= ~SAVAGE_SKIP_Z; /* all mesa vertices have a z coordinate */
1012
1013    if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) || !(ctx->_TriangleCaps & DD_FLATSHADE))
1014       NEED_ATTR( SAVAGE_EMIT_W, SAVAGE_SKIP_W );
1015
1016    /* t_context.c always includes a diffuse color */
1017    NEED_ATTR( SAVAGE_EMIT_C0, SAVAGE_SKIP_C0 );
1018
1019    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ))
1020       NEED_ATTR( SAVAGE_EMIT_C1, SAVAGE_SKIP_C1 );
1021    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
1022       NEED_ATTR( SAVAGE_EMIT_FOG, SAVAGE_SKIP_C1 );
1023
1024    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
1025       if (imesa->ptexHack)
1026          NEED_ATTR( SAVAGE_EMIT_STQ0, SAVAGE_SKIP_ST0);
1027       else if (VB->AttribPtr[_TNL_ATTRIB_TEX0]->size == 4)
1028          assert (0); /* should be caught by savageCheckPTexHack */
1029       else if (VB->AttribPtr[_TNL_ATTRIB_TEX0]->size >= 2)
1030          /* The chromium menu emits some 3D tex coords even though no
1031           * 3D texture is enabled. Ignore the 3rd coordinate. */
1032          NEED_ATTR( SAVAGE_EMIT_ST0, SAVAGE_SKIP_ST0 );
1033       else
1034          NEED_ATTR( SAVAGE_EMIT_S0, SAVAGE_SKIP_S0 );
1035    }
1036    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) {
1037       if (VB->AttribPtr[_TNL_ATTRIB_TEX1]->size == 4)
1038          /* projective textures are not supported by the hardware */
1039          assert (0); /* should be caught by savageCheckPTexHack */
1040       else if (VB->AttribPtr[_TNL_ATTRIB_TEX1]->size >= 2)
1041          NEED_ATTR( SAVAGE_EMIT_ST1, SAVAGE_SKIP_ST1 );
1042       else
1043          NEED_ATTR( SAVAGE_EMIT_S1, SAVAGE_SKIP_S1 );
1044    }
1045
1046    /* if nothing changed we can skip the rest */
1047    if (setupIndex == imesa->SetupIndex && imesa->vertex_size != 0)
1048       return setupIndex;
1049
1050    if (imesa->enable_vdma) {
1051       mask = SAVAGE_SKIP_W;
1052       size = 10 - (skip & 1) - (skip >> 1 & 1) -
1053          (skip >> 2 & 1) - (skip >> 3 & 1) - (skip >> 4 & 1) -
1054          (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1);
1055
1056       while (size < 8) {
1057          if (skip & mask) {
1058             skip &= ~mask;
1059             size++;
1060          }
1061          mask <<= 1;
1062       }
1063    }
1064
1065    imesa->vertex_attr_count = 0;
1066
1067    if (skip & SAVAGE_SKIP_W)
1068       DO_EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT );
1069    else if (setupIndex & SAVAGE_EMIT_W)
1070       DO_EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT );
1071    else {
1072       DO_EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT );
1073       EMIT_PAD( 4 );
1074    }
1075
1076    DO_EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA );
1077
1078    if (!(skip & SAVAGE_SKIP_C1)) {
1079       if (!(setupIndex & (SAVAGE_EMIT_C1|SAVAGE_EMIT_FOG)))
1080          EMIT_PAD( 4 );
1081       else {
1082          if (setupIndex & SAVAGE_EMIT_C1)
1083             DO_EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR );
1084          else
1085             EMIT_PAD( 3 );
1086          if (setupIndex & SAVAGE_EMIT_FOG)
1087             DO_EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F );
1088          else
1089             EMIT_PAD( 1 );
1090       }
1091    }
1092
1093    if ((skip & SAVAGE_SKIP_ST0) != SAVAGE_SKIP_ST0) {
1094       if ((setupIndex & SAVAGE_EMIT_STQ0) == SAVAGE_EMIT_STQ0)
1095          DO_EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW );
1096       else if ((setupIndex & SAVAGE_EMIT_ST0) == SAVAGE_EMIT_ST0)
1097          DO_EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F );
1098       else if ((setupIndex & SAVAGE_EMIT_ST0) == SAVAGE_EMIT_S0) {
1099          DO_EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_1F );
1100          if (!(skip & SAVAGE_SKIP_T0)) EMIT_PAD( 4 );
1101       } else {
1102          if (!(skip & SAVAGE_SKIP_S0)) EMIT_PAD( 4 );
1103          if (!(skip & SAVAGE_SKIP_T0)) EMIT_PAD( 4 );
1104       }
1105    }
1106
1107    if ((skip & SAVAGE_SKIP_ST1) != SAVAGE_SKIP_ST1) {
1108       if ((setupIndex & SAVAGE_EMIT_ST1) == SAVAGE_EMIT_ST1)
1109          DO_EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F );
1110       else if ((setupIndex & SAVAGE_EMIT_ST1) == SAVAGE_EMIT_S1) {
1111          DO_EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_1F );
1112          if (!(skip & SAVAGE_SKIP_T1)) EMIT_PAD( 4 );
1113       } else {
1114          if (!(skip & SAVAGE_SKIP_S1)) EMIT_PAD( 4 );
1115          if (!(skip & SAVAGE_SKIP_T1)) EMIT_PAD( 4 );
1116       }
1117    }
1118
1119    imesa->skip = skip;
1120    return setupIndex;
1121 }
1122
1123
1124 static void savageRenderStart( struct gl_context *ctx )
1125 {
1126    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1127    TNLcontext *tnl = TNL_CONTEXT(ctx);
1128    struct vertex_buffer *VB = &tnl->vb;
1129    GLuint setupIndex = SAVAGE_EMIT_XYZ;
1130    GLboolean ptexHack;
1131
1132    /* Check if we need to apply the ptex hack. Choose a new render
1133     * state if necessary. (Note: this can't be done in
1134     * savageRunPipeline, since the number of vertex coordinates can
1135     * change in the pipeline. texmat or texgen or both?) */
1136    ptexHack = savageCheckPTexHack( ctx );
1137    if (ptexHack != imesa->ptexHack) {
1138       imesa->ptexHack = ptexHack;
1139       savageChooseRenderState (ctx);
1140    }
1141    /* Handle fallback cases identified in savageCheckPTexHack. */
1142    if (SAVAGE_CONTEXT(ctx)->Fallback) {
1143       tnl->Driver.Render.Start(ctx);
1144       return;
1145    }
1146
1147    /* Important:
1148     */
1149    VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
1150  
1151    if (imesa->savageScreen->chipset < S3_SAVAGE4) {
1152       setupIndex = savageChooseVertexFormat_s3d(ctx);
1153    } else {
1154       setupIndex = savageChooseVertexFormat_s4(ctx);
1155    }
1156
1157    /* Need to change the vertex emit code if the SetupIndex changed or
1158     * is set for the first time (indicated by vertex_size == 0). */
1159    if (setupIndex != imesa->SetupIndex || imesa->vertex_size == 0) {
1160       GLuint hwVertexSize;
1161       imesa->vertex_size =
1162          _tnl_install_attrs( ctx, 
1163                              imesa->vertex_attrs, 
1164                              imesa->vertex_attr_count,
1165                              imesa->hw_viewport, 0 );
1166       imesa->vertex_size >>= 2;
1167       imesa->SetupIndex = setupIndex;
1168
1169       hwVertexSize = imesa->vertex_size;
1170       if (setupIndex & SAVAGE_EMIT_Q0) {
1171          /* The vertex setup code emits homogenous texture
1172           * coordinates. They are converted to normal 2D coords by
1173           * savage_ptex_tri/line/point. Now we have two different
1174           * vertex sizes. Functions that emit vertices to the hardware
1175           * need to use HwVertexSize, anything that manipulates the
1176           * vertices generated by t_vertex uses vertex_size. */
1177          hwVertexSize--;
1178          assert (imesa->ptexHack);
1179       } else
1180          assert (!imesa->ptexHack);
1181
1182       if (hwVertexSize != imesa->HwVertexSize) {
1183          /* Changing the vertex size: flush vertex and command buffer and
1184           * discard the DMA buffer, if we were using one. */
1185          savageFlushVertices(imesa);
1186          savageFlushCmdBuf(imesa, GL_TRUE);
1187          if (hwVertexSize == 8 && imesa->enable_vdma) {
1188             if (SAVAGE_DEBUG & DEBUG_DMA)
1189                fprintf (stderr, "Using DMA, skip=0x%02x\n", imesa->skip);
1190             /* we can use vertex dma */
1191             imesa->vtxBuf = &imesa->dmaVtxBuf;
1192          } else {
1193             if (SAVAGE_DEBUG & DEBUG_DMA)
1194                fprintf (stderr, "Not using DMA, skip=0x%02x\n", imesa->skip);
1195             imesa->vtxBuf = &imesa->clientVtxBuf;
1196          }
1197          imesa->HwVertexSize = hwVertexSize;
1198       }
1199    }
1200 }
1201
1202 static void savageRenderFinish( struct gl_context *ctx )
1203 {
1204    /* Flush the last primitive now, before any state is changed. */
1205    savageFlushVertices(SAVAGE_CONTEXT(ctx));
1206
1207    if (SAVAGE_CONTEXT(ctx)->RenderIndex & SAVAGE_FALLBACK_BIT)
1208       _swrast_flush( ctx );
1209 }
1210
1211
1212 /**********************************************************************/
1213 /*           Transition to/from hardware rasterization.               */
1214 /**********************************************************************/
1215
1216 static const char * const fallbackStrings[] = {
1217    "Texture mode",
1218    "Draw buffer",
1219    "Read buffer",
1220    "Color mask",
1221    "Specular",
1222    "LogicOp",
1223    "glEnable(GL_STENCIL) without hw stencil buffer",
1224    "glRenderMode(selection or feedback)",
1225    "glBlendEquation",
1226    "Hardware rasterization disabled",
1227    "Projective texture",
1228 };
1229
1230 void savageFallback( struct gl_context *ctx, GLuint bit, GLboolean mode )
1231 {
1232    TNLcontext *tnl = TNL_CONTEXT(ctx);
1233    savageContextPtr imesa = SAVAGE_CONTEXT(ctx);
1234    GLuint oldfallback = imesa->Fallback;
1235    GLuint index;
1236    for (index = 0; (1 << index) < bit; ++index);
1237
1238    if (mode) {
1239       imesa->Fallback |= bit;
1240       if (oldfallback == 0) {
1241          /* the first fallback */
1242          _swsetup_Wakeup( ctx );
1243          imesa->RenderIndex = ~0;
1244       }
1245       if (!(oldfallback & bit) && (SAVAGE_DEBUG & DEBUG_FALLBACKS))
1246          fprintf (stderr, "Savage begin fallback: 0x%x %s\n",
1247                   bit, fallbackStrings[index]);
1248    }
1249    else {
1250       imesa->Fallback &= ~bit;
1251       if (oldfallback == bit) {
1252          /* the last fallback */
1253          _swrast_flush( ctx );
1254          tnl->Driver.Render.Start = savageRenderStart;
1255          tnl->Driver.Render.PrimitiveNotify = savageRenderPrimitive;
1256          tnl->Driver.Render.Finish = savageRenderFinish;
1257
1258          tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1259          tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1260          tnl->Driver.Render.Interp = _tnl_interp;
1261
1262          _tnl_invalidate_vertex_state( ctx, ~0 );
1263          _tnl_invalidate_vertices( ctx, ~0 );
1264          _tnl_install_attrs( ctx, 
1265                              imesa->vertex_attrs, 
1266                              imesa->vertex_attr_count,
1267                              imesa->hw_viewport, 0 ); 
1268
1269          imesa->new_gl_state |= _SAVAGE_NEW_RENDER_STATE;
1270       }
1271       if ((oldfallback & bit) && (SAVAGE_DEBUG & DEBUG_FALLBACKS))
1272          fprintf (stderr, "Savage end fallback: 0x%x %s\n",
1273                   bit, fallbackStrings[index]);
1274    }
1275 }
1276
1277
1278 /**********************************************************************/
1279 /*                            Initialization.                         */
1280 /**********************************************************************/
1281
1282 void savageInitTriFuncs( struct gl_context *ctx )
1283 {
1284    TNLcontext *tnl = TNL_CONTEXT(ctx);
1285    static int firsttime = 1;
1286
1287    if (firsttime) {
1288       init_rast_tab();
1289       firsttime = 0;
1290    }
1291
1292    tnl->Driver.RunPipeline = savageRunPipeline;
1293    tnl->Driver.Render.Start = savageRenderStart;
1294    tnl->Driver.Render.Finish = savageRenderFinish;
1295    tnl->Driver.Render.PrimitiveNotify = savageRenderPrimitive;
1296    tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
1297
1298    tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1299    tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1300    tnl->Driver.Render.Interp = _tnl_interp;
1301
1302    _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 
1303                        (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
1304    
1305    SAVAGE_CONTEXT(ctx)->verts = (char *)tnl->clipspace.vertex_buf;
1306 }