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"
45 #include "via_3d_reg.h"
48 /***********************************************************************
49 * Emit primitives as inline vertices *
50 ***********************************************************************/
53 #define COPY_DWORDS(vb, vertsize, v) \
55 via_sse_memcpy(vb, v, vertsize * 4); \
60 #define COPY_DWORDS(vb, vertsize, v) \
64 __asm__ __volatile__("rep ; movsl" \
65 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
71 #define COPY_DWORDS(vb, vertsize, v) \
74 for (j = 0; j < vertsize; j++) \
75 vb[j] = ((GLuint *)v)[j]; \
81 static void via_draw_triangle(struct via_context
*vmesa
,
86 GLuint vertsize
= vmesa
->vertexSize
;
87 GLuint
*vb
= viaExtendPrimitive(vmesa
, 3 * 4 * vertsize
);
89 COPY_DWORDS(vb
, vertsize
, v0
);
90 COPY_DWORDS(vb
, vertsize
, v1
);
91 COPY_DWORDS(vb
, vertsize
, v2
);
95 static void via_draw_quad(struct via_context
*vmesa
,
101 GLuint vertsize
= vmesa
->vertexSize
;
102 GLuint
*vb
= viaExtendPrimitive(vmesa
, 6 * 4 * vertsize
);
104 COPY_DWORDS(vb
, vertsize
, v0
);
105 COPY_DWORDS(vb
, vertsize
, v1
);
106 COPY_DWORDS(vb
, vertsize
, v3
);
107 COPY_DWORDS(vb
, vertsize
, v1
);
108 COPY_DWORDS(vb
, vertsize
, v2
);
109 COPY_DWORDS(vb
, vertsize
, v3
);
112 static void via_draw_line(struct via_context
*vmesa
,
116 GLuint vertsize
= vmesa
->vertexSize
;
117 GLuint
*vb
= viaExtendPrimitive(vmesa
, 2 * 4 * vertsize
);
118 COPY_DWORDS(vb
, vertsize
, v0
);
119 COPY_DWORDS(vb
, vertsize
, v1
);
123 static void via_draw_point(struct via_context
*vmesa
,
126 GLuint vertsize
= vmesa
->vertexSize
;
127 GLuint
*vb
= viaExtendPrimitive(vmesa
, 4 * vertsize
);
128 COPY_DWORDS(vb
, vertsize
, v0
);
132 /* Fallback drawing functions for the ptex hack.
134 #define PTEX_VERTEX( tmp, vertex_size, v) \
137 GLfloat rhw = 1.0 / v->f[vertex_size]; \
138 for ( j = 0 ; j < vertex_size ; j++ ) \
139 tmp.f[j] = v->f[j]; \
140 tmp.f[3] *= v->f[vertex_size]; \
141 tmp.f[vertex_size-2] *= rhw; \
142 tmp.f[vertex_size-1] *= rhw; \
145 static void via_ptex_tri (struct via_context
*vmesa
,
150 GLuint vertsize
= vmesa
->hwVertexSize
;
151 GLuint
*vb
= viaExtendPrimitive(vmesa
, 3*4*vertsize
);
154 PTEX_VERTEX(tmp
, vertsize
, v0
); COPY_DWORDS(vb
, vertsize
, &tmp
);
155 PTEX_VERTEX(tmp
, vertsize
, v1
); COPY_DWORDS(vb
, vertsize
, &tmp
);
156 PTEX_VERTEX(tmp
, vertsize
, v2
); COPY_DWORDS(vb
, vertsize
, &tmp
);
159 static void via_ptex_line (struct via_context
*vmesa
,
163 GLuint vertsize
= vmesa
->hwVertexSize
;
164 GLuint
*vb
= viaExtendPrimitive(vmesa
, 2*4*vertsize
);
167 PTEX_VERTEX(tmp
, vertsize
, v0
); COPY_DWORDS(vb
, vertsize
, &tmp
);
168 PTEX_VERTEX(tmp
, vertsize
, v1
); COPY_DWORDS(vb
, vertsize
, &tmp
);
171 static void via_ptex_point (struct via_context
*vmesa
,
174 GLuint vertsize
= vmesa
->hwVertexSize
;
175 GLuint
*vb
= viaExtendPrimitive(vmesa
, 1*4*vertsize
);
178 PTEX_VERTEX(tmp
, vertsize
, v0
); COPY_DWORDS(vb
, vertsize
, &tmp
);
185 /***********************************************************************
186 * Macros for via_dd_tritmp.h to draw basic primitives *
187 ***********************************************************************/
189 #define TRI(a, b, c) \
192 vmesa->drawTri(vmesa, a, b, c); \
194 via_draw_triangle(vmesa, a, b, c); \
197 #define QUAD(a, b, c, d) \
200 vmesa->drawTri(vmesa, a, b, d); \
201 vmesa->drawTri(vmesa, b, c, d); \
204 via_draw_quad(vmesa, a, b, c, d); \
207 #define LINE(v0, v1) \
210 vmesa->drawLine(vmesa, v0, v1); \
212 via_draw_line(vmesa, v0, v1); \
218 vmesa->drawPoint(vmesa, v0); \
220 via_draw_point(vmesa, v0); \
224 /***********************************************************************
225 * Build render functions from dd templates *
226 ***********************************************************************/
228 #define VIA_OFFSET_BIT 0x01
229 #define VIA_TWOSIDE_BIT 0x02
230 #define VIA_UNFILLED_BIT 0x04
231 #define VIA_FALLBACK_BIT 0x08
232 #define VIA_MAX_TRIFUNC 0x10
236 tnl_points_func points
;
238 tnl_triangle_func triangle
;
240 } rast_tab
[VIA_MAX_TRIFUNC
];
243 #define DO_FALLBACK (IND & VIA_FALLBACK_BIT)
244 #define DO_OFFSET (IND & VIA_OFFSET_BIT)
245 #define DO_UNFILLED (IND & VIA_UNFILLED_BIT)
246 #define DO_TWOSIDE (IND & VIA_TWOSIDE_BIT)
252 #define DO_FULL_QUAD 1
256 #define HAVE_BACK_COLORS 0
257 #define HAVE_HW_FLATSHADE 1
258 #define VERTEX viaVertex
261 /* Only used to pull back colors into vertices (ie, we know color is
264 #define VIA_COLOR(dst, src) \
272 #define VIA_SPEC(dst, src) \
280 #define DEPTH_SCALE vmesa->polygon_offset_scale
281 #define UNFILLED_TRI unfilled_tri
282 #define UNFILLED_QUAD unfilled_quad
283 #define VERT_X(_v) _v->v.x
284 #define VERT_Y(_v) _v->v.y
285 #define VERT_Z(_v) _v->v.z
286 #define AREA_IS_CCW(a) (a > 0)
287 #define GET_VERTEX(e) (vmesa->verts + (e * vmesa->vertexSize * sizeof(int)))
289 #define VERT_SET_RGBA( v, c ) \
291 via_color_t *color = (via_color_t *)&((v)->ui[coloroffset]); \
292 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
293 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
294 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
295 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
298 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
300 #define VERT_SET_SPEC( v0, c ) \
303 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
304 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
305 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
308 #define VERT_COPY_SPEC( v0, v1 ) \
311 v0->v.specular.red = v1->v.specular.red; \
312 v0->v.specular.green = v1->v.specular.green; \
313 v0->v.specular.blue = v1->v.specular.blue; \
318 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
319 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
320 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
321 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
324 #define LOCAL_VARS(n) \
325 struct via_context *vmesa = VIA_CONTEXT(ctx); \
326 GLuint color[n], spec[n]; \
327 GLuint coloroffset = vmesa->coloroffset; \
328 GLuint specoffset = vmesa->specoffset; \
329 (void)color; (void)spec; (void)coloroffset; (void)specoffset;
332 /***********************************************************************
333 * Helpers for rendering unfilled primitives *
334 ***********************************************************************/
336 static const GLenum hwPrim
[GL_POLYGON
+ 2] = {
351 #define RASTERIZE(x) viaRasterPrimitive( ctx, x, hwPrim[x] )
352 #define RENDER_PRIMITIVE vmesa->renderPrimitive
354 #define IND VIA_FALLBACK_BIT
355 #include "tnl_dd/t_dd_unfilled.h"
359 /***********************************************************************
360 * Generate GL render functions *
361 ***********************************************************************/
366 #include "tnl_dd/t_dd_tritmp.h"
368 #define IND (VIA_OFFSET_BIT)
369 #define TAG(x) x##_offset
370 #include "tnl_dd/t_dd_tritmp.h"
372 #define IND (VIA_TWOSIDE_BIT)
373 #define TAG(x) x##_twoside
374 #include "tnl_dd/t_dd_tritmp.h"
376 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT)
377 #define TAG(x) x##_twoside_offset
378 #include "tnl_dd/t_dd_tritmp.h"
380 #define IND (VIA_UNFILLED_BIT)
381 #define TAG(x) x##_unfilled
382 #include "tnl_dd/t_dd_tritmp.h"
384 #define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT)
385 #define TAG(x) x##_offset_unfilled
386 #include "tnl_dd/t_dd_tritmp.h"
388 #define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT)
389 #define TAG(x) x##_twoside_unfilled
390 #include "tnl_dd/t_dd_tritmp.h"
392 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT)
393 #define TAG(x) x##_twoside_offset_unfilled
394 #include "tnl_dd/t_dd_tritmp.h"
396 #define IND (VIA_FALLBACK_BIT)
397 #define TAG(x) x##_fallback
398 #include "tnl_dd/t_dd_tritmp.h"
400 #define IND (VIA_OFFSET_BIT|VIA_FALLBACK_BIT)
401 #define TAG(x) x##_offset_fallback
402 #include "tnl_dd/t_dd_tritmp.h"
404 #define IND (VIA_TWOSIDE_BIT|VIA_FALLBACK_BIT)
405 #define TAG(x) x##_twoside_fallback
406 #include "tnl_dd/t_dd_tritmp.h"
408 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_FALLBACK_BIT)
409 #define TAG(x) x##_twoside_offset_fallback
410 #include "tnl_dd/t_dd_tritmp.h"
412 #define IND (VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
413 #define TAG(x) x##_unfilled_fallback
414 #include "tnl_dd/t_dd_tritmp.h"
416 #define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
417 #define TAG(x) x##_offset_unfilled_fallback
418 #include "tnl_dd/t_dd_tritmp.h"
420 #define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
421 #define TAG(x) x##_twoside_unfilled_fallback
422 #include "tnl_dd/t_dd_tritmp.h"
424 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT| \
426 #define TAG(x) x##_twoside_offset_unfilled_fallback
427 #include "tnl_dd/t_dd_tritmp.h"
430 static void init_rast_tab(void)
435 init_twoside_offset();
437 init_offset_unfilled();
438 init_twoside_unfilled();
439 init_twoside_offset_unfilled();
441 init_offset_fallback();
442 init_twoside_fallback();
443 init_twoside_offset_fallback();
444 init_unfilled_fallback();
445 init_offset_unfilled_fallback();
446 init_twoside_unfilled_fallback();
447 init_twoside_offset_unfilled_fallback();
451 /***********************************************************************
452 * Rasterization fallback helpers *
453 ***********************************************************************/
456 /* This code is hit only when a mix of accelerated and unaccelerated
457 * primitives are being drawn, and only for the unaccelerated
461 via_fallback_tri(struct via_context
*vmesa
,
466 GLcontext
*ctx
= vmesa
->glCtx
;
468 _swsetup_Translate(ctx
, v0
, &v
[0]);
469 _swsetup_Translate(ctx
, v1
, &v
[1]);
470 _swsetup_Translate(ctx
, v2
, &v
[2]);
471 viaSpanRenderStart( ctx
);
472 _swrast_Triangle(ctx
, &v
[0], &v
[1], &v
[2]);
473 viaSpanRenderFinish( ctx
);
478 via_fallback_line(struct via_context
*vmesa
,
482 GLcontext
*ctx
= vmesa
->glCtx
;
484 _swsetup_Translate(ctx
, v0
, &v
[0]);
485 _swsetup_Translate(ctx
, v1
, &v
[1]);
486 viaSpanRenderStart( ctx
);
487 _swrast_Line(ctx
, &v
[0], &v
[1]);
488 viaSpanRenderFinish( ctx
);
493 via_fallback_point(struct via_context
*vmesa
,
496 GLcontext
*ctx
= vmesa
->glCtx
;
498 _swsetup_Translate(ctx
, v0
, &v
[0]);
499 viaSpanRenderStart( ctx
);
500 _swrast_Point(ctx
, &v
[0]);
501 viaSpanRenderFinish( ctx
);
504 static void viaResetLineStipple( GLcontext
*ctx
)
506 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
507 vmesa
->regCmdB
|= HC_HLPrst_MASK
;
510 /**********************************************************************/
511 /* Render unclipped begin/end objects */
512 /**********************************************************************/
514 #define V(x) (viaVertex *)(vertptr + ((x) * vertsize * sizeof(int)))
515 #define RENDER_POINTS(start, count) \
516 for (; start < count; start++) POINT(V(ELT(start)));
517 #define RENDER_LINE(v0, v1) LINE(V(v0), V(v1))
518 #define RENDER_TRI( v0, v1, v2) TRI( V(v0), V(v1), V(v2))
519 #define RENDER_QUAD(v0, v1, v2, v3) QUAD(V(v0), V(v1), V(v2), V(v3))
520 #define INIT(x) viaRasterPrimitive(ctx, x, hwPrim[x])
523 struct via_context *vmesa = VIA_CONTEXT(ctx); \
524 GLubyte *vertptr = (GLubyte *)vmesa->verts; \
525 const GLuint vertsize = vmesa->vertexSize; \
526 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
527 const GLboolean stipple = ctx->Line.StippleFlag; \
528 (void) elt; (void) stipple;
529 #define RESET_STIPPLE if ( stipple ) viaResetLineStipple( ctx );
530 #define RESET_OCCLUSION
531 #define PRESERVE_VB_DEFS
533 #define TAG(x) via_##x##_verts
534 #include "tnl/t_vb_rendertmp.h"
537 #define TAG(x) via_##x##_elts
538 #define ELT(x) elt[x]
539 #include "tnl/t_vb_rendertmp.h"
542 #undef NEED_EDGEFLAG_SETUP
545 #undef RESET_OCCLUSION
548 /**********************************************************************/
549 /* Render clipped primitives */
550 /**********************************************************************/
554 static void viaRenderClippedPoly(GLcontext
*ctx
, const GLuint
*elts
,
557 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
558 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
559 GLuint prim
= VIA_CONTEXT(ctx
)->renderPrimitive
;
561 /* Render the new vertices as an unclipped polygon.
564 GLuint
*tmp
= VB
->Elts
;
565 VB
->Elts
= (GLuint
*)elts
;
566 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
](ctx
, 0, n
,
567 PRIM_BEGIN
|PRIM_END
);
571 /* Restore the render primitive
573 if (prim
!= GL_POLYGON
&&
574 prim
!= GL_POLYGON
+ 1)
575 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
578 static void viaRenderClippedLine(GLcontext
*ctx
, GLuint ii
, GLuint jj
)
580 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
581 tnl
->Driver
.Render
.Line(ctx
, ii
, jj
);
584 static void viaFastRenderClippedPoly(GLcontext
*ctx
, const GLuint
*elts
,
587 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
588 GLuint vertsize
= vmesa
->vertexSize
;
589 GLuint
*vb
= viaExtendPrimitive(vmesa
, (n
- 2) * 3 * 4 * vertsize
);
590 GLubyte
*vertptr
= (GLubyte
*)vmesa
->verts
;
591 const GLuint
*start
= (const GLuint
*)V(elts
[0]);
594 for (i
= 2; i
< n
; i
++) {
595 COPY_DWORDS(vb
, vertsize
, V(elts
[i
- 1]));
596 COPY_DWORDS(vb
, vertsize
, V(elts
[i
]));
597 COPY_DWORDS(vb
, vertsize
, start
);
601 /**********************************************************************/
602 /* Choose render functions */
603 /**********************************************************************/
608 #define _VIA_NEW_VERTEX (_NEW_TEXTURE | \
609 _DD_NEW_SEPARATE_SPECULAR | \
610 _DD_NEW_TRI_UNFILLED | \
611 _DD_NEW_TRI_LIGHT_TWOSIDE | \
614 #define _VIA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
615 _DD_NEW_TRI_UNFILLED | \
616 _DD_NEW_TRI_LIGHT_TWOSIDE | \
617 _DD_NEW_TRI_OFFSET | \
618 _DD_NEW_TRI_STIPPLE | \
621 #define LINE_FALLBACK (0)
622 #define POINT_FALLBACK (0)
623 #define TRI_FALLBACK (0)
624 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
625 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
627 static void viaChooseRenderState(GLcontext
*ctx
)
629 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
630 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
631 GLuint flags
= ctx
->_TriangleCaps
;
634 if (vmesa
->ptexHack
) {
635 vmesa
->drawPoint
= via_ptex_point
;
636 vmesa
->drawLine
= via_ptex_line
;
637 vmesa
->drawTri
= via_ptex_tri
;
638 index
|= VIA_FALLBACK_BIT
;
641 vmesa
->drawPoint
= via_draw_point
;
642 vmesa
->drawLine
= via_draw_line
;
643 vmesa
->drawTri
= via_draw_triangle
;
646 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
647 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= VIA_TWOSIDE_BIT
;
648 if (flags
& DD_TRI_OFFSET
) index
|= VIA_OFFSET_BIT
;
649 if (flags
& DD_TRI_UNFILLED
) index
|= VIA_UNFILLED_BIT
;
650 if (flags
& ANY_FALLBACK_FLAGS
) index
|= VIA_FALLBACK_BIT
;
652 /* Hook in fallbacks for specific primitives.
654 if (flags
& POINT_FALLBACK
)
655 vmesa
->drawPoint
= via_fallback_point
;
657 if (flags
& LINE_FALLBACK
)
658 vmesa
->drawLine
= via_fallback_line
;
660 if (flags
& TRI_FALLBACK
)
661 vmesa
->drawTri
= via_fallback_tri
;
664 if (vmesa
->renderIndex
!= index
) {
665 vmesa
->renderIndex
= index
;
667 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
668 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
669 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
670 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
673 tnl
->Driver
.Render
.PrimTabVerts
= via_render_tab_verts
;
674 tnl
->Driver
.Render
.PrimTabElts
= via_render_tab_elts
;
675 tnl
->Driver
.Render
.ClippedLine
= line
; /* from tritmp.h */
676 tnl
->Driver
.Render
.ClippedPolygon
= viaFastRenderClippedPoly
;
679 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
680 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
681 tnl
->Driver
.Render
.ClippedLine
= viaRenderClippedLine
;
682 tnl
->Driver
.Render
.ClippedPolygon
= viaRenderClippedPoly
;
688 #define VIA_EMIT_TEX1 0x01
689 #define VIA_EMIT_TEX0 0x02
690 #define VIA_EMIT_PTEX0 0x04
691 #define VIA_EMIT_RGBA 0x08
692 #define VIA_EMIT_SPEC 0x10
693 #define VIA_EMIT_FOG 0x20
694 #define VIA_EMIT_W 0x40
696 #define EMIT_ATTR( ATTR, STYLE, INDEX, REGB ) \
698 vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = (ATTR); \
699 vmesa->vertex_attrs[vmesa->vertex_attr_count].format = (STYLE); \
700 vmesa->vertex_attr_count++; \
701 setupIndex |= (INDEX); \
705 #define EMIT_PAD( N ) \
707 vmesa->vertex_attrs[vmesa->vertex_attr_count].attrib = 0; \
708 vmesa->vertex_attrs[vmesa->vertex_attr_count].format = EMIT_PAD; \
709 vmesa->vertex_attrs[vmesa->vertex_attr_count].offset = (N); \
710 vmesa->vertex_attr_count++; \
715 static void viaChooseVertexState( GLcontext
*ctx
)
717 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
718 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
719 GLuint index
= tnl
->render_inputs
;
720 GLuint regCmdB
= HC_HVPMSK_X
| HC_HVPMSK_Y
| HC_HVPMSK_Z
;
721 GLuint setupIndex
= 0;
723 vmesa
->vertex_attr_count
= 0;
725 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
726 * build up a hardware vertex.
728 if (index
& (_TNL_BITS_TEX_ANY
|_TNL_BIT_FOG
)) {
729 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
, VIA_EMIT_W
, HC_HVPMSK_W
);
730 vmesa
->coloroffset
= 4;
733 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
, 0, 0 );
734 vmesa
->coloroffset
= 3;
737 /* t_context.c always includes a diffuse color */
738 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
, VIA_EMIT_RGBA
,
741 vmesa
->specoffset
= 0;
742 if (index
& (_TNL_BIT_COLOR1
|_TNL_BIT_FOG
)) {
743 if ((index
& _TNL_BIT_COLOR1
)) {
744 vmesa
->specoffset
= vmesa
->coloroffset
+ 1;
745 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
, VIA_EMIT_SPEC
,
751 if ((index
& _TNL_BIT_FOG
))
752 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, VIA_EMIT_FOG
, HC_HVPMSK_Cs
);
757 if (index
& _TNL_BIT_TEX(0)) {
759 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_3F_XYW
, VIA_EMIT_PTEX0
,
760 (HC_HVPMSK_S
| HC_HVPMSK_T
) );
762 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_2F
, VIA_EMIT_TEX0
,
763 (HC_HVPMSK_S
| HC_HVPMSK_T
) );
766 if (index
& _TNL_BIT_TEX(1)) {
767 EMIT_ATTR( _TNL_ATTRIB_TEX1
, EMIT_2F
, VIA_EMIT_TEX1
,
768 (HC_HVPMSK_S
| HC_HVPMSK_T
) );
771 if (setupIndex
!= vmesa
->setupIndex
) {
772 vmesa
->vertexSize
= _tnl_install_attrs( ctx
,
774 vmesa
->vertex_attr_count
,
775 vmesa
->ViewportMatrix
.m
, 0 );
776 vmesa
->vertexSize
>>= 2;
777 vmesa
->setupIndex
= setupIndex
;
778 vmesa
->regCmdB
&= ~HC_HVPMSK_MASK
;
779 vmesa
->regCmdB
|= regCmdB
;
782 vmesa
->hwVertexSize
= vmesa
->vertexSize
- 1;
784 vmesa
->hwVertexSize
= vmesa
->vertexSize
;
791 /* Check if projective texture coordinates are used and if we can fake
792 * them. Fallback to swrast if we can't. Returns GL_TRUE if projective
793 * texture coordinates must be faked, GL_FALSE otherwise.
795 static GLboolean
viaCheckPTexHack( GLcontext
*ctx
)
797 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
798 struct vertex_buffer
*VB
= &tnl
->vb
;
799 GLuint index
= tnl
->render_inputs
;
800 GLboolean fallback
= GL_FALSE
;
801 GLboolean ptexHack
= GL_FALSE
;
803 if (index
& _TNL_BIT_TEX(0) && VB
->TexCoordPtr
[0]->size
== 4) {
804 if ((index
& _TNL_BITS_TEX_ANY
) == _TNL_BIT_TEX(0))
809 if ((index
& _TNL_BIT_TEX(1)) && VB
->TexCoordPtr
[1]->size
== 4)
812 FALLBACK(VIA_CONTEXT(ctx
), VIA_FALLBACK_PROJ_TEXTURE
, fallback
);
819 /**********************************************************************/
820 /* High level hooks for t_vb_render.c */
821 /**********************************************************************/
824 static void viaRenderStart(GLcontext
*ctx
)
826 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
827 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
828 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
831 GLboolean ptexHack
= viaCheckPTexHack( ctx
);
832 if (ptexHack
!= vmesa
->ptexHack
) {
833 vmesa
->ptexHack
= ptexHack
;
834 vmesa
->newRenderState
|= _VIA_NEW_RENDERSTATE
;
838 if (vmesa
->newState
) {
839 vmesa
->newRenderState
|= vmesa
->newState
;
840 viaValidateState( ctx
);
843 if (vmesa
->Fallback
) {
844 tnl
->Driver
.Render
.Start(ctx
);
848 if (vmesa
->newRenderState
) {
849 viaChooseVertexState(ctx
);
850 viaChooseRenderState(ctx
);
851 vmesa
->newRenderState
= 0;
856 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
859 static void viaRenderFinish(GLcontext
*ctx
)
861 VIA_FINISH_PRIM(VIA_CONTEXT(ctx
));
865 /* System to flush dma and emit state changes based on the rasterized
868 void viaRasterPrimitive(GLcontext
*ctx
,
872 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
876 if (VIA_DEBUG
& DEBUG_PRIMS
)
877 fprintf(stderr
, "%s: %s/%s\n",
878 __FUNCTION__
, _mesa_lookup_enum_by_nr(glprim
),
879 _mesa_lookup_enum_by_nr(hwprim
));
881 vmesa
->renderPrimitive
= glprim
;
883 if (hwprim
!= vmesa
->hwPrimitive
) {
884 VIA_FINISH_PRIM(vmesa
);
886 /* Ensure no wrapping inside this function */
887 viaCheckDma( vmesa
, 1024 );
889 if (vmesa
->newEmitState
) {
893 vmesa
->regCmdA_End
= HC_ACMD_HCmdA
;
895 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
896 vmesa
->regCmdA_End
|= HC_HShading_Gouraud
;
899 regCmdB
= vmesa
->regCmdB
;
903 vmesa
->regCmdA_End
|= HC_HPMType_Point
| HC_HVCycle_Full
;
904 vmesa
->regCmdA_End
|= HC_HShading_Gouraud
; /* always Gouraud
908 vmesa
->regCmdA_End
|= HC_HPMType_Line
| HC_HVCycle_Full
;
909 regCmdB
|= HC_HLPrst_MASK
;
910 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
911 vmesa
->regCmdA_End
|= HC_HShading_FlatB
;
915 vmesa
->regCmdA_End
|= HC_HPMType_Line
| HC_HVCycle_AFP
|
916 HC_HVCycle_AB
| HC_HVCycle_NewB
;
917 regCmdB
|= HC_HVCycle_AB
| HC_HVCycle_NewB
| HC_HLPrst_MASK
;
918 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
919 vmesa
->regCmdA_End
|= HC_HShading_FlatB
;
922 vmesa
->regCmdA_End
|= HC_HPMType_Tri
| HC_HVCycle_Full
;
923 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
924 vmesa
->regCmdA_End
|= HC_HShading_FlatC
;
926 case GL_TRIANGLE_STRIP
:
927 vmesa
->regCmdA_End
|= HC_HPMType_Tri
| HC_HVCycle_AFP
|
928 HC_HVCycle_AC
| HC_HVCycle_BB
| HC_HVCycle_NewC
;
929 regCmdB
|= HC_HVCycle_AA
| HC_HVCycle_BC
| HC_HVCycle_NewC
;
930 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
931 vmesa
->regCmdA_End
|= HC_HShading_FlatC
;
933 case GL_TRIANGLE_FAN
:
934 vmesa
->regCmdA_End
|= HC_HPMType_Tri
| HC_HVCycle_AFP
|
935 HC_HVCycle_AA
| HC_HVCycle_BC
| HC_HVCycle_NewC
;
936 regCmdB
|= HC_HVCycle_AA
| HC_HVCycle_BC
| HC_HVCycle_NewC
;
937 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
938 vmesa
->regCmdA_End
|= HC_HShading_FlatC
;
947 vmesa
->regCmdA_End
|= HC_HPMType_Tri
| HC_HVCycle_AFP
|
948 HC_HVCycle_AA
| HC_HVCycle_BC
| HC_HVCycle_NewC
;
949 regCmdB
|= HC_HVCycle_AA
| HC_HVCycle_BC
| HC_HVCycle_NewC
;
950 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
951 vmesa
->regCmdA_End
|= HC_HShading_FlatC
;
958 /* assert((vmesa->dmaLow & 0x4) == 0); */
960 if (vmesa
->dmaCliprectAddr
== ~0) {
961 if (VIA_DEBUG
& DEBUG_DMA
)
962 fprintf(stderr
, "reserve cliprect space at %x\n", vmesa
->dmaLow
);
963 vmesa
->dmaCliprectAddr
= vmesa
->dmaLow
;
965 OUT_RING( HC_HEADER2
);
966 OUT_RING( (HC_ParaType_NotTex
<< 16) );
967 OUT_RING( 0xCCCCCCCC );
968 OUT_RING( 0xCCCCCCCC );
969 OUT_RING( 0xCCCCCCCC );
970 OUT_RING( 0xCCCCCCCC );
971 OUT_RING( 0xCCCCCCCC );
972 OUT_RING( 0xCCCCCCCC );
976 assert(vmesa
->dmaLastPrim
== 0);
979 OUT_RING( HC_HEADER2
);
980 OUT_RING( (HC_ParaType_NotTex
<< 16) );
981 OUT_RING( 0xCCCCCCCC );
982 OUT_RING( 0xDDDDDDDD );
984 OUT_RING( HC_HEADER2
);
985 OUT_RING( (HC_ParaType_CmdVdata
<< 16) );
987 OUT_RING( vmesa
->regCmdA_End
);
990 vmesa
->hwPrimitive
= hwprim
;
991 vmesa
->dmaLastPrim
= vmesa
->dmaLow
;
994 assert(!vmesa
->newEmitState
);
998 /* Callback for mesa:
1000 static void viaRenderPrimitive( GLcontext
*ctx
, GLuint prim
)
1002 viaRasterPrimitive( ctx
, prim
, hwPrim
[prim
] );
1006 void viaFinishPrimitive(struct via_context
*vmesa
)
1008 if (VIA_DEBUG
& (DEBUG_DMA
|DEBUG_PRIMS
))
1009 fprintf(stderr
, "%s\n", __FUNCTION__
);
1011 if (!vmesa
->dmaLastPrim
|| vmesa
->dmaCliprectAddr
== ~0) {
1014 else if (vmesa
->dmaLow
!= vmesa
->dmaLastPrim
) {
1015 GLuint cmdA
= (vmesa
->regCmdA_End
| HC_HPLEND_MASK
|
1016 HC_HPMValidN_MASK
| HC_HE3Fire_MASK
);
1019 vmesa
->dmaLastPrim
= 0;
1021 /* KW: modified 0x1 to 0x4 below:
1023 if ((vmesa
->dmaLow
& 0x4) || !vmesa
->useAgp
) {
1024 BEGIN_RING_NOCHECK( 1 );
1029 BEGIN_RING_NOCHECK( 2 );
1035 if (vmesa
->dmaLow
> VIA_DMA_HIGHWATER
)
1036 viaFlushDma( vmesa
);
1039 if (VIA_DEBUG
& (DEBUG_DMA
|DEBUG_PRIMS
))
1040 fprintf(stderr
, "remove empty primitive\n");
1042 /* Remove the primitive header:
1044 vmesa
->dmaLastPrim
= 0;
1045 vmesa
->dmaLow
-= 8 * sizeof(GLuint
);
1047 /* Maybe remove the cliprect as well:
1049 if (vmesa
->dmaCliprectAddr
== vmesa
->dmaLow
- 8 * sizeof(GLuint
)) {
1050 vmesa
->dmaLow
-= 8 * sizeof(GLuint
);
1051 vmesa
->dmaCliprectAddr
= ~0;
1055 vmesa
->renderPrimitive
= GL_POLYGON
+ 1;
1056 vmesa
->hwPrimitive
= GL_POLYGON
+ 1;
1057 vmesa
->dmaLastPrim
= 0;
1061 /**********************************************************************/
1062 /* Transition to/from hardware rasterization. */
1063 /**********************************************************************/
1066 void viaFallback(struct via_context
*vmesa
, GLuint bit
, GLboolean mode
)
1068 GLcontext
*ctx
= vmesa
->glCtx
;
1069 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1070 GLuint oldfallback
= vmesa
->Fallback
;
1073 vmesa
->Fallback
|= bit
;
1074 if (oldfallback
== 0) {
1075 VIA_FLUSH_DMA(vmesa
);
1077 if (VIA_DEBUG
& DEBUG_FALLBACKS
)
1078 fprintf(stderr
, "ENTER FALLBACK %x\n", bit
);
1080 _swsetup_Wakeup(ctx
);
1081 vmesa
->renderIndex
= ~0;
1085 vmesa
->Fallback
&= ~bit
;
1086 if (oldfallback
== bit
) {
1087 _swrast_flush( ctx
);
1089 if (VIA_DEBUG
& DEBUG_FALLBACKS
)
1090 fprintf(stderr
, "LEAVE FALLBACK %x\n", bit
);
1092 tnl
->Driver
.Render
.Start
= viaRenderStart
;
1093 tnl
->Driver
.Render
.PrimitiveNotify
= viaRenderPrimitive
;
1094 tnl
->Driver
.Render
.Finish
= viaRenderFinish
;
1096 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1097 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1098 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1099 tnl
->Driver
.Render
.ResetLineStipple
= viaResetLineStipple
;
1101 _tnl_invalidate_vertex_state( ctx
, ~0 );
1102 _tnl_invalidate_vertices( ctx
, ~0 );
1103 _tnl_install_attrs( ctx
,
1104 vmesa
->vertex_attrs
,
1105 vmesa
->vertex_attr_count
,
1106 vmesa
->ViewportMatrix
.m
, 0 );
1108 vmesa
->newState
|= (_VIA_NEW_RENDERSTATE
|_VIA_NEW_VERTEX
);
1113 static void viaRunPipeline( GLcontext
*ctx
)
1115 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
1117 if (vmesa
->newState
) {
1118 vmesa
->newRenderState
|= vmesa
->newState
;
1119 viaValidateState( ctx
);
1122 _tnl_run_pipeline( ctx
);
1126 /**********************************************************************/
1127 /* Initialization. */
1128 /**********************************************************************/
1131 void viaInitTriFuncs(GLcontext
*ctx
)
1133 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
1134 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1135 static int firsttime
= 1;
1142 tnl
->Driver
.RunPipeline
= viaRunPipeline
;
1143 tnl
->Driver
.Render
.Start
= viaRenderStart
;
1144 tnl
->Driver
.Render
.Finish
= viaRenderFinish
;
1145 tnl
->Driver
.Render
.PrimitiveNotify
= viaRenderPrimitive
;
1146 tnl
->Driver
.Render
.ResetLineStipple
= viaResetLineStipple
;
1147 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1148 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1149 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1151 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
1152 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
1154 vmesa
->verts
= (GLubyte
*)tnl
->clipspace
.vertex_buf
;