1 /* $XFree86$ */ /* -*- c-basic-offset: 3 -*- */
2 /**************************************************************************
4 Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
5 VA Linux Systems Inc., Fremont, California.
9 Permission is hereby granted, free of charge, to any person obtaining a
10 copy of this software and associated documentation files (the "Software"),
11 to deal in the Software without restriction, including without limitation
12 on the rights to use, copy, modify, merge, publish, distribute, sub
13 license, and/or sell copies of the Software, and to permit persons to whom
14 the Software is furnished to do so, subject to the following conditions:
16 The above copyright notice and this permission notice (including the next
17 paragraph) shall be included in all copies or substantial portions of the
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
23 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
24 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
25 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
26 USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
32 * Keith Whitwell <keithw@valinux.com>
33 * Felix Kuehling <fxkuehl@gmx.de>
45 #include "swrast/swrast.h"
46 #include "swrast_setup/swrast_setup.h"
48 #include "tnl/t_context.h"
49 #include "tnl/t_pipeline.h"
51 #include "savagetris.h"
52 #include "savagestate.h"
53 #include "savagetex.h"
54 #include "savageioctl.h"
55 #include "savage_bci.h"
57 static void savageRasterPrimitive( GLcontext
*ctx
, GLuint prim
);
58 static void savageRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
61 static GLenum reduced_prim
[GL_POLYGON
+1] = {
75 /***********************************************************************
77 ***********************************************************************/
79 #if defined (USE_X86_ASM)
80 #define EMIT_VERT( j, vb, vertex_size, start, v ) \
83 __asm__ __volatile__( "rep ; movsl" \
84 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
85 : "0" (vertex_size-start), \
87 "S" ((long)&v->ui[start])); \
90 #define EMIT_VERT( j, vb, vertex_size, start, v ) \
92 for ( j = start ; j < vertex_size ; j++ ) \
98 static void __inline__
savage_draw_triangle (savageContextPtr imesa
,
101 savageVertexPtr v2
) {
102 GLuint vertsize
= imesa
->vertex_size
;
103 uint32_t *vb
= savageAllocDmaLow (imesa
, 3*4*vertsize
);
106 EMIT_VERT (j
, vb
, vertsize
, 0, v0
);
107 EMIT_VERT (j
, vb
, vertsize
, 0, v1
);
108 EMIT_VERT (j
, vb
, vertsize
, 0, v2
);
111 static void __inline__
savage_draw_quad (savageContextPtr imesa
,
115 savageVertexPtr v3
) {
116 GLuint vertsize
= imesa
->vertex_size
;
117 uint32_t *vb
= savageAllocDmaLow (imesa
, 6*4*vertsize
);
120 EMIT_VERT (j
, vb
, vertsize
, 0, v0
);
121 EMIT_VERT (j
, vb
, vertsize
, 0, v1
);
122 EMIT_VERT (j
, vb
, vertsize
, 0, v3
);
123 EMIT_VERT (j
, vb
, vertsize
, 0, v1
);
124 EMIT_VERT (j
, vb
, vertsize
, 0, v2
);
125 EMIT_VERT (j
, vb
, vertsize
, 0, v3
);
128 static __inline__
void savage_draw_point (savageContextPtr imesa
,
129 savageVertexPtr tmp
) {
130 GLuint vertsize
= imesa
->vertex_size
;
131 uint32_t *vb
= savageAllocDmaLow (imesa
, 6*4*vertsize
);
132 const GLfloat x
= tmp
->v
.x
;
133 const GLfloat y
= tmp
->v
.y
;
134 const GLfloat sz
= imesa
->glCtx
->Point
._Size
* .5;
137 *(float *)&vb
[0] = x
- sz
;
138 *(float *)&vb
[1] = y
- sz
;
139 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
141 *(float *)&vb
[0] = x
+ sz
;
142 *(float *)&vb
[1] = y
- sz
;
143 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
145 *(float *)&vb
[0] = x
+ sz
;
146 *(float *)&vb
[1] = y
+ sz
;
147 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
149 *(float *)&vb
[0] = x
+ sz
;
150 *(float *)&vb
[1] = y
+ sz
;
151 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
153 *(float *)&vb
[0] = x
- sz
;
154 *(float *)&vb
[1] = y
+ sz
;
155 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
157 *(float *)&vb
[0] = x
- sz
;
158 *(float *)&vb
[1] = y
- sz
;
159 EMIT_VERT (j
, vb
, vertsize
, 2, tmp
);
162 static __inline__
void savage_draw_line (savageContextPtr imesa
,
164 savageVertexPtr v1
) {
165 GLuint vertsize
= imesa
->vertex_size
;
166 uint32_t *vb
= savageAllocDmaLow (imesa
, 6*4*vertsize
);
167 GLfloat width
= imesa
->glCtx
->Line
._Width
;
168 GLfloat dx
, dy
, ix
, iy
;
171 dx
= v0
->v
.x
- v1
->v
.x
;
172 dy
= v0
->v
.y
- v1
->v
.y
;
174 ix
= width
* .5; iy
= 0;
175 if (dx
* dx
> dy
* dy
) {
179 *(float *)&vb
[0] = v0
->v
.x
- ix
;
180 *(float *)&vb
[1] = v0
->v
.y
- iy
;
181 EMIT_VERT (j
, vb
, vertsize
, 2, v0
);
183 *(float *)&vb
[0] = v1
->v
.x
+ ix
;
184 *(float *)&vb
[1] = v1
->v
.y
+ iy
;
185 EMIT_VERT (j
, vb
, vertsize
, 2, v1
);
187 *(float *)&vb
[0] = v0
->v
.x
+ ix
;
188 *(float *)&vb
[1] = v0
->v
.y
+ iy
;
189 EMIT_VERT (j
, vb
, vertsize
, 2, v0
);
191 *(float *)&vb
[0] = v0
->v
.x
- ix
;
192 *(float *)&vb
[1] = v0
->v
.y
- iy
;
193 EMIT_VERT (j
, vb
, vertsize
, 2, v0
);
195 *(float *)&vb
[0] = v1
->v
.x
- ix
;
196 *(float *)&vb
[1] = v1
->v
.y
- iy
;
197 EMIT_VERT (j
, vb
, vertsize
, 2, v1
);
199 *(float *)&vb
[0] = v1
->v
.x
+ ix
;
200 *(float *)&vb
[1] = v1
->v
.y
+ iy
;
201 EMIT_VERT (j
, vb
, vertsize
, 2, v1
);
204 /***********************************************************************
205 * Macros for t_dd_tritmp.h to draw basic primitives *
206 ***********************************************************************/
208 #define TRI( a, b, c ) \
211 imesa->draw_tri( imesa, a, b, c ); \
213 savage_draw_triangle( imesa, a, b, c ); \
216 #define QUAD( a, b, c, d ) \
219 imesa->draw_tri( imesa, a, b, d ); \
220 imesa->draw_tri( imesa, b, c, d ); \
222 savage_draw_quad( imesa, a, b, c, d ); \
225 #define LINE( v0, v1 ) \
228 imesa->draw_line( imesa, v0, v1 ); \
230 savage_draw_line( imesa, v0, v1 ); \
233 #define POINT( v0 ) \
236 imesa->draw_point( imesa, v0 ); \
238 savage_draw_point( imesa, v0 ); \
242 /***********************************************************************
243 * Build render functions from dd templates *
244 ***********************************************************************/
246 #define SAVAGE_OFFSET_BIT 0x1
247 #define SAVAGE_TWOSIDE_BIT 0x2
248 #define SAVAGE_UNFILLED_BIT 0x4
249 #define SAVAGE_FALLBACK_BIT 0x8
250 #define SAVAGE_MAX_TRIFUNC 0x10
254 tnl_points_func points
;
256 tnl_triangle_func triangle
;
258 } rast_tab
[SAVAGE_MAX_TRIFUNC
];
261 #define DO_FALLBACK (IND & SAVAGE_FALLBACK_BIT)
262 #define DO_OFFSET (IND & SAVAGE_OFFSET_BIT)
263 #define DO_UNFILLED (IND & SAVAGE_UNFILLED_BIT)
264 #define DO_TWOSIDE (IND & SAVAGE_TWOSIDE_BIT)
270 #define DO_FULL_QUAD 1
274 #define HAVE_BACK_COLORS 0
275 #define HAVE_HW_FLATSHADE 1
276 #define VERTEX savageVertex
279 #define DEPTH_SCALE imesa->depth_scale
280 #define UNFILLED_TRI unfilled_tri
281 #define UNFILLED_QUAD unfilled_quad
282 #define VERT_X(_v) _v->v.x
283 #define VERT_Y(_v) _v->v.y
284 #define VERT_Z(_v) _v->v.z
285 #define AREA_IS_CCW( a ) (a > 0)
286 #define GET_VERTEX(e) (imesa->verts + (e * imesa->vertex_size * sizeof(int)))
288 #define VERT_SET_RGBA( v, c ) \
290 savage_color_t *color = (savage_color_t *)&((v)->ub4[coloroffset]); \
291 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
292 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
293 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
294 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
296 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
297 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
298 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
300 #define VERT_SET_SPEC( v, c ) \
303 savage_color_t *spec = (savage_color_t *)&((v)->ub4[specoffset]); \
304 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
305 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
306 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
309 #define VERT_COPY_SPEC( v0, v1 ) \
310 if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset])
311 #define VERT_SAVE_SPEC( idx ) \
312 if (specoffset) spec[idx] = v[idx]->ui[specoffset]
313 #define VERT_RESTORE_SPEC( idx ) \
314 if (specoffset) v[idx]->ui[specoffset] = spec[idx]
316 #define LOCAL_VARS(n) \
317 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
318 GLuint color[n], spec[n]; \
319 GLuint coloroffset = \
320 ((imesa->DrawPrimitiveCmd & SAVAGE_HW_NO_W) ? 3 : 4); \
321 GLboolean specoffset = \
322 ((imesa->DrawPrimitiveCmd & SAVAGE_HW_NO_CS) ? 0 : coloroffset+1);\
323 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
325 /***********************************************************************
326 * Helpers for rendering unfilled primitives *
327 ***********************************************************************/
329 #define RASTERIZE(x) if (imesa->raster_primitive != reduced_prim[x]) \
330 savageRasterPrimitive( ctx, x )
331 #define RENDER_PRIMITIVE imesa->render_primitive
332 #define IND SAVAGE_FALLBACK_BIT
334 #include "tnl_dd/t_dd_unfilled.h"
338 /***********************************************************************
339 * Generate GL render functions *
340 ***********************************************************************/
345 #include "tnl_dd/t_dd_tritmp.h"
347 #define IND (SAVAGE_OFFSET_BIT)
348 #define TAG(x) x##_offset
349 #include "tnl_dd/t_dd_tritmp.h"
351 #define IND (SAVAGE_TWOSIDE_BIT)
352 #define TAG(x) x##_twoside
353 #include "tnl_dd/t_dd_tritmp.h"
355 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT)
356 #define TAG(x) x##_twoside_offset
357 #include "tnl_dd/t_dd_tritmp.h"
359 #define IND (SAVAGE_UNFILLED_BIT)
360 #define TAG(x) x##_unfilled
361 #include "tnl_dd/t_dd_tritmp.h"
363 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
364 #define TAG(x) x##_offset_unfilled
365 #include "tnl_dd/t_dd_tritmp.h"
367 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT)
368 #define TAG(x) x##_twoside_unfilled
369 #include "tnl_dd/t_dd_tritmp.h"
371 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT)
372 #define TAG(x) x##_twoside_offset_unfilled
373 #include "tnl_dd/t_dd_tritmp.h"
375 #define IND (SAVAGE_FALLBACK_BIT)
376 #define TAG(x) x##_fallback
377 #include "tnl_dd/t_dd_tritmp.h"
379 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
380 #define TAG(x) x##_offset_fallback
381 #include "tnl_dd/t_dd_tritmp.h"
383 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_FALLBACK_BIT)
384 #define TAG(x) x##_twoside_fallback
385 #include "tnl_dd/t_dd_tritmp.h"
387 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_FALLBACK_BIT)
388 #define TAG(x) x##_twoside_offset_fallback
389 #include "tnl_dd/t_dd_tritmp.h"
391 #define IND (SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
392 #define TAG(x) x##_unfilled_fallback
393 #include "tnl_dd/t_dd_tritmp.h"
395 #define IND (SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
396 #define TAG(x) x##_offset_unfilled_fallback
397 #include "tnl_dd/t_dd_tritmp.h"
399 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_UNFILLED_BIT|SAVAGE_FALLBACK_BIT)
400 #define TAG(x) x##_twoside_unfilled_fallback
401 #include "tnl_dd/t_dd_tritmp.h"
403 #define IND (SAVAGE_TWOSIDE_BIT|SAVAGE_OFFSET_BIT|SAVAGE_UNFILLED_BIT| \
405 #define TAG(x) x##_twoside_offset_unfilled_fallback
406 #include "tnl_dd/t_dd_tritmp.h"
409 static void init_rast_tab( void )
414 init_twoside_offset();
416 init_offset_unfilled();
417 init_twoside_unfilled();
418 init_twoside_offset_unfilled();
420 init_offset_fallback();
421 init_twoside_fallback();
422 init_twoside_offset_fallback();
423 init_unfilled_fallback();
424 init_offset_unfilled_fallback();
425 init_twoside_unfilled_fallback();
426 init_twoside_offset_unfilled_fallback();
431 /***********************************************************************
432 * Rasterization fallback helpers *
433 ***********************************************************************/
436 /* This code is hit only when a mix of accelerated and unaccelerated
437 * primitives are being drawn, and only for the unaccelerated
441 savage_fallback_tri( savageContextPtr imesa
,
446 GLcontext
*ctx
= imesa
->glCtx
;
448 _swsetup_Translate( ctx
, v0
, &v
[0] );
449 _swsetup_Translate( ctx
, v1
, &v
[1] );
450 _swsetup_Translate( ctx
, v2
, &v
[2] );
451 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
456 savage_fallback_line( savageContextPtr imesa
,
460 GLcontext
*ctx
= imesa
->glCtx
;
462 _swsetup_Translate( ctx
, v0
, &v
[0] );
463 _swsetup_Translate( ctx
, v1
, &v
[1] );
464 _swrast_Line( ctx
, &v
[0], &v
[1] );
469 savage_fallback_point( savageContextPtr imesa
,
472 GLcontext
*ctx
= imesa
->glCtx
;
474 _swsetup_Translate( ctx
, v0
, &v
[0] );
475 _swrast_Point( ctx
, &v
[0] );
480 /**********************************************************************/
481 /* Render unclipped begin/end objects */
482 /**********************************************************************/
484 #define VERT(x) (savageVertexPtr)(savageVerts + (x * vertsize * sizeof(int)))
485 #define RENDER_POINTS( start, count ) \
486 for ( ; start < count ; start++) \
487 savage_draw_point( imesa, VERT(start) )
488 #define RENDER_LINE( v0, v1 ) \
489 savage_draw_line( imesa, VERT(v0), VERT(v1) )
490 #define RENDER_TRI( v0, v1, v2 ) \
491 savage_draw_triangle( imesa, VERT(v0), VERT(v1), VERT(v2) )
492 #define RENDER_QUAD( v0, v1, v2, v3 ) \
493 savage_draw_quad( imesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
494 #define INIT(x) do { \
495 if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
496 savageRenderPrimitive( ctx, x ); \
497 /*SAVAGE_CONTEXT(ctx)->render_primitive = x;*/ \
501 savageContextPtr imesa = SAVAGE_CONTEXT(ctx); \
502 const GLuint vertsize = imesa->vertex_size; \
503 const char *savageVerts = (char *)imesa->verts; \
504 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
506 #define RESET_STIPPLE
507 #define RESET_OCCLUSION
508 #define PRESERVE_VB_DEFS
510 #define TAG(x) savage_##x##_verts
511 #include "tnl/t_vb_rendertmp.h"
514 #define TAG(x) savage_##x##_elts
515 #define ELT(x) elt[x]
516 #include "tnl/t_vb_rendertmp.h"
519 /**********************************************************************/
520 /* Render clipped primitives */
521 /**********************************************************************/
523 static void savageRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
526 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
527 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
529 /* Render the new vertices as an unclipped polygon.
532 GLuint
*tmp
= VB
->Elts
;
533 VB
->Elts
= (GLuint
*)elts
;
534 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
, PRIM_BEGIN
|PRIM_END
);
539 static void savageRenderClippedLine( GLcontext
*ctx
, GLuint ii
, GLuint jj
)
541 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
542 tnl
->Driver
.Render
.Line( ctx
, ii
, jj
);
545 static void savageFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
548 r128ContextPtr rmesa = R128_CONTEXT( ctx );
549 GLuint vertsize = rmesa->vertex_size;
550 GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
551 GLubyte *r128verts = (GLubyte *)rmesa->verts;
552 const GLuint shift = rmesa->vertex_stride_shift;
553 const GLuint *start = (const GLuint *)VERT(elts[0]);
556 rmesa->num_verts += (n-2) * 3;
558 for (i = 2 ; i < n ; i++) {
559 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
560 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
561 COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
568 /**********************************************************************/
569 /* Choose render functions */
570 /**********************************************************************/
572 #define _SAVAGE_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
573 _DD_NEW_LINE_SMOOTH | \
574 _DD_NEW_POINT_SMOOTH | \
575 _DD_NEW_TRI_SMOOTH | \
576 _DD_NEW_TRI_UNFILLED | \
577 _DD_NEW_TRI_LIGHT_TWOSIDE | \
578 _DD_NEW_TRI_OFFSET) \
580 /* original driver didn't have DD_POINT_SMOOTH. really needed? */
581 #define POINT_FALLBACK (DD_POINT_SMOOTH)
582 #define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
583 #define TRI_FALLBACK (DD_TRI_SMOOTH)
584 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
585 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
588 static void savageChooseRenderState(GLcontext
*ctx
)
590 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
591 GLuint flags
= ctx
->_TriangleCaps
;
594 if (flags
& (ANY_RASTER_FLAGS
|ANY_FALLBACK_FLAGS
)) {
595 imesa
->draw_point
= savage_draw_point
;
596 imesa
->draw_line
= savage_draw_line
;
597 imesa
->draw_tri
= savage_draw_triangle
;
599 if (flags
& ANY_RASTER_FLAGS
) {
600 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= SAVAGE_TWOSIDE_BIT
;
601 if (flags
& DD_TRI_OFFSET
) index
|= SAVAGE_OFFSET_BIT
;
602 if (flags
& DD_TRI_UNFILLED
) index
|= SAVAGE_UNFILLED_BIT
;
605 /* Hook in fallbacks for specific primitives.
607 if (flags
& (POINT_FALLBACK
|LINE_FALLBACK
|TRI_FALLBACK
)) {
608 if (flags
& POINT_FALLBACK
) imesa
->draw_point
= savage_fallback_point
;
609 if (flags
& LINE_FALLBACK
) imesa
->draw_line
= savage_fallback_line
;
610 if (flags
& TRI_FALLBACK
) imesa
->draw_tri
= savage_fallback_tri
;
611 index
|= SAVAGE_FALLBACK_BIT
;
615 if (index
!= imesa
->RenderIndex
) {
616 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
617 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
618 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
619 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
620 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
623 tnl
->Driver
.Render
.PrimTabVerts
= savage_render_tab_verts
;
624 tnl
->Driver
.Render
.PrimTabElts
= savage_render_tab_elts
;
625 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
626 tnl
->Driver
.Render
.ClippedPolygon
= savageRenderClippedPoly
/*r128FastRenderClippedPoly*/;
628 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
629 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
630 tnl
->Driver
.Render
.ClippedLine
= savageRenderClippedLine
;
631 tnl
->Driver
.Render
.ClippedPolygon
= savageRenderClippedPoly
;
634 imesa
->RenderIndex
= index
;
638 /**********************************************************************/
639 /* Validate state at pipeline start */
640 /**********************************************************************/
642 static void savageRunPipeline( GLcontext
*ctx
)
644 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
646 if (imesa
->new_state
)
647 savageDDUpdateHwState( ctx
);
649 if (!imesa
->Fallback
&& imesa
->new_gl_state
) {
650 if (imesa
->new_gl_state
& _SAVAGE_NEW_RENDER_STATE
)
651 savageChooseRenderState( ctx
);
653 imesa
->new_gl_state
= 0;
656 _tnl_run_pipeline( ctx
);
659 /**********************************************************************/
660 /* High level hooks for t_vb_render.c */
661 /**********************************************************************/
663 /* This is called when Mesa switches between rendering triangle
664 * primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
665 * and lines, points and bitmaps.
667 * As the r128 uses triangles to render lines and points, it is
668 * necessary to turn off hardware culling when rendering these
672 static void savageRasterPrimitive( GLcontext
*ctx
, GLuint prim
)
674 savageContextPtr imesa
= SAVAGE_CONTEXT( ctx
);
677 if (imesa
->raster_primitive
!= prim
) {
678 imesa
->raster_primitive
= prim
;
679 imesa
->new_state
|= SAVAGE_NEW_CULL
;
680 savageDDUpdateHwState (ctx
);
684 if (ctx
->Polygon
.StippleFlag
&& mmesa
->haveHwStipple
)
686 mmesa
->dirty
|= MGA_UPLOAD_CONTEXT
;
687 mmesa
->setup
.dwgctl
&= ~(0xf<<20);
688 if (mmesa
->raster_primitive
== GL_TRIANGLES
)
689 mmesa
->setup
.dwgctl
|= mmesa
->poly_stipple
;
694 static void savageRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
696 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
697 GLuint rprim
= reduced_prim
[prim
];
699 imesa
->render_primitive
= prim
;
701 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
704 if (imesa
->raster_primitive
!= rprim
) {
705 savageRasterPrimitive( ctx
, rprim
);
710 #define EMIT_ATTR( ATTR, STYLE, INDEX, SKIP ) \
712 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = (ATTR); \
713 imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE); \
714 imesa->vertex_attr_count++; \
715 setupIndex |= (INDEX); \
716 drawCmd &= ~(SKIP); \
719 #define EMIT_PAD( N ) \
721 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = 0; \
722 imesa->vertex_attrs[imesa->vertex_attr_count].format = EMIT_PAD; \
723 imesa->vertex_attrs[imesa->vertex_attr_count].offset = (N); \
724 imesa->vertex_attr_count++; \
727 #define SAVAGE_EMIT_XYZ 0x0001
728 #define SAVAGE_EMIT_W 0x0002
729 #define SAVAGE_EMIT_C0 0x0004
730 #define SAVAGE_EMIT_C1 0x0008
731 #define SAVAGE_EMIT_FOG 0x0010
732 #define SAVAGE_EMIT_S0 0x0020
733 #define SAVAGE_EMIT_T0 0x0040
734 #define SAVAGE_EMIT_ST0 0x0060
735 #define SAVAGE_EMIT_S1 0x0080
736 #define SAVAGE_EMIT_T1 0x0100
737 #define SAVAGE_EMIT_ST1 0x0180
740 static void savageRenderStart( GLcontext
*ctx
)
742 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
743 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
744 struct vertex_buffer
*VB
= &tnl
->vb
;
745 GLuint index
= tnl
->render_inputs
;
746 GLuint setupIndex
= SAVAGE_EMIT_XYZ
;
747 GLuint drawCmd
= SAVAGE_HW_SKIPFLAGS
;
748 if (imesa
->savageScreen
->chipset
< S3_SAVAGE4
)
749 drawCmd
&= ~SAVAGE_HW_NO_UV1
;
750 drawCmd
&= ~SAVAGE_HW_NO_Z
; /* all mesa vertices have a z coordinate */
754 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
755 imesa
->vertex_attr_count
= 0;
757 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
758 * build up a hardware vertex.
760 if ((index
& _TNL_BITS_TEX_ANY
) || !(ctx
->_TriangleCaps
& DD_FLATSHADE
)) {
761 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
, SAVAGE_EMIT_W
, SAVAGE_HW_NO_W
);
764 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
, 0, 0 );
767 /* t_context.c always includes a diffuse color */
768 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_BGRA
, SAVAGE_EMIT_C0
, SAVAGE_HW_NO_CD
);
770 if (index
& (_TNL_BIT_COLOR1
|_TNL_BIT_FOG
)) {
771 if ((index
& _TNL_BIT_COLOR1
))
772 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
, SAVAGE_EMIT_C1
, SAVAGE_HW_NO_CS
);
775 if ((index
& _TNL_BIT_FOG
))
776 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, SAVAGE_EMIT_FOG
, SAVAGE_HW_NO_CS
);
781 if (index
& _TNL_BIT_TEX(0)) {
782 if (VB
->TexCoordPtr
[0]->size
> 2) {
783 /* projective textures are not supported by the hardware */
784 FALLBACK(ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
786 if (VB
->TexCoordPtr
[0]->size
== 2)
787 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_2F
, SAVAGE_EMIT_ST0
, SAVAGE_HW_NO_UV0
);
789 EMIT_ATTR( _TNL_ATTRIB_TEX0
, EMIT_1F
, SAVAGE_EMIT_S0
, SAVAGE_HW_NO_U0
);
791 if (index
& _TNL_BIT_TEX(1)) {
792 if (VB
->TexCoordPtr
[1]->size
> 2) {
793 /* projective textures are not supported by the hardware */
794 FALLBACK(ctx
, SAVAGE_FALLBACK_TEXTURE
, GL_TRUE
);
796 if (VB
->TexCoordPtr
[1]->size
== 2)
797 EMIT_ATTR( _TNL_ATTRIB_TEX1
, EMIT_2F
, SAVAGE_EMIT_ST1
, SAVAGE_HW_NO_UV1
);
799 EMIT_ATTR( _TNL_ATTRIB_TEX1
, EMIT_1F
, SAVAGE_EMIT_S1
, SAVAGE_HW_NO_U1
);
802 /* Need to change the vertex emit code if the SetupIndex changed or
803 * is set for the first time (indicated by vertex_size == 0). */
804 if (setupIndex
!= imesa
->SetupIndex
|| imesa
->vertex_size
== 0) {
806 _tnl_install_attrs( ctx
,
808 imesa
->vertex_attr_count
,
809 imesa
->hw_viewport
, 0 );
810 imesa
->vertex_size
>>= 2;
811 imesa
->SetupIndex
= setupIndex
;
813 imesa
->DrawPrimitiveCmd
= drawCmd
;
816 if (!SAVAGE_CONTEXT(ctx
)->Fallback
) {
817 /* Update hardware state and get the lock */
818 savageDDRenderStart( ctx
);
820 tnl
->Driver
.Render
.Start(ctx
);
824 static void savageRenderFinish( GLcontext
*ctx
)
826 /* Release the lock */
827 savageDDRenderEnd( ctx
);
829 /* Flush the last primitive now, before any state is changed.
830 * Alternatively state could be emitted in all state-changing
831 * functions in savagestate.c and when changing the vertex format
833 FLUSH_BATCH(SAVAGE_CONTEXT(ctx
));
835 if (SAVAGE_CONTEXT(ctx
)->RenderIndex
& SAVAGE_FALLBACK_BIT
)
836 _swrast_flush( ctx
);
840 /**********************************************************************/
841 /* Transition to/from hardware rasterization. */
842 /**********************************************************************/
844 void savageFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
846 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
847 savageContextPtr imesa
= SAVAGE_CONTEXT(ctx
);
848 GLuint oldfallback
= imesa
->Fallback
;
851 imesa
->Fallback
|= bit
;
852 if (oldfallback
== 0) {
853 /* the first fallback */
854 FLUSH_BATCH( imesa
);
855 _swsetup_Wakeup( ctx
);
856 imesa
->RenderIndex
= ~0;
860 imesa
->Fallback
&= ~bit
;
861 if (oldfallback
== bit
) {
862 /* the last fallback */
863 _swrast_flush( ctx
);
864 tnl
->Driver
.Render
.Start
= savageRenderStart
;
865 tnl
->Driver
.Render
.PrimitiveNotify
= savageRenderPrimitive
;
866 tnl
->Driver
.Render
.Finish
= savageRenderFinish
;
868 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
869 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
870 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
872 _tnl_invalidate_vertex_state( ctx
, ~0 );
873 _tnl_invalidate_vertices( ctx
, ~0 );
874 _tnl_install_attrs( ctx
,
876 imesa
->vertex_attr_count
,
877 imesa
->hw_viewport
, 0 );
879 imesa
->new_gl_state
|= _SAVAGE_NEW_RENDER_STATE
;
885 /**********************************************************************/
886 /* Initialization. */
887 /**********************************************************************/
889 void savageInitTriFuncs( GLcontext
*ctx
)
891 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
892 static int firsttime
= 1;
899 tnl
->Driver
.RunPipeline
= savageRunPipeline
;
900 tnl
->Driver
.Render
.Start
= savageRenderStart
;
901 tnl
->Driver
.Render
.Finish
= savageRenderFinish
;
902 tnl
->Driver
.Render
.PrimitiveNotify
= savageRenderPrimitive
;
903 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
905 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
906 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
907 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
909 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
910 (6 + 2*ctx
->Const
.MaxTextureUnits
) * sizeof(GLfloat
) );
912 SAVAGE_CONTEXT(ctx
)->verts
= (char *)tnl
->clipspace
.vertex_buf
;