2 Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved.
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 **************************************************************************/
32 * Keith Whitwell <keith@tungstengraphics.com>
35 #include "main/glheader.h"
36 #include "main/mtypes.h"
37 #include "main/colormac.h"
38 #include "main/enums.h"
39 #include "main/image.h"
40 #include "main/imports.h"
41 #include "main/macros.h"
43 #include "swrast/s_context.h"
44 #include "swrast/s_fog.h"
45 #include "swrast_setup/swrast_setup.h"
46 #include "math/m_translate.h"
48 #include "tnl/t_context.h"
49 #include "tnl/t_pipeline.h"
51 #include "r200_context.h"
52 #include "r200_ioctl.h"
53 #include "r200_state.h"
54 #include "r200_swtcl.h"
58 static void flush_last_swtcl_prim( r200ContextPtr rmesa
);
61 /***********************************************************************
63 ***********************************************************************/
65 #define EMIT_ATTR( ATTR, STYLE, F0 ) \
67 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = (ATTR); \
68 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = (STYLE); \
69 rmesa->swtcl.vertex_attr_count++; \
73 #define EMIT_PAD( N ) \
75 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].attrib = 0; \
76 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].format = EMIT_PAD; \
77 rmesa->swtcl.vertex_attrs[rmesa->swtcl.vertex_attr_count].offset = (N); \
78 rmesa->swtcl.vertex_attr_count++; \
81 static void r200SetVertexFormat( GLcontext
*ctx
)
83 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
84 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
85 struct vertex_buffer
*VB
= &tnl
->vb
;
86 DECLARE_RENDERINPUTS(index_bitset
);
91 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
95 if ( VB
->NdcPtr
!= NULL
) {
96 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
99 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->ClipPtr
;
102 assert( VB
->AttribPtr
[VERT_ATTRIB_POS
] != NULL
);
103 rmesa
->swtcl
.vertex_attr_count
= 0;
105 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
106 * build up a hardware vertex.
108 if ( !rmesa
->swtcl
.needproj
||
109 RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)) { /* need w coord for projected textures */
110 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F
, R200_VTX_XY
| R200_VTX_Z0
| R200_VTX_W0
);
114 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F
, R200_VTX_XY
| R200_VTX_Z0
);
118 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_POINTSIZE
)) {
119 EMIT_ATTR( _TNL_ATTRIB_POINTSIZE
, EMIT_1F
, R200_VTX_POINT_SIZE
);
123 rmesa
->swtcl
.coloroffset
= offset
;
124 #if MESA_LITTLE_ENDIAN
125 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_RGBA
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
) );
127 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_ABGR
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
) );
131 rmesa
->swtcl
.specoffset
= 0;
132 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
) ||
133 RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
135 #if MESA_LITTLE_ENDIAN
136 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
)) {
137 rmesa
->swtcl
.specoffset
= offset
;
138 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_RGB
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
144 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
145 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
151 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
152 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
158 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
)) {
159 rmesa
->swtcl
.specoffset
= offset
;
160 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
168 if (RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)) {
171 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
172 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX(i
) )) {
173 GLuint sz
= VB
->TexCoordPtr
[i
]->size
;
175 fmt_1
|= sz
<< (3 * i
);
176 EMIT_ATTR( _TNL_ATTRIB_TEX0
+i
, EMIT_1F
+ sz
- 1, 0 );
181 if ( (rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] & R200_FOG_USE_MASK
)
182 != R200_FOG_USE_SPEC_ALPHA
) {
183 R200_STATECHANGE( rmesa
, ctx
);
184 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_USE_MASK
;
185 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= R200_FOG_USE_SPEC_ALPHA
;
188 if (!RENDERINPUTS_EQUAL( rmesa
->tnl_index_bitset
, index_bitset
) ||
189 (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] != fmt_0
) ||
190 (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] != fmt_1
) ) {
192 R200_STATECHANGE( rmesa
, vtx
);
193 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
194 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] = fmt_1
;
196 rmesa
->swtcl
.vertex_size
=
197 _tnl_install_attrs( ctx
,
198 rmesa
->swtcl
.vertex_attrs
,
199 rmesa
->swtcl
.vertex_attr_count
,
201 rmesa
->swtcl
.vertex_size
/= 4;
202 RENDERINPUTS_COPY( rmesa
->tnl_index_bitset
, index_bitset
);
207 static void r200RenderStart( GLcontext
*ctx
)
209 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
211 r200SetVertexFormat( ctx
);
213 if (rmesa
->dma
.flush
!= 0 &&
214 rmesa
->dma
.flush
!= flush_last_swtcl_prim
)
215 rmesa
->dma
.flush( rmesa
);
220 * Set vertex state for SW TCL. The primary purpose of this function is to
221 * determine in advance whether or not the hardware can / should do the
222 * projection divide or Mesa should do it.
224 void r200ChooseVertexState( GLcontext
*ctx
)
226 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
227 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
231 /* We must ensure that we don't do _tnl_need_projected_coords while in a
232 * rasterization fallback. As this function will be called again when we
233 * leave a rasterization fallback, we can just skip it for now.
235 if (rmesa
->Fallback
!= 0)
238 vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
239 vap
= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
];
241 /* HW perspective divide is a win, but tiny vertex formats are a
244 if (!RENDERINPUTS_TEST_RANGE( tnl
->render_inputs_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)
245 || (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
246 rmesa
->swtcl
.needproj
= GL_TRUE
;
247 vte
|= R200_VTX_XY_FMT
| R200_VTX_Z_FMT
;
248 vte
&= ~R200_VTX_W0_FMT
;
249 if (RENDERINPUTS_TEST_RANGE( tnl
->render_inputs_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)) {
250 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
253 vap
|= R200_VAP_FORCE_W_TO_ONE
;
257 rmesa
->swtcl
.needproj
= GL_FALSE
;
258 vte
&= ~(R200_VTX_XY_FMT
| R200_VTX_Z_FMT
);
259 vte
|= R200_VTX_W0_FMT
;
260 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
263 _tnl_need_projected_coords( ctx
, rmesa
->swtcl
.needproj
);
265 if (vte
!= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
]) {
266 R200_STATECHANGE( rmesa
, vte
);
267 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = vte
;
270 if (vap
!= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
]) {
271 R200_STATECHANGE( rmesa
, vap
);
272 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] = vap
;
277 /* Flush vertices in the current dma region.
279 static void flush_last_swtcl_prim( r200ContextPtr rmesa
)
281 if (R200_DEBUG
& DEBUG_IOCTL
)
282 fprintf(stderr
, "%s\n", __FUNCTION__
);
284 rmesa
->dma
.flush
= NULL
;
286 if (rmesa
->dma
.current
.buf
) {
287 struct r200_dma_region
*current
= &rmesa
->dma
.current
;
288 GLuint current_offset
= (rmesa
->r200Screen
->gart_buffer_offset
+
289 current
->buf
->buf
->idx
* RADEON_BUFFER_SIZE
+
292 assert (!(rmesa
->swtcl
.hw_primitive
& R200_VF_PRIM_WALK_IND
));
294 assert (current
->start
+
295 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
298 if (rmesa
->dma
.current
.start
!= rmesa
->dma
.current
.ptr
) {
299 r200EnsureCmdBufSpace( rmesa
, VERT_AOS_BUFSZ
+
300 rmesa
->hw
.max_state_size
+ VBUF_BUFSZ
);
301 r200EmitVertexAOS( rmesa
,
302 rmesa
->swtcl
.vertex_size
,
305 r200EmitVbufPrim( rmesa
,
306 rmesa
->swtcl
.hw_primitive
,
307 rmesa
->swtcl
.numverts
);
310 rmesa
->swtcl
.numverts
= 0;
311 current
->start
= current
->ptr
;
316 /* Alloc space in the current dma region.
319 r200AllocDmaLowVerts( r200ContextPtr rmesa
, int nverts
, int vsize
)
321 GLuint bytes
= vsize
* nverts
;
323 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
324 r200RefillCurrentDmaRegion( rmesa
);
326 if (!rmesa
->dma
.flush
) {
327 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
328 rmesa
->dma
.flush
= flush_last_swtcl_prim
;
331 ASSERT( vsize
== rmesa
->swtcl
.vertex_size
* 4 );
332 ASSERT( rmesa
->dma
.flush
== flush_last_swtcl_prim
);
333 ASSERT( rmesa
->dma
.current
.start
+
334 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
335 rmesa
->dma
.current
.ptr
);
339 GLubyte
*head
= (GLubyte
*) (rmesa
->dma
.current
.address
+ rmesa
->dma
.current
.ptr
);
340 rmesa
->dma
.current
.ptr
+= bytes
;
341 rmesa
->swtcl
.numverts
+= nverts
;
348 /**************************************************************************/
351 static INLINE GLuint
reduced_hw_prim( GLcontext
*ctx
, GLuint prim
)
355 return (ctx
->Point
.PointSprite
||
356 ((ctx
->_TriangleCaps
& (DD_POINT_SIZE
| DD_POINT_ATTEN
)) &&
357 !(ctx
->_TriangleCaps
& (DD_POINT_SMOOTH
)))) ?
358 R200_VF_PRIM_POINT_SPRITES
: R200_VF_PRIM_POINTS
;
364 return R200_VF_PRIM_LINES
;
366 /* all others reduced to triangles */
367 return R200_VF_PRIM_TRIANGLES
;
372 static void r200RasterPrimitive( GLcontext
*ctx
, GLuint hwprim
);
373 static void r200RenderPrimitive( GLcontext
*ctx
, GLenum prim
);
374 static void r200ResetLineStipple( GLcontext
*ctx
);
376 /***********************************************************************
377 * Emit primitives as inline vertices *
378 ***********************************************************************/
380 #define HAVE_POINTS 1
382 #define HAVE_LINE_STRIPS 1
383 #define HAVE_TRIANGLES 1
384 #define HAVE_TRI_STRIPS 1
385 #define HAVE_TRI_STRIP_1 0
386 #define HAVE_TRI_FANS 1
388 #define HAVE_QUAD_STRIPS 0
389 #define HAVE_POLYGONS 1
394 #define CTX_ARG r200ContextPtr rmesa
395 #define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
396 #define ALLOC_VERTS( n, size ) r200AllocDmaLowVerts( rmesa, n, size * 4 )
398 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
399 const char *r200verts = (char *)rmesa->swtcl.verts;
400 #define VERT(x) (r200Vertex *)(r200verts + ((x) * vertsize * sizeof(int)))
401 #define VERTEX r200Vertex
402 #define DO_DEBUG_VERTS (1 && (R200_DEBUG & DEBUG_VERTS))
405 #define TAG(x) r200_##x
406 #include "tnl_dd/t_dd_triemit.h"
409 /***********************************************************************
410 * Macros for t_dd_tritmp.h to draw basic primitives *
411 ***********************************************************************/
413 #define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d )
414 #define TRI( a, b, c ) r200_triangle( rmesa, a, b, c )
415 #define LINE( a, b ) r200_line( rmesa, a, b )
416 #define POINT( a ) r200_point( rmesa, a )
418 /***********************************************************************
419 * Build render functions from dd templates *
420 ***********************************************************************/
422 #define R200_TWOSIDE_BIT 0x01
423 #define R200_UNFILLED_BIT 0x02
424 #define R200_MAX_TRIFUNC 0x04
428 tnl_points_func points
;
430 tnl_triangle_func triangle
;
432 } rast_tab
[R200_MAX_TRIFUNC
];
435 #define DO_FALLBACK 0
436 #define DO_UNFILLED (IND & R200_UNFILLED_BIT)
437 #define DO_TWOSIDE (IND & R200_TWOSIDE_BIT)
444 #define DO_FULL_QUAD 1
448 #define HAVE_BACK_COLORS 0
449 #define HAVE_HW_FLATSHADE 1
452 #define DEPTH_SCALE 1.0
453 #define UNFILLED_TRI unfilled_tri
454 #define UNFILLED_QUAD unfilled_quad
455 #define VERT_X(_v) _v->v.x
456 #define VERT_Y(_v) _v->v.y
457 #define VERT_Z(_v) _v->v.z
458 #define AREA_IS_CCW( a ) (a < 0)
459 #define GET_VERTEX(e) (rmesa->swtcl.verts + (e*rmesa->swtcl.vertex_size*sizeof(int)))
461 #define VERT_SET_RGBA( v, c ) \
463 r200_color_t *color = (r200_color_t *)&((v)->ui[coloroffset]); \
464 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
465 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
466 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
467 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
470 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
472 #define VERT_SET_SPEC( v, c ) \
475 r200_color_t *spec = (r200_color_t *)&((v)->ui[specoffset]); \
476 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
477 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
478 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
481 #define VERT_COPY_SPEC( v0, v1 ) \
484 r200_color_t *spec0 = (r200_color_t *)&((v0)->ui[specoffset]); \
485 r200_color_t *spec1 = (r200_color_t *)&((v1)->ui[specoffset]); \
486 spec0->red = spec1->red; \
487 spec0->green = spec1->green; \
488 spec0->blue = spec1->blue; \
492 /* These don't need LE32_TO_CPU() as they used to save and restore
493 * colors which are already in the correct format.
495 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
496 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
497 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
498 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
504 #define LOCAL_VARS(n) \
505 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
506 GLuint color[n], spec[n]; \
507 GLuint coloroffset = rmesa->swtcl.coloroffset; \
508 GLuint specoffset = rmesa->swtcl.specoffset; \
509 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
511 /***********************************************************************
512 * Helpers for rendering unfilled primitives *
513 ***********************************************************************/
515 #define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim(ctx, x) )
516 #define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
519 #include "tnl_dd/t_dd_unfilled.h"
523 /***********************************************************************
524 * Generate GL render functions *
525 ***********************************************************************/
530 #include "tnl_dd/t_dd_tritmp.h"
532 #define IND (R200_TWOSIDE_BIT)
533 #define TAG(x) x##_twoside
534 #include "tnl_dd/t_dd_tritmp.h"
536 #define IND (R200_UNFILLED_BIT)
537 #define TAG(x) x##_unfilled
538 #include "tnl_dd/t_dd_tritmp.h"
540 #define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT)
541 #define TAG(x) x##_twoside_unfilled
542 #include "tnl_dd/t_dd_tritmp.h"
545 static void init_rast_tab( void )
550 init_twoside_unfilled();
553 /**********************************************************************/
554 /* Render unclipped begin/end objects */
555 /**********************************************************************/
557 #define RENDER_POINTS( start, count ) \
558 for ( ; start < count ; start++) \
559 r200_point( rmesa, VERT(start) )
560 #define RENDER_LINE( v0, v1 ) \
561 r200_line( rmesa, VERT(v0), VERT(v1) )
562 #define RENDER_TRI( v0, v1, v2 ) \
563 r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
564 #define RENDER_QUAD( v0, v1, v2, v3 ) \
565 r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
566 #define INIT(x) do { \
567 r200RenderPrimitive( ctx, x ); \
571 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
572 const GLuint vertsize = rmesa->swtcl.vertex_size; \
573 const char *r200verts = (char *)rmesa->swtcl.verts; \
574 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
575 const GLboolean stipple = ctx->Line.StippleFlag; \
576 (void) elt; (void) stipple;
577 #define RESET_STIPPLE if ( stipple ) r200ResetLineStipple( ctx );
578 #define RESET_OCCLUSION
579 #define PRESERVE_VB_DEFS
581 #define TAG(x) r200_##x##_verts
582 #include "tnl/t_vb_rendertmp.h"
585 #define TAG(x) r200_##x##_elts
586 #define ELT(x) elt[x]
587 #include "tnl/t_vb_rendertmp.h"
591 /**********************************************************************/
592 /* Choose render functions */
593 /**********************************************************************/
595 void r200ChooseRenderState( GLcontext
*ctx
)
597 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
598 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
600 GLuint flags
= ctx
->_TriangleCaps
;
602 if (!rmesa
->TclFallback
|| rmesa
->Fallback
)
605 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= R200_TWOSIDE_BIT
;
606 if (flags
& DD_TRI_UNFILLED
) index
|= R200_UNFILLED_BIT
;
608 if (index
!= rmesa
->swtcl
.RenderIndex
) {
609 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
610 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
611 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
612 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
613 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
616 tnl
->Driver
.Render
.PrimTabVerts
= r200_render_tab_verts
;
617 tnl
->Driver
.Render
.PrimTabElts
= r200_render_tab_elts
;
618 tnl
->Driver
.Render
.ClippedPolygon
= r200_fast_clipped_poly
;
620 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
621 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
622 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
625 rmesa
->swtcl
.RenderIndex
= index
;
630 /**********************************************************************/
631 /* High level hooks for t_vb_render.c */
632 /**********************************************************************/
635 static void r200RasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
637 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
639 if (rmesa
->swtcl
.hw_primitive
!= hwprim
) {
640 /* need to disable perspective-correct texturing for point sprites */
641 if ((hwprim
& 0xf) == R200_VF_PRIM_POINT_SPRITES
&& ctx
->Point
.PointSprite
) {
642 if (rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & R200_PERSPECTIVE_ENABLE
) {
643 R200_STATECHANGE( rmesa
, set
);
644 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PERSPECTIVE_ENABLE
;
647 else if (!(rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & R200_PERSPECTIVE_ENABLE
)) {
648 R200_STATECHANGE( rmesa
, set
);
649 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PERSPECTIVE_ENABLE
;
651 R200_NEWPRIM( rmesa
);
652 rmesa
->swtcl
.hw_primitive
= hwprim
;
656 static void r200RenderPrimitive( GLcontext
*ctx
, GLenum prim
)
658 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
659 rmesa
->swtcl
.render_primitive
= prim
;
660 if (prim
< GL_TRIANGLES
|| !(ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
661 r200RasterPrimitive( ctx
, reduced_hw_prim(ctx
, prim
) );
664 static void r200RenderFinish( GLcontext
*ctx
)
668 static void r200ResetLineStipple( GLcontext
*ctx
)
670 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
671 R200_STATECHANGE( rmesa
, lin
);
675 /**********************************************************************/
676 /* Transition to/from hardware rasterization. */
677 /**********************************************************************/
679 static const char * const fallbackStrings
[] = {
681 "glDrawBuffer(GL_FRONT_AND_BACK)",
682 "glEnable(GL_STENCIL) without hw stencil buffer",
683 "glRenderMode(selection or feedback)",
685 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
689 static const char *getFallbackString(GLuint bit
)
696 return fallbackStrings
[i
];
700 void r200Fallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
702 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
703 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
704 GLuint oldfallback
= rmesa
->Fallback
;
707 rmesa
->Fallback
|= bit
;
708 if (oldfallback
== 0) {
709 R200_FIREVERTICES( rmesa
);
710 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_RASTER
, GL_TRUE
);
711 _swsetup_Wakeup( ctx
);
712 rmesa
->swtcl
.RenderIndex
= ~0;
713 if (R200_DEBUG
& DEBUG_FALLBACKS
) {
714 fprintf(stderr
, "R200 begin rasterization fallback: 0x%x %s\n",
715 bit
, getFallbackString(bit
));
720 rmesa
->Fallback
&= ~bit
;
721 if (oldfallback
== bit
) {
723 _swrast_flush( ctx
);
724 tnl
->Driver
.Render
.Start
= r200RenderStart
;
725 tnl
->Driver
.Render
.PrimitiveNotify
= r200RenderPrimitive
;
726 tnl
->Driver
.Render
.Finish
= r200RenderFinish
;
728 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
729 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
730 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
732 tnl
->Driver
.Render
.ResetLineStipple
= r200ResetLineStipple
;
733 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_RASTER
, GL_FALSE
);
734 if (rmesa
->TclFallback
) {
735 /* These are already done if rmesa->TclFallback goes to
736 * zero above. But not if it doesn't (R200_NO_TCL for
739 _tnl_invalidate_vertex_state( ctx
, ~0 );
740 _tnl_invalidate_vertices( ctx
, ~0 );
741 RENDERINPUTS_ZERO( rmesa
->tnl_index_bitset
);
742 r200ChooseVertexState( ctx
);
743 r200ChooseRenderState( ctx
);
745 if (R200_DEBUG
& DEBUG_FALLBACKS
) {
746 fprintf(stderr
, "R200 end rasterization fallback: 0x%x %s\n",
747 bit
, getFallbackString(bit
));
757 * Cope with depth operations by drawing individual pixels as points.
760 * The way the vertex state is set in this routine is hokey. It seems to
761 * work, but it's very hackish. This whole routine is pretty hackish. If
762 * the bitmap is small enough, it seems like it would be faster to copy it
763 * to AGP memory and use it as a non-power-of-two texture (i.e.,
764 * NV_texture_rectangle).
767 r200PointsBitmap( GLcontext
*ctx
, GLint px
, GLint py
,
768 GLsizei width
, GLsizei height
,
769 const struct gl_pixelstore_attrib
*unpack
,
770 const GLubyte
*bitmap
)
772 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
773 const GLfloat
*rc
= ctx
->Current
.RasterColor
;
782 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_BITMAP
, 1 );
784 /* Choose tiny vertex format
787 const GLuint fmt_0
= R200_VTX_XY
| R200_VTX_Z0
| R200_VTX_W0
788 | (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
);
789 const GLuint fmt_1
= 0;
790 GLuint vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
791 GLuint vap
= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
];
793 vte
&= ~(R200_VTX_XY_FMT
| R200_VTX_Z_FMT
);
794 vte
|= R200_VTX_W0_FMT
;
795 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
797 rmesa
->swtcl
.vertex_size
= 5;
799 if ( (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] != fmt_0
)
800 || (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] != fmt_1
) ) {
802 R200_STATECHANGE( rmesa
, vtx
);
803 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
804 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] = fmt_1
;
807 if (vte
!= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
]) {
808 R200_STATECHANGE( rmesa
, vte
);
809 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = vte
;
812 if (vap
!= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
]) {
813 R200_STATECHANGE( rmesa
, vap
);
814 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] = vap
;
818 /* Ready for point primitives:
820 r200RenderPrimitive( ctx
, GL_POINTS
);
822 /* Turn off the hw viewport transformation:
824 R200_STATECHANGE( rmesa
, vte
);
825 orig_vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
826 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] &= ~(R200_VPORT_X_SCALE_ENA
|
827 R200_VPORT_Y_SCALE_ENA
|
828 R200_VPORT_Z_SCALE_ENA
|
829 R200_VPORT_X_OFFSET_ENA
|
830 R200_VPORT_Y_OFFSET_ENA
|
831 R200_VPORT_Z_OFFSET_ENA
);
833 /* Turn off other stuff: Stipple?, texture?, blending?, etc.
837 /* Populate the vertex
839 * Incorporate FOG into RGBA
841 if (ctx
->Fog
.Enabled
) {
842 const GLfloat
*fc
= ctx
->Fog
.Color
;
846 if (ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORDINATE_EXT
)
847 f
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.Attrib
[VERT_ATTRIB_FOG
][0]);
849 f
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
851 color
[0] = f
* rc
[0] + (1.F
- f
) * fc
[0];
852 color
[1] = f
* rc
[1] + (1.F
- f
) * fc
[1];
853 color
[2] = f
* rc
[2] + (1.F
- f
) * fc
[2];
856 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.red
, color
[0]);
857 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.green
, color
[1]);
858 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.blue
, color
[2]);
859 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.alpha
, color
[3]);
862 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.red
, rc
[0]);
863 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.green
, rc
[1]);
864 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.blue
, rc
[2]);
865 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.alpha
, rc
[3]);
869 vert
.tv
.z
= ctx
->Current
.RasterPos
[2];
872 /* Update window height
874 LOCK_HARDWARE( rmesa
);
875 UNLOCK_HARDWARE( rmesa
);
876 h
= rmesa
->dri
.drawable
->h
+ rmesa
->dri
.drawable
->y
;
877 px
+= rmesa
->dri
.drawable
->x
;
879 /* Clipping handled by existing mechansims in r200_ioctl.c?
881 for (row
=0; row
<height
; row
++) {
882 const GLubyte
*src
= (const GLubyte
*)
883 _mesa_image_address2d(unpack
, bitmap
, width
, height
,
884 GL_COLOR_INDEX
, GL_BITMAP
, row
, 0 );
886 if (unpack
->LsbFirst
) {
888 GLubyte mask
= 1U << (unpack
->SkipPixels
& 0x7);
889 for (col
=0; col
<width
; col
++) {
892 vert
.tv
.y
= h
- (py
+row
) - 1;
893 r200_point( rmesa
, &vert
);
896 mask
= ((mask
<< 1) & 0xff) | (mask
>> 7);
899 /* get ready for next row */
905 GLubyte mask
= 128U >> (unpack
->SkipPixels
& 0x7);
906 for (col
=0; col
<width
; col
++) {
909 vert
.tv
.y
= h
- (py
+row
) - 1;
910 r200_point( rmesa
, &vert
);
913 mask
= ((mask
<< 7) & 0xff) | (mask
>> 1);
915 /* get ready for next row */
921 /* Fire outstanding vertices, restore state
923 R200_STATECHANGE( rmesa
, vte
);
924 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = orig_vte
;
928 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_BITMAP
, 0 );
930 /* Need to restore vertexformat?
932 if (rmesa
->TclFallback
)
933 r200ChooseVertexState( ctx
);
938 /**********************************************************************/
939 /* Initialization. */
940 /**********************************************************************/
942 void r200InitSwtcl( GLcontext
*ctx
)
944 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
945 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
946 static int firsttime
= 1;
953 tnl
->Driver
.Render
.Start
= r200RenderStart
;
954 tnl
->Driver
.Render
.Finish
= r200RenderFinish
;
955 tnl
->Driver
.Render
.PrimitiveNotify
= r200RenderPrimitive
;
956 tnl
->Driver
.Render
.ResetLineStipple
= r200ResetLineStipple
;
957 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
958 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
959 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
961 /* FIXME: what are these numbers? */
962 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
963 36 * sizeof(GLfloat
) );
965 rmesa
->swtcl
.verts
= (GLubyte
*)tnl
->clipspace
.vertex_buf
;
966 rmesa
->swtcl
.RenderIndex
= ~0;
967 rmesa
->swtcl
.render_primitive
= GL_TRIANGLES
;
968 rmesa
->swtcl
.hw_primitive
= 0;
972 void r200DestroySwtcl( GLcontext
*ctx
)
974 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
976 if (rmesa
->swtcl
.indexed_verts
.buf
)
977 r200ReleaseDmaRegion( rmesa
, &rmesa
->swtcl
.indexed_verts
, __FUNCTION__
);