1 /* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_tris.c,v 1.4 2002/12/10 01:26:54 dawes Exp $ */
2 /**************************************************************************
4 Copyright 2001 VA Linux Systems Inc., Fremont, California.
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
27 **************************************************************************/
31 * Keith Whitwell <keith@tungstengraphics.com>
32 * Adapted for use on the I830M:
33 * Jeff Hartmann <jhartmann@2d3d.com>
42 #include "swrast/swrast.h"
43 #include "swrast_setup/swrast_setup.h"
44 #include "tnl/t_context.h"
45 #include "tnl/t_pipeline.h"
47 #include "i830_screen.h"
50 #include "i830_tris.h"
51 #include "i830_state.h"
52 #include "i830_ioctl.h"
53 #include "i830_span.h"
55 static void i830RenderPrimitive( GLcontext
*ctx
, GLenum prim
);
57 /***********************************************************************
58 * Emit primitives as inline vertices *
59 ***********************************************************************/
61 #if defined(USE_X86_ASM)
62 #define COPY_DWORDS( j, vb, vertsize, v ) \
65 __asm__ __volatile__( "rep ; movsl" \
66 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
72 #define COPY_DWORDS( j, vb, vertsize, v ) \
74 for ( j = 0 ; j < vertsize ; j++ ) \
75 vb[j] = ((GLuint *)v)[j]; \
80 static void __inline__
i830_draw_triangle( i830ContextPtr imesa
,
85 GLuint vertsize
= imesa
->vertex_size
;
86 GLuint
*vb
= i830AllocDmaLow( imesa
, 3 * 4 * vertsize
);
89 COPY_DWORDS( j
, vb
, vertsize
, v0
);
90 COPY_DWORDS( j
, vb
, vertsize
, v1
);
91 COPY_DWORDS( j
, vb
, vertsize
, v2
);
95 static void __inline__
i830_draw_quad( i830ContextPtr imesa
,
101 GLuint vertsize
= imesa
->vertex_size
;
102 GLuint
*vb
= i830AllocDmaLow( imesa
, 6 * 4 * vertsize
);
105 COPY_DWORDS( j
, vb
, vertsize
, v0
);
106 COPY_DWORDS( j
, vb
, vertsize
, v1
);
107 COPY_DWORDS( j
, vb
, vertsize
, v3
);
108 COPY_DWORDS( j
, vb
, vertsize
, v1
);
109 COPY_DWORDS( j
, vb
, vertsize
, v2
);
110 COPY_DWORDS( j
, vb
, vertsize
, v3
);
114 static __inline__
void i830_draw_point( i830ContextPtr imesa
,
117 GLuint vertsize
= imesa
->vertex_size
;
118 GLuint
*vb
= i830AllocDmaLow( imesa
, 4 * vertsize
);
121 /* Adjust for sub pixel position */
122 *(float *)&vb
[0] = tmp
->v
.x
- 0.125;
123 *(float *)&vb
[1] = tmp
->v
.y
- 0.125;
124 for (j
= 2 ; j
< vertsize
; j
++)
129 static __inline__
void i830_draw_line( i830ContextPtr imesa
,
133 GLuint vertsize
= imesa
->vertex_size
;
134 GLuint
*vb
= i830AllocDmaLow( imesa
, 2 * 4 * vertsize
);
137 COPY_DWORDS( j
, vb
, vertsize
, v0
);
138 COPY_DWORDS( j
, vb
, vertsize
, v1
);
143 /***********************************************************************
144 * Macros for t_dd_tritmp.h to draw basic primitives *
145 ***********************************************************************/
147 #define TRI( a, b, c ) \
150 imesa->draw_tri( imesa, a, b, c ); \
152 i830_draw_triangle( imesa, a, b, c ); \
155 #define QUAD( a, b, c, d ) \
158 imesa->draw_tri( imesa, a, b, d ); \
159 imesa->draw_tri( imesa, b, c, d ); \
161 i830_draw_quad( imesa, a, b, c, d ); \
164 #define LINE( v0, v1 ) \
167 imesa->draw_line( imesa, v0, v1 ); \
169 i830_draw_line( imesa, v0, v1 ); \
172 #define POINT( v0 ) \
175 imesa->draw_point( imesa, v0 ); \
177 i830_draw_point( imesa, v0 ); \
181 /***********************************************************************
182 * Build render functions from dd templates *
183 ***********************************************************************/
185 #define I830_OFFSET_BIT 0x01
186 #define I830_TWOSIDE_BIT 0x02
187 #define I830_UNFILLED_BIT 0x04
188 #define I830_FALLBACK_BIT 0x08
189 #define I830_MAX_TRIFUNC 0x10
195 triangle_func triangle
;
197 } rast_tab
[I830_MAX_TRIFUNC
];
200 #define DO_FALLBACK (IND & I830_FALLBACK_BIT)
201 #define DO_OFFSET (IND & I830_OFFSET_BIT)
202 #define DO_UNFILLED (IND & I830_UNFILLED_BIT)
203 #define DO_TWOSIDE (IND & I830_TWOSIDE_BIT)
209 #define DO_FULL_QUAD 1
213 #define HAVE_BACK_COLORS 0
214 #define HAVE_HW_FLATSHADE 1
215 #define VERTEX i830Vertex
218 #define DEPTH_SCALE (imesa->depth_scale)
219 #define UNFILLED_TRI unfilled_tri
220 #define UNFILLED_QUAD unfilled_quad
221 #define VERT_X(_v) _v->v.x
222 #define VERT_Y(_v) _v->v.y
223 #define VERT_Z(_v) _v->v.z
224 #define AREA_IS_CCW( a ) (a > 0)
225 #define GET_VERTEX(e) (imesa->verts + (e * imesa->vertex_size * sizeof(int)))
227 #define VERT_SET_RGBA( v, c ) \
229 i830_color_t *color = (i830_color_t *)&((v)->ui[coloroffset]); \
230 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
231 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
232 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
233 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
236 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
238 #define VERT_SET_SPEC( v0, c ) \
241 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.red, (c)[0]); \
242 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.green, (c)[1]); \
243 UNCLAMPED_FLOAT_TO_UBYTE(v0->v.specular.blue, (c)[2]); \
246 #define VERT_COPY_SPEC( v0, v1 ) \
249 v0->v.specular.red = v1->v.specular.red; \
250 v0->v.specular.green = v1->v.specular.green; \
251 v0->v.specular.blue = v1->v.specular.blue; \
255 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
256 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
257 #define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
258 #define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
260 #define LOCAL_VARS(n) \
261 i830ContextPtr imesa = I830_CONTEXT(ctx); \
262 GLuint color[n], spec[n]; \
263 GLuint coloroffset = (imesa->vertex_size == 4 ? 3 : 4); \
264 GLboolean havespec = (imesa->vertex_size > 4); \
265 (void) color; (void) spec; (void) coloroffset; (void) havespec;
268 /***********************************************************************
269 * Helpers for rendering unfilled primitives *
270 ***********************************************************************/
272 static const GLuint hw_prim
[GL_POLYGON
+1] = {
285 #define RASTERIZE(x) if (imesa->hw_primitive != hw_prim[x]) \
286 i830RasterPrimitive( ctx, x, hw_prim[x] )
287 #define RENDER_PRIMITIVE imesa->render_primitive
289 #define IND I830_FALLBACK_BIT
290 #include "tnl_dd/t_dd_unfilled.h"
293 /***********************************************************************
294 * Generate GL render functions *
295 ***********************************************************************/
299 #include "tnl_dd/t_dd_tritmp.h"
301 #define IND (I830_OFFSET_BIT)
302 #define TAG(x) x##_offset
303 #include "tnl_dd/t_dd_tritmp.h"
305 #define IND (I830_TWOSIDE_BIT)
306 #define TAG(x) x##_twoside
307 #include "tnl_dd/t_dd_tritmp.h"
309 #define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT)
310 #define TAG(x) x##_twoside_offset
311 #include "tnl_dd/t_dd_tritmp.h"
313 #define IND (I830_UNFILLED_BIT)
314 #define TAG(x) x##_unfilled
315 #include "tnl_dd/t_dd_tritmp.h"
317 #define IND (I830_OFFSET_BIT|I830_UNFILLED_BIT)
318 #define TAG(x) x##_offset_unfilled
319 #include "tnl_dd/t_dd_tritmp.h"
321 #define IND (I830_TWOSIDE_BIT|I830_UNFILLED_BIT)
322 #define TAG(x) x##_twoside_unfilled
323 #include "tnl_dd/t_dd_tritmp.h"
325 #define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_UNFILLED_BIT)
326 #define TAG(x) x##_twoside_offset_unfilled
327 #include "tnl_dd/t_dd_tritmp.h"
329 #define IND (I830_FALLBACK_BIT)
330 #define TAG(x) x##_fallback
331 #include "tnl_dd/t_dd_tritmp.h"
333 #define IND (I830_OFFSET_BIT|I830_FALLBACK_BIT)
334 #define TAG(x) x##_offset_fallback
335 #include "tnl_dd/t_dd_tritmp.h"
337 #define IND (I830_TWOSIDE_BIT|I830_FALLBACK_BIT)
338 #define TAG(x) x##_twoside_fallback
339 #include "tnl_dd/t_dd_tritmp.h"
341 #define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_FALLBACK_BIT)
342 #define TAG(x) x##_twoside_offset_fallback
343 #include "tnl_dd/t_dd_tritmp.h"
345 #define IND (I830_UNFILLED_BIT|I830_FALLBACK_BIT)
346 #define TAG(x) x##_unfilled_fallback
347 #include "tnl_dd/t_dd_tritmp.h"
349 #define IND (I830_OFFSET_BIT|I830_UNFILLED_BIT|I830_FALLBACK_BIT)
350 #define TAG(x) x##_offset_unfilled_fallback
351 #include "tnl_dd/t_dd_tritmp.h"
353 #define IND (I830_TWOSIDE_BIT|I830_UNFILLED_BIT|I830_FALLBACK_BIT)
354 #define TAG(x) x##_twoside_unfilled_fallback
355 #include "tnl_dd/t_dd_tritmp.h"
357 #define IND (I830_TWOSIDE_BIT|I830_OFFSET_BIT|I830_UNFILLED_BIT| \
359 #define TAG(x) x##_twoside_offset_unfilled_fallback
360 #include "tnl_dd/t_dd_tritmp.h"
363 static void init_rast_tab( void )
368 init_twoside_offset();
370 init_offset_unfilled();
371 init_twoside_unfilled();
372 init_twoside_offset_unfilled();
374 init_offset_fallback();
375 init_twoside_fallback();
376 init_twoside_offset_fallback();
377 init_unfilled_fallback();
378 init_offset_unfilled_fallback();
379 init_twoside_unfilled_fallback();
380 init_twoside_offset_unfilled_fallback();
384 /***********************************************************************
385 * Rasterization fallback helpers *
386 ***********************************************************************/
389 /* This code is hit only when a mix of accelerated and unaccelerated
390 * primitives are being drawn, and only for the unaccelerated
394 i830_fallback_tri( i830ContextPtr imesa
,
399 GLcontext
*ctx
= imesa
->glCtx
;
403 fprintf(stderr
, "\n%s\n", __FUNCTION__
);
405 _swsetup_Translate( ctx
, v0
, &v
[0] );
406 _swsetup_Translate( ctx
, v1
, &v
[1] );
407 _swsetup_Translate( ctx
, v2
, &v
[2] );
408 i830SpanRenderStart( ctx
);
409 _swrast_Triangle( ctx
, &v
[0], &v
[1], &v
[2] );
410 i830SpanRenderFinish( ctx
);
415 i830_fallback_line( i830ContextPtr imesa
,
419 GLcontext
*ctx
= imesa
->glCtx
;
423 fprintf(stderr
, "\n%s\n", __FUNCTION__
);
425 _swsetup_Translate( ctx
, v0
, &v
[0] );
426 _swsetup_Translate( ctx
, v1
, &v
[1] );
427 i830SpanRenderStart( ctx
);
428 _swrast_Line( ctx
, &v
[0], &v
[1] );
429 i830SpanRenderFinish( ctx
);
434 i830_fallback_point( i830ContextPtr imesa
,
437 GLcontext
*ctx
= imesa
->glCtx
;
441 fprintf(stderr
, "\n%s\n", __FUNCTION__
);
443 _swsetup_Translate( ctx
, v0
, &v
[0] );
444 i830SpanRenderStart( ctx
);
445 _swrast_Point( ctx
, &v
[0] );
446 i830SpanRenderFinish( ctx
);
451 /**********************************************************************/
452 /* Render unclipped begin/end objects */
453 /**********************************************************************/
456 #define V(x) (i830Vertex *)(vertptr + ((x) * vertsize * sizeof(int)))
457 #define RENDER_POINTS( start, count ) \
458 for ( ; start < count ; start++) POINT( V(ELT(start)) );
459 #define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) )
460 #define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) )
461 #define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
462 #define INIT(x) i830RenderPrimitive( ctx, x )
465 i830ContextPtr imesa = I830_CONTEXT(ctx); \
466 GLubyte *vertptr = (GLubyte *)imesa->verts; \
467 const GLuint vertsize = imesa->vertex_size; \
468 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
470 #define RESET_STIPPLE
471 #define RESET_OCCLUSION
472 #define PRESERVE_VB_DEFS
474 #define TAG(x) i830_##x##_verts
475 #include "tnl/t_vb_rendertmp.h"
478 #define TAG(x) i830_##x##_elts
479 #define ELT(x) elt[x]
480 #include "tnl/t_vb_rendertmp.h"
482 /**********************************************************************/
483 /* Render clipped primitives */
484 /**********************************************************************/
488 static void i830RenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
491 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
492 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
493 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
494 GLuint prim
= imesa
->render_primitive
;
496 /* Render the new vertices as an unclipped polygon.
499 GLuint
*tmp
= VB
->Elts
;
500 VB
->Elts
= (GLuint
*)elts
;
501 tnl
->Driver
.Render
.PrimTabElts
[GL_POLYGON
]( ctx
, 0, n
,
502 PRIM_BEGIN
|PRIM_END
);
506 /* Restore the render primitive
508 if (prim
!= GL_POLYGON
)
509 tnl
->Driver
.Render
.PrimitiveNotify( ctx
, prim
);
512 static void i830RenderClippedLine( GLcontext
*ctx
, GLuint ii
, GLuint jj
)
514 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
516 tnl
->Driver
.Render
.Line( ctx
, ii
, jj
);
519 static void i830FastRenderClippedPoly( GLcontext
*ctx
, const GLuint
*elts
,
522 i830ContextPtr imesa
= I830_CONTEXT( ctx
);
523 GLuint vertsize
= imesa
->vertex_size
;
524 GLuint
*vb
= i830AllocDmaLow( imesa
, (n
-2) * 3 * 4 * vertsize
);
525 GLubyte
*vertptr
= (GLubyte
*)imesa
->verts
;
526 const GLuint
*start
= (const GLuint
*)V(elts
[0]);
529 for (i
= 2 ; i
< n
; i
++) {
530 COPY_DWORDS( j
, vb
, vertsize
, V(elts
[i
-1]) );
531 COPY_DWORDS( j
, vb
, vertsize
, V(elts
[i
]) );
532 COPY_DWORDS( j
, vb
, vertsize
, start
);
536 /**********************************************************************/
537 /* Choose render functions */
538 /**********************************************************************/
542 #define _I830_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
543 _DD_NEW_TRI_UNFILLED | \
544 _DD_NEW_TRI_LIGHT_TWOSIDE | \
545 _DD_NEW_TRI_OFFSET | \
546 _DD_NEW_TRI_STIPPLE | \
549 #define POINT_FALLBACK (0)
550 #define LINE_FALLBACK (DD_LINE_STIPPLE)
551 #define TRI_FALLBACK (0)
552 #define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK|\
554 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
556 static void i830ChooseRenderState(GLcontext
*ctx
)
558 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
559 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
560 GLuint flags
= ctx
->_TriangleCaps
;
563 if (I830_DEBUG
& DEBUG_STATE
)
564 fprintf(stderr
,"\n%s\n",__FUNCTION__
);
566 if (flags
& (ANY_FALLBACK_FLAGS
|ANY_RASTER_FLAGS
)) {
567 if (flags
& ANY_RASTER_FLAGS
) {
568 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= I830_TWOSIDE_BIT
;
569 if (flags
& DD_TRI_OFFSET
) index
|= I830_OFFSET_BIT
;
570 if (flags
& DD_TRI_UNFILLED
) index
|= I830_UNFILLED_BIT
;
573 imesa
->draw_point
= i830_draw_point
;
574 imesa
->draw_line
= i830_draw_line
;
575 imesa
->draw_tri
= i830_draw_triangle
;
577 /* Hook in fallbacks for specific primitives.
579 if (flags
& ANY_FALLBACK_FLAGS
)
581 if (flags
& POINT_FALLBACK
)
582 imesa
->draw_point
= i830_fallback_point
;
584 if (flags
& LINE_FALLBACK
)
585 imesa
->draw_line
= i830_fallback_line
;
587 if (flags
& TRI_FALLBACK
)
588 imesa
->draw_tri
= i830_fallback_tri
;
590 if ((flags
& DD_TRI_STIPPLE
) && !imesa
->hw_stipple
) {
591 imesa
->draw_tri
= i830_fallback_tri
;
594 index
|= I830_FALLBACK_BIT
;
598 if (imesa
->RenderIndex
!= index
) {
599 imesa
->RenderIndex
= index
;
601 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
602 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
603 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
604 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
607 tnl
->Driver
.Render
.PrimTabVerts
= i830_render_tab_verts
;
608 tnl
->Driver
.Render
.PrimTabElts
= i830_render_tab_elts
;
609 tnl
->Driver
.Render
.ClippedLine
= line
; /* from tritmp.h */
610 tnl
->Driver
.Render
.ClippedPolygon
= i830FastRenderClippedPoly
;
612 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
613 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
614 tnl
->Driver
.Render
.ClippedLine
= i830RenderClippedLine
;
615 tnl
->Driver
.Render
.ClippedPolygon
= i830RenderClippedPoly
;
620 static const GLenum reduced_prim
[GL_POLYGON
+1] = {
634 /**********************************************************************/
635 /* High level hooks for t_vb_render.c */
636 /**********************************************************************/
640 /* Determine the rasterized primitive when not drawing unfilled
643 * Used only for the default render stage which always decomposes
644 * primitives to trianges/lines/points. For the accelerated stage,
645 * which renders strips as strips, the equivalent calculations are
646 * performed in i810render.c.
648 static void i830RenderPrimitive( GLcontext
*ctx
, GLenum prim
)
650 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
651 GLuint rprim
= reduced_prim
[prim
];
653 imesa
->render_primitive
= prim
;
655 if (rprim
== GL_TRIANGLES
&& (ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
658 if (imesa
->reduced_primitive
!= rprim
||
659 hw_prim
[prim
] != imesa
->hw_primitive
) {
660 i830RasterPrimitive( ctx
, rprim
, hw_prim
[prim
] );
664 static void i830RunPipeline( GLcontext
*ctx
)
666 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
668 if (imesa
->NewGLState
) {
669 if (imesa
->NewGLState
& _NEW_TEXTURE
) {
670 I830_FIREVERTICES( imesa
);
671 i830UpdateTextureState( ctx
); /* may modify imesa->NewGLState */
674 if (!imesa
->Fallback
) {
675 if (imesa
->NewGLState
& _I830_NEW_RENDERSTATE
)
676 i830ChooseRenderState( ctx
);
679 imesa
->NewGLState
= 0;
682 _tnl_run_pipeline( ctx
);
686 #define TEXCOORDTYPE_MASK (3<<11)
690 static void set_projective_texturing( i830ContextPtr imesa
,
694 GLuint mcs
= (imesa
->CurrentTexObj
[i
]->Setup
[I830_TEXREG_MCS
] &
698 mcs
|= TEXCOORDTYPE_HOMOGENEOUS
;
700 mcs
|= TEXCOORDTYPE_CARTESIAN
;
703 if (mcs
!= imesa
->CurrentTexObj
[i
]->Setup
[I830_TEXREG_MCS
]) {
704 I830_STATECHANGE(imesa
, I830_UPLOAD_TEX_N(i
));
705 imesa
->CurrentTexObj
[i
]->Setup
[I830_TEXREG_MCS
] = mcs
;
710 #define SZ_TO_HW(sz) ((sz-2)&0x3)
711 #define EMIT_SZ(sz) (EMIT_1F + (sz) - 1)
712 #define EMIT_ATTR( ATTR, STYLE, V0 ) \
714 imesa->vertex_attrs[imesa->vertex_attr_count].attrib = (ATTR); \
715 imesa->vertex_attrs[imesa->vertex_attr_count].format = (STYLE); \
716 imesa->vertex_attr_count++; \
721 #define VRTX_TEX_SET_FMT(n, x) ((x)<<((n)*2))
723 /* Make sure hardware vertex format is appropriate for VB state.
725 static void i830RenderStart( GLcontext
*ctx
)
727 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
728 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
729 struct vertex_buffer
*VB
= &tnl
->vb
;
730 GLuint index
= tnl
->render_inputs
;
731 GLuint v0
= STATE3D_VERTEX_FORMAT_CMD
;
732 GLuint v2
= STATE3D_VERTEX_FORMAT_2_CMD
;
736 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
737 imesa
->vertex_attr_count
= 0;
739 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
740 * build up a hardware vertex.
742 if (index
& _TNL_BITS_TEX_ANY
) {
743 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F_VIEWPORT
, VRTX_HAS_XYZW
);
746 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F_VIEWPORT
, VRTX_HAS_XYZ
);
749 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_RGBA
, VRTX_HAS_DIFFUSE
);
751 if (index
& (_TNL_BIT_COLOR1
|_TNL_BIT_FOG
)) {
752 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_RGB
, VRTX_HAS_SPEC
);
753 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, VRTX_HAS_SPEC
);
756 if (index
& _TNL_BITS_TEX_ANY
) {
757 int i
, last_stage
= 0;
759 /* Still using 2 as max tex units, but this code is fine for all
760 * 8 units supported by mesa:
762 for (i
= 0; i
< 2 ; i
++)
763 if (index
& _TNL_BIT_TEX(i
))
767 for (i
= 0; i
< last_stage
; i
++) {
768 GLuint sz
= VB
->TexCoordPtr
[i
]->size
;
770 v2
|= VRTX_TEX_SET_FMT(i
, SZ_TO_HW(sz
));
771 EMIT_ATTR( _TNL_ATTRIB_TEX0
+i
, EMIT_SZ(sz
), 0 );
773 if (imesa
->CurrentTexObj
[i
])
774 set_projective_texturing( imesa
, i
, sz
);
777 v0
|= VRTX_TEX_COORD_COUNT(last_stage
);
780 /* Only need to change the vertex emit code if there has been a
781 * statechange to a new hardware vertex format:
783 if (v0
!= imesa
->Setup
[I830_CTXREG_VF
] ||
784 v2
!= imesa
->Setup
[I830_CTXREG_VF2
] ) {
786 I830_STATECHANGE( imesa
, I830_UPLOAD_CTX
);
788 /* Must do this *after* statechange, so as not to affect
789 * buffered vertices reliant on the old state:
792 _tnl_install_attrs( ctx
,
794 imesa
->vertex_attr_count
,
795 imesa
->ViewportMatrix
.m
, 0 );
797 imesa
->vertex_size
>>= 2;
799 imesa
->Setup
[I830_CTXREG_VF
] = v0
;
800 imesa
->Setup
[I830_CTXREG_VF2
] = v2
;
805 static void i830RenderFinish( GLcontext
*ctx
)
807 if (I830_CONTEXT(ctx
)->RenderIndex
& I830_FALLBACK_BIT
)
808 _swrast_flush( ctx
);
814 /* System to flush dma and emit state changes based on the rasterized
817 void i830RasterPrimitive( GLcontext
*ctx
,
821 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
822 GLuint aa
= imesa
->Setup
[I830_CTXREG_AA
];
823 GLuint st1
= imesa
->StippleSetup
[I830_STPREG_ST1
];
825 aa
&= ~AA_LINE_ENABLE
;
827 if (I830_DEBUG
& DEBUG_PRIMS
) {
828 /* Prints reduced prim, and hw prim */
829 char *prim_name
= "Unknown";
832 case PRIM3D_POINTLIST
:
833 prim_name
= "PointList";
835 case PRIM3D_LINELIST
:
836 prim_name
= "LineList";
838 case PRIM3D_LINESTRIP
:
839 prim_name
= "LineStrip";
842 prim_name
= "TriList";
844 case PRIM3D_TRISTRIP
:
845 prim_name
= "TriStrip";
848 prim_name
= "TriFan";
851 prim_name
= "Polygons";
857 fprintf(stderr
, "%s : rprim(%s), hwprim(%s)\n",
859 _mesa_lookup_enum_by_nr(rprim
),
865 aa
|= AA_LINE_DISABLE
;
866 if (ctx
->Polygon
.StippleFlag
)
873 if (ctx
->Line
.SmoothFlag
) {
874 aa
|= AA_LINE_ENABLE
;
876 aa
|= AA_LINE_DISABLE
;
881 aa
|= AA_LINE_DISABLE
;
887 imesa
->reduced_primitive
= rprim
;
889 if (aa
!= imesa
->Setup
[I830_CTXREG_AA
]) {
890 I830_STATECHANGE(imesa
, I830_UPLOAD_CTX
);
891 imesa
->Setup
[I830_CTXREG_AA
] = aa
;
895 if (st1
!= imesa
->StippleSetup
[I830_STPREG_ST1
]) {
896 I830_STATECHANGE(imesa
, I830_UPLOAD_STIPPLE
);
897 imesa
->StippleSetup
[I830_STPREG_ST1
] = st1
;
901 if (hwprim
!= imesa
->hw_primitive
) {
902 I830_STATECHANGE(imesa
, 0);
903 imesa
->hw_primitive
= hwprim
;
907 /**********************************************************************/
908 /* Transition to/from hardware rasterization. */
909 /**********************************************************************/
911 static char *fallbackStrings
[] = {
923 static char *getFallbackString(GLuint bit
)
930 return fallbackStrings
[i
];
935 void i830Fallback( i830ContextPtr imesa
, GLuint bit
, GLboolean mode
)
937 GLcontext
*ctx
= imesa
->glCtx
;
938 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
939 GLuint oldfallback
= imesa
->Fallback
;
942 imesa
->Fallback
|= bit
;
943 if (oldfallback
== 0) {
944 I830_FIREVERTICES(imesa
);
945 if (I830_DEBUG
& DEBUG_FALLBACKS
)
946 fprintf(stderr
, "ENTER FALLBACK %s\n", getFallbackString( bit
));
947 _swsetup_Wakeup( ctx
);
948 imesa
->RenderIndex
= ~0;
952 imesa
->Fallback
&= ~bit
;
953 if (oldfallback
== bit
) {
954 _swrast_flush( ctx
);
955 if (I830_DEBUG
& DEBUG_FALLBACKS
)
956 fprintf(stderr
, "LEAVE FALLBACK %s\n", getFallbackString( bit
));
957 tnl
->Driver
.Render
.Start
= i830RenderStart
;
958 tnl
->Driver
.Render
.PrimitiveNotify
= i830RenderPrimitive
;
959 tnl
->Driver
.Render
.Finish
= i830RenderFinish
;
961 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
962 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
963 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
965 _tnl_invalidate_vertex_state( ctx
, ~0 );
966 _tnl_invalidate_vertices( ctx
, ~0 );
967 _tnl_install_attrs( ctx
,
969 imesa
->vertex_attr_count
,
970 imesa
->ViewportMatrix
.m
, 0 );
972 imesa
->NewGLState
|= _I830_NEW_RENDERSTATE
;
980 /**********************************************************************/
981 /* Initialization. */
982 /**********************************************************************/
985 void i830InitTriFuncs( GLcontext
*ctx
)
987 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
988 static int firsttime
= 1;
995 tnl
->Driver
.RunPipeline
= i830RunPipeline
;
996 tnl
->Driver
.Render
.Start
= i830RenderStart
;
997 tnl
->Driver
.Render
.Finish
= i830RenderFinish
;
998 tnl
->Driver
.Render
.PrimitiveNotify
= i830RenderPrimitive
;
999 tnl
->Driver
.Render
.ResetLineStipple
= _swrast_ResetLineStipple
;
1000 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
1001 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
1002 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
1004 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
1005 22 * sizeof(GLfloat
) );
1007 I830_CONTEXT(ctx
)->verts
= (char *)tnl
->clipspace
.vertex_buf
;