2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
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:
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
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.
35 #include "swrast/swrast.h"
36 #include "swrast_setup/swrast_setup.h"
37 #include "tnl/t_context.h"
38 #include "tnl/t_pipeline.h"
40 #include "via_context.h"
42 #include "via_state.h"
44 #include "via_ioctl.h"
46 /***********************************************************************
47 * Emit primitives as inline vertices *
48 ***********************************************************************/
51 #define COPY_DWORDS(vb, vertsize, v) \
55 __asm__ __volatile__("rep ; movsl" \
56 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
62 #define COPY_DWORDS(vb, vertsize, v) \
65 for (j = 0; j < vertsize; j++) \
66 vb[j] = ((GLuint *)v)[j]; \
71 static void via_draw_triangle(viaContextPtr vmesa
,
76 GLuint vertsize
= vmesa
->vertexSize
;
77 GLuint
*vb
= viaExtendPrimitive(vmesa
, 3 * 4 * vertsize
);
79 COPY_DWORDS(vb
, vertsize
, v0
);
80 COPY_DWORDS(vb
, vertsize
, v1
);
81 COPY_DWORDS(vb
, vertsize
, v2
);
85 static void via_draw_quad(viaContextPtr vmesa
,
91 GLuint vertsize
= vmesa
->vertexSize
;
92 GLuint
*vb
= viaExtendPrimitive(vmesa
, 6 * 4 * vertsize
);
94 COPY_DWORDS(vb
, vertsize
, v0
);
95 COPY_DWORDS(vb
, vertsize
, v1
);
96 COPY_DWORDS(vb
, vertsize
, v3
);
97 COPY_DWORDS(vb
, vertsize
, v1
);
98 COPY_DWORDS(vb
, vertsize
, v2
);
99 COPY_DWORDS(vb
, vertsize
, v3
);
102 static void via_draw_line(viaContextPtr vmesa
,
106 GLuint vertsize
= vmesa
->vertexSize
;
107 GLuint
*vb
= viaExtendPrimitive(vmesa
, 2 * 4 * vertsize
);
108 COPY_DWORDS(vb
, vertsize
, v0
);
109 COPY_DWORDS(vb
, vertsize
, v1
);
113 static void via_draw_point(viaContextPtr vmesa
,
116 GLuint vertsize
= vmesa
->vertexSize
;
117 GLuint
*vb
= viaExtendPrimitive(vmesa
, 4 * vertsize
);
118 COPY_DWORDS(vb
, vertsize
, v0
);
122 /* Fallback drawing functions for the ptex hack.
124 #define PTEX_VERTEX( tmp, vertex_size, v) \
127 GLfloat rhw = 1.0 / v->f[vertex_size]; \
128 for ( j = 0 ; j < vertex_size ; j++ ) \
129 tmp.f[j] = v->f[j]; \
130 tmp.f[3] *= v->f[vertex_size]; \
131 tmp.f[vertex_size-2] *= rhw; \
132 tmp.f[vertex_size-1] *= rhw; \
135 static void via_ptex_tri (viaContextPtr vmesa
,
140 GLuint vertsize
= vmesa
->hwVertexSize
;
141 GLuint
*vb
= viaExtendPrimitive(vmesa
, 3*4*vertsize
);
144 PTEX_VERTEX(tmp
, vertsize
, v0
); COPY_DWORDS(vb
, vertsize
, &tmp
);
145 PTEX_VERTEX(tmp
, vertsize
, v1
); COPY_DWORDS(vb
, vertsize
, &tmp
);
146 PTEX_VERTEX(tmp
, vertsize
, v2
); COPY_DWORDS(vb
, vertsize
, &tmp
);
149 static void via_ptex_line (viaContextPtr vmesa
,
153 GLuint vertsize
= vmesa
->hwVertexSize
;
154 GLuint
*vb
= viaExtendPrimitive(vmesa
, 2*4*vertsize
);
157 PTEX_VERTEX(tmp
, vertsize
, v0
); COPY_DWORDS(vb
, vertsize
, &tmp
);
158 PTEX_VERTEX(tmp
, vertsize
, v1
); COPY_DWORDS(vb
, vertsize
, &tmp
);
161 static void via_ptex_point (viaContextPtr vmesa
,
164 GLuint vertsize
= vmesa
->hwVertexSize
;
165 GLuint
*vb
= viaExtendPrimitive(vmesa
, 1*4*vertsize
);
168 PTEX_VERTEX(tmp
, vertsize
, v0
); COPY_DWORDS(vb
, vertsize
, &tmp
);
175 /***********************************************************************
176 * Macros for via_dd_tritmp.h to draw basic primitives *
177 ***********************************************************************/
179 #define TRI(a, b, c) \
182 vmesa->drawTri(vmesa, a, b, c); \
184 via_draw_triangle(vmesa, a, b, c); \
187 #define QUAD(a, b, c, d) \
190 vmesa->drawTri(vmesa, a, b, d); \
191 vmesa->drawTri(vmesa, b, c, d); \
194 via_draw_quad(vmesa, a, b, c, d); \
197 #define LINE(v0, v1) \
200 vmesa->drawLine(vmesa, v0, v1); \
202 via_draw_line(vmesa, v0, v1); \
208 vmesa->drawPoint(vmesa, v0); \
210 via_draw_point(vmesa, v0); \
214 /***********************************************************************
215 * Build render functions from dd templates *
216 ***********************************************************************/
218 #define VIA_OFFSET_BIT 0x01
219 #define VIA_TWOSIDE_BIT 0x02
220 #define VIA_UNFILLED_BIT 0x04
221 #define VIA_FALLBACK_BIT 0x08
222 #define VIA_MAX_TRIFUNC 0x10
226 tnl_points_func points
;
228 tnl_triangle_func triangle
;
230 } rast_tab
[VIA_MAX_TRIFUNC
];
233 #define DO_FALLBACK (IND & VIA_FALLBACK_BIT)
234 #define DO_OFFSET (IND & VIA_OFFSET_BIT)
235 #define DO_UNFILLED (IND & VIA_UNFILLED_BIT)
236 #define DO_TWOSIDE (IND & VIA_TWOSIDE_BIT)
242 #define DO_FULL_QUAD 1
246 #define HAVE_BACK_COLORS 0
247 #define HAVE_HW_FLATSHADE 1
248 #define VERTEX viaVertex
251 /* Only used to pull back colors into vertices (ie, we know color is
254 #define VIA_COLOR(dst, src) \
262 #define VIA_SPEC(dst, src) \
270 #define DEPTH_SCALE vmesa->polygon_offset_scale
271 #define UNFILLED_TRI unfilled_tri
272 #define UNFILLED_QUAD unfilled_quad
273 #define VERT_X(_v) _v->v.x
274 #define VERT_Y(_v) _v->v.y
275 #define VERT_Z(_v) _v->v.z
276 #define AREA_IS_CCW(a) (a > 0)
277 #define GET_VERTEX(e) (vmesa->verts + (e * vmesa->vertexSize * sizeof(int)))
279 #define VERT_SET_RGBA( v, c ) \
281 via_color_t *color = (via_color_t *)&((v)->ui[coloroffset]); \
282 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
283 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
284 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
285 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
288 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
290 #define VERT_SET_SPEC( v0, c ) \
293 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
294 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
295 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
298 #define VERT_COPY_SPEC( v0, v1 ) \
301 v0->v.specular.red = v1->v.specular.red; \
302 v0->v.specular.green = v1->v.specular.green; \
303 v0->v.specular.blue = v1->v.specular.blue; \
308 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
309 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
310 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
311 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
314 #define LOCAL_VARS(n) \
315 viaContextPtr vmesa = VIA_CONTEXT(ctx); \
316 GLuint color[n], spec[n]; \
317 GLuint coloroffset = vmesa->coloroffset; \
318 GLuint specoffset = vmesa->specoffset; \
319 (void)color; (void)spec; (void)coloroffset; (void)specoffset;
322 /***********************************************************************
323 * Helpers for rendering unfilled primitives *
324 ***********************************************************************/
326 static const GLenum hwPrim
[GL_POLYGON
+ 1] = {
340 #define RASTERIZE(x) viaRasterPrimitive( ctx, x, hwPrim[x] )
341 #define RENDER_PRIMITIVE vmesa->renderPrimitive
343 #define IND VIA_FALLBACK_BIT
344 #include "tnl_dd/t_dd_unfilled.h"
348 /***********************************************************************
349 * Generate GL render functions *
350 ***********************************************************************/
355 #include "tnl_dd/t_dd_tritmp.h"
357 #define IND (VIA_OFFSET_BIT)
358 #define TAG(x) x##_offset
359 #include "tnl_dd/t_dd_tritmp.h"
361 #define IND (VIA_TWOSIDE_BIT)
362 #define TAG(x) x##_twoside
363 #include "tnl_dd/t_dd_tritmp.h"
365 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT)
366 #define TAG(x) x##_twoside_offset
367 #include "tnl_dd/t_dd_tritmp.h"
369 #define IND (VIA_UNFILLED_BIT)
370 #define TAG(x) x##_unfilled
371 #include "tnl_dd/t_dd_tritmp.h"
373 #define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT)
374 #define TAG(x) x##_offset_unfilled
375 #include "tnl_dd/t_dd_tritmp.h"
377 #define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT)
378 #define TAG(x) x##_twoside_unfilled
379 #include "tnl_dd/t_dd_tritmp.h"
381 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT)
382 #define TAG(x) x##_twoside_offset_unfilled
383 #include "tnl_dd/t_dd_tritmp.h"
385 #define IND (VIA_FALLBACK_BIT)
386 #define TAG(x) x##_fallback
387 #include "tnl_dd/t_dd_tritmp.h"
389 #define IND (VIA_OFFSET_BIT|VIA_FALLBACK_BIT)
390 #define TAG(x) x##_offset_fallback
391 #include "tnl_dd/t_dd_tritmp.h"
393 #define IND (VIA_TWOSIDE_BIT|VIA_FALLBACK_BIT)
394 #define TAG(x) x##_twoside_fallback
395 #include "tnl_dd/t_dd_tritmp.h"
397 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_FALLBACK_BIT)
398 #define TAG(x) x##_twoside_offset_fallback
399 #include "tnl_dd/t_dd_tritmp.h"
401 #define IND (VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
402 #define TAG(x) x##_unfilled_fallback
403 #include "tnl_dd/t_dd_tritmp.h"
405 #define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
406 #define TAG(x) x##_offset_unfilled_fallback
407 #include "tnl_dd/t_dd_tritmp.h"
409 #define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
410 #define TAG(x) x##_twoside_unfilled_fallback
411 #include "tnl_dd/t_dd_tritmp.h"
413 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT| \
415 #define TAG(x) x##_twoside_offset_unfilled_fallback
416 #include "tnl_dd/t_dd_tritmp.h"
419 static void init_rast_tab(void)
424 init_twoside_offset();
426 init_offset_unfilled();
427 init_twoside_unfilled();
428 init_twoside_offset_unfilled();
430 init_offset_fallback();
431 init_twoside_fallback();
432 init_twoside_offset_fallback();
433 init_unfilled_fallback();
434 init_offset_unfilled_fallback();
435 init_twoside_unfilled_fallback();
436 init_twoside_offset_unfilled_fallback();
440 /***********************************************************************
441 * Rasterization fallback helpers *
442 ***********************************************************************/
445 /* This code is hit only when a mix of accelerated and unaccelerated
446 * primitives are being drawn, and only for the unaccelerated
450 via_fallback_tri(viaContextPtr vmesa
,
455 GLcontext
*ctx
= vmesa
->glCtx
;
457 _swsetup_Translate(ctx
, v0
, &v
[0]);
458 _swsetup_Translate(ctx
, v1
, &v
[1]);
459 _swsetup_Translate(ctx
, v2
, &v
[2]);
460 viaSpanRenderStart( ctx
);
461 _swrast_Triangle(ctx
, &v
[0], &v
[1], &v
[2]);
462 viaSpanRenderFinish( ctx
);
467 via_fallback_line(viaContextPtr vmesa
,
471 GLcontext
*ctx
= vmesa
->glCtx
;
473 _swsetup_Translate(ctx
, v0
, &v
[0]);
474 _swsetup_Translate(ctx
, v1
, &v
[1]);
475 viaSpanRenderStart( ctx
);
476 _swrast_Line(ctx
, &v
[0], &v
[1]);
477 viaSpanRenderFinish( ctx
);
482 via_fallback_point(viaContextPtr vmesa
,
485 GLcontext
*ctx
= vmesa
->glCtx
;
487 _swsetup_Translate(ctx
, v0
, &v
[0]);
488 viaSpanRenderStart( ctx
);
489 _swrast_Point(ctx
, &v
[0]);
490 viaSpanRenderFinish( ctx
);
493 /**********************************************************************/
494 /* Render unclipped begin/end objects */
495 /**********************************************************************/
497 #define V(x) (viaVertex *)(vertptr + ((x) * vertsize * sizeof(int)))
498 #define RENDER_POINTS(start, count) \
499 for (; start < count; start++) POINT(V(ELT(start)));
500 #define RENDER_LINE(v0, v1) LINE(V(v0), V(v1))
501 #define RENDER_TRI( v0, v1, v2) TRI( V(v0), V(v1), V(v2))
502 #define RENDER_QUAD(v0, v1, v2, v3) QUAD(V(v0), V(v1), V(v2), V(v3))
503 #define INIT(x) viaRasterPrimitive(ctx, x, hwPrim[x])
506 viaContextPtr vmesa = VIA_CONTEXT(ctx); \
507 GLubyte *vertptr = (GLubyte *)vmesa->verts; \
508 const GLuint vertsize = vmesa->vertexSize; \
509 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
511 #define RESET_STIPPLE
512 #define RESET_OCCLUSION
513 #define PRESERVE_VB_DEFS
515 #define TAG(x) via_fast##x##_verts
516 #include "tnl/t_vb_rendertmp.h"
519 #define TAG(x) via_fast##x##_elts
520 #define ELT(x) elt[x]
521 #include "tnl/t_vb_rendertmp.h"
524 #undef NEED_EDGEFLAG_SETUP
527 #undef RESET_OCCLUSION
530 /**********************************************************************/
531 /* Render clipped primitives */
532 /**********************************************************************/
536 static void viaRenderClippedPoly(GLcontext
*ctx
, const GLuint
*elts
,
539 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
540 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
541 GLuint prim
= VIA_CONTEXT(ctx
)->renderPrimitive
;
543 /* Render the new vertices as an unclipped polygon.
546 GLuint
*tmp
= VB
->Elts
;
547 VB
->Elts
= (GLuint
*)elts
;
548 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
](ctx
, 0, n
,
549 PRIM_BEGIN
|PRIM_END
);
553 /* Restore the render primitive
555 if (prim
!= GL_POLYGON
)
556 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
559 static void viaRenderClippedLine(GLcontext
*ctx
, GLuint ii
, GLuint jj
)
561 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
562 tnl
->Driver
.Render
.Line(ctx
, ii
, jj
);
565 static void viaFastRenderClippedPoly(GLcontext
*ctx
, const GLuint
*elts
,
568 viaContextPtr vmesa
= VIA_CONTEXT(ctx
);
569 GLuint vertsize
= vmesa
->vertexSize
;
570 GLuint
*vb
= viaExtendPrimitive(vmesa
, (n
- 2) * 3 * 4 * vertsize
);
571 GLubyte
*vertptr
= (GLubyte
*)vmesa
->verts
;
572 const GLuint
*start
= (const GLuint
*)V(elts
[0]);
575 for (i
= 2; i
< n
; i
++) {
576 COPY_DWORDS(vb
, vertsize
, V(elts
[i
- 1]));
577 COPY_DWORDS(vb
, vertsize
, V(elts
[i
]));
578 COPY_DWORDS(vb
, vertsize
, start
);
582 /**********************************************************************/
583 /* Choose render functions */
584 /**********************************************************************/
589 #define _VIA_NEW_VERTEX (_NEW_TEXTURE | \
590 _DD_NEW_SEPARATE_SPECULAR | \
591 _DD_NEW_TRI_UNFILLED | \
592 _DD_NEW_TRI_LIGHT_TWOSIDE | \
595 #define _VIA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
596 _DD_NEW_TRI_UNFILLED | \
597 _DD_NEW_TRI_LIGHT_TWOSIDE | \
598 _DD_NEW_TRI_OFFSET | \
599 _DD_NEW_TRI_STIPPLE | \
602 /* Via does support line stipple in hardware, and it is partially
603 * working in the older versions of this driver:
605 #define LINE_FALLBACK (DD_LINE_STIPPLE)
606 #define POINT_FALLBACK (0)
607 #define TRI_FALLBACK (0)
608 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
609 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
611 static void viaChooseRenderState(GLcontext
*ctx
)
613 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
614 viaContextPtr vmesa
= VIA_CONTEXT(ctx
);
615 GLuint flags
= ctx
->_TriangleCaps
;
618 if (vmesa
->ptexHack
) {
619 vmesa
->drawPoint
= via_ptex_point
;
620 vmesa
->drawLine
= via_ptex_line
;
621 vmesa
->drawTri
= via_ptex_tri
;
622 index
|= VIA_FALLBACK_BIT
;
625 vmesa
->drawPoint
= via_draw_point
;
626 vmesa
->drawLine
= via_draw_line
;
627 vmesa
->drawTri
= via_draw_triangle
;
630 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
631 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= VIA_TWOSIDE_BIT
;
632 if (flags
& DD_TRI_OFFSET
) index
|= VIA_OFFSET_BIT
;
633 if (flags
& DD_TRI_UNFILLED
) index
|= VIA_UNFILLED_BIT
;
634 if (flags
& ANY_FALLBACK_FLAGS
) index
|= VIA_FALLBACK_BIT
;
636 /* Hook in fallbacks for specific primitives.
638 if (flags
& POINT_FALLBACK
)
639 vmesa
->drawPoint
= via_fallback_point
;
641 if (flags
& LINE_FALLBACK
)
642 vmesa
->drawLine
= via_fallback_line
;
644 if (flags
& TRI_FALLBACK
)
645 vmesa
->drawTri
= via_fallback_tri
;
648 if (vmesa
->renderIndex
!= index
) {
649 vmesa
->renderIndex
= index
;
651 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
652 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
653 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
654 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
657 tnl
->Driver
.Render
.PrimTabVerts
= via_fastrender_tab_verts
;
658 tnl
->Driver
.Render
.PrimTabElts
= via_fastrender_tab_elts
;
659 tnl
->Driver
.Render
.ClippedLine
= line
; /* from tritmp.h */
660 tnl
->Driver
.Render
.ClippedPolygon
= viaFastRenderClippedPoly
;
663 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
664 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
665 tnl
->Driver
.Render
.ClippedLine
= viaRenderClippedLine
;
666 tnl
->Driver
.Render
.ClippedPolygon
= viaRenderClippedPoly
;
672 #define VIA_EMIT_TEX1 0x01
673 #define VIA_EMIT_TEX0 0x02
674 #define VIA_EMIT_PTEX0 0x04
675 #define VIA_EMIT_RGBA 0x08
676 #define VIA_EMIT_SPEC 0x10
677 #define VIA_EMIT_FOG 0x20
678 #define VIA_EMIT_W 0x40
680 #define EMIT_ATTR( ATTR, STYLE, INDEX, REGB ) \
682 vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = (ATTR); \
683 vmesa->vertex_attrs[vmesa->vertex_attr_count].format = (STYLE); \
684 vmesa->vertex_attr_count++; \
685 setupIndex |= (INDEX); \
689 #define EMIT_PAD( N ) \
691 vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = 0; \
692 vmesa->vertex_attrs[vmesa->vertex_attr_count].format = EMIT_PAD; \
693 vmesa->vertex_attrs[vmesa->vertex_attr_count].offset = (N); \
694 vmesa->vertex_attr_count++; \
699 static void viaChooseVertexState( GLcontext
*ctx
)
701 viaContextPtr vmesa
= VIA_CONTEXT(ctx
);
702 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
703 GLuint index
= tnl
->render_inputs
;
704 GLuint regCmdB
= HC_HVPMSK_X
| HC_HVPMSK_Y
| HC_HVPMSK_Z
;
705 GLuint setupIndex
= 0;
707 vmesa
->vertex_attr_count
= 0;
709 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
710 * build up a hardware vertex.
712 if (index
& (_TNL_BITS_TEX_ANY
|_TNL_BIT_FOG
)) {
713 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
, VIA_EMIT_W
, HC_HVPMSK_W
);
714 vmesa
->coloroffset
= 4;
717 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
, 0, 0 );
718 vmesa
->coloroffset
= 3;
721 /* t_context.c always includes a diffuse color */
722 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
, VIA_EMIT_RGBA
, HC_HVPMSK_Cd
);
724 vmesa
->specoffset
= 0;
725 if (index
& (_TNL_BIT_COLOR1
|_TNL_BIT_FOG
)) {
726 if ((index
& _TNL_BIT_COLOR1
)) {
727 vmesa
->specoffset
= vmesa
->coloroffset
+ 1;
728 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
, VIA_EMIT_SPEC
, HC_HVPMSK_Cs
);
733 if ((index
& _TNL_BIT_FOG
))
734 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, VIA_EMIT_FOG
, HC_HVPMSK_Cs
);
739 if (index
& _TNL_BIT_TEX(0)) {
741 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_3F_XYW
, VIA_EMIT_PTEX0
, (HC_HVPMSK_S
| HC_HVPMSK_T
) );
743 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_2F
, VIA_EMIT_TEX0
, (HC_HVPMSK_S
| HC_HVPMSK_T
) );
746 if (index
& _TNL_BIT_TEX(1)) {
747 EMIT_ATTR( _TNL_ATTRIB_TEX1
, EMIT_2F
, VIA_EMIT_TEX1
, 0 ); /* how does the hardware find out about this? */
750 if (setupIndex
!= vmesa
->setupIndex
) {
751 vmesa
->vertexSize
= _tnl_install_attrs( ctx
,
753 vmesa
->vertex_attr_count
,
754 vmesa
->ViewportMatrix
.m
, 0 );
755 vmesa
->vertexSize
>>= 2;
756 vmesa
->setupIndex
= setupIndex
;
757 vmesa
->regCmdB
&= ~HC_HVPMSK_MASK
;
758 vmesa
->regCmdB
|= regCmdB
;
761 vmesa
->hwVertexSize
= vmesa
->vertexSize
- 1;
763 vmesa
->hwVertexSize
= vmesa
->vertexSize
;
770 /* Check if projective texture coordinates are used and if we can fake
771 * them. Fallback to swrast we can't. Returns GL_TRUE if projective
772 * texture coordinates must be faked, GL_FALSE otherwise.
774 static GLboolean
viaCheckPTexHack( GLcontext
*ctx
)
776 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
777 struct vertex_buffer
*VB
= &tnl
->vb
;
778 GLuint index
= tnl
->render_inputs
;
779 GLboolean fallback
= GL_FALSE
;
780 GLboolean ptexHack
= GL_FALSE
;
782 if (index
& _TNL_BIT_TEX(0) && VB
->TexCoordPtr
[0]->size
== 4) {
783 if ((index
& _TNL_BITS_TEX_ANY
) == _TNL_BIT_TEX(0))
788 if ((index
& _TNL_BIT_TEX(1)) && VB
->TexCoordPtr
[1]->size
== 4)
791 FALLBACK(VIA_CONTEXT(ctx
), VIA_FALLBACK_PROJ_TEXTURE
, fallback
);
798 /**********************************************************************/
799 /* High level hooks for t_vb_render.c */
800 /**********************************************************************/
803 static void viaRenderStart(GLcontext
*ctx
)
805 viaContextPtr vmesa
= VIA_CONTEXT(ctx
);
806 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
807 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
810 GLboolean ptexHack
= viaCheckPTexHack( ctx
);
811 if (ptexHack
!= vmesa
->ptexHack
) {
812 vmesa
->ptexHack
= ptexHack
;
813 vmesa
->newRenderState
|= _VIA_NEW_RENDERSTATE
;
817 if (vmesa
->newState
) {
818 vmesa
->newRenderState
|= vmesa
->newState
;
819 viaValidateState( ctx
);
822 if (vmesa
->Fallback
) {
823 tnl
->Driver
.Render
.Start(ctx
);
827 if (vmesa
->newRenderState
) {
828 viaChooseVertexState(ctx
);
829 viaChooseRenderState(ctx
);
830 vmesa
->newRenderState
= 0;
835 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
838 static void viaRenderFinish(GLcontext
*ctx
)
840 if (VIA_CONTEXT(ctx
)->renderIndex
& VIA_FALLBACK_BIT
)
843 VIA_FINISH_PRIM(VIA_CONTEXT(ctx
));
848 /* System to flush dma and emit state changes based on the rasterized
851 void viaRasterPrimitive(GLcontext
*ctx
,
855 viaContextPtr vmesa
= VIA_CONTEXT(ctx
);
860 fprintf(stderr
, "%s: %s/%s\n", __FUNCTION__
, _mesa_lookup_enum_by_nr(glprim
),
861 _mesa_lookup_enum_by_nr(hwprim
));
863 VIA_FINISH_PRIM(vmesa
);
865 viaCheckDma( vmesa
, 1024 ); /* Ensure no wrapping inside this function */
867 if (vmesa
->newEmitState
) {
872 regCmdB
= vmesa
->regCmdB
;
876 vmesa
->regCmdA_End
= vmesa
->regCmdA
| HC_HPMType_Point
| HC_HVCycle_Full
;
877 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
878 vmesa
->regCmdA_End
|= HC_HShading_FlatA
;
881 vmesa
->regCmdA_End
= vmesa
->regCmdA
| HC_HPMType_Line
| HC_HVCycle_Full
;
882 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
883 vmesa
->regCmdA_End
|= HC_HShading_FlatB
;
887 vmesa
->regCmdA_End
= vmesa
->regCmdA
| HC_HPMType_Line
| HC_HVCycle_AFP
|
888 HC_HVCycle_AB
| HC_HVCycle_NewB
;
889 regCmdB
|= HC_HVCycle_AB
| HC_HVCycle_NewB
| HC_HLPrst_MASK
;
890 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
891 vmesa
->regCmdA_End
|= HC_HShading_FlatB
;
894 vmesa
->regCmdA_End
= vmesa
->regCmdA
| HC_HPMType_Tri
| HC_HVCycle_Full
;
895 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
896 vmesa
->regCmdA_End
|= HC_HShading_FlatC
;
898 case GL_TRIANGLE_STRIP
:
899 vmesa
->regCmdA_End
= vmesa
->regCmdA
| HC_HPMType_Tri
| HC_HVCycle_AFP
|
900 HC_HVCycle_AC
| HC_HVCycle_BB
| HC_HVCycle_NewC
;
901 regCmdB
|= HC_HVCycle_AA
| HC_HVCycle_BC
| HC_HVCycle_NewC
;
902 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
903 vmesa
->regCmdA_End
|= HC_HShading_FlatB
;
905 case GL_TRIANGLE_FAN
:
906 vmesa
->regCmdA_End
= vmesa
->regCmdA
| HC_HPMType_Tri
| HC_HVCycle_AFP
|
907 HC_HVCycle_AA
| HC_HVCycle_BC
| HC_HVCycle_NewC
;
908 regCmdB
|= HC_HVCycle_AA
| HC_HVCycle_BC
| HC_HVCycle_NewC
;
909 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
910 vmesa
->regCmdA_End
|= HC_HShading_FlatC
;
919 vmesa
->regCmdA_End
= vmesa
->regCmdA
| HC_HPMType_Tri
| HC_HVCycle_AFP
|
920 HC_HVCycle_AA
| HC_HVCycle_BC
| HC_HVCycle_NewC
;
921 regCmdB
|= HC_HVCycle_AA
| HC_HVCycle_BC
| HC_HVCycle_NewC
;
922 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
923 vmesa
->regCmdA_End
|= HC_HShading_FlatC
;
930 /* assert((vmesa->dmaLow & 0x4) == 0); */
932 if (vmesa
->dmaCliprectAddr
== ~0) {
933 if (VIA_DEBUG
) fprintf(stderr
, "reserve cliprect space at %x\n", vmesa
->dmaLow
);
934 vmesa
->dmaCliprectAddr
= vmesa
->dmaLow
;
936 OUT_RING( HC_HEADER2
);
937 OUT_RING( (HC_ParaType_NotTex
<< 16) );
938 OUT_RING( 0xCCCCCCCC );
939 OUT_RING( 0xCCCCCCCC );
940 OUT_RING( 0xCCCCCCCC );
941 OUT_RING( 0xCCCCCCCC );
942 OUT_RING( 0xCCCCCCCC );
943 OUT_RING( 0xCCCCCCCC );
949 OUT_RING( HC_HEADER2
);
950 OUT_RING( (HC_ParaType_NotTex
<< 16) );
951 OUT_RING( 0xCCCCCCCC );
952 OUT_RING( 0xDDDDDDDD );
954 OUT_RING( HC_HEADER2
);
955 OUT_RING( (HC_ParaType_CmdVdata
<< 16) );
957 OUT_RING( vmesa
->regCmdA_End
);
961 vmesa
->renderPrimitive
= glprim
;
962 vmesa
->hwPrimitive
= hwprim
;
963 vmesa
->dmaLastPrim
= vmesa
->dmaLow
;
966 /* Callback for mesa:
968 static void viaRenderPrimitive( GLcontext
*ctx
, GLuint prim
)
970 viaRasterPrimitive( ctx
, prim
, hwPrim
[prim
] );
974 void viaFinishPrimitive(viaContextPtr vmesa
)
977 fprintf(stderr
, "%s\n", __FUNCTION__
);
979 if (!vmesa
->dmaLastPrim
|| vmesa
->dmaCliprectAddr
== ~0) {
982 else if (vmesa
->dmaLow
!= vmesa
->dmaLastPrim
) {
983 GLuint cmdA
= vmesa
->regCmdA_End
| HC_HPLEND_MASK
| HC_HPMValidN_MASK
| HC_HE3Fire_MASK
;
986 vmesa
->dmaLastPrim
= 0;
988 /* KW: modified 0x1 to 0x4 below:
990 if ((vmesa
->dmaLow
& 0x1) || !vmesa
->useAgp
) {
991 BEGIN_RING_NOCHECK( 1 );
996 BEGIN_RING_NOCHECK( 2 );
1002 if (vmesa
->dmaLow
> VIA_DMA_HIGHWATER
)
1003 viaFlushDma( vmesa
);
1007 fprintf(stderr
, "remove empty primitive\n");
1009 /* Remove the primitive header:
1011 vmesa
->dmaLastPrim
= 0;
1012 vmesa
->dmaLow
-= 8 * sizeof(GLuint
);
1014 /* Maybe remove the cliprect as well:
1016 if (vmesa
->dmaCliprectAddr
== vmesa
->dmaLow
- 8 * sizeof(GLuint
)) {
1017 vmesa
->dmaLow
-= 8 * sizeof(GLuint
);
1018 vmesa
->dmaCliprectAddr
= ~0;
1022 vmesa
->renderPrimitive
= GL_POLYGON
+ 1;
1023 vmesa
->hwPrimitive
= GL_POLYGON
+ 1;
1024 vmesa
->dmaLastPrim
= 0;
1028 /**********************************************************************/
1029 /* Transition to/from hardware rasterization. */
1030 /**********************************************************************/
1033 void viaFallback(viaContextPtr vmesa
, GLuint bit
, GLboolean mode
)
1035 GLcontext
*ctx
= vmesa
->glCtx
;
1036 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1037 GLuint oldfallback
= vmesa
->Fallback
;
1038 if (VIA_DEBUG
) fprintf(stderr
, "%s old %x bit %x mode %d\n", __FUNCTION__
,
1039 vmesa
->Fallback
, bit
, mode
);
1042 vmesa
->Fallback
|= bit
;
1043 if (oldfallback
== 0) {
1044 VIA_FLUSH_DMA(vmesa
);
1045 _swsetup_Wakeup(ctx
);
1046 vmesa
->renderIndex
= ~0;
1050 vmesa
->Fallback
&= ~bit
;
1051 if (oldfallback
== bit
) {
1052 _swrast_flush( ctx
);
1054 tnl
->Driver
.Render
.Start
= viaRenderStart
;
1055 tnl
->Driver
.Render
.PrimitiveNotify
= viaRenderPrimitive
;
1056 tnl
->Driver
.Render
.Finish
= viaRenderFinish
;
1058 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1059 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1060 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1062 _tnl_invalidate_vertex_state( ctx
, ~0 );
1063 _tnl_invalidate_vertices( ctx
, ~0 );
1064 _tnl_install_attrs( ctx
,
1065 vmesa
->vertex_attrs
,
1066 vmesa
->vertex_attr_count
,
1067 vmesa
->ViewportMatrix
.m
, 0 );
1069 vmesa
->newState
|= (_VIA_NEW_RENDERSTATE
|_VIA_NEW_VERTEX
);
1075 /**********************************************************************/
1076 /* Initialization. */
1077 /**********************************************************************/
1080 void viaInitTriFuncs(GLcontext
*ctx
)
1082 viaContextPtr vmesa
= VIA_CONTEXT(ctx
);
1083 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1084 static int firsttime
= 1;
1091 tnl
->Driver
.RunPipeline
= _tnl_run_pipeline
;
1092 tnl
->Driver
.Render
.Start
= viaRenderStart
;
1093 tnl
->Driver
.Render
.Finish
= viaRenderFinish
;
1094 tnl
->Driver
.Render
.PrimitiveNotify
= viaRenderPrimitive
;
1095 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1096 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1097 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1098 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1100 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
1101 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
1103 vmesa
->verts
= (char *)tnl
->clipspace
.vertex_buf
;