Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / mesa / drivers / dri / unichrome / via_tris.c
1 /*
2  * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3  * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sub license,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial portions
14  * of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19  * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24
25 #include <stdio.h>
26 #include <math.h>
27
28 #include "main/glheader.h"
29 #include "main/context.h"
30 #include "main/mtypes.h"
31 #include "main/macros.h"
32 #include "main/colormac.h"
33 #include "main/enums.h"
34
35 #include "swrast/swrast.h"
36 #include "swrast_setup/swrast_setup.h"
37 #include "tnl/t_context.h"
38 #include "tnl/t_pipeline.h"
39
40 #include "via_context.h"
41 #include "via_tris.h"
42 #include "via_state.h"
43 #include "via_span.h"
44 #include "via_ioctl.h"
45 #include "via_3d_reg.h"
46 #include "via_tex.h"
47
48 /***********************************************************************
49  *                    Emit primitives as inline vertices               *
50  ***********************************************************************/
51 #define LINE_FALLBACK (0)
52 #define POINT_FALLBACK (0)
53 #define TRI_FALLBACK (0)
54 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
55 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
56
57
58 #if 0
59 #define COPY_DWORDS(vb, vertsize, v)            \
60 do {                                            \
61    via_sse_memcpy(vb, v, vertsize * 4);         \
62    vb += vertsize;                              \
63 } while (0)
64 #else
65 #if defined( USE_X86_ASM )
66 #define COPY_DWORDS(vb, vertsize, v)                                    \
67     do {                                                                \
68         int j;                                                          \
69         int __tmp;                                                      \
70         __asm__ __volatile__("rep ; movsl"                              \
71                               : "=%c" (j), "=D" (vb), "=S" (__tmp)      \
72                               : "0" (vertsize),                         \
73                                 "D" ((long)vb),                         \
74                                 "S" ((long)v));                         \
75     } while (0)
76 #else
77 #define COPY_DWORDS(vb, vertsize, v)            \
78     do {                                        \
79         int j;                                  \
80         for (j = 0; j < vertsize; j++)          \
81             vb[j] = ((GLuint *)v)[j];           \
82         vb += vertsize;                         \
83     } while (0)
84 #endif
85 #endif
86
87 static void via_draw_triangle(struct via_context *vmesa,
88                               viaVertexPtr v0,
89                               viaVertexPtr v1,
90                               viaVertexPtr v2)
91 {
92    GLuint vertsize = vmesa->vertexSize;
93    GLuint *vb = viaExtendPrimitive(vmesa, 3 * 4 * vertsize);
94
95    COPY_DWORDS(vb, vertsize, v0);
96    COPY_DWORDS(vb, vertsize, v1);
97    COPY_DWORDS(vb, vertsize, v2);
98 }
99
100
101 static void via_draw_quad(struct via_context *vmesa,
102                           viaVertexPtr v0,
103                           viaVertexPtr v1,
104                           viaVertexPtr v2,
105                           viaVertexPtr v3)
106 {
107    GLuint vertsize = vmesa->vertexSize;
108    GLuint *vb = viaExtendPrimitive(vmesa, 6 * 4 * vertsize);
109
110    COPY_DWORDS(vb, vertsize, v0);
111    COPY_DWORDS(vb, vertsize, v1);
112    COPY_DWORDS(vb, vertsize, v3);
113    COPY_DWORDS(vb, vertsize, v1);
114    COPY_DWORDS(vb, vertsize, v2);
115    COPY_DWORDS(vb, vertsize, v3);
116 }
117
118 static void via_draw_line(struct via_context *vmesa,
119                           viaVertexPtr v0,
120                           viaVertexPtr v1)
121 {
122    GLuint vertsize = vmesa->vertexSize;
123    GLuint *vb = viaExtendPrimitive(vmesa, 2 * 4 * vertsize);
124    COPY_DWORDS(vb, vertsize, v0);
125    COPY_DWORDS(vb, vertsize, v1);
126 }
127
128
129 static void via_draw_point(struct via_context *vmesa,
130                            viaVertexPtr v0)
131 {
132    GLuint vertsize = vmesa->vertexSize;
133    GLuint *vb = viaExtendPrimitive(vmesa, 4 * vertsize);
134    COPY_DWORDS(vb, vertsize, v0);
135 }
136
137
138 /* Fallback drawing functions for the ptex hack.
139  */
140 #define PTEX_VERTEX( tmp, vertex_size, v)       \
141 do {                                                    \
142    GLuint j;                                            \
143    GLfloat rhw = 1.0 / v->f[vertex_size];               \
144    for ( j = 0 ; j < vertex_size ; j++ )                \
145       tmp.f[j] = v->f[j];                               \
146    tmp.f[3] *= v->f[vertex_size];                       \
147    tmp.f[vertex_size-2] *= rhw;                         \
148    tmp.f[vertex_size-1] *= rhw;                         \
149 } while (0)
150
151 static void via_ptex_tri (struct via_context *vmesa,
152                           viaVertexPtr v0,
153                           viaVertexPtr v1,
154                           viaVertexPtr v2)
155 {
156    GLuint vertsize = vmesa->hwVertexSize;
157    GLuint *vb = viaExtendPrimitive(vmesa, 3*4*vertsize);
158    viaVertex tmp;
159
160    PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
161    PTEX_VERTEX(tmp, vertsize, v1); COPY_DWORDS(vb, vertsize, &tmp);
162    PTEX_VERTEX(tmp, vertsize, v2); COPY_DWORDS(vb, vertsize, &tmp);
163 }
164
165 static void via_ptex_line (struct via_context *vmesa,
166                            viaVertexPtr v0,
167                            viaVertexPtr v1)
168 {
169    GLuint vertsize = vmesa->hwVertexSize;
170    GLuint *vb = viaExtendPrimitive(vmesa, 2*4*vertsize);
171    viaVertex tmp;
172
173    PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
174    PTEX_VERTEX(tmp, vertsize, v1); COPY_DWORDS(vb, vertsize, &tmp);
175 }
176
177 static void via_ptex_point (struct via_context *vmesa,
178                             viaVertexPtr v0)
179 {
180    GLuint vertsize = vmesa->hwVertexSize;
181    GLuint *vb = viaExtendPrimitive(vmesa, 1*4*vertsize);
182    viaVertex tmp;
183
184    PTEX_VERTEX(tmp, vertsize, v0); COPY_DWORDS(vb, vertsize, &tmp);
185 }
186
187
188
189
190
191 /***********************************************************************
192  *          Macros for via_dd_tritmp.h to draw basic primitives        *
193  ***********************************************************************/
194
195 #define TRI(a, b, c)                                \
196     do {                                            \
197         if (DO_FALLBACK)                            \
198             vmesa->drawTri(vmesa, a, b, c);         \
199         else                                        \
200             via_draw_triangle(vmesa, a, b, c);      \
201     } while (0)
202
203 #define QUAD(a, b, c, d)                            \
204     do {                                            \
205         if (DO_FALLBACK) {                          \
206             vmesa->drawTri(vmesa, a, b, d);         \
207             vmesa->drawTri(vmesa, b, c, d);         \
208         }                                           \
209         else                                        \
210             via_draw_quad(vmesa, a, b, c, d);       \
211     } while (0)
212
213 #define LINE(v0, v1)                                \
214     do {                                            \
215         if (DO_FALLBACK)                            \
216             vmesa->drawLine(vmesa, v0, v1);         \
217         else                                        \
218             via_draw_line(vmesa, v0, v1);           \
219     } while (0)
220
221 #define POINT(v0)                                    \
222     do {                                             \
223         if (DO_FALLBACK)                             \
224             vmesa->drawPoint(vmesa, v0);             \
225         else                                         \
226             via_draw_point(vmesa, v0);               \
227     } while (0)
228
229
230 /***********************************************************************
231  *              Build render functions from dd templates               *
232  ***********************************************************************/
233
234 #define VIA_OFFSET_BIT         0x01
235 #define VIA_TWOSIDE_BIT        0x02
236 #define VIA_UNFILLED_BIT       0x04
237 #define VIA_FALLBACK_BIT       0x08
238 #define VIA_MAX_TRIFUNC        0x10
239
240
241 static struct {
242     tnl_points_func          points;
243     tnl_line_func            line;
244     tnl_triangle_func        triangle;
245     tnl_quad_func            quad;
246 } rast_tab[VIA_MAX_TRIFUNC + 1];
247
248
249 #define DO_FALLBACK (IND & VIA_FALLBACK_BIT)
250 #define DO_OFFSET   (IND & VIA_OFFSET_BIT)
251 #define DO_UNFILLED (IND & VIA_UNFILLED_BIT)
252 #define DO_TWOSIDE  (IND & VIA_TWOSIDE_BIT)
253 #define DO_FLAT      0
254 #define DO_TRI       1
255 #define DO_QUAD      1
256 #define DO_LINE      1
257 #define DO_POINTS    1
258 #define DO_FULL_QUAD 1
259
260 #define HAVE_SPEC         1
261 #define HAVE_BACK_COLORS  0
262 #define HAVE_HW_FLATSHADE 1
263 #define VERTEX            viaVertex
264 #define TAB               rast_tab
265
266 /* Only used to pull back colors into vertices (ie, we know color is
267  * floating point).
268  */
269 #define VIA_COLOR(dst, src)                     \
270     do {                                        \
271         dst[0] = src[2];                        \
272         dst[1] = src[1];                        \
273         dst[2] = src[0];                        \
274         dst[3] = src[3];                        \
275     } while (0)
276
277 #define VIA_SPEC(dst, src)                      \
278     do {                                        \
279         dst[0] = src[2];                        \
280         dst[1] = src[1];                        \
281         dst[2] = src[0];                        \
282     } while (0)
283
284
285 #define DEPTH_SCALE vmesa->polygon_offset_scale
286 #define UNFILLED_TRI unfilled_tri
287 #define UNFILLED_QUAD unfilled_quad
288 #define VERT_X(_v) _v->v.x
289 #define VERT_Y(_v) _v->v.y
290 #define VERT_Z(_v) _v->v.z
291 #define AREA_IS_CCW(a) (a > 0)
292 #define GET_VERTEX(e) (vmesa->verts + (e * vmesa->vertexSize * sizeof(int)))
293
294 #define VERT_SET_RGBA( v, c )                                   \
295 do {                                                            \
296    via_color_t *color = (via_color_t *)&((v)->ui[coloroffset]); \
297    UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]);                \
298    UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]);              \
299    UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]);               \
300    UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]);              \
301 } while (0)
302
303 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
304
305 #define VERT_SET_SPEC( v, c )                                   \
306 do {                                                            \
307    if (specoffset) {                                            \
308      via_color_t *color = (via_color_t *)&((v)->ui[specoffset]);        \
309      UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]);              \
310      UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]);            \
311      UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]);             \
312    }                                                            \
313 } while (0)
314 #define VERT_COPY_SPEC( v0, v1 )                        \
315 do {                                                    \
316    if (specoffset) {                                    \
317       v0->ub4[specoffset][0] = v1->ub4[specoffset][0];  \
318       v0->ub4[specoffset][1] = v1->ub4[specoffset][1];  \
319       v0->ub4[specoffset][2] = v1->ub4[specoffset][2];  \
320    }                                                    \
321 } while (0)
322
323
324 #define VERT_SAVE_RGBA( idx )    color[idx] = v[idx]->ui[coloroffset]
325 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
326 #define VERT_SAVE_SPEC( idx )    if (specoffset) spec[idx] = v[idx]->ui[specoffset]
327 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
328
329
330 #define LOCAL_VARS(n)                                                   \
331     struct via_context *vmesa = VIA_CONTEXT(ctx);                             \
332     GLuint color[n] = { 0 };                                          \
333     GLuint spec[n] = { 0 };                                           \
334     GLuint coloroffset = vmesa->coloroffset;              \
335     GLuint specoffset = vmesa->specoffset;                       \
336     (void)color; (void)spec; (void)coloroffset; (void)specoffset;
337
338
339 /***********************************************************************
340  *                Helpers for rendering unfilled primitives            *
341  ***********************************************************************/
342
343 static const GLenum hwPrim[GL_POLYGON + 2] = {
344     GL_POINTS,
345     GL_LINES,
346     GL_LINES,
347     GL_LINES,
348     GL_TRIANGLES,
349     GL_TRIANGLES,
350     GL_TRIANGLES,
351     GL_TRIANGLES,
352     GL_TRIANGLES,
353     GL_TRIANGLES,
354     GL_POLYGON+1
355 };
356
357
358 #define RASTERIZE(x) viaRasterPrimitive( ctx, x, hwPrim[x] )
359 #define RENDER_PRIMITIVE vmesa->renderPrimitive
360 #define TAG(x) x
361 #define IND VIA_FALLBACK_BIT
362 #include "tnl_dd/t_dd_unfilled.h"
363 #undef IND
364 #undef RASTERIZE
365
366 /***********************************************************************
367  *                      Generate GL render functions                   *
368  ***********************************************************************/
369 #define RASTERIZE(x)
370
371 #define IND (0)
372 #define TAG(x) x
373 #include "tnl_dd/t_dd_tritmp.h"
374
375 #define IND (VIA_OFFSET_BIT)
376 #define TAG(x) x##_offset
377 #include "tnl_dd/t_dd_tritmp.h"
378
379 #define IND (VIA_TWOSIDE_BIT)
380 #define TAG(x) x##_twoside
381 #include "tnl_dd/t_dd_tritmp.h"
382
383 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT)
384 #define TAG(x) x##_twoside_offset
385 #include "tnl_dd/t_dd_tritmp.h"
386
387 #define IND (VIA_UNFILLED_BIT)
388 #define TAG(x) x##_unfilled
389 #include "tnl_dd/t_dd_tritmp.h"
390
391 #define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT)
392 #define TAG(x) x##_offset_unfilled
393 #include "tnl_dd/t_dd_tritmp.h"
394
395 #define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT)
396 #define TAG(x) x##_twoside_unfilled
397 #include "tnl_dd/t_dd_tritmp.h"
398
399 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT)
400 #define TAG(x) x##_twoside_offset_unfilled
401 #include "tnl_dd/t_dd_tritmp.h"
402
403 #define IND (VIA_FALLBACK_BIT)
404 #define TAG(x) x##_fallback
405 #include "tnl_dd/t_dd_tritmp.h"
406
407 #define IND (VIA_OFFSET_BIT|VIA_FALLBACK_BIT)
408 #define TAG(x) x##_offset_fallback
409 #include "tnl_dd/t_dd_tritmp.h"
410
411 #define IND (VIA_TWOSIDE_BIT|VIA_FALLBACK_BIT)
412 #define TAG(x) x##_twoside_fallback
413 #include "tnl_dd/t_dd_tritmp.h"
414
415 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_FALLBACK_BIT)
416 #define TAG(x) x##_twoside_offset_fallback
417 #include "tnl_dd/t_dd_tritmp.h"
418
419 #define IND (VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
420 #define TAG(x) x##_unfilled_fallback
421 #include "tnl_dd/t_dd_tritmp.h"
422
423 #define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
424 #define TAG(x) x##_offset_unfilled_fallback
425 #include "tnl_dd/t_dd_tritmp.h"
426
427 #define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
428 #define TAG(x) x##_twoside_unfilled_fallback
429 #include "tnl_dd/t_dd_tritmp.h"
430
431 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT| \
432              VIA_FALLBACK_BIT)
433 #define TAG(x) x##_twoside_offset_unfilled_fallback
434 #include "tnl_dd/t_dd_tritmp.h"
435
436
437 /* Catchall case for flat, separate specular triangles (via has flat
438  * diffuse shading, but always does specular color with gouraud).
439  */
440 #undef  DO_FALLBACK
441 #undef  DO_OFFSET
442 #undef  DO_UNFILLED
443 #undef  DO_TWOSIDE
444 #undef  DO_FLAT
445 #define DO_FALLBACK (0)
446 #define DO_OFFSET   (ctx->_TriangleCaps & DD_TRI_OFFSET)
447 #define DO_UNFILLED (ctx->_TriangleCaps & DD_TRI_UNFILLED)
448 #define DO_TWOSIDE  (ctx->_TriangleCaps & DD_TRI_LIGHT_TWOSIDE)
449 #define DO_FLAT     1
450 #define TAG(x) x##_flat_specular
451 #define IND VIA_MAX_TRIFUNC
452 #include "tnl_dd/t_dd_tritmp.h"
453
454
455 static void init_rast_tab(void)
456 {
457     init();
458     init_offset();
459     init_twoside();
460     init_twoside_offset();
461     init_unfilled();
462     init_offset_unfilled();
463     init_twoside_unfilled();
464     init_twoside_offset_unfilled();
465     init_fallback();
466     init_offset_fallback();
467     init_twoside_fallback();
468     init_twoside_offset_fallback();
469     init_unfilled_fallback();
470     init_offset_unfilled_fallback();
471     init_twoside_unfilled_fallback();
472     init_twoside_offset_unfilled_fallback();
473
474     init_flat_specular();       /* special! */
475 }
476
477
478 /***********************************************************************
479  *                    Rasterization fallback helpers                   *
480  ***********************************************************************/
481
482
483 /* This code is hit only when a mix of accelerated and unaccelerated
484  * primitives are being drawn, and only for the unaccelerated
485  * primitives.
486  */
487 static void
488 via_fallback_tri(struct via_context *vmesa,
489                  viaVertex *v0,
490                  viaVertex *v1,
491                  viaVertex *v2)
492 {    
493     struct gl_context *ctx = vmesa->glCtx;
494     SWvertex v[3];
495     _swsetup_Translate(ctx, v0, &v[0]);
496     _swsetup_Translate(ctx, v1, &v[1]);
497     _swsetup_Translate(ctx, v2, &v[2]);
498     viaSpanRenderStart( ctx );
499     _swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
500     viaSpanRenderFinish( ctx );
501 }
502
503
504 static void
505 via_fallback_line(struct via_context *vmesa,
506                   viaVertex *v0,
507                   viaVertex *v1)
508 {
509     struct gl_context *ctx = vmesa->glCtx;
510     SWvertex v[2];
511     _swsetup_Translate(ctx, v0, &v[0]);
512     _swsetup_Translate(ctx, v1, &v[1]);
513     viaSpanRenderStart( ctx );
514     _swrast_Line(ctx, &v[0], &v[1]);
515     viaSpanRenderFinish( ctx );
516 }
517
518
519 static void
520 via_fallback_point(struct via_context *vmesa,
521                    viaVertex *v0)
522 {
523     struct gl_context *ctx = vmesa->glCtx;
524     SWvertex v[1];
525     _swsetup_Translate(ctx, v0, &v[0]);
526     viaSpanRenderStart( ctx );
527     _swrast_Point(ctx, &v[0]);
528     viaSpanRenderFinish( ctx );
529 }
530
531 static void viaResetLineStipple( struct gl_context *ctx )
532 {
533    struct via_context *vmesa = VIA_CONTEXT(ctx);
534    vmesa->regCmdB |= HC_HLPrst_MASK;
535 }
536
537 /**********************************************************************/
538 /*               Render unclipped begin/end objects                   */
539 /**********************************************************************/
540 #define IND 0
541 #define V(x) (viaVertex *)(vertptr + ((x) * vertsize * sizeof(int)))
542 #define RENDER_POINTS(start, count)   \
543     for (; start < count; start++) POINT(V(ELT(start)));
544 #define RENDER_LINE(v0, v1)         LINE(V(v0), V(v1))
545 #define RENDER_TRI( v0, v1, v2)     TRI( V(v0), V(v1), V(v2))
546 #define RENDER_QUAD(v0, v1, v2, v3) QUAD(V(v0), V(v1), V(v2), V(v3))
547 #define INIT(x) viaRasterPrimitive(ctx, x, hwPrim[x])
548 #undef LOCAL_VARS
549 #define LOCAL_VARS                                              \
550     struct via_context *vmesa = VIA_CONTEXT(ctx);                     \
551     GLubyte *vertptr = (GLubyte *)vmesa->verts;                 \
552     const GLuint vertsize = vmesa->vertexSize;          \
553     const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;       \
554    const GLboolean stipple = ctx->Line.StippleFlag;             \
555    (void) elt; (void) stipple;
556 #define RESET_STIPPLE   if ( stipple ) viaResetLineStipple( ctx );
557 #define RESET_OCCLUSION
558 #define PRESERVE_VB_DEFS
559 #define ELT(x) x
560 #define TAG(x) via_##x##_verts
561 #include "tnl/t_vb_rendertmp.h"
562 #undef ELT
563 #undef TAG
564 #define TAG(x) via_##x##_elts
565 #define ELT(x) elt[x]
566 #include "tnl/t_vb_rendertmp.h"
567 #undef ELT
568 #undef TAG
569 #undef NEED_EDGEFLAG_SETUP
570 #undef EDGEFLAG_GET
571 #undef EDGEFLAG_SET
572 #undef RESET_OCCLUSION
573
574
575 /**********************************************************************/
576 /*                   Render clipped primitives                        */
577 /**********************************************************************/
578
579
580
581 static void viaRenderClippedPoly(struct gl_context *ctx, const GLuint *elts,
582                                  GLuint n)
583 {
584     TNLcontext *tnl = TNL_CONTEXT(ctx);
585     struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
586     GLuint prim = VIA_CONTEXT(ctx)->renderPrimitive;
587
588     /* Render the new vertices as an unclipped polygon.
589      */
590     {
591         GLuint *tmp = VB->Elts;
592         VB->Elts = (GLuint *)elts;
593         tnl->Driver.Render.PrimTabElts[GL_POLYGON](ctx, 0, n,
594                                                    PRIM_BEGIN|PRIM_END);
595         VB->Elts = tmp;
596     }
597
598     /* Restore the render primitive
599      */
600     if (prim != GL_POLYGON &&
601         prim != GL_POLYGON + 1)
602        tnl->Driver.Render.PrimitiveNotify( ctx, prim );
603 }
604
605 static void viaRenderClippedLine(struct gl_context *ctx, GLuint ii, GLuint jj)
606 {
607     TNLcontext *tnl = TNL_CONTEXT(ctx);
608     tnl->Driver.Render.Line(ctx, ii, jj);
609 }
610
611 static void viaFastRenderClippedPoly(struct gl_context *ctx, const GLuint *elts,
612                                      GLuint n)
613 {
614     struct via_context *vmesa = VIA_CONTEXT(ctx);
615     GLuint vertsize = vmesa->vertexSize;
616     GLuint *vb = viaExtendPrimitive(vmesa, (n - 2) * 3 * 4 * vertsize);
617     GLubyte *vertptr = (GLubyte *)vmesa->verts;
618     const GLuint *start = (const GLuint *)V(elts[0]);
619     int i;
620
621     for (i = 2; i < n; i++) {
622         COPY_DWORDS(vb, vertsize, V(elts[i - 1]));
623         COPY_DWORDS(vb, vertsize, V(elts[i]));
624         COPY_DWORDS(vb, vertsize, start);       
625     }
626 }
627
628
629 /**********************************************************************/
630 /*                    Choose render functions                         */
631 /**********************************************************************/
632
633
634 #define _VIA_NEW_VERTEX (_NEW_TEXTURE |                         \
635                          _DD_NEW_SEPARATE_SPECULAR |            \
636                          _DD_NEW_TRI_UNFILLED |                 \
637                          _DD_NEW_TRI_LIGHT_TWOSIDE |            \
638                          _NEW_FOG)
639
640 #define _VIA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE |            \
641                               _DD_NEW_TRI_UNFILLED |            \
642                               _DD_NEW_TRI_LIGHT_TWOSIDE |       \
643                               _DD_NEW_TRI_OFFSET |              \
644                               _DD_NEW_TRI_STIPPLE |             \
645                               _NEW_POLYGONSTIPPLE)
646
647
648 static void viaChooseRenderState(struct gl_context *ctx)
649 {
650    TNLcontext *tnl = TNL_CONTEXT(ctx);
651    struct via_context *vmesa = VIA_CONTEXT(ctx);
652    GLuint flags = ctx->_TriangleCaps;
653    GLuint index = 0;
654
655    if (vmesa->ptexHack) {
656       vmesa->drawPoint = via_ptex_point;
657       vmesa->drawLine = via_ptex_line;
658       vmesa->drawTri = via_ptex_tri;
659       index |= VIA_FALLBACK_BIT;
660    }
661    else {
662       vmesa->drawPoint = via_draw_point;
663       vmesa->drawLine = via_draw_line;
664       vmesa->drawTri = via_draw_triangle;
665    }
666
667    if (flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) {
668       if (ctx->Light.Enabled && ctx->Light.Model.TwoSide)
669          index |= VIA_TWOSIDE_BIT;
670       if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
671          index |= VIA_UNFILLED_BIT;
672       if (flags & DD_TRI_OFFSET)
673          index |= VIA_OFFSET_BIT;
674       if (flags & ANY_FALLBACK_FLAGS)
675          index |= VIA_FALLBACK_BIT;
676
677       /* Hook in fallbacks for specific primitives. */
678       if (flags & POINT_FALLBACK)
679          vmesa->drawPoint = via_fallback_point;
680       
681       if (flags & LINE_FALLBACK)
682          vmesa->drawLine = via_fallback_line;
683
684       if (flags & TRI_FALLBACK)
685          vmesa->drawTri = via_fallback_tri;
686    }
687
688    if ((flags & DD_SEPARATE_SPECULAR) && ctx->Light.ShadeModel == GL_FLAT)
689       index = VIA_MAX_TRIFUNC;  /* flat specular */
690
691    if (vmesa->renderIndex != index) {
692       vmesa->renderIndex = index;
693
694       tnl->Driver.Render.Points = rast_tab[index].points;
695       tnl->Driver.Render.Line = rast_tab[index].line;
696       tnl->Driver.Render.Triangle = rast_tab[index].triangle;
697       tnl->Driver.Render.Quad = rast_tab[index].quad;
698
699       if (index == 0) {
700          tnl->Driver.Render.PrimTabVerts = via_render_tab_verts;
701          tnl->Driver.Render.PrimTabElts = via_render_tab_elts;
702          tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
703          tnl->Driver.Render.ClippedPolygon = viaFastRenderClippedPoly;
704       }
705       else {
706          tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
707          tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
708          tnl->Driver.Render.ClippedLine = viaRenderClippedLine;
709          tnl->Driver.Render.ClippedPolygon = viaRenderClippedPoly;
710       }
711    }
712 }
713
714
715 #define VIA_EMIT_TEX1   0x01
716 #define VIA_EMIT_TEX0   0x02
717 #define VIA_EMIT_PTEX0  0x04
718 #define VIA_EMIT_RGBA   0x08
719 #define VIA_EMIT_SPEC   0x10
720 #define VIA_EMIT_FOG    0x20
721 #define VIA_EMIT_W      0x40
722
723 #define EMIT_ATTR( ATTR, STYLE, INDEX, REGB )                           \
724 do {                                                                    \
725    vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = (ATTR);       \
726    vmesa->vertex_attrs[vmesa->vertex_attr_count].format = (STYLE);      \
727    vmesa->vertex_attr_count++;                                          \
728    setupIndex |= (INDEX);                                               \
729    regCmdB |= (REGB);                                                   \
730 } while (0)
731
732 #define EMIT_PAD( N )                                                   \
733 do {                                                                    \
734    vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = 0;            \
735    vmesa->vertex_attrs[vmesa->vertex_attr_count].format = EMIT_PAD;     \
736    vmesa->vertex_attrs[vmesa->vertex_attr_count].offset = (N);          \
737    vmesa->vertex_attr_count++;                                          \
738 } while (0)
739
740
741
742 static void viaChooseVertexState( struct gl_context *ctx )
743 {
744    struct via_context *vmesa = VIA_CONTEXT(ctx);
745    TNLcontext *tnl = TNL_CONTEXT(ctx);
746    DECLARE_RENDERINPUTS(index_bitset);
747    GLuint regCmdB = HC_HVPMSK_X | HC_HVPMSK_Y | HC_HVPMSK_Z;
748    GLuint setupIndex = 0;
749
750    RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
751    vmesa->vertex_attr_count = 0;
752  
753    /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
754     * build up a hardware vertex.
755     */
756    if (RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_FIRST_TEX, _TNL_LAST_TEX ) ||
757        RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
758       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F_VIEWPORT, VIA_EMIT_W, HC_HVPMSK_W );
759       vmesa->coloroffset = 4;
760    }
761    else {
762       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F_VIEWPORT, 0, 0 );
763       vmesa->coloroffset = 3;
764    }
765
766    /* t_context.c always includes a diffuse color */
767    EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_BGRA, VIA_EMIT_RGBA, 
768               HC_HVPMSK_Cd );
769       
770    vmesa->specoffset = 0;
771    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 ) ||
772        RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG )) {
773       if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_COLOR1 )) {
774          vmesa->specoffset = vmesa->coloroffset + 1;
775          EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, VIA_EMIT_SPEC, 
776                     HC_HVPMSK_Cs );
777       }
778       else
779          EMIT_PAD( 3 );
780
781       if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_FOG ))
782          EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, VIA_EMIT_FOG, HC_HVPMSK_Cs );
783       else
784          EMIT_PAD( 1 );
785    }
786
787    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 )) {
788       if (vmesa->ptexHack)
789          EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_3F_XYW, VIA_EMIT_PTEX0, 
790                     (HC_HVPMSK_S | HC_HVPMSK_T) );
791       else 
792          EMIT_ATTR( _TNL_ATTRIB_TEX0, EMIT_2F, VIA_EMIT_TEX0, 
793                     (HC_HVPMSK_S | HC_HVPMSK_T) );
794    }
795
796    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 )) {
797       EMIT_ATTR( _TNL_ATTRIB_TEX1, EMIT_2F, VIA_EMIT_TEX1, 
798                  (HC_HVPMSK_S | HC_HVPMSK_T) );
799    }
800
801    if (setupIndex != vmesa->setupIndex) {
802       vmesa->vertexSize = _tnl_install_attrs( ctx, 
803                                                vmesa->vertex_attrs, 
804                                                vmesa->vertex_attr_count,
805                                                vmesa->ViewportMatrix.m, 0 );
806       vmesa->vertexSize >>= 2;
807       vmesa->setupIndex = setupIndex;
808       vmesa->regCmdB &= ~HC_HVPMSK_MASK;
809       vmesa->regCmdB |= regCmdB;
810
811       if (vmesa->ptexHack) 
812          vmesa->hwVertexSize = vmesa->vertexSize - 1;
813       else
814          vmesa->hwVertexSize = vmesa->vertexSize;
815    }
816 }
817
818
819
820
821 /* Check if projective texture coordinates are used and if we can fake
822  * them. Fallback to swrast if we can't. Returns GL_TRUE if projective
823  * texture coordinates must be faked, GL_FALSE otherwise.
824  */
825 static GLboolean viaCheckPTexHack( struct gl_context *ctx )
826 {
827    TNLcontext *tnl = TNL_CONTEXT(ctx);
828    struct vertex_buffer *VB = &tnl->vb;
829    DECLARE_RENDERINPUTS(index_bitset);
830    GLboolean fallback = GL_FALSE;
831    GLboolean ptexHack = GL_FALSE;
832
833    RENDERINPUTS_COPY( index_bitset, tnl->render_inputs_bitset );
834
835    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX0 ) && VB->AttribPtr[_TNL_ATTRIB_TEX0]->size == 4) {
836       if (!RENDERINPUTS_TEST_RANGE( index_bitset, _TNL_ATTRIB_TEX1, _TNL_LAST_TEX ))
837          ptexHack = GL_TRUE; 
838       else
839          fallback = GL_TRUE;
840    }
841    if (RENDERINPUTS_TEST( index_bitset, _TNL_ATTRIB_TEX1 ) && VB->AttribPtr[_TNL_ATTRIB_TEX1]->size == 4)
842       fallback = GL_TRUE;
843
844    FALLBACK(VIA_CONTEXT(ctx), VIA_FALLBACK_PROJ_TEXTURE, fallback);
845    return ptexHack;
846 }
847
848
849
850
851 /**********************************************************************/
852 /*                 High level hooks for t_vb_render.c                 */
853 /**********************************************************************/
854
855
856 static void viaRenderStart(struct gl_context *ctx)
857 {
858    struct via_context *vmesa = VIA_CONTEXT(ctx);
859    TNLcontext *tnl = TNL_CONTEXT(ctx);
860    struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
861
862    {
863       GLboolean ptexHack = viaCheckPTexHack( ctx );
864       if (ptexHack != vmesa->ptexHack) {
865          vmesa->ptexHack = ptexHack;
866          vmesa->newRenderState |= _VIA_NEW_RENDERSTATE;
867       }
868    }
869
870    if (vmesa->newState) {
871       vmesa->newRenderState |= vmesa->newState;
872       viaValidateState( ctx );
873    }
874
875    if (vmesa->Fallback) {
876       tnl->Driver.Render.Start(ctx);
877       return;
878    }
879
880    if (vmesa->newRenderState) {
881       viaChooseVertexState(ctx);
882       viaChooseRenderState(ctx);
883       vmesa->newRenderState = 0;
884    }
885
886    /* Important:
887     */
888    VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
889 }
890
891 static void viaRenderFinish(struct gl_context *ctx)
892 {
893    VIA_FINISH_PRIM(VIA_CONTEXT(ctx));
894 }
895
896
897 /* System to flush dma and emit state changes based on the rasterized
898  * primitive.
899  */
900 void viaRasterPrimitive(struct gl_context *ctx,
901                         GLenum glprim,
902                         GLenum hwprim)
903 {
904    struct via_context *vmesa = VIA_CONTEXT(ctx);
905    GLuint regCmdB;
906    RING_VARS;
907
908    if (VIA_DEBUG & DEBUG_PRIMS) 
909       fprintf(stderr, "%s: %s/%s/%s\n", 
910               __FUNCTION__, _mesa_lookup_enum_by_nr(glprim),
911               _mesa_lookup_enum_by_nr(hwprim),
912               _mesa_lookup_enum_by_nr(ctx->Light.ShadeModel));
913
914    assert (!vmesa->newState);
915
916    vmesa->renderPrimitive = glprim;
917
918    if (hwprim != vmesa->hwPrimitive ||
919        ctx->Light.ShadeModel != vmesa->hwShadeModel) {
920
921       VIA_FINISH_PRIM(vmesa);
922
923       /* Ensure no wrapping inside this function  */    
924       viaCheckDma( vmesa, 1024 );       
925
926       if (vmesa->newEmitState) {
927          viaEmitState(vmesa);
928       }
929        
930       vmesa->regCmdA_End = HC_ACMD_HCmdA;
931
932       if (ctx->Light.ShadeModel == GL_SMOOTH) {
933          vmesa->regCmdA_End |= HC_HShading_Gouraud;
934       }
935       
936       vmesa->hwShadeModel = ctx->Light.ShadeModel;
937       regCmdB = vmesa->regCmdB;
938
939       switch (hwprim) {
940       case GL_POINTS:
941          vmesa->regCmdA_End |= HC_HPMType_Point | HC_HVCycle_Full;
942          vmesa->regCmdA_End |= HC_HShading_Gouraud; /* always Gouraud 
943                                                        shade points?!? */
944          break;
945       case GL_LINES:
946          vmesa->regCmdA_End |= HC_HPMType_Line | HC_HVCycle_Full;
947          regCmdB |= HC_HLPrst_MASK;
948          if (ctx->Light.ShadeModel == GL_FLAT)
949             vmesa->regCmdA_End |= HC_HShading_FlatB; 
950          break;
951       case GL_LINE_LOOP:
952       case GL_LINE_STRIP:
953          vmesa->regCmdA_End |= HC_HPMType_Line | HC_HVCycle_AFP |
954             HC_HVCycle_AB | HC_HVCycle_NewB;
955          regCmdB |= HC_HVCycle_AB | HC_HVCycle_NewB | HC_HLPrst_MASK;
956          if (ctx->Light.ShadeModel == GL_FLAT)
957             vmesa->regCmdA_End |= HC_HShading_FlatB; 
958          break;
959       case GL_TRIANGLES:
960          vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_Full;
961          if (ctx->Light.ShadeModel == GL_FLAT)
962             vmesa->regCmdA_End |= HC_HShading_FlatC; 
963          break;
964       case GL_TRIANGLE_STRIP:
965          vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
966             HC_HVCycle_AC | HC_HVCycle_BB | HC_HVCycle_NewC;
967          regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
968          if (ctx->Light.ShadeModel == GL_FLAT)
969             vmesa->regCmdA_End |= HC_HShading_FlatC; 
970          break;
971       case GL_TRIANGLE_FAN:
972          vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
973             HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
974          regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
975          if (ctx->Light.ShadeModel == GL_FLAT)
976             vmesa->regCmdA_End |= HC_HShading_FlatC; 
977          break;
978       case GL_QUADS:
979          abort();
980          return;
981       case GL_QUAD_STRIP:
982          abort();
983          return;
984       case GL_POLYGON:
985          vmesa->regCmdA_End |= HC_HPMType_Tri | HC_HVCycle_AFP |
986             HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
987          regCmdB |= HC_HVCycle_AA | HC_HVCycle_BC | HC_HVCycle_NewC;
988          if (ctx->Light.ShadeModel == GL_FLAT)
989             vmesa->regCmdA_End |= HC_HShading_FlatC; 
990          break;                          
991       default:
992          abort();
993          return;
994       }
995     
996 /*     assert((vmesa->dmaLow & 0x4) == 0); */
997
998       if (vmesa->dmaCliprectAddr == ~0) {
999          if (VIA_DEBUG & DEBUG_DMA) 
1000             fprintf(stderr, "reserve cliprect space at %x\n", vmesa->dmaLow);
1001          vmesa->dmaCliprectAddr = vmesa->dmaLow;
1002          BEGIN_RING(8);
1003          OUT_RING( HC_HEADER2 );    
1004          OUT_RING( (HC_ParaType_NotTex << 16) );
1005          OUT_RING( 0xCCCCCCCC );
1006          OUT_RING( 0xCCCCCCCC );
1007          OUT_RING( 0xCCCCCCCC );
1008          OUT_RING( 0xCCCCCCCC );
1009          OUT_RING( 0xCCCCCCCC );
1010          OUT_RING( 0xCCCCCCCC );
1011          ADVANCE_RING();
1012       }
1013
1014       assert(vmesa->dmaLastPrim == 0);
1015
1016       BEGIN_RING(8);
1017       OUT_RING( HC_HEADER2 );    
1018       OUT_RING( (HC_ParaType_NotTex << 16) );
1019       OUT_RING( 0xCCCCCCCC );
1020       OUT_RING( 0xDDDDDDDD );
1021
1022       OUT_RING( HC_HEADER2 );    
1023       OUT_RING( (HC_ParaType_CmdVdata << 16) );
1024       OUT_RING( regCmdB );
1025       OUT_RING( vmesa->regCmdA_End );
1026       ADVANCE_RING();
1027
1028       vmesa->hwPrimitive = hwprim;        
1029       vmesa->dmaLastPrim = vmesa->dmaLow;
1030    }
1031    else {
1032       assert(!vmesa->newEmitState);
1033    }
1034 }
1035
1036 /* Callback for mesa:
1037  */
1038 static void viaRenderPrimitive( struct gl_context *ctx, GLuint prim )
1039 {
1040    viaRasterPrimitive( ctx, prim, hwPrim[prim] );
1041 }
1042
1043
1044 void viaFinishPrimitive(struct via_context *vmesa)
1045 {
1046    if (VIA_DEBUG & (DEBUG_DMA|DEBUG_PRIMS)) 
1047       fprintf(stderr, "%s\n", __FUNCTION__);
1048
1049    if (!vmesa->dmaLastPrim || vmesa->dmaCliprectAddr == ~0) {
1050       assert(0);
1051    }
1052    else if (vmesa->dmaLow != vmesa->dmaLastPrim) {
1053       GLuint cmdA = (vmesa->regCmdA_End | HC_HPLEND_MASK | 
1054                      HC_HPMValidN_MASK | HC_HE3Fire_MASK); 
1055       RING_VARS;
1056
1057       vmesa->dmaLastPrim = 0;
1058
1059       /* KW: modified 0x1 to 0x4 below:
1060        */
1061       if ((vmesa->dmaLow & 0x4) || !vmesa->useAgp) {
1062          BEGIN_RING_NOCHECK( 1 );
1063          OUT_RING( cmdA );
1064          ADVANCE_RING();
1065       }   
1066       else {      
1067          BEGIN_RING_NOCHECK( 2 );
1068          OUT_RING( cmdA );
1069          OUT_RING( cmdA );
1070          ADVANCE_RING();
1071       }   
1072
1073       if (vmesa->dmaLow > VIA_DMA_HIGHWATER)
1074          viaFlushDma( vmesa );
1075    }
1076    else {
1077       if (VIA_DEBUG & (DEBUG_DMA|DEBUG_PRIMS)) 
1078          fprintf(stderr, "remove empty primitive\n");
1079
1080       /* Remove the primitive header:
1081        */
1082       vmesa->dmaLastPrim = 0;
1083       vmesa->dmaLow -= 8 * sizeof(GLuint);
1084
1085       /* Maybe remove the cliprect as well:
1086        */
1087       if (vmesa->dmaCliprectAddr == vmesa->dmaLow - 8 * sizeof(GLuint)) {
1088          vmesa->dmaLow -= 8 * sizeof(GLuint);
1089          vmesa->dmaCliprectAddr = ~0;
1090       }
1091    }
1092
1093    vmesa->renderPrimitive = GL_POLYGON + 1;
1094    vmesa->hwPrimitive = GL_POLYGON + 1;
1095    vmesa->dmaLastPrim = 0;
1096 }
1097
1098
1099 /**********************************************************************/
1100 /*           Transition to/from hardware rasterization.               */
1101 /**********************************************************************/
1102
1103
1104 void viaFallback(struct via_context *vmesa, GLuint bit, GLboolean mode)
1105 {
1106     struct gl_context *ctx = vmesa->glCtx;
1107     TNLcontext *tnl = TNL_CONTEXT(ctx);
1108     GLuint oldfallback = vmesa->Fallback;
1109     
1110     if (mode) {
1111         vmesa->Fallback |= bit;
1112         if (oldfallback == 0) {
1113             VIA_FLUSH_DMA(vmesa);
1114
1115             if (VIA_DEBUG & DEBUG_FALLBACKS) 
1116                fprintf(stderr, "ENTER FALLBACK %x\n", bit);
1117
1118             _swsetup_Wakeup(ctx);
1119             vmesa->renderIndex = ~0;
1120         }
1121     }
1122     else {
1123         vmesa->Fallback &= ~bit;
1124         if (oldfallback == bit) {
1125             _swrast_flush( ctx );
1126
1127             if (VIA_DEBUG & DEBUG_FALLBACKS) 
1128                fprintf(stderr, "LEAVE FALLBACK %x\n", bit);
1129
1130             tnl->Driver.Render.Start = viaRenderStart;
1131             tnl->Driver.Render.PrimitiveNotify = viaRenderPrimitive;
1132             tnl->Driver.Render.Finish = viaRenderFinish;
1133
1134             tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1135             tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1136             tnl->Driver.Render.Interp = _tnl_interp;
1137             tnl->Driver.Render.ResetLineStipple = viaResetLineStipple;
1138
1139             _tnl_invalidate_vertex_state( ctx, ~0 );
1140             _tnl_invalidate_vertices( ctx, ~0 );
1141             _tnl_install_attrs( ctx, 
1142                                 vmesa->vertex_attrs, 
1143                                 vmesa->vertex_attr_count,
1144                                 vmesa->ViewportMatrix.m, 0 ); 
1145
1146             vmesa->newState |= (_VIA_NEW_RENDERSTATE|_VIA_NEW_VERTEX);
1147         }
1148     }    
1149 }
1150
1151 static void viaRunPipeline( struct gl_context *ctx )
1152 {
1153    struct via_context *vmesa = VIA_CONTEXT(ctx);
1154
1155    if (vmesa->newState) {
1156       vmesa->newRenderState |= vmesa->newState;
1157       viaValidateState( ctx );
1158    }
1159
1160    _tnl_run_pipeline( ctx );
1161 }
1162
1163
1164 /**********************************************************************/
1165 /*                            Initialization.                         */
1166 /**********************************************************************/
1167
1168
1169 void viaInitTriFuncs(struct gl_context *ctx)
1170 {
1171     struct via_context *vmesa = VIA_CONTEXT(ctx);
1172     TNLcontext *tnl = TNL_CONTEXT(ctx);
1173     static int firsttime = 1;
1174
1175     if (firsttime) {
1176         init_rast_tab();
1177         firsttime = 0;
1178     }
1179
1180     tnl->Driver.RunPipeline = viaRunPipeline;
1181     tnl->Driver.Render.Start = viaRenderStart;
1182     tnl->Driver.Render.Finish = viaRenderFinish;
1183     tnl->Driver.Render.PrimitiveNotify = viaRenderPrimitive;
1184     tnl->Driver.Render.ResetLineStipple = viaResetLineStipple;
1185     tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1186     tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1187     tnl->Driver.Render.Interp = _tnl_interp;
1188
1189     _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12, 
1190                         (6 + 2*ctx->Const.MaxTextureUnits) * sizeof(GLfloat) );
1191    
1192     vmesa->verts = (GLubyte *)tnl->clipspace.vertex_buf;
1193
1194 }