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 <keithw@vmware.com>
35 #include "main/glheader.h"
36 #include "main/mtypes.h"
37 #include "main/enums.h"
38 #include "main/image.h"
39 #include "main/imports.h"
40 #include "main/macros.h"
42 #include "swrast/s_context.h"
43 #include "swrast/s_fog.h"
44 #include "swrast_setup/swrast_setup.h"
46 #include "tnl/t_context.h"
47 #include "tnl/t_pipeline.h"
49 #include "r200_context.h"
50 #include "r200_ioctl.h"
51 #include "r200_state.h"
52 #include "r200_swtcl.h"
56 /***********************************************************************
58 ***********************************************************************/
60 #define EMIT_ATTR( ATTR, STYLE, F0 ) \
62 rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = (ATTR); \
63 rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = (STYLE); \
64 rmesa->radeon.swtcl.vertex_attr_count++; \
68 #define EMIT_PAD( N ) \
70 rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = 0; \
71 rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = EMIT_PAD; \
72 rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].offset = (N); \
73 rmesa->radeon.swtcl.vertex_attr_count++; \
76 static void r200SetVertexFormat( struct gl_context
*ctx
)
78 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
79 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
80 struct vertex_buffer
*VB
= &tnl
->vb
;
81 GLbitfield64 index_bitset
= tnl
->render_inputs_bitset
;
88 if ( VB
->NdcPtr
!= NULL
) {
89 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
92 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->ClipPtr
;
95 assert( VB
->AttribPtr
[VERT_ATTRIB_POS
] != NULL
);
96 rmesa
->radeon
.swtcl
.vertex_attr_count
= 0;
98 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
99 * build up a hardware vertex.
101 if ( !rmesa
->swtcl
.needproj
||
102 (index_bitset
& BITFIELD64_RANGE(_TNL_ATTRIB_TEX0
, _TNL_NUM_TEX
)) ) {
103 /* need w coord for projected textures */
104 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_4F
, R200_VTX_XY
| R200_VTX_Z0
| R200_VTX_W0
);
108 EMIT_ATTR( _TNL_ATTRIB_POS
, EMIT_3F
, R200_VTX_XY
| R200_VTX_Z0
);
112 if (index_bitset
& BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE
)) {
113 EMIT_ATTR( _TNL_ATTRIB_POINTSIZE
, EMIT_1F
, R200_VTX_POINT_SIZE
);
117 rmesa
->swtcl
.coloroffset
= offset
;
118 #if MESA_LITTLE_ENDIAN
119 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_RGBA
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
) );
121 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_ABGR
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
) );
125 rmesa
->swtcl
.specoffset
= 0;
127 (BITFIELD64_BIT(_TNL_ATTRIB_COLOR1
) | BITFIELD64_BIT(_TNL_ATTRIB_FOG
))) {
129 #if MESA_LITTLE_ENDIAN
130 if (index_bitset
& BITFIELD64_BIT(_TNL_ATTRIB_COLOR1
)) {
131 rmesa
->swtcl
.specoffset
= offset
;
132 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_RGB
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
138 if (index_bitset
& BITFIELD64_BIT(_TNL_ATTRIB_FOG
)) {
139 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
145 if (index_bitset
& BITFIELD64_BIT(_TNL_ATTRIB_FOG
)) {
146 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
152 if (index_bitset
& BITFIELD64_BIT(_TNL_ATTRIB_COLOR1
)) {
153 rmesa
->swtcl
.specoffset
= offset
;
154 EMIT_ATTR( _TNL_ATTRIB_COLOR1
, EMIT_3UB_3F_BGR
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
162 if (index_bitset
& BITFIELD64_RANGE(_TNL_ATTRIB_TEX0
, _TNL_NUM_TEX
)) {
165 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
166 if (index_bitset
& BITFIELD64_BIT(_TNL_ATTRIB_TEX(i
))) {
167 GLuint sz
= VB
->AttribPtr
[_TNL_ATTRIB_TEX0
+ i
]->size
;
169 fmt_1
|= sz
<< (3 * i
);
170 EMIT_ATTR( _TNL_ATTRIB_TEX0
+i
, EMIT_1F
+ sz
- 1, 0 );
175 if ( (rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] & R200_FOG_USE_MASK
)
176 != R200_FOG_USE_SPEC_ALPHA
) {
177 R200_STATECHANGE( rmesa
, ctx
);
178 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] &= ~R200_FOG_USE_MASK
;
179 rmesa
->hw
.ctx
.cmd
[CTX_PP_FOG_COLOR
] |= R200_FOG_USE_SPEC_ALPHA
;
182 if (rmesa
->radeon
.tnl_index_bitset
!= index_bitset
||
183 (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] != fmt_0
) ||
184 (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] != fmt_1
) ) {
186 R200_STATECHANGE( rmesa
, vtx
);
187 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
188 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] = fmt_1
;
190 rmesa
->radeon
.swtcl
.vertex_size
=
191 _tnl_install_attrs( ctx
,
192 rmesa
->radeon
.swtcl
.vertex_attrs
,
193 rmesa
->radeon
.swtcl
.vertex_attr_count
,
195 rmesa
->radeon
.swtcl
.vertex_size
/= 4;
196 rmesa
->radeon
.tnl_index_bitset
= index_bitset
;
200 static void r200_predict_emit_size( r200ContextPtr rmesa
)
202 if (RADEON_DEBUG
& RADEON_VERTS
)
203 fprintf(stderr
, "%s\n", __func__
);
204 const int vertex_array_size
= 7;
205 const int prim_size
= 3;
206 if (!rmesa
->radeon
.swtcl
.emit_prediction
) {
207 const int state_size
= radeonCountStateEmitSize(&rmesa
->radeon
);
208 if (rcommonEnsureCmdBufSpace(&rmesa
->radeon
,
210 vertex_array_size
+ prim_size
,
212 rmesa
->radeon
.swtcl
.emit_prediction
= radeonCountStateEmitSize(&rmesa
->radeon
);
214 rmesa
->radeon
.swtcl
.emit_prediction
= state_size
;
215 rmesa
->radeon
.swtcl
.emit_prediction
+= vertex_array_size
+ prim_size
216 + rmesa
->radeon
.cmdbuf
.cs
->cdw
;
221 static void r200RenderStart( struct gl_context
*ctx
)
223 r200SetVertexFormat( ctx
);
224 if (RADEON_DEBUG
& RADEON_VERTS
)
225 fprintf(stderr
, "%s\n", __func__
);
230 * Set vertex state for SW TCL. The primary purpose of this function is to
231 * determine in advance whether or not the hardware can / should do the
232 * projection divide or Mesa should do it.
234 void r200ChooseVertexState( struct gl_context
*ctx
)
236 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
237 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
240 GLboolean unfilled
= (ctx
->Polygon
.FrontMode
!= GL_FILL
||
241 ctx
->Polygon
.BackMode
!= GL_FILL
);
242 GLboolean twosided
= ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
;
244 /* We must ensure that we don't do _tnl_need_projected_coords while in a
245 * rasterization fallback. As this function will be called again when we
246 * leave a rasterization fallback, we can just skip it for now.
248 if (rmesa
->radeon
.Fallback
!= 0)
251 vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
252 vap
= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
];
254 /* HW perspective divide is a win, but tiny vertex formats are a
257 if ((0 == (tnl
->render_inputs_bitset
& BITFIELD64_RANGE(_TNL_ATTRIB_TEX0
, _TNL_NUM_TEX
)))
260 rmesa
->swtcl
.needproj
= GL_TRUE
;
261 vte
|= R200_VTX_XY_FMT
| R200_VTX_Z_FMT
;
262 vte
&= ~R200_VTX_W0_FMT
;
263 if (tnl
->render_inputs_bitset
& BITFIELD64_RANGE(_TNL_ATTRIB_TEX0
, _TNL_NUM_TEX
)) {
264 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
267 vap
|= R200_VAP_FORCE_W_TO_ONE
;
271 rmesa
->swtcl
.needproj
= GL_FALSE
;
272 vte
&= ~(R200_VTX_XY_FMT
| R200_VTX_Z_FMT
);
273 vte
|= R200_VTX_W0_FMT
;
274 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
277 _tnl_need_projected_coords( ctx
, rmesa
->swtcl
.needproj
);
279 if (vte
!= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
]) {
280 R200_STATECHANGE( rmesa
, vte
);
281 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = vte
;
284 if (vap
!= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
]) {
285 R200_STATECHANGE( rmesa
, vap
);
286 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] = vap
;
290 void r200_swtcl_flush(struct gl_context
*ctx
, uint32_t current_offset
)
292 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
293 if (RADEON_DEBUG
& RADEON_VERTS
)
294 fprintf(stderr
, "%s\n", __func__
);
297 radeonEmitState(&rmesa
->radeon
);
298 r200EmitVertexAOS( rmesa
,
299 rmesa
->radeon
.swtcl
.vertex_size
,
300 rmesa
->radeon
.swtcl
.bo
,
304 r200EmitVbufPrim( rmesa
,
305 rmesa
->radeon
.swtcl
.hw_primitive
,
306 rmesa
->radeon
.swtcl
.numverts
);
307 if ( rmesa
->radeon
.swtcl
.emit_prediction
< rmesa
->radeon
.cmdbuf
.cs
->cdw
)
308 WARN_ONCE("Rendering was %d commands larger than predicted size."
309 " We might overflow command buffer.\n",
310 rmesa
->radeon
.cmdbuf
.cs
->cdw
- rmesa
->radeon
.swtcl
.emit_prediction
);
312 rmesa
->radeon
.swtcl
.emit_prediction
= 0;
316 /**************************************************************************/
319 static inline GLuint
reduced_hw_prim( struct gl_context
*ctx
, GLuint prim
)
323 return ((!ctx
->Point
.SmoothFlag
) ?
324 R200_VF_PRIM_POINT_SPRITES
: R200_VF_PRIM_POINTS
);
330 return R200_VF_PRIM_LINES
;
332 /* all others reduced to triangles */
333 return R200_VF_PRIM_TRIANGLES
;
338 static void r200RasterPrimitive( struct gl_context
*ctx
, GLuint hwprim
);
339 static void r200RenderPrimitive( struct gl_context
*ctx
, GLenum prim
);
340 static void r200ResetLineStipple( struct gl_context
*ctx
);
342 /***********************************************************************
343 * Emit primitives as inline vertices *
344 ***********************************************************************/
346 #define HAVE_POINTS 1
348 #define HAVE_LINE_STRIPS 1
349 #define HAVE_TRIANGLES 1
350 #define HAVE_TRI_STRIPS 1
351 #define HAVE_TRI_FANS 1
353 #define HAVE_QUAD_STRIPS 0
354 #define HAVE_POLYGONS 1
357 static void* r200_alloc_verts( r200ContextPtr rmesa
, GLuint n
, GLuint size
)
361 r200_predict_emit_size( rmesa
);
362 rv
= rcommonAllocDmaLowVerts( &rmesa
->radeon
, n
, size
* 4 );
369 #define CTX_ARG r200ContextPtr rmesa
370 #define GET_VERTEX_DWORDS() rmesa->radeon.swtcl.vertex_size
371 #define ALLOC_VERTS( n, size ) r200_alloc_verts(rmesa, n, size)
373 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
374 const char *r200verts = (char *)rmesa->radeon.swtcl.verts;
375 #define VERT(x) (radeonVertex *)(r200verts + ((x) * vertsize * sizeof(int)))
376 #define VERTEX radeonVertex
377 #define DO_DEBUG_VERTS (1 && (R200_DEBUG & RADEON_VERTS))
380 #define TAG(x) r200_##x
381 #include "tnl_dd/t_dd_triemit.h"
384 /***********************************************************************
385 * Macros for t_dd_tritmp.h to draw basic primitives *
386 ***********************************************************************/
388 #define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d )
389 #define TRI( a, b, c ) r200_triangle( rmesa, a, b, c )
390 #define LINE( a, b ) r200_line( rmesa, a, b )
391 #define POINT( a ) r200_point( rmesa, a )
393 /***********************************************************************
394 * Build render functions from dd templates *
395 ***********************************************************************/
397 #define R200_TWOSIDE_BIT 0x01
398 #define R200_UNFILLED_BIT 0x02
399 #define R200_MAX_TRIFUNC 0x04
403 tnl_points_func points
;
405 tnl_triangle_func triangle
;
407 } rast_tab
[R200_MAX_TRIFUNC
];
410 #define DO_FALLBACK 0
411 #define DO_UNFILLED ((IND & R200_UNFILLED_BIT) != 0)
412 #define DO_TWOSIDE ((IND & R200_TWOSIDE_BIT) != 0)
419 #define DO_FULL_QUAD 1
422 #define HAVE_BACK_COLORS 0
423 #define HAVE_HW_FLATSHADE 1
426 #define DEPTH_SCALE 1.0
427 #define UNFILLED_TRI unfilled_tri
428 #define UNFILLED_QUAD unfilled_quad
429 #define VERT_X(_v) _v->v.x
430 #define VERT_Y(_v) _v->v.y
431 #define VERT_Z(_v) _v->v.z
432 #define AREA_IS_CCW( a ) (a < 0)
433 #define GET_VERTEX(e) (rmesa->radeon.swtcl.verts + (e*rmesa->radeon.swtcl.vertex_size*sizeof(int)))
435 #define VERT_SET_RGBA( v, c ) \
437 radeon_color_t *color = (radeon_color_t *)&((v)->ui[coloroffset]); \
438 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
439 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
440 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
441 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
444 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
446 #define VERT_SET_SPEC( v, c ) \
449 radeon_color_t *spec = (radeon_color_t *)&((v)->ui[specoffset]); \
450 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
451 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
452 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
455 #define VERT_COPY_SPEC( v0, v1 ) \
458 radeon_color_t *spec0 = (radeon_color_t *)&((v0)->ui[specoffset]); \
459 radeon_color_t *spec1 = (radeon_color_t *)&((v1)->ui[specoffset]); \
460 spec0->red = spec1->red; \
461 spec0->green = spec1->green; \
462 spec0->blue = spec1->blue; \
466 /* These don't need LE32_TO_CPU() as they used to save and restore
467 * colors which are already in the correct format.
469 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
470 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
471 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
472 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
478 #define LOCAL_VARS(n) \
479 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
480 GLuint color[n] = {0}, spec[n] = {0}; \
481 GLuint coloroffset = rmesa->swtcl.coloroffset; \
482 GLuint specoffset = rmesa->swtcl.specoffset; \
483 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
485 /***********************************************************************
486 * Helpers for rendering unfilled primitives *
487 ***********************************************************************/
489 #define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim(ctx, x) )
490 #define RENDER_PRIMITIVE rmesa->radeon.swtcl.render_primitive
493 #include "tnl_dd/t_dd_unfilled.h"
497 /***********************************************************************
498 * Generate GL render functions *
499 ***********************************************************************/
504 #include "tnl_dd/t_dd_tritmp.h"
506 #define IND (R200_TWOSIDE_BIT)
507 #define TAG(x) x##_twoside
508 #include "tnl_dd/t_dd_tritmp.h"
510 #define IND (R200_UNFILLED_BIT)
511 #define TAG(x) x##_unfilled
512 #include "tnl_dd/t_dd_tritmp.h"
514 #define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT)
515 #define TAG(x) x##_twoside_unfilled
516 #include "tnl_dd/t_dd_tritmp.h"
519 static void init_rast_tab( void )
524 init_twoside_unfilled();
527 /**********************************************************************/
528 /* Render unclipped begin/end objects */
529 /**********************************************************************/
531 #define RENDER_POINTS( start, count ) \
532 for ( ; start < count ; start++) \
533 r200_point( rmesa, VERT(start) )
534 #define RENDER_LINE( v0, v1 ) \
535 r200_line( rmesa, VERT(v0), VERT(v1) )
536 #define RENDER_TRI( v0, v1, v2 ) \
537 r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
538 #define RENDER_QUAD( v0, v1, v2, v3 ) \
539 r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
540 #define INIT(x) do { \
541 r200RenderPrimitive( ctx, x ); \
545 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
546 const GLuint vertsize = rmesa->radeon.swtcl.vertex_size; \
547 const char *r200verts = (char *)rmesa->radeon.swtcl.verts; \
548 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
549 const GLboolean stipple = ctx->Line.StippleFlag; \
550 (void) elt; (void) stipple;
551 #define RESET_STIPPLE if ( stipple ) r200ResetLineStipple( ctx );
552 #define RESET_OCCLUSION
553 #define PRESERVE_VB_DEFS
555 #define TAG(x) r200_##x##_verts
556 #include "tnl/t_vb_rendertmp.h"
559 #define TAG(x) r200_##x##_elts
560 #define ELT(x) elt[x]
561 #include "tnl/t_vb_rendertmp.h"
565 /**********************************************************************/
566 /* Choose render functions */
567 /**********************************************************************/
569 void r200ChooseRenderState( struct gl_context
*ctx
)
571 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
572 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
574 GLboolean unfilled
= (ctx
->Polygon
.FrontMode
!= GL_FILL
||
575 ctx
->Polygon
.BackMode
!= GL_FILL
);
576 GLboolean twosided
= ctx
->Light
.Enabled
&& ctx
->Light
.Model
.TwoSide
;
578 if (!rmesa
->radeon
.TclFallback
|| rmesa
->radeon
.Fallback
)
582 index
|= R200_TWOSIDE_BIT
;
584 index
|= R200_UNFILLED_BIT
;
586 if (index
!= rmesa
->radeon
.swtcl
.RenderIndex
) {
587 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
588 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
589 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
590 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
591 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
594 tnl
->Driver
.Render
.PrimTabVerts
= r200_render_tab_verts
;
595 tnl
->Driver
.Render
.PrimTabElts
= r200_render_tab_elts
;
596 tnl
->Driver
.Render
.ClippedPolygon
= r200_fast_clipped_poly
;
598 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
599 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
600 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
603 rmesa
->radeon
.swtcl
.RenderIndex
= index
;
608 /**********************************************************************/
609 /* High level hooks for t_vb_render.c */
610 /**********************************************************************/
613 static void r200RasterPrimitive( struct gl_context
*ctx
, GLuint hwprim
)
615 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
617 radeon_prepare_render(&rmesa
->radeon
);
618 if (rmesa
->radeon
.NewGLState
)
619 r200ValidateState( ctx
);
622 if (rmesa
->radeon
.swtcl
.hw_primitive
!= hwprim
) {
623 /* need to disable perspective-correct texturing for point sprites */
624 if ((hwprim
& 0xf) == R200_VF_PRIM_POINT_SPRITES
&& ctx
->Point
.PointSprite
) {
625 if (rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & R200_PERSPECTIVE_ENABLE
) {
626 R200_STATECHANGE( rmesa
, set
);
627 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] &= ~R200_PERSPECTIVE_ENABLE
;
630 else if (!(rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] & R200_PERSPECTIVE_ENABLE
)) {
631 R200_STATECHANGE( rmesa
, set
);
632 rmesa
->hw
.set
.cmd
[SET_RE_CNTL
] |= R200_PERSPECTIVE_ENABLE
;
634 R200_NEWPRIM( rmesa
);
635 rmesa
->radeon
.swtcl
.hw_primitive
= hwprim
;
639 static void r200RenderPrimitive( struct gl_context
*ctx
, GLenum prim
)
641 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
642 GLboolean unfilled
= (ctx
->Polygon
.FrontMode
!= GL_FILL
||
643 ctx
->Polygon
.BackMode
!= GL_FILL
);
645 rmesa
->radeon
.swtcl
.render_primitive
= prim
;
646 if (prim
< GL_TRIANGLES
|| !unfilled
)
647 r200RasterPrimitive( ctx
, reduced_hw_prim(ctx
, prim
) );
650 static void r200RenderFinish( struct gl_context
*ctx
)
654 static void r200ResetLineStipple( struct gl_context
*ctx
)
656 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
657 R200_STATECHANGE( rmesa
, lin
);
661 /**********************************************************************/
662 /* Transition to/from hardware rasterization. */
663 /**********************************************************************/
665 static const char * const fallbackStrings
[] = {
667 "glDrawBuffer(GL_FRONT_AND_BACK)",
668 "glEnable(GL_STENCIL) without hw stencil buffer",
669 "glRenderMode(selection or feedback)",
671 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
675 static const char *getFallbackString(GLuint bit
)
682 return fallbackStrings
[i
];
686 void r200Fallback( struct gl_context
*ctx
, GLuint bit
, GLboolean mode
)
688 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
689 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
690 GLuint oldfallback
= rmesa
->radeon
.Fallback
;
693 rmesa
->radeon
.Fallback
|= bit
;
694 if (oldfallback
== 0) {
695 radeon_firevertices(&rmesa
->radeon
);
696 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_RASTER
, GL_TRUE
);
697 _swsetup_Wakeup( ctx
);
698 rmesa
->radeon
.swtcl
.RenderIndex
= ~0;
699 if (R200_DEBUG
& RADEON_FALLBACKS
) {
700 fprintf(stderr
, "R200 begin rasterization fallback: 0x%x %s\n",
701 bit
, getFallbackString(bit
));
706 rmesa
->radeon
.Fallback
&= ~bit
;
707 if (oldfallback
== bit
) {
709 _swrast_flush( ctx
);
710 tnl
->Driver
.Render
.Start
= r200RenderStart
;
711 tnl
->Driver
.Render
.PrimitiveNotify
= r200RenderPrimitive
;
712 tnl
->Driver
.Render
.Finish
= r200RenderFinish
;
714 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
715 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
716 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
718 tnl
->Driver
.Render
.ResetLineStipple
= r200ResetLineStipple
;
719 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_RASTER
, GL_FALSE
);
720 if (rmesa
->radeon
.TclFallback
) {
721 /* These are already done if rmesa->radeon.TclFallback goes to
722 * zero above. But not if it doesn't (R200_NO_TCL for
725 _tnl_invalidate_vertex_state( ctx
, ~0 );
726 _tnl_invalidate_vertices( ctx
, ~0 );
727 rmesa
->radeon
.tnl_index_bitset
= 0;
728 r200ChooseVertexState( ctx
);
729 r200ChooseRenderState( ctx
);
731 if (R200_DEBUG
& RADEON_FALLBACKS
) {
732 fprintf(stderr
, "R200 end rasterization fallback: 0x%x %s\n",
733 bit
, getFallbackString(bit
));
743 * Cope with depth operations by drawing individual pixels as points.
746 * The way the vertex state is set in this routine is hokey. It seems to
747 * work, but it's very hackish. This whole routine is pretty hackish. If
748 * the bitmap is small enough, it seems like it would be faster to copy it
749 * to AGP memory and use it as a non-power-of-two texture (i.e.,
750 * NV_texture_rectangle).
753 r200PointsBitmap( struct gl_context
*ctx
, GLint px
, GLint py
,
754 GLsizei width
, GLsizei height
,
755 const struct gl_pixelstore_attrib
*unpack
,
756 const GLubyte
*bitmap
)
758 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
759 const GLfloat
*rc
= ctx
->Current
.RasterColor
;
768 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_BITMAP
, 1 );
770 /* Choose tiny vertex format
773 const GLuint fmt_0
= R200_VTX_XY
| R200_VTX_Z0
| R200_VTX_W0
774 | (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
);
775 const GLuint fmt_1
= 0;
776 GLuint vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
777 GLuint vap
= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
];
779 vte
&= ~(R200_VTX_XY_FMT
| R200_VTX_Z_FMT
);
780 vte
|= R200_VTX_W0_FMT
;
781 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
783 rmesa
->radeon
.swtcl
.vertex_size
= 5;
785 if ( (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] != fmt_0
)
786 || (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] != fmt_1
) ) {
788 R200_STATECHANGE( rmesa
, vtx
);
789 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
790 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] = fmt_1
;
793 if (vte
!= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
]) {
794 R200_STATECHANGE( rmesa
, vte
);
795 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = vte
;
798 if (vap
!= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
]) {
799 R200_STATECHANGE( rmesa
, vap
);
800 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] = vap
;
804 /* Ready for point primitives:
806 r200RenderPrimitive( ctx
, GL_POINTS
);
808 /* Turn off the hw viewport transformation:
810 R200_STATECHANGE( rmesa
, vte
);
811 orig_vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
812 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] &= ~(R200_VPORT_X_SCALE_ENA
|
813 R200_VPORT_Y_SCALE_ENA
|
814 R200_VPORT_Z_SCALE_ENA
|
815 R200_VPORT_X_OFFSET_ENA
|
816 R200_VPORT_Y_OFFSET_ENA
|
817 R200_VPORT_Z_OFFSET_ENA
);
819 /* Turn off other stuff: Stipple?, texture?, blending?, etc.
823 /* Populate the vertex
825 * Incorporate FOG into RGBA
827 if (ctx
->Fog
.Enabled
) {
828 const GLfloat
*fc
= ctx
->Fog
.Color
;
832 if (ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORDINATE_EXT
)
833 f
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.Attrib
[VERT_ATTRIB_FOG
][0]);
835 f
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
837 color
[0] = f
* rc
[0] + (1.F
- f
) * fc
[0];
838 color
[1] = f
* rc
[1] + (1.F
- f
) * fc
[1];
839 color
[2] = f
* rc
[2] + (1.F
- f
) * fc
[2];
842 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.red
, color
[0]);
843 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.green
, color
[1]);
844 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.blue
, color
[2]);
845 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.alpha
, color
[3]);
848 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.red
, rc
[0]);
849 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.green
, rc
[1]);
850 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.blue
, rc
[2]);
851 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.alpha
, rc
[3]);
855 vert
.tv
.z
= ctx
->Current
.RasterPos
[2];
858 /* Update window height
860 h
= radeon_get_drawable(&rmesa
->radeon
)->h
;
862 /* Clipping handled by existing mechansims in r200_ioctl.c?
864 for (row
=0; row
<height
; row
++) {
865 const GLubyte
*src
= (const GLubyte
*)
866 _mesa_image_address2d(unpack
, bitmap
, width
, height
,
867 GL_COLOR_INDEX
, GL_BITMAP
, row
, 0 );
869 if (unpack
->LsbFirst
) {
871 GLubyte mask
= 1U << (unpack
->SkipPixels
& 0x7);
872 for (col
=0; col
<width
; col
++) {
875 vert
.tv
.y
= h
- (py
+row
) - 1;
876 r200_point( rmesa
, &vert
);
879 mask
= ((mask
<< 1) & 0xff) | (mask
>> 7);
882 /* get ready for next row */
888 GLubyte mask
= 128U >> (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
<< 7) & 0xff) | (mask
>> 1);
898 /* get ready for next row */
904 /* Fire outstanding vertices, restore state
906 R200_STATECHANGE( rmesa
, vte
);
907 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = orig_vte
;
911 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_BITMAP
, 0 );
913 /* Need to restore vertexformat?
915 if (rmesa
->radeon
.TclFallback
)
916 r200ChooseVertexState( ctx
);
921 /**********************************************************************/
922 /* Initialization. */
923 /**********************************************************************/
925 void r200InitSwtcl( struct gl_context
*ctx
)
927 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
928 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
929 static int firsttime
= 1;
935 rmesa
->radeon
.swtcl
.emit_prediction
= 0;
937 tnl
->Driver
.Render
.Start
= r200RenderStart
;
938 tnl
->Driver
.Render
.Finish
= r200RenderFinish
;
939 tnl
->Driver
.Render
.PrimitiveNotify
= r200RenderPrimitive
;
940 tnl
->Driver
.Render
.ResetLineStipple
= r200ResetLineStipple
;
941 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
942 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
943 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
945 /* FIXME: what are these numbers? */
946 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
947 36 * sizeof(GLfloat
) );
949 rmesa
->radeon
.swtcl
.verts
= (GLubyte
*)tnl
->clipspace
.vertex_buf
;
950 rmesa
->radeon
.swtcl
.RenderIndex
= ~0;
951 rmesa
->radeon
.swtcl
.render_primitive
= GL_TRIANGLES
;
952 rmesa
->radeon
.swtcl
.hw_primitive
= 0;