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 ***********************************************************************/
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)
59 #define COPY_DWORDS(vb, vertsize, v) \
61 via_sse_memcpy(vb, v, vertsize * 4); \
65 #if defined( USE_X86_ASM )
66 #define COPY_DWORDS(vb, vertsize, v) \
70 __asm__ __volatile__("rep ; movsl" \
71 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
77 #define COPY_DWORDS(vb, vertsize, v) \
80 for (j = 0; j < vertsize; j++) \
81 vb[j] = ((GLuint *)v)[j]; \
87 static void via_draw_triangle(struct via_context
*vmesa
,
92 GLuint vertsize
= vmesa
->vertexSize
;
93 GLuint
*vb
= viaExtendPrimitive(vmesa
, 3 * 4 * vertsize
);
95 COPY_DWORDS(vb
, vertsize
, v0
);
96 COPY_DWORDS(vb
, vertsize
, v1
);
97 COPY_DWORDS(vb
, vertsize
, v2
);
101 static void via_draw_quad(struct via_context
*vmesa
,
107 GLuint vertsize
= vmesa
->vertexSize
;
108 GLuint
*vb
= viaExtendPrimitive(vmesa
, 6 * 4 * vertsize
);
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
);
118 static void via_draw_line(struct via_context
*vmesa
,
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
);
129 static void via_draw_point(struct via_context
*vmesa
,
132 GLuint vertsize
= vmesa
->vertexSize
;
133 GLuint
*vb
= viaExtendPrimitive(vmesa
, 4 * vertsize
);
134 COPY_DWORDS(vb
, vertsize
, v0
);
138 /* Fallback drawing functions for the ptex hack.
140 #define PTEX_VERTEX( tmp, vertex_size, v) \
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; \
151 static void via_ptex_tri (struct via_context
*vmesa
,
156 GLuint vertsize
= vmesa
->hwVertexSize
;
157 GLuint
*vb
= viaExtendPrimitive(vmesa
, 3*4*vertsize
);
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
);
165 static void via_ptex_line (struct via_context
*vmesa
,
169 GLuint vertsize
= vmesa
->hwVertexSize
;
170 GLuint
*vb
= viaExtendPrimitive(vmesa
, 2*4*vertsize
);
173 PTEX_VERTEX(tmp
, vertsize
, v0
); COPY_DWORDS(vb
, vertsize
, &tmp
);
174 PTEX_VERTEX(tmp
, vertsize
, v1
); COPY_DWORDS(vb
, vertsize
, &tmp
);
177 static void via_ptex_point (struct via_context
*vmesa
,
180 GLuint vertsize
= vmesa
->hwVertexSize
;
181 GLuint
*vb
= viaExtendPrimitive(vmesa
, 1*4*vertsize
);
184 PTEX_VERTEX(tmp
, vertsize
, v0
); COPY_DWORDS(vb
, vertsize
, &tmp
);
191 /***********************************************************************
192 * Macros for via_dd_tritmp.h to draw basic primitives *
193 ***********************************************************************/
195 #define TRI(a, b, c) \
198 vmesa->drawTri(vmesa, a, b, c); \
200 via_draw_triangle(vmesa, a, b, c); \
203 #define QUAD(a, b, c, d) \
206 vmesa->drawTri(vmesa, a, b, d); \
207 vmesa->drawTri(vmesa, b, c, d); \
210 via_draw_quad(vmesa, a, b, c, d); \
213 #define LINE(v0, v1) \
216 vmesa->drawLine(vmesa, v0, v1); \
218 via_draw_line(vmesa, v0, v1); \
224 vmesa->drawPoint(vmesa, v0); \
226 via_draw_point(vmesa, v0); \
230 /***********************************************************************
231 * Build render functions from dd templates *
232 ***********************************************************************/
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
242 tnl_points_func points
;
244 tnl_triangle_func triangle
;
246 } rast_tab
[VIA_MAX_TRIFUNC
+ 1];
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)
258 #define DO_FULL_QUAD 1
262 #define HAVE_BACK_COLORS 0
263 #define HAVE_HW_FLATSHADE 1
264 #define VERTEX viaVertex
267 /* Only used to pull back colors into vertices (ie, we know color is
270 #define VIA_COLOR(dst, src) \
278 #define VIA_SPEC(dst, src) \
286 #define DEPTH_SCALE vmesa->polygon_offset_scale
287 #define UNFILLED_TRI unfilled_tri
288 #define UNFILLED_QUAD unfilled_quad
289 #define VERT_X(_v) _v->v.x
290 #define VERT_Y(_v) _v->v.y
291 #define VERT_Z(_v) _v->v.z
292 #define AREA_IS_CCW(a) (a > 0)
293 #define GET_VERTEX(e) (vmesa->verts + (e * vmesa->vertexSize * sizeof(int)))
295 #define VERT_SET_RGBA( v, c ) \
297 via_color_t *color = (via_color_t *)&((v)->ui[coloroffset]); \
298 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
299 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
300 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
301 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
304 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
306 #define VERT_SET_SPEC( v, c ) \
309 via_color_t *color = (via_color_t *)&((v)->ui[specoffset]); \
310 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
311 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
312 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
315 #define VERT_COPY_SPEC( v0, v1 ) \
318 v0->ub4[specoffset][0] = v1->ub4[specoffset][0]; \
319 v0->ub4[specoffset][1] = v1->ub4[specoffset][1]; \
320 v0->ub4[specoffset][2] = v1->ub4[specoffset][2]; \
325 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
326 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
327 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
328 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
331 #define LOCAL_VARS(n) \
332 struct via_context *vmesa = VIA_CONTEXT(ctx); \
333 GLuint color[n], spec[n]; \
334 GLuint coloroffset = vmesa->coloroffset; \
335 GLuint specoffset = vmesa->specoffset; \
336 (void)color; (void)spec; (void)coloroffset; (void)specoffset;
339 /***********************************************************************
340 * Helpers for rendering unfilled primitives *
341 ***********************************************************************/
343 static const GLenum hwPrim
[GL_POLYGON
+ 2] = {
358 #define RASTERIZE(x) viaRasterPrimitive( ctx, x, hwPrim[x] )
359 #define RENDER_PRIMITIVE vmesa->renderPrimitive
361 #define IND VIA_FALLBACK_BIT
362 #include "tnl_dd/t_dd_unfilled.h"
366 /***********************************************************************
367 * Generate GL render functions *
368 ***********************************************************************/
373 #include "tnl_dd/t_dd_tritmp.h"
375 #define IND (VIA_OFFSET_BIT)
376 #define TAG(x) x##_offset
377 #include "tnl_dd/t_dd_tritmp.h"
379 #define IND (VIA_TWOSIDE_BIT)
380 #define TAG(x) x##_twoside
381 #include "tnl_dd/t_dd_tritmp.h"
383 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT)
384 #define TAG(x) x##_twoside_offset
385 #include "tnl_dd/t_dd_tritmp.h"
387 #define IND (VIA_UNFILLED_BIT)
388 #define TAG(x) x##_unfilled
389 #include "tnl_dd/t_dd_tritmp.h"
391 #define IND (VIA_OFFSET_BIT|VIA_UNFILLED_BIT)
392 #define TAG(x) x##_offset_unfilled
393 #include "tnl_dd/t_dd_tritmp.h"
395 #define IND (VIA_TWOSIDE_BIT|VIA_UNFILLED_BIT)
396 #define TAG(x) x##_twoside_unfilled
397 #include "tnl_dd/t_dd_tritmp.h"
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"
403 #define IND (VIA_FALLBACK_BIT)
404 #define TAG(x) x##_fallback
405 #include "tnl_dd/t_dd_tritmp.h"
407 #define IND (VIA_OFFSET_BIT|VIA_FALLBACK_BIT)
408 #define TAG(x) x##_offset_fallback
409 #include "tnl_dd/t_dd_tritmp.h"
411 #define IND (VIA_TWOSIDE_BIT|VIA_FALLBACK_BIT)
412 #define TAG(x) x##_twoside_fallback
413 #include "tnl_dd/t_dd_tritmp.h"
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"
419 #define IND (VIA_UNFILLED_BIT|VIA_FALLBACK_BIT)
420 #define TAG(x) x##_unfilled_fallback
421 #include "tnl_dd/t_dd_tritmp.h"
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"
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"
431 #define IND (VIA_TWOSIDE_BIT|VIA_OFFSET_BIT|VIA_UNFILLED_BIT| \
433 #define TAG(x) x##_twoside_offset_unfilled_fallback
434 #include "tnl_dd/t_dd_tritmp.h"
437 /* Catchall case for flat, separate specular triangles (via has flat
438 * diffuse shading, but always does specular color with gouraud).
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)
450 #define TAG(x) x##_flat_specular
451 #define IND VIA_MAX_TRIFUNC
452 #include "tnl_dd/t_dd_tritmp.h"
455 static void init_rast_tab(void)
460 init_twoside_offset();
462 init_offset_unfilled();
463 init_twoside_unfilled();
464 init_twoside_offset_unfilled();
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();
474 init_flat_specular(); /* special! */
478 /***********************************************************************
479 * Rasterization fallback helpers *
480 ***********************************************************************/
483 /* This code is hit only when a mix of accelerated and unaccelerated
484 * primitives are being drawn, and only for the unaccelerated
488 via_fallback_tri(struct via_context
*vmesa
,
493 GLcontext
*ctx
= vmesa
->glCtx
;
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
);
505 via_fallback_line(struct via_context
*vmesa
,
509 GLcontext
*ctx
= vmesa
->glCtx
;
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
);
520 via_fallback_point(struct via_context
*vmesa
,
523 GLcontext
*ctx
= vmesa
->glCtx
;
525 _swsetup_Translate(ctx
, v0
, &v
[0]);
526 viaSpanRenderStart( ctx
);
527 _swrast_Point(ctx
, &v
[0]);
528 viaSpanRenderFinish( ctx
);
531 static void viaResetLineStipple( GLcontext
*ctx
)
533 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
534 vmesa
->regCmdB
|= HC_HLPrst_MASK
;
537 /**********************************************************************/
538 /* Render unclipped begin/end objects */
539 /**********************************************************************/
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])
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
560 #define TAG(x) via_##x##_verts
561 #include "tnl/t_vb_rendertmp.h"
564 #define TAG(x) via_##x##_elts
565 #define ELT(x) elt[x]
566 #include "tnl/t_vb_rendertmp.h"
569 #undef NEED_EDGEFLAG_SETUP
572 #undef RESET_OCCLUSION
575 /**********************************************************************/
576 /* Render clipped primitives */
577 /**********************************************************************/
581 static void viaRenderClippedPoly(GLcontext
*ctx
, const GLuint
*elts
,
584 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
585 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
586 GLuint prim
= VIA_CONTEXT(ctx
)->renderPrimitive
;
588 /* Render the new vertices as an unclipped polygon.
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
);
598 /* Restore the render primitive
600 if (prim
!= GL_POLYGON
&&
601 prim
!= GL_POLYGON
+ 1)
602 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
605 static void viaRenderClippedLine(GLcontext
*ctx
, GLuint ii
, GLuint jj
)
607 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
608 tnl
->Driver
.Render
.Line(ctx
, ii
, jj
);
611 static void viaFastRenderClippedPoly(GLcontext
*ctx
, const GLuint
*elts
,
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]);
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
);
629 /**********************************************************************/
630 /* Choose render functions */
631 /**********************************************************************/
634 #define _VIA_NEW_VERTEX (_NEW_TEXTURE | \
635 _DD_NEW_SEPARATE_SPECULAR | \
636 _DD_NEW_TRI_UNFILLED | \
637 _DD_NEW_TRI_LIGHT_TWOSIDE | \
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 | \
648 static void viaChooseRenderState(GLcontext
*ctx
)
650 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
651 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
652 GLuint flags
= ctx
->_TriangleCaps
;
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
;
662 vmesa
->drawPoint
= via_draw_point
;
663 vmesa
->drawLine
= via_draw_line
;
664 vmesa
->drawTri
= via_draw_triangle
;
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
;
677 /* Hook in fallbacks for specific primitives. */
678 if (flags
& POINT_FALLBACK
)
679 vmesa
->drawPoint
= via_fallback_point
;
681 if (flags
& LINE_FALLBACK
)
682 vmesa
->drawLine
= via_fallback_line
;
684 if (flags
& TRI_FALLBACK
)
685 vmesa
->drawTri
= via_fallback_tri
;
688 if ((flags
& DD_SEPARATE_SPECULAR
) && ctx
->Light
.ShadeModel
== GL_FLAT
)
689 index
= VIA_MAX_TRIFUNC
; /* flat specular */
691 if (vmesa
->renderIndex
!= index
) {
692 vmesa
->renderIndex
= index
;
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
;
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
;
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
;
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
723 #define EMIT_ATTR( ATTR, STYLE, INDEX, REGB ) \
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); \
732 #define EMIT_PAD( N ) \
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++; \
742 static void viaChooseVertexState( GLcontext
*ctx
)
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;
750 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
751 vmesa
->vertex_attr_count
= 0;
753 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
754 * build up a hardware vertex.
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;
762 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
, 0, 0 );
763 vmesa
->coloroffset
= 3;
766 /* t_context.c always includes a diffuse color */
767 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
, VIA_EMIT_RGBA
,
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
,
781 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
))
782 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, VIA_EMIT_FOG
, HC_HVPMSK_Cs
);
787 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX0
)) {
789 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_3F_XYW
, VIA_EMIT_PTEX0
,
790 (HC_HVPMSK_S
| HC_HVPMSK_T
) );
792 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_2F
, VIA_EMIT_TEX0
,
793 (HC_HVPMSK_S
| HC_HVPMSK_T
) );
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
) );
801 if (setupIndex
!= vmesa
->setupIndex
) {
802 vmesa
->vertexSize
= _tnl_install_attrs( ctx
,
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
;
812 vmesa
->hwVertexSize
= vmesa
->vertexSize
- 1;
814 vmesa
->hwVertexSize
= vmesa
->vertexSize
;
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.
825 static GLboolean
viaCheckPTexHack( GLcontext
*ctx
)
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
;
833 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
835 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX0
) && VB
->TexCoordPtr
[0]->size
== 4) {
836 if (!RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_ATTRIB_TEX1
, _TNL_LAST_TEX
))
841 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX1
) && VB
->TexCoordPtr
[1]->size
== 4)
844 FALLBACK(VIA_CONTEXT(ctx
), VIA_FALLBACK_PROJ_TEXTURE
, fallback
);
851 /**********************************************************************/
852 /* High level hooks for t_vb_render.c */
853 /**********************************************************************/
856 static void viaRenderStart(GLcontext
*ctx
)
858 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
859 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
860 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
863 GLboolean ptexHack
= viaCheckPTexHack( ctx
);
864 if (ptexHack
!= vmesa
->ptexHack
) {
865 vmesa
->ptexHack
= ptexHack
;
866 vmesa
->newRenderState
|= _VIA_NEW_RENDERSTATE
;
870 if (vmesa
->newState
) {
871 vmesa
->newRenderState
|= vmesa
->newState
;
872 viaValidateState( ctx
);
875 if (vmesa
->Fallback
) {
876 tnl
->Driver
.Render
.Start(ctx
);
880 if (vmesa
->newRenderState
) {
881 viaChooseVertexState(ctx
);
882 viaChooseRenderState(ctx
);
883 vmesa
->newRenderState
= 0;
888 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
891 static void viaRenderFinish(GLcontext
*ctx
)
893 VIA_FINISH_PRIM(VIA_CONTEXT(ctx
));
897 /* System to flush dma and emit state changes based on the rasterized
900 void viaRasterPrimitive(GLcontext
*ctx
,
904 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
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
));
914 assert (!vmesa
->newState
);
916 vmesa
->renderPrimitive
= glprim
;
918 if (hwprim
!= vmesa
->hwPrimitive
||
919 ctx
->Light
.ShadeModel
!= vmesa
->hwShadeModel
) {
921 VIA_FINISH_PRIM(vmesa
);
923 /* Ensure no wrapping inside this function */
924 viaCheckDma( vmesa
, 1024 );
926 if (vmesa
->newEmitState
) {
930 vmesa
->regCmdA_End
= HC_ACMD_HCmdA
;
932 if (ctx
->Light
.ShadeModel
== GL_SMOOTH
) {
933 vmesa
->regCmdA_End
|= HC_HShading_Gouraud
;
936 vmesa
->hwShadeModel
= ctx
->Light
.ShadeModel
;
937 regCmdB
= vmesa
->regCmdB
;
941 vmesa
->regCmdA_End
|= HC_HPMType_Point
| HC_HVCycle_Full
;
942 vmesa
->regCmdA_End
|= HC_HShading_Gouraud
; /* always Gouraud
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
;
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
;
960 vmesa
->regCmdA_End
|= HC_HPMType_Tri
| HC_HVCycle_Full
;
961 if (ctx
->Light
.ShadeModel
== GL_FLAT
)
962 vmesa
->regCmdA_End
|= HC_HShading_FlatC
;
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
;
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
;
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
;
996 /* assert((vmesa->dmaLow & 0x4) == 0); */
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
;
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 );
1014 assert(vmesa
->dmaLastPrim
== 0);
1017 OUT_RING( HC_HEADER2
);
1018 OUT_RING( (HC_ParaType_NotTex
<< 16) );
1019 OUT_RING( 0xCCCCCCCC );
1020 OUT_RING( 0xDDDDDDDD );
1022 OUT_RING( HC_HEADER2
);
1023 OUT_RING( (HC_ParaType_CmdVdata
<< 16) );
1024 OUT_RING( regCmdB
);
1025 OUT_RING( vmesa
->regCmdA_End
);
1028 vmesa
->hwPrimitive
= hwprim
;
1029 vmesa
->dmaLastPrim
= vmesa
->dmaLow
;
1032 assert(!vmesa
->newEmitState
);
1036 /* Callback for mesa:
1038 static void viaRenderPrimitive( GLcontext
*ctx
, GLuint prim
)
1040 viaRasterPrimitive( ctx
, prim
, hwPrim
[prim
] );
1044 void viaFinishPrimitive(struct via_context
*vmesa
)
1046 if (VIA_DEBUG
& (DEBUG_DMA
|DEBUG_PRIMS
))
1047 fprintf(stderr
, "%s\n", __FUNCTION__
);
1049 if (!vmesa
->dmaLastPrim
|| vmesa
->dmaCliprectAddr
== ~0) {
1052 else if (vmesa
->dmaLow
!= vmesa
->dmaLastPrim
) {
1053 GLuint cmdA
= (vmesa
->regCmdA_End
| HC_HPLEND_MASK
|
1054 HC_HPMValidN_MASK
| HC_HE3Fire_MASK
);
1057 vmesa
->dmaLastPrim
= 0;
1059 /* KW: modified 0x1 to 0x4 below:
1061 if ((vmesa
->dmaLow
& 0x4) || !vmesa
->useAgp
) {
1062 BEGIN_RING_NOCHECK( 1 );
1067 BEGIN_RING_NOCHECK( 2 );
1073 if (vmesa
->dmaLow
> VIA_DMA_HIGHWATER
)
1074 viaFlushDma( vmesa
);
1077 if (VIA_DEBUG
& (DEBUG_DMA
|DEBUG_PRIMS
))
1078 fprintf(stderr
, "remove empty primitive\n");
1080 /* Remove the primitive header:
1082 vmesa
->dmaLastPrim
= 0;
1083 vmesa
->dmaLow
-= 8 * sizeof(GLuint
);
1085 /* Maybe remove the cliprect as well:
1087 if (vmesa
->dmaCliprectAddr
== vmesa
->dmaLow
- 8 * sizeof(GLuint
)) {
1088 vmesa
->dmaLow
-= 8 * sizeof(GLuint
);
1089 vmesa
->dmaCliprectAddr
= ~0;
1093 vmesa
->renderPrimitive
= GL_POLYGON
+ 1;
1094 vmesa
->hwPrimitive
= GL_POLYGON
+ 1;
1095 vmesa
->dmaLastPrim
= 0;
1099 /**********************************************************************/
1100 /* Transition to/from hardware rasterization. */
1101 /**********************************************************************/
1104 void viaFallback(struct via_context
*vmesa
, GLuint bit
, GLboolean mode
)
1106 GLcontext
*ctx
= vmesa
->glCtx
;
1107 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1108 GLuint oldfallback
= vmesa
->Fallback
;
1111 vmesa
->Fallback
|= bit
;
1112 if (oldfallback
== 0) {
1113 VIA_FLUSH_DMA(vmesa
);
1115 if (VIA_DEBUG
& DEBUG_FALLBACKS
)
1116 fprintf(stderr
, "ENTER FALLBACK %x\n", bit
);
1118 _swsetup_Wakeup(ctx
);
1119 vmesa
->renderIndex
= ~0;
1123 vmesa
->Fallback
&= ~bit
;
1124 if (oldfallback
== bit
) {
1125 _swrast_flush( ctx
);
1127 if (VIA_DEBUG
& DEBUG_FALLBACKS
)
1128 fprintf(stderr
, "LEAVE FALLBACK %x\n", bit
);
1130 tnl
->Driver
.Render
.Start
= viaRenderStart
;
1131 tnl
->Driver
.Render
.PrimitiveNotify
= viaRenderPrimitive
;
1132 tnl
->Driver
.Render
.Finish
= viaRenderFinish
;
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
;
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 );
1146 vmesa
->newState
|= (_VIA_NEW_RENDERSTATE
|_VIA_NEW_VERTEX
);
1151 static void viaRunPipeline( GLcontext
*ctx
)
1153 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
1155 if (vmesa
->newState
) {
1156 vmesa
->newRenderState
|= vmesa
->newState
;
1157 viaValidateState( ctx
);
1160 _tnl_run_pipeline( ctx
);
1164 /**********************************************************************/
1165 /* Initialization. */
1166 /**********************************************************************/
1169 void viaInitTriFuncs(GLcontext
*ctx
)
1171 struct via_context
*vmesa
= VIA_CONTEXT(ctx
);
1172 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
1173 static int firsttime
= 1;
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
;
1189 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
1190 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
1192 vmesa
->verts
= (GLubyte
*)tnl
->clipspace
.vertex_buf
;