1 /* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_swtcl.c,v 1.6 2003/05/06 23:52:08 daenzer Exp $ */
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
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>
43 #include "swrast_setup/swrast_setup.h"
44 #include "math/m_translate.h"
46 #include "tnl/t_context.h"
47 #include "tnl/t_pipeline.h"
48 #include "tnl/t_vtx_api.h" /* for _tnl_FlushVertices */
50 #include "radeon_context.h"
51 #include "radeon_ioctl.h"
52 #include "radeon_state.h"
53 #include "radeon_swtcl.h"
54 #include "radeon_tcl.h"
57 static void flush_last_swtcl_prim( radeonContextPtr rmesa
);
59 /* R100: xyzw, c0, c1/fog, stq[0..2] = 4+1+1+3*3 = 15 right? */
60 /* R200: xyzw, c0, c1/fog, strq[0..5] = 4+1+1+4*6 = 30 */
61 #define RADEON_MAX_TNL_VERTEX_SIZE (15 * sizeof(GLfloat)) /* for mesa _tnl stage */
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 GLuint radeon_cp_vc_frmts
[3][2] =
85 { RADEON_CP_VC_FRMT_ST0
, RADEON_CP_VC_FRMT_ST0
| RADEON_CP_VC_FRMT_Q0
},
86 { RADEON_CP_VC_FRMT_ST1
, RADEON_CP_VC_FRMT_ST1
| RADEON_CP_VC_FRMT_Q1
},
87 { RADEON_CP_VC_FRMT_ST2
, RADEON_CP_VC_FRMT_ST2
| RADEON_CP_VC_FRMT_Q2
},
90 static void radeonSetVertexFormat( GLcontext
*ctx
)
92 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
93 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
94 struct vertex_buffer
*VB
= &tnl
->vb
;
95 DECLARE_RENDERINPUTS(index_bitset
);
99 RENDERINPUTS_COPY( index_bitset
, tnl
->render_inputs_bitset
);
103 if ( VB
->NdcPtr
!= NULL
) {
104 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
107 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->ClipPtr
;
110 assert( VB
->AttribPtr
[VERT_ATTRIB_POS
] != NULL
);
111 rmesa
->swtcl
.vertex_attr_count
= 0;
113 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
114 * build up a hardware vertex.
116 if ( !rmesa
->swtcl
.needproj
||
117 RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)) { /* for projtex */
118 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F
,
119 RADEON_CP_VC_FRMT_XY
| RADEON_CP_VC_FRMT_Z
| RADEON_CP_VC_FRMT_W0
);
123 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F
,
124 RADEON_CP_VC_FRMT_XY
| RADEON_CP_VC_FRMT_Z
);
128 rmesa
->swtcl
.coloroffset
= offset
;
129 #if MESA_LITTLE_ENDIAN
130 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_RGBA
,
131 RADEON_CP_VC_FRMT_PKCOLOR
);
133 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_ABGR
,
134 RADEON_CP_VC_FRMT_PKCOLOR
);
138 rmesa
->swtcl
.specoffset
= 0;
139 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
) ||
140 RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
142 #if MESA_LITTLE_ENDIAN
143 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
)) {
144 rmesa
->swtcl
.specoffset
= offset
;
145 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_RGB
,
146 RADEON_CP_VC_FRMT_PKSPEC
);
152 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
153 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
,
154 RADEON_CP_VC_FRMT_PKSPEC
);
160 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_FOG
)) {
161 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
,
162 RADEON_CP_VC_FRMT_PKSPEC
);
168 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_COLOR1
)) {
169 rmesa
->swtcl
.specoffset
= offset
;
170 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
,
171 RADEON_CP_VC_FRMT_PKSPEC
);
179 if (RENDERINPUTS_TEST_RANGE( index_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
)) {
182 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
183 if (RENDERINPUTS_TEST( index_bitset
, _TNL_ATTRIB_TEX(i
) )) {
184 GLuint sz
= VB
->TexCoordPtr
[i
]->size
;
189 EMIT_ATTR( _TNL_ATTRIB_TEX0
+i
, EMIT_2F
,
190 radeon_cp_vc_frmts
[i
][0] );
194 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
& (TEXTURE_CUBE_BIT
) ) {
195 EMIT_ATTR( _TNL_ATTRIB_TEX0
+i
, EMIT_3F
,
196 radeon_cp_vc_frmts
[i
][1] );
198 EMIT_ATTR( _TNL_ATTRIB_TEX0
+i
, EMIT_3F_XYW
,
199 radeon_cp_vc_frmts
[i
][1] );
209 if (!RENDERINPUTS_EQUAL( rmesa
->tnl_index_bitset
, index_bitset
) ||
210 fmt_0
!= rmesa
->swtcl
.vertex_format
) {
211 RADEON_NEWPRIM(rmesa
);
212 rmesa
->swtcl
.vertex_format
= fmt_0
;
213 rmesa
->swtcl
.vertex_size
=
214 _tnl_install_attrs( ctx
,
215 rmesa
->swtcl
.vertex_attrs
,
216 rmesa
->swtcl
.vertex_attr_count
,
218 rmesa
->swtcl
.vertex_size
/= 4;
219 RENDERINPUTS_COPY( rmesa
->tnl_index_bitset
, index_bitset
);
220 if (RADEON_DEBUG
& DEBUG_VERTS
)
221 fprintf( stderr
, "%s: vertex_size= %d floats\n",
222 __FUNCTION__
, rmesa
->swtcl
.vertex_size
);
227 static void radeonRenderStart( GLcontext
*ctx
)
229 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
231 radeonSetVertexFormat( ctx
);
233 if (rmesa
->dma
.flush
!= 0 &&
234 rmesa
->dma
.flush
!= flush_last_swtcl_prim
)
235 rmesa
->dma
.flush( rmesa
);
240 * Set vertex state for SW TCL. The primary purpose of this function is to
241 * determine in advance whether or not the hardware can / should do the
242 * projection divide or Mesa should do it.
244 void radeonChooseVertexState( GLcontext
*ctx
)
246 radeonContextPtr rmesa
= RADEON_CONTEXT( ctx
);
247 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
251 /* We must ensure that we don't do _tnl_need_projected_coords while in a
252 * rasterization fallback. As this function will be called again when we
253 * leave a rasterization fallback, we can just skip it for now.
255 if (rmesa
->Fallback
!= 0)
258 /* HW perspective divide is a win, but tiny vertex formats are a
262 if ((!RENDERINPUTS_TEST_RANGE( tnl
->render_inputs_bitset
, _TNL_FIRST_TEX
, _TNL_LAST_TEX
) &&
263 !RENDERINPUTS_TEST( tnl
->render_inputs_bitset
, _TNL_ATTRIB_COLOR1
))
264 || (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
265 rmesa
->swtcl
.needproj
= GL_TRUE
;
266 se_coord_fmt
= (RADEON_VTX_XY_PRE_MULT_1_OVER_W0
|
267 RADEON_VTX_Z_PRE_MULT_1_OVER_W0
|
268 RADEON_TEX1_W_ROUTING_USE_Q1
);
271 rmesa
->swtcl
.needproj
= GL_FALSE
;
272 se_coord_fmt
= (RADEON_VTX_W0_IS_NOT_1_OVER_W0
|
273 RADEON_TEX1_W_ROUTING_USE_Q1
);
276 _tnl_need_projected_coords( ctx
, rmesa
->swtcl
.needproj
);
278 if ( se_coord_fmt
!= rmesa
->hw
.set
.cmd
[SET_SE_COORDFMT
] ) {
279 RADEON_STATECHANGE( rmesa
, set
);
280 rmesa
->hw
.set
.cmd
[SET_SE_COORDFMT
] = se_coord_fmt
;
285 /* Flush vertices in the current dma region.
287 static void flush_last_swtcl_prim( radeonContextPtr rmesa
)
289 if (RADEON_DEBUG
& DEBUG_IOCTL
)
290 fprintf(stderr
, "%s\n", __FUNCTION__
);
292 rmesa
->dma
.flush
= NULL
;
294 if (rmesa
->dma
.current
.buf
) {
295 struct radeon_dma_region
*current
= &rmesa
->dma
.current
;
296 GLuint current_offset
= (rmesa
->radeonScreen
->gart_buffer_offset
+
297 current
->buf
->buf
->idx
* RADEON_BUFFER_SIZE
+
300 assert (!(rmesa
->swtcl
.hw_primitive
& RADEON_CP_VC_CNTL_PRIM_WALK_IND
));
302 assert (current
->start
+
303 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
306 if (rmesa
->dma
.current
.start
!= rmesa
->dma
.current
.ptr
) {
307 radeonEnsureCmdBufSpace( rmesa
, VERT_AOS_BUFSZ
+
308 rmesa
->hw
.max_state_size
+ VBUF_BUFSZ
);
310 radeonEmitVertexAOS( rmesa
,
311 rmesa
->swtcl
.vertex_size
,
314 radeonEmitVbufPrim( rmesa
,
315 rmesa
->swtcl
.vertex_format
,
316 rmesa
->swtcl
.hw_primitive
,
317 rmesa
->swtcl
.numverts
);
320 rmesa
->swtcl
.numverts
= 0;
321 current
->start
= current
->ptr
;
326 /* Alloc space in the current dma region.
329 radeonAllocDmaLowVerts( radeonContextPtr rmesa
, int nverts
, int vsize
)
331 GLuint bytes
= vsize
* nverts
;
333 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
334 radeonRefillCurrentDmaRegion( rmesa
);
336 if (!rmesa
->dma
.flush
) {
337 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
338 rmesa
->dma
.flush
= flush_last_swtcl_prim
;
341 assert( vsize
== rmesa
->swtcl
.vertex_size
* 4 );
342 assert( rmesa
->dma
.flush
== flush_last_swtcl_prim
);
343 assert (rmesa
->dma
.current
.start
+
344 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
345 rmesa
->dma
.current
.ptr
);
349 GLubyte
*head
= (GLubyte
*)(rmesa
->dma
.current
.address
+ rmesa
->dma
.current
.ptr
);
350 rmesa
->dma
.current
.ptr
+= bytes
;
351 rmesa
->swtcl
.numverts
+= nverts
;
359 * Render unclipped vertex buffers by emitting vertices directly to
360 * dma buffers. Use strip/fan hardware primitives where possible.
361 * Try to simulate missing primitives with indexed vertices.
363 #define HAVE_POINTS 1
365 #define HAVE_LINE_STRIPS 1
366 #define HAVE_TRIANGLES 1
367 #define HAVE_TRI_STRIPS 1
368 #define HAVE_TRI_STRIP_1 0
369 #define HAVE_TRI_FANS 1
371 #define HAVE_QUAD_STRIPS 0
372 #define HAVE_POLYGONS 0
373 /* \todo: is it possible to make "ELTS" work with t_vertex code ? */
376 static const GLuint hw_prim
[GL_POLYGON
+1] = {
377 RADEON_CP_VC_CNTL_PRIM_TYPE_POINT
,
378 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
,
380 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP
,
381 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
382 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP
,
383 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN
,
390 radeonDmaPrimitive( radeonContextPtr rmesa
, GLenum prim
)
392 RADEON_NEWPRIM( rmesa
);
393 rmesa
->swtcl
.hw_primitive
= hw_prim
[prim
];
394 assert(rmesa
->dma
.current
.ptr
== rmesa
->dma
.current
.start
);
397 #define LOCAL_VARS radeonContextPtr rmesa = RADEON_CONTEXT(ctx)
398 #define INIT( prim ) radeonDmaPrimitive( rmesa, prim )
399 #define FLUSH() RADEON_NEWPRIM( rmesa )
400 #define GET_CURRENT_VB_MAX_VERTS() \
401 (((int)rmesa->dma.current.end - (int)rmesa->dma.current.ptr) / (rmesa->swtcl.vertex_size*4))
402 #define GET_SUBSEQUENT_VB_MAX_VERTS() \
403 ((RADEON_BUFFER_SIZE) / (rmesa->swtcl.vertex_size*4))
404 #define ALLOC_VERTS( nr ) \
405 radeonAllocDmaLowVerts( rmesa, nr, rmesa->swtcl.vertex_size * 4 )
406 #define EMIT_VERTS( ctx, j, nr, buf ) \
407 _tnl_emit_vertices_to_buffer(ctx, j, (j)+(nr), buf)
409 #define TAG(x) radeon_dma_##x
410 #include "tnl_dd/t_dd_dmatmp.h"
413 /**********************************************************************/
414 /* Render pipeline stage */
415 /**********************************************************************/
418 static GLboolean
radeon_run_render( GLcontext
*ctx
,
419 struct tnl_pipeline_stage
*stage
)
421 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
422 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
423 struct vertex_buffer
*VB
= &tnl
->vb
;
424 tnl_render_func
*tab
= TAG(render_tab_verts
);
427 if (rmesa
->swtcl
.indexed_verts
.buf
)
430 if (rmesa
->swtcl
.RenderIndex
!= 0 ||
431 !radeon_dma_validate_render( ctx
, VB
))
434 tnl
->Driver
.Render
.Start( ctx
);
436 for (i
= 0 ; i
< VB
->PrimitiveCount
; i
++)
438 GLuint prim
= VB
->Primitive
[i
].mode
;
439 GLuint start
= VB
->Primitive
[i
].start
;
440 GLuint length
= VB
->Primitive
[i
].count
;
445 if (RADEON_DEBUG
& DEBUG_PRIMS
)
446 fprintf(stderr
, "radeon_render.c: prim %s %d..%d\n",
447 _mesa_lookup_enum_by_nr(prim
& PRIM_MODE_MASK
),
448 start
, start
+length
);
451 tab
[prim
& PRIM_MODE_MASK
]( ctx
, start
, start
+ length
, prim
);
454 tnl
->Driver
.Render
.Finish( ctx
);
456 return GL_FALSE
; /* finished the pipe */
462 const struct tnl_pipeline_stage _radeon_render_stage
=
469 radeon_run_render
/* run */
473 /**************************************************************************/
475 /* Radeon texture rectangle expects coords in 0..1 range, not 0..dimension
476 * as in the extension spec. Need to translate here.
478 * Note that swrast expects 0..dimension, so if a fallback is active,
479 * don't do anything. (Maybe need to configure swrast to match hw)
481 struct texrect_stage_data
{
482 GLvector4f texcoord
[MAX_TEXTURE_UNITS
];
485 #define TEXRECT_STAGE_DATA(stage) ((struct texrect_stage_data *)stage->privatePtr)
488 static GLboolean
run_texrect_stage( GLcontext
*ctx
,
489 struct tnl_pipeline_stage
*stage
)
491 struct texrect_stage_data
*store
= TEXRECT_STAGE_DATA(stage
);
492 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
493 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
494 struct vertex_buffer
*VB
= &tnl
->vb
;
500 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
501 if (ctx
->Texture
.Unit
[i
]._ReallyEnabled
& TEXTURE_RECT_BIT
) {
502 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[i
].CurrentRect
;
503 struct gl_texture_image
*texImage
= texObj
->Image
[0][texObj
->BaseLevel
];
504 const GLfloat iw
= 1.0/texImage
->Width
;
505 const GLfloat ih
= 1.0/texImage
->Height
;
506 GLfloat
*in
= (GLfloat
*)VB
->TexCoordPtr
[i
]->data
;
507 GLint instride
= VB
->TexCoordPtr
[i
]->stride
;
508 GLfloat (*out
)[4] = store
->texcoord
[i
].data
;
511 store
->texcoord
[i
].size
= VB
->TexCoordPtr
[i
]->size
;
512 for (j
= 0 ; j
< VB
->Count
; j
++) {
513 switch (VB
->TexCoordPtr
[i
]->size
) {
521 out
[j
][0] = in
[0] * iw
;
522 out
[j
][1] = in
[1] * ih
;
524 in
= (GLfloat
*)((GLubyte
*)in
+ instride
);
527 VB
->AttribPtr
[VERT_ATTRIB_TEX0
+i
] = VB
->TexCoordPtr
[i
] = &store
->texcoord
[i
];
535 /* Called the first time stage->run() is invoked.
537 static GLboolean
alloc_texrect_data( GLcontext
*ctx
,
538 struct tnl_pipeline_stage
*stage
)
540 struct vertex_buffer
*VB
= &TNL_CONTEXT(ctx
)->vb
;
541 struct texrect_stage_data
*store
;
544 stage
->privatePtr
= CALLOC(sizeof(*store
));
545 store
= TEXRECT_STAGE_DATA(stage
);
549 for (i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++)
550 _mesa_vector4f_alloc( &store
->texcoord
[i
], 0, VB
->Size
, 32 );
555 static void free_texrect_data( struct tnl_pipeline_stage
*stage
)
557 struct texrect_stage_data
*store
= TEXRECT_STAGE_DATA(stage
);
561 for (i
= 0 ; i
< MAX_TEXTURE_UNITS
; i
++)
562 if (store
->texcoord
[i
].data
)
563 _mesa_vector4f_free( &store
->texcoord
[i
] );
565 stage
->privatePtr
= NULL
;
569 const struct tnl_pipeline_stage _radeon_texrect_stage
=
571 "radeon texrect stage", /* name */
580 /**************************************************************************/
583 static const GLuint reduced_hw_prim
[GL_POLYGON
+1] = {
584 RADEON_CP_VC_CNTL_PRIM_TYPE_POINT
,
585 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
,
586 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
,
587 RADEON_CP_VC_CNTL_PRIM_TYPE_LINE
,
588 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
589 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
590 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
591 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
592 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
,
593 RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST
596 static void radeonRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
);
597 static void radeonRenderPrimitive( GLcontext
*ctx
, GLenum prim
);
598 static void radeonResetLineStipple( GLcontext
*ctx
);
601 /***********************************************************************
602 * Emit primitives as inline vertices *
603 ***********************************************************************/
607 #define CTX_ARG radeonContextPtr rmesa
608 #define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
609 #define ALLOC_VERTS( n, size ) radeonAllocDmaLowVerts( rmesa, n, (size) * 4 )
612 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
613 const char *radeonverts = (char *)rmesa->swtcl.verts;
614 #define VERT(x) (radeonVertex *)(radeonverts + ((x) * (vertsize) * sizeof(int)))
615 #define VERTEX radeonVertex
617 #define TAG(x) radeon_##x
618 #include "tnl_dd/t_dd_triemit.h"
621 /***********************************************************************
622 * Macros for t_dd_tritmp.h to draw basic primitives *
623 ***********************************************************************/
625 #define QUAD( a, b, c, d ) radeon_quad( rmesa, a, b, c, d )
626 #define TRI( a, b, c ) radeon_triangle( rmesa, a, b, c )
627 #define LINE( a, b ) radeon_line( rmesa, a, b )
628 #define POINT( a ) radeon_point( rmesa, a )
630 /***********************************************************************
631 * Build render functions from dd templates *
632 ***********************************************************************/
634 #define RADEON_TWOSIDE_BIT 0x01
635 #define RADEON_UNFILLED_BIT 0x02
636 #define RADEON_MAX_TRIFUNC 0x04
640 tnl_points_func points
;
642 tnl_triangle_func triangle
;
644 } rast_tab
[RADEON_MAX_TRIFUNC
];
647 #define DO_FALLBACK 0
649 #define DO_UNFILLED (IND & RADEON_UNFILLED_BIT)
650 #define DO_TWOSIDE (IND & RADEON_TWOSIDE_BIT)
656 #define DO_FULL_QUAD 1
660 #define HAVE_BACK_COLORS 0
661 #define HAVE_HW_FLATSHADE 1
664 #define DEPTH_SCALE 1.0
665 #define UNFILLED_TRI unfilled_tri
666 #define UNFILLED_QUAD unfilled_quad
667 #define VERT_X(_v) _v->v.x
668 #define VERT_Y(_v) _v->v.y
669 #define VERT_Z(_v) _v->v.z
670 #define AREA_IS_CCW( a ) (a < 0)
671 #define GET_VERTEX(e) (rmesa->swtcl.verts + ((e) * rmesa->swtcl.vertex_size * sizeof(int)))
673 #define VERT_SET_RGBA( v, c ) \
675 radeon_color_t *color = (radeon_color_t *)&((v)->ui[coloroffset]); \
676 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
677 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
678 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
679 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
682 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
684 #define VERT_SET_SPEC( v, c ) \
687 radeon_color_t *spec = (radeon_color_t *)&((v)->ui[specoffset]); \
688 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
689 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
690 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
693 #define VERT_COPY_SPEC( v0, v1 ) \
696 radeon_color_t *spec0 = (radeon_color_t *)&((v0)->ui[specoffset]); \
697 radeon_color_t *spec1 = (radeon_color_t *)&((v1)->ui[specoffset]); \
698 spec0->red = spec1->red; \
699 spec0->green = spec1->green; \
700 spec0->blue = spec1->blue; \
704 /* These don't need LE32_TO_CPU() as they used to save and restore
705 * colors which are already in the correct format.
707 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
708 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
709 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
710 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
716 #define LOCAL_VARS(n) \
717 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
718 GLuint color[n], spec[n]; \
719 GLuint coloroffset = rmesa->swtcl.coloroffset; \
720 GLuint specoffset = rmesa->swtcl.specoffset; \
721 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
723 /***********************************************************************
724 * Helpers for rendering unfilled primitives *
725 ***********************************************************************/
727 #define RASTERIZE(x) radeonRasterPrimitive( ctx, reduced_hw_prim[x] )
728 #define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
731 #include "tnl_dd/t_dd_unfilled.h"
735 /***********************************************************************
736 * Generate GL render functions *
737 ***********************************************************************/
742 #include "tnl_dd/t_dd_tritmp.h"
744 #define IND (RADEON_TWOSIDE_BIT)
745 #define TAG(x) x##_twoside
746 #include "tnl_dd/t_dd_tritmp.h"
748 #define IND (RADEON_UNFILLED_BIT)
749 #define TAG(x) x##_unfilled
750 #include "tnl_dd/t_dd_tritmp.h"
752 #define IND (RADEON_TWOSIDE_BIT|RADEON_UNFILLED_BIT)
753 #define TAG(x) x##_twoside_unfilled
754 #include "tnl_dd/t_dd_tritmp.h"
757 static void init_rast_tab( void )
762 init_twoside_unfilled();
765 /**********************************************************************/
766 /* Render unclipped begin/end objects */
767 /**********************************************************************/
769 #define RENDER_POINTS( start, count ) \
770 for ( ; start < count ; start++) \
771 radeon_point( rmesa, VERT(start) )
772 #define RENDER_LINE( v0, v1 ) \
773 radeon_line( rmesa, VERT(v0), VERT(v1) )
774 #define RENDER_TRI( v0, v1, v2 ) \
775 radeon_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
776 #define RENDER_QUAD( v0, v1, v2, v3 ) \
777 radeon_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
779 #define INIT(x) do { \
780 radeonRenderPrimitive( ctx, x ); \
784 radeonContextPtr rmesa = RADEON_CONTEXT(ctx); \
785 const GLuint vertsize = rmesa->swtcl.vertex_size; \
786 const char *radeonverts = (char *)rmesa->swtcl.verts; \
787 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
788 const GLboolean stipple = ctx->Line.StippleFlag; \
789 (void) elt; (void) stipple;
790 #define RESET_STIPPLE if ( stipple ) radeonResetLineStipple( ctx );
791 #define RESET_OCCLUSION
792 #define PRESERVE_VB_DEFS
794 #define TAG(x) radeon_##x##_verts
795 #include "tnl/t_vb_rendertmp.h"
798 #define TAG(x) radeon_##x##_elts
799 #define ELT(x) elt[x]
800 #include "tnl/t_vb_rendertmp.h"
804 /**********************************************************************/
805 /* Choose render functions */
806 /**********************************************************************/
808 void radeonChooseRenderState( GLcontext
*ctx
)
810 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
811 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
813 GLuint flags
= ctx
->_TriangleCaps
;
815 if (!rmesa
->TclFallback
|| rmesa
->Fallback
)
818 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= RADEON_TWOSIDE_BIT
;
819 if (flags
& DD_TRI_UNFILLED
) index
|= RADEON_UNFILLED_BIT
;
821 if (index
!= rmesa
->swtcl
.RenderIndex
) {
822 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
823 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
824 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
825 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
826 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
829 tnl
->Driver
.Render
.PrimTabVerts
= radeon_render_tab_verts
;
830 tnl
->Driver
.Render
.PrimTabElts
= radeon_render_tab_elts
;
831 tnl
->Driver
.Render
.ClippedPolygon
= radeon_fast_clipped_poly
;
833 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
834 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
835 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
838 rmesa
->swtcl
.RenderIndex
= index
;
843 /**********************************************************************/
844 /* High level hooks for t_vb_render.c */
845 /**********************************************************************/
848 static void radeonRasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
850 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
852 if (rmesa
->swtcl
.hw_primitive
!= hwprim
) {
853 RADEON_NEWPRIM( rmesa
);
854 rmesa
->swtcl
.hw_primitive
= hwprim
;
858 static void radeonRenderPrimitive( GLcontext
*ctx
, GLenum prim
)
860 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
861 rmesa
->swtcl
.render_primitive
= prim
;
862 if (prim
< GL_TRIANGLES
|| !(ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
863 radeonRasterPrimitive( ctx
, reduced_hw_prim
[prim
] );
866 static void radeonRenderFinish( GLcontext
*ctx
)
870 static void radeonResetLineStipple( GLcontext
*ctx
)
872 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
873 RADEON_STATECHANGE( rmesa
, lin
);
877 /**********************************************************************/
878 /* Transition to/from hardware rasterization. */
879 /**********************************************************************/
881 static const char * const fallbackStrings
[] = {
883 "glDrawBuffer(GL_FRONT_AND_BACK)",
884 "glEnable(GL_STENCIL) without hw stencil buffer",
885 "glRenderMode(selection or feedback)",
889 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
893 static const char *getFallbackString(GLuint bit
)
900 return fallbackStrings
[i
];
904 void radeonFallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
906 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
907 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
908 GLuint oldfallback
= rmesa
->Fallback
;
911 rmesa
->Fallback
|= bit
;
912 if (oldfallback
== 0) {
913 RADEON_FIREVERTICES( rmesa
);
914 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_RASTER
, GL_TRUE
);
915 _swsetup_Wakeup( ctx
);
916 rmesa
->swtcl
.RenderIndex
= ~0;
917 if (RADEON_DEBUG
& DEBUG_FALLBACKS
) {
918 fprintf(stderr
, "Radeon begin rasterization fallback: 0x%x %s\n",
919 bit
, getFallbackString(bit
));
924 rmesa
->Fallback
&= ~bit
;
925 if (oldfallback
== bit
) {
926 _swrast_flush( ctx
);
927 tnl
->Driver
.Render
.Start
= radeonRenderStart
;
928 tnl
->Driver
.Render
.PrimitiveNotify
= radeonRenderPrimitive
;
929 tnl
->Driver
.Render
.Finish
= radeonRenderFinish
;
931 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
932 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
933 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
935 tnl
->Driver
.Render
.ResetLineStipple
= radeonResetLineStipple
;
936 TCL_FALLBACK( ctx
, RADEON_TCL_FALLBACK_RASTER
, GL_FALSE
);
937 if (rmesa
->TclFallback
) {
938 /* These are already done if rmesa->TclFallback goes to
939 * zero above. But not if it doesn't (RADEON_NO_TCL for
942 _tnl_invalidate_vertex_state( ctx
, ~0 );
943 _tnl_invalidate_vertices( ctx
, ~0 );
944 RENDERINPUTS_ZERO( rmesa
->tnl_index_bitset
);
945 radeonChooseVertexState( ctx
);
946 radeonChooseRenderState( ctx
);
948 if (RADEON_DEBUG
& DEBUG_FALLBACKS
) {
949 fprintf(stderr
, "Radeon end rasterization fallback: 0x%x %s\n",
950 bit
, getFallbackString(bit
));
957 void radeonFlushVertices( GLcontext
*ctx
, GLuint flags
)
959 _tnl_FlushVertices( ctx
, flags
);
961 if (flags
& FLUSH_STORED_VERTICES
)
962 RADEON_NEWPRIM( RADEON_CONTEXT( ctx
) );
965 /**********************************************************************/
966 /* Initialization. */
967 /**********************************************************************/
969 void radeonInitSwtcl( GLcontext
*ctx
)
971 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
972 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
973 static int firsttime
= 1;
980 tnl
->Driver
.Render
.Start
= radeonRenderStart
;
981 tnl
->Driver
.Render
.Finish
= radeonRenderFinish
;
982 tnl
->Driver
.Render
.PrimitiveNotify
= radeonRenderPrimitive
;
983 tnl
->Driver
.Render
.ResetLineStipple
= radeonResetLineStipple
;
984 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
985 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
986 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
988 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
989 RADEON_MAX_TNL_VERTEX_SIZE
);
991 rmesa
->swtcl
.verts
= (GLubyte
*)tnl
->clipspace
.vertex_buf
;
992 rmesa
->swtcl
.RenderIndex
= ~0;
993 rmesa
->swtcl
.render_primitive
= GL_TRIANGLES
;
994 rmesa
->swtcl
.hw_primitive
= 0;
998 void radeonDestroySwtcl( GLcontext
*ctx
)
1000 radeonContextPtr rmesa
= RADEON_CONTEXT(ctx
);
1002 if (rmesa
->swtcl
.indexed_verts
.buf
)
1003 radeonReleaseDmaRegion( rmesa
, &rmesa
->swtcl
.indexed_verts
,