1 /* $XFree86: xc/lib/GL/mesa/src/drv/r200/r200_swtcl.c,v 1.5 2003/05/06 23:52:08 daenzer Exp $ */
3 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
5 The Weather Channel (TM) funded Tungsten Graphics to develop the
6 initial release of the Radeon 8500 driver under the XFree86 license.
7 This notice must be preserved.
9 Permission is hereby granted, free of charge, to any person obtaining
10 a copy of this software and associated documentation files (the
11 "Software"), to deal in the Software without restriction, including
12 without limitation the rights to use, copy, modify, merge, publish,
13 distribute, sublicense, and/or sell copies of the Software, and to
14 permit persons to whom the Software is furnished to do so, subject to
15 the following conditions:
17 The above copyright notice and this permission notice (including the
18 next paragraph) shall be included in all copies or substantial
19 portions of the Software.
21 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 **************************************************************************/
33 * Keith Whitwell <keith@tungstengraphics.com>
44 #include "swrast/s_context.h"
45 #include "swrast/s_fog.h"
46 #include "swrast_setup/swrast_setup.h"
47 #include "math/m_translate.h"
49 #include "tnl/t_context.h"
50 #include "tnl/t_pipeline.h"
51 #include "tnl/t_vtx_api.h"
53 #include "r200_context.h"
54 #include "r200_ioctl.h"
55 #include "r200_state.h"
56 #include "r200_swtcl.h"
60 static void flush_last_swtcl_prim( r200ContextPtr rmesa
);
63 /***********************************************************************
65 ***********************************************************************/
67 #define EMIT_ATTR( ATTR, STYLE, F0 ) \
69 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = (ATTR); \
70 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = (STYLE); \
71 rmesa->swtcl.vertex_attr_count++; \
75 #define EMIT_PAD( N ) \
77 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = 0; \
78 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = EMIT_PAD; \
79 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].offset = (N); \
80 rmesa->swtcl.vertex_attr_count++; \
83 static void r200SetVertexFormat( GLcontext
*ctx
)
85 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
86 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
87 struct vertex_buffer
*VB
= &tnl
->vb
;
88 DECLARE_RENDERINPUTS(index_bitset
);
93 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
97 if ( VB
->NdcPtr
!= NULL
) {
98 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
101 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->ClipPtr
;
104 assert( VB
->AttribPtr
[VERT_ATTRIB_POS
] != NULL
);
105 rmesa
->swtcl
.vertex_attr_count
= 0;
107 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
108 * build up a hardware vertex.
110 if ( !rmesa
->swtcl
.needproj
||
111 RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)) { /* need w coord for projected textures */
112 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F
, R200_VTX_XY
| R200_VTX_Z0
| R200_VTX_W0
);
116 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F
, R200_VTX_XY
| R200_VTX_Z0
);
120 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_POINTSIZE
)) {
121 EMIT_ATTR( _TNL_ATTRIB_POINTSIZE
, EMIT_1F
, R200_VTX_POINT_SIZE
);
125 rmesa
->swtcl
.coloroffset
= offset
;
126 #if MESA_LITTLE_ENDIAN
127 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_RGBA
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
) );
129 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_ABGR
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
) );
133 rmesa
->swtcl
.specoffset
= 0;
134 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
) ||
135 RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
137 #if MESA_LITTLE_ENDIAN
138 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
)) {
139 rmesa
->swtcl
.specoffset
= offset
;
140 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_RGB
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
146 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
147 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
153 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
154 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
160 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
)) {
161 rmesa
->swtcl
.specoffset
= offset
;
162 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
170 if (RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)) {
173 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
174 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX(i
) )) {
175 GLuint sz
= VB
->TexCoordPtr
[i
]->size
;
177 fmt_1
|= sz
<< (3 * i
);
178 EMIT_ATTR( _TNL_ATTRIB_TEX0
+i
, EMIT_1F
+ sz
- 1, 0 );
183 if ( (rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] & R200_FOG_USE_MASK
)
184 != R200_FOG_USE_SPEC_ALPHA
) {
185 R200_STATECHANGE( rmesa
, ctx
);
186 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_USE_MASK
;
187 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= R200_FOG_USE_SPEC_ALPHA
;
190 if (!RENDERINPUTS_EQUAL( rmesa
->tnl_index_bitset
, index_bitset
) ||
191 (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] != fmt_0
) ||
192 (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] != fmt_1
) ) {
194 R200_STATECHANGE( rmesa
, vtx
);
195 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
196 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] = fmt_1
;
198 rmesa
->swtcl
.vertex_size
=
199 _tnl_install_attrs( ctx
,
200 rmesa
->swtcl
.vertex_attrs
,
201 rmesa
->swtcl
.vertex_attr_count
,
203 rmesa
->swtcl
.vertex_size
/= 4;
204 RENDERINPUTS_COPY( rmesa
->tnl_index_bitset
, index_bitset
);
209 static void r200RenderStart( GLcontext
*ctx
)
211 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
213 r200SetVertexFormat( ctx
);
215 if (rmesa
->dma
.flush
!= 0 &&
216 rmesa
->dma
.flush
!= flush_last_swtcl_prim
)
217 rmesa
->dma
.flush( rmesa
);
222 * Set vertex state for SW TCL. The primary purpose of this function is to
223 * determine in advance whether or not the hardware can / should do the
224 * projection divide or Mesa should do it.
226 void r200ChooseVertexState( GLcontext
*ctx
)
228 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
229 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
233 /* We must ensure that we don't do _tnl_need_projected_coords while in a
234 * rasterization fallback. As this function will be called again when we
235 * leave a rasterization fallback, we can just skip it for now.
237 if (rmesa
->Fallback
!= 0)
240 vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
241 vap
= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
];
243 /* HW perspective divide is a win, but tiny vertex formats are a
246 if (!RENDERINPUTS_TEST_RANGE( tnl
->render_inputs_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)
247 || (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
248 rmesa
->swtcl
.needproj
= GL_TRUE
;
249 vte
|= R200_VTX_XY_FMT
| R200_VTX_Z_FMT
;
250 vte
&= ~R200_VTX_W0_FMT
;
251 if (RENDERINPUTS_TEST_RANGE( tnl
->render_inputs_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)) {
252 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
255 vap
|= R200_VAP_FORCE_W_TO_ONE
;
259 rmesa
->swtcl
.needproj
= GL_FALSE
;
260 vte
&= ~(R200_VTX_XY_FMT
| R200_VTX_Z_FMT
);
261 vte
|= R200_VTX_W0_FMT
;
262 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
265 _tnl_need_projected_coords( ctx
, rmesa
->swtcl
.needproj
);
267 if (vte
!= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
]) {
268 R200_STATECHANGE( rmesa
, vte
);
269 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = vte
;
272 if (vap
!= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
]) {
273 R200_STATECHANGE( rmesa
, vap
);
274 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] = vap
;
279 /* Flush vertices in the current dma region.
281 static void flush_last_swtcl_prim( r200ContextPtr rmesa
)
283 if (R200_DEBUG
& DEBUG_IOCTL
)
284 fprintf(stderr
, "%s\n", __FUNCTION__
);
286 rmesa
->dma
.flush
= NULL
;
288 if (rmesa
->dma
.current
.buf
) {
289 struct r200_dma_region
*current
= &rmesa
->dma
.current
;
290 GLuint current_offset
= (rmesa
->r200Screen
->gart_buffer_offset
+
291 current
->buf
->buf
->idx
* RADEON_BUFFER_SIZE
+
294 assert (!(rmesa
->swtcl
.hw_primitive
& R200_VF_PRIM_WALK_IND
));
296 assert (current
->start
+
297 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
300 if (rmesa
->dma
.current
.start
!= rmesa
->dma
.current
.ptr
) {
301 r200EnsureCmdBufSpace( rmesa
, VERT_AOS_BUFSZ
+
302 rmesa
->hw
.max_state_size
+ VBUF_BUFSZ
);
303 r200EmitVertexAOS( rmesa
,
304 rmesa
->swtcl
.vertex_size
,
307 r200EmitVbufPrim( rmesa
,
308 rmesa
->swtcl
.hw_primitive
,
309 rmesa
->swtcl
.numverts
);
312 rmesa
->swtcl
.numverts
= 0;
313 current
->start
= current
->ptr
;
318 /* Alloc space in the current dma region.
321 r200AllocDmaLowVerts( r200ContextPtr rmesa
, int nverts
, int vsize
)
323 GLuint bytes
= vsize
* nverts
;
325 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
326 r200RefillCurrentDmaRegion( rmesa
);
328 if (!rmesa
->dma
.flush
) {
329 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
330 rmesa
->dma
.flush
= flush_last_swtcl_prim
;
333 ASSERT( vsize
== rmesa
->swtcl
.vertex_size
* 4 );
334 ASSERT( rmesa
->dma
.flush
== flush_last_swtcl_prim
);
335 ASSERT( rmesa
->dma
.current
.start
+
336 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
337 rmesa
->dma
.current
.ptr
);
341 GLubyte
*head
= (GLubyte
*) (rmesa
->dma
.current
.address
+ rmesa
->dma
.current
.ptr
);
342 rmesa
->dma
.current
.ptr
+= bytes
;
343 rmesa
->swtcl
.numverts
+= nverts
;
350 /**************************************************************************/
353 static INLINE GLuint
reduced_hw_prim( GLcontext
*ctx
, GLuint prim
)
357 return (ctx
->Point
.PointSprite
||
358 ((ctx
->_TriangleCaps
& (DD_POINT_SIZE
| DD_POINT_ATTEN
)) &&
359 !(ctx
->_TriangleCaps
& (DD_POINT_SMOOTH
)))) ?
360 R200_VF_PRIM_POINT_SPRITES
: R200_VF_PRIM_POINTS
;
366 return R200_VF_PRIM_LINES
;
368 /* all others reduced to triangles */
369 return R200_VF_PRIM_TRIANGLES
;
374 static void r200RasterPrimitive( GLcontext
*ctx
, GLuint hwprim
);
375 static void r200RenderPrimitive( GLcontext
*ctx
, GLenum prim
);
376 static void r200ResetLineStipple( GLcontext
*ctx
);
378 /***********************************************************************
379 * Emit primitives as inline vertices *
380 ***********************************************************************/
382 #define HAVE_POINTS 1
384 #define HAVE_LINE_STRIPS 1
385 #define HAVE_TRIANGLES 1
386 #define HAVE_TRI_STRIPS 1
387 #define HAVE_TRI_STRIP_1 0
388 #define HAVE_TRI_FANS 1
390 #define HAVE_QUAD_STRIPS 0
391 #define HAVE_POLYGONS 1
396 #define CTX_ARG r200ContextPtr rmesa
397 #define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
398 #define ALLOC_VERTS( n, size ) r200AllocDmaLowVerts( rmesa, n, size * 4 )
400 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
401 const char *r200verts = (char *)rmesa->swtcl.verts;
402 #define VERT(x) (r200Vertex *)(r200verts + ((x) * vertsize * sizeof(int)))
403 #define VERTEX r200Vertex
404 #define DO_DEBUG_VERTS (1 && (R200_DEBUG & DEBUG_VERTS))
407 #define TAG(x) r200_##x
408 #include "tnl_dd/t_dd_triemit.h"
411 /***********************************************************************
412 * Macros for t_dd_tritmp.h to draw basic primitives *
413 ***********************************************************************/
415 #define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d )
416 #define TRI( a, b, c ) r200_triangle( rmesa, a, b, c )
417 #define LINE( a, b ) r200_line( rmesa, a, b )
418 #define POINT( a ) r200_point( rmesa, a )
420 /***********************************************************************
421 * Build render functions from dd templates *
422 ***********************************************************************/
424 #define R200_TWOSIDE_BIT 0x01
425 #define R200_UNFILLED_BIT 0x02
426 #define R200_MAX_TRIFUNC 0x04
430 tnl_points_func points
;
432 tnl_triangle_func triangle
;
434 } rast_tab
[R200_MAX_TRIFUNC
];
437 #define DO_FALLBACK 0
438 #define DO_UNFILLED (IND & R200_UNFILLED_BIT)
439 #define DO_TWOSIDE (IND & R200_TWOSIDE_BIT)
446 #define DO_FULL_QUAD 1
450 #define HAVE_BACK_COLORS 0
451 #define HAVE_HW_FLATSHADE 1
454 #define DEPTH_SCALE 1.0
455 #define UNFILLED_TRI unfilled_tri
456 #define UNFILLED_QUAD unfilled_quad
457 #define VERT_X(_v) _v->v.x
458 #define VERT_Y(_v) _v->v.y
459 #define VERT_Z(_v) _v->v.z
460 #define AREA_IS_CCW( a ) (a < 0)
461 #define GET_VERTEX(e) (rmesa->swtcl.verts + (e*rmesa->swtcl.vertex_size*sizeof(int)))
463 #define VERT_SET_RGBA( v, c ) \
465 r200_color_t *color = (r200_color_t *)&((v)->ui[coloroffset]); \
466 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
467 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
468 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
469 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
472 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
474 #define VERT_SET_SPEC( v, c ) \
477 r200_color_t *spec = (r200_color_t *)&((v)->ui[specoffset]); \
478 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
479 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
480 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
483 #define VERT_COPY_SPEC( v0, v1 ) \
486 r200_color_t *spec0 = (r200_color_t *)&((v0)->ui[specoffset]); \
487 r200_color_t *spec1 = (r200_color_t *)&((v1)->ui[specoffset]); \
488 spec0->red = spec1->red; \
489 spec0->green = spec1->green; \
490 spec0->blue = spec1->blue; \
494 /* These don't need LE32_TO_CPU() as they used to save and restore
495 * colors which are already in the correct format.
497 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
498 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
499 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
500 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
506 #define LOCAL_VARS(n) \
507 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
508 GLuint color[n], spec[n]; \
509 GLuint coloroffset = rmesa->swtcl.coloroffset; \
510 GLuint specoffset = rmesa->swtcl.specoffset; \
511 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
513 /***********************************************************************
514 * Helpers for rendering unfilled primitives *
515 ***********************************************************************/
517 #define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim(ctx, x) )
518 #define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
521 #include "tnl_dd/t_dd_unfilled.h"
525 /***********************************************************************
526 * Generate GL render functions *
527 ***********************************************************************/
532 #include "tnl_dd/t_dd_tritmp.h"
534 #define IND (R200_TWOSIDE_BIT)
535 #define TAG(x) x##_twoside
536 #include "tnl_dd/t_dd_tritmp.h"
538 #define IND (R200_UNFILLED_BIT)
539 #define TAG(x) x##_unfilled
540 #include "tnl_dd/t_dd_tritmp.h"
542 #define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT)
543 #define TAG(x) x##_twoside_unfilled
544 #include "tnl_dd/t_dd_tritmp.h"
547 static void init_rast_tab( void )
552 init_twoside_unfilled();
555 /**********************************************************************/
556 /* Render unclipped begin/end objects */
557 /**********************************************************************/
559 #define RENDER_POINTS( start, count ) \
560 for ( ; start < count ; start++) \
561 r200_point( rmesa, VERT(start) )
562 #define RENDER_LINE( v0, v1 ) \
563 r200_line( rmesa, VERT(v0), VERT(v1) )
564 #define RENDER_TRI( v0, v1, v2 ) \
565 r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
566 #define RENDER_QUAD( v0, v1, v2, v3 ) \
567 r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
568 #define INIT(x) do { \
569 r200RenderPrimitive( ctx, x ); \
573 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
574 const GLuint vertsize = rmesa->swtcl.vertex_size; \
575 const char *r200verts = (char *)rmesa->swtcl.verts; \
576 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
577 const GLboolean stipple = ctx->Line.StippleFlag; \
578 (void) elt; (void) stipple;
579 #define RESET_STIPPLE if ( stipple ) r200ResetLineStipple( ctx );
580 #define RESET_OCCLUSION
581 #define PRESERVE_VB_DEFS
583 #define TAG(x) r200_##x##_verts
584 #include "tnl/t_vb_rendertmp.h"
587 #define TAG(x) r200_##x##_elts
588 #define ELT(x) elt[x]
589 #include "tnl/t_vb_rendertmp.h"
593 /**********************************************************************/
594 /* Choose render functions */
595 /**********************************************************************/
597 void r200ChooseRenderState( GLcontext
*ctx
)
599 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
600 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
602 GLuint flags
= ctx
->_TriangleCaps
;
604 if (!rmesa
->TclFallback
|| rmesa
->Fallback
)
607 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= R200_TWOSIDE_BIT
;
608 if (flags
& DD_TRI_UNFILLED
) index
|= R200_UNFILLED_BIT
;
610 if (index
!= rmesa
->swtcl
.RenderIndex
) {
611 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
612 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
613 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
614 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
615 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
618 tnl
->Driver
.Render
.PrimTabVerts
= r200_render_tab_verts
;
619 tnl
->Driver
.Render
.PrimTabElts
= r200_render_tab_elts
;
620 tnl
->Driver
.Render
.ClippedPolygon
= r200_fast_clipped_poly
;
622 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
623 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
624 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
627 rmesa
->swtcl
.RenderIndex
= index
;
632 /**********************************************************************/
633 /* High level hooks for t_vb_render.c */
634 /**********************************************************************/
637 static void r200RasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
639 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
641 if (rmesa
->swtcl
.hw_primitive
!= hwprim
) {
642 /* need to disable perspective-correct texturing for point sprites */
643 if ((hwprim
& 0xf) == R200_VF_PRIM_POINT_SPRITES
&& ctx
->Point
.PointSprite
) {
644 if (rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & R200_PERSPECTIVE_ENABLE
) {
645 R200_STATECHANGE( rmesa
, set
);
646 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PERSPECTIVE_ENABLE
;
649 else if (!(rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & R200_PERSPECTIVE_ENABLE
)) {
650 R200_STATECHANGE( rmesa
, set
);
651 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PERSPECTIVE_ENABLE
;
653 R200_NEWPRIM( rmesa
);
654 rmesa
->swtcl
.hw_primitive
= hwprim
;
658 static void r200RenderPrimitive( GLcontext
*ctx
, GLenum prim
)
660 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
661 rmesa
->swtcl
.render_primitive
= prim
;
662 if (prim
< GL_TRIANGLES
|| !(ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
663 r200RasterPrimitive( ctx
, reduced_hw_prim(ctx
, prim
) );
666 static void r200RenderFinish( GLcontext
*ctx
)
670 static void r200ResetLineStipple( GLcontext
*ctx
)
672 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
673 R200_STATECHANGE( rmesa
, lin
);
677 /**********************************************************************/
678 /* Transition to/from hardware rasterization. */
679 /**********************************************************************/
681 static const char * const fallbackStrings
[] = {
683 "glDrawBuffer(GL_FRONT_AND_BACK)",
684 "glEnable(GL_STENCIL) without hw stencil buffer",
685 "glRenderMode(selection or feedback)",
687 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
691 static const char *getFallbackString(GLuint bit
)
698 return fallbackStrings
[i
];
702 void r200Fallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
704 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
705 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
706 GLuint oldfallback
= rmesa
->Fallback
;
709 rmesa
->Fallback
|= bit
;
710 if (oldfallback
== 0) {
711 R200_FIREVERTICES( rmesa
);
712 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_RASTER
, GL_TRUE
);
713 _swsetup_Wakeup( ctx
);
714 rmesa
->swtcl
.RenderIndex
= ~0;
715 if (R200_DEBUG
& DEBUG_FALLBACKS
) {
716 fprintf(stderr
, "R200 begin rasterization fallback: 0x%x %s\n",
717 bit
, getFallbackString(bit
));
722 rmesa
->Fallback
&= ~bit
;
723 if (oldfallback
== bit
) {
725 _swrast_flush( ctx
);
726 tnl
->Driver
.Render
.Start
= r200RenderStart
;
727 tnl
->Driver
.Render
.PrimitiveNotify
= r200RenderPrimitive
;
728 tnl
->Driver
.Render
.Finish
= r200RenderFinish
;
730 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
731 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
732 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
734 tnl
->Driver
.Render
.ResetLineStipple
= r200ResetLineStipple
;
735 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_RASTER
, GL_FALSE
);
736 if (rmesa
->TclFallback
) {
737 /* These are already done if rmesa->TclFallback goes to
738 * zero above. But not if it doesn't (R200_NO_TCL for
741 _tnl_invalidate_vertex_state( ctx
, ~0 );
742 _tnl_invalidate_vertices( ctx
, ~0 );
743 RENDERINPUTS_ZERO( rmesa
->tnl_index_bitset
);
744 r200ChooseVertexState( ctx
);
745 r200ChooseRenderState( ctx
);
747 if (R200_DEBUG
& DEBUG_FALLBACKS
) {
748 fprintf(stderr
, "R200 end rasterization fallback: 0x%x %s\n",
749 bit
, getFallbackString(bit
));
759 * Cope with depth operations by drawing individual pixels as points.
762 * The way the vertex state is set in this routine is hokey. It seems to
763 * work, but it's very hackish. This whole routine is pretty hackish. If
764 * the bitmap is small enough, it seems like it would be faster to copy it
765 * to AGP memory and use it as a non-power-of-two texture (i.e.,
766 * NV_texture_rectangle).
769 r200PointsBitmap( GLcontext
*ctx
, GLint px
, GLint py
,
770 GLsizei width
, GLsizei height
,
771 const struct gl_pixelstore_attrib
*unpack
,
772 const GLubyte
*bitmap
)
774 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
775 const GLfloat
*rc
= ctx
->Current
.RasterColor
;
784 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_BITMAP
, 1 );
786 /* Choose tiny vertex format
789 const GLuint fmt_0
= R200_VTX_XY
| R200_VTX_Z0
| R200_VTX_W0
790 | (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
);
791 const GLuint fmt_1
= 0;
792 GLuint vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
793 GLuint vap
= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
];
795 vte
&= ~(R200_VTX_XY_FMT
| R200_VTX_Z_FMT
);
796 vte
|= R200_VTX_W0_FMT
;
797 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
799 rmesa
->swtcl
.vertex_size
= 5;
801 if ( (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] != fmt_0
)
802 || (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] != fmt_1
) ) {
804 R200_STATECHANGE( rmesa
, vtx
);
805 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
806 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] = fmt_1
;
809 if (vte
!= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
]) {
810 R200_STATECHANGE( rmesa
, vte
);
811 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = vte
;
814 if (vap
!= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
]) {
815 R200_STATECHANGE( rmesa
, vap
);
816 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] = vap
;
820 /* Ready for point primitives:
822 r200RenderPrimitive( ctx
, GL_POINTS
);
824 /* Turn off the hw viewport transformation:
826 R200_STATECHANGE( rmesa
, vte
);
827 orig_vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
828 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] &= ~(R200_VPORT_X_SCALE_ENA
|
829 R200_VPORT_Y_SCALE_ENA
|
830 R200_VPORT_Z_SCALE_ENA
|
831 R200_VPORT_X_OFFSET_ENA
|
832 R200_VPORT_Y_OFFSET_ENA
|
833 R200_VPORT_Z_OFFSET_ENA
);
835 /* Turn off other stuff: Stipple?, texture?, blending?, etc.
839 /* Populate the vertex
841 * Incorporate FOG into RGBA
843 if (ctx
->Fog
.Enabled
) {
844 const GLfloat
*fc
= ctx
->Fog
.Color
;
848 if (ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORDINATE_EXT
)
849 f
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.Attrib
[VERT_ATTRIB_FOG
][0]);
851 f
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
853 color
[0] = f
* rc
[0] + (1.F
- f
) * fc
[0];
854 color
[1] = f
* rc
[1] + (1.F
- f
) * fc
[1];
855 color
[2] = f
* rc
[2] + (1.F
- f
) * fc
[2];
858 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.red
, color
[0]);
859 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.green
, color
[1]);
860 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.blue
, color
[2]);
861 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.alpha
, color
[3]);
864 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.red
, rc
[0]);
865 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.green
, rc
[1]);
866 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.blue
, rc
[2]);
867 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.alpha
, rc
[3]);
871 vert
.tv
.z
= ctx
->Current
.RasterPos
[2];
874 /* Update window height
876 LOCK_HARDWARE( rmesa
);
877 UNLOCK_HARDWARE( rmesa
);
878 h
= rmesa
->dri
.drawable
->h
+ rmesa
->dri
.drawable
->y
;
879 px
+= rmesa
->dri
.drawable
->x
;
881 /* Clipping handled by existing mechansims in r200_ioctl.c?
883 for (row
=0; row
<height
; row
++) {
884 const GLubyte
*src
= (const GLubyte
*)
885 _mesa_image_address2d(unpack
, bitmap
, width
, height
,
886 GL_COLOR_INDEX
, GL_BITMAP
, row
, 0 );
888 if (unpack
->LsbFirst
) {
890 GLubyte mask
= 1U << (unpack
->SkipPixels
& 0x7);
891 for (col
=0; col
<width
; col
++) {
894 vert
.tv
.y
= h
- (py
+row
) - 1;
895 r200_point( rmesa
, &vert
);
898 mask
= ((mask
<< 1) & 0xff) | (mask
>> 7);
901 /* get ready for next row */
907 GLubyte mask
= 128U >> (unpack
->SkipPixels
& 0x7);
908 for (col
=0; col
<width
; col
++) {
911 vert
.tv
.y
= h
- (py
+row
) - 1;
912 r200_point( rmesa
, &vert
);
915 mask
= ((mask
<< 7) & 0xff) | (mask
>> 1);
917 /* get ready for next row */
923 /* Fire outstanding vertices, restore state
925 R200_STATECHANGE( rmesa
, vte
);
926 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = orig_vte
;
930 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_BITMAP
, 0 );
932 /* Need to restore vertexformat?
934 if (rmesa
->TclFallback
)
935 r200ChooseVertexState( ctx
);
939 void r200FlushVertices( GLcontext
*ctx
, GLuint flags
)
941 _tnl_FlushVertices( ctx
, flags
);
943 if (flags
& FLUSH_STORED_VERTICES
)
944 R200_NEWPRIM( R200_CONTEXT( ctx
) );
947 /**********************************************************************/
948 /* Initialization. */
949 /**********************************************************************/
951 void r200InitSwtcl( GLcontext
*ctx
)
953 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
954 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
955 static int firsttime
= 1;
962 tnl
->Driver
.Render
.Start
= r200RenderStart
;
963 tnl
->Driver
.Render
.Finish
= r200RenderFinish
;
964 tnl
->Driver
.Render
.PrimitiveNotify
= r200RenderPrimitive
;
965 tnl
->Driver
.Render
.ResetLineStipple
= r200ResetLineStipple
;
966 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
967 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
968 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
970 /* FIXME: what are these numbers? */
971 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
972 36 * sizeof(GLfloat
) );
974 rmesa
->swtcl
.verts
= (GLubyte
*)tnl
->clipspace
.vertex_buf
;
975 rmesa
->swtcl
.RenderIndex
= ~0;
976 rmesa
->swtcl
.render_primitive
= GL_TRIANGLES
;
977 rmesa
->swtcl
.hw_primitive
= 0;
981 void r200DestroySwtcl( GLcontext
*ctx
)
983 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
985 if (rmesa
->swtcl
.indexed_verts
.buf
)
986 r200ReleaseDmaRegion( rmesa
, &rmesa
->swtcl
.indexed_verts
, __FUNCTION__
);