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 GLuint index
= tnl
->render_inputs
;
96 if ( VB
->NdcPtr
!= NULL
) {
97 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->NdcPtr
;
100 VB
->AttribPtr
[VERT_ATTRIB_POS
] = VB
->ClipPtr
;
103 assert( VB
->AttribPtr
[VERT_ATTRIB_POS
] != NULL
);
104 rmesa
->swtcl
.vertex_attr_count
= 0;
106 /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
107 * build up a hardware vertex.
109 if ( !rmesa
->swtcl
.needproj
) {
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 rmesa
->swtcl
.coloroffset
= offset
;
119 #if MESA_LITTLE_ENDIAN
120 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_RGBA
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
) );
122 EMIT_ATTR( _TNL_ATTRIB_COLOR0
, EMIT_4UB_4F_ABGR
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
) );
126 rmesa
->swtcl
.specoffset
= 0;
127 if (index
& (_TNL_BIT_COLOR1
|_TNL_BIT_FOG
)) {
129 #if MESA_LITTLE_ENDIAN
130 if (index
& _TNL_BIT_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
& _TNL_BIT_FOG
) {
139 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
145 if (index
& _TNL_BIT_FOG
) {
146 EMIT_ATTR( _TNL_ATTRIB_FOG
, EMIT_1UB_1F
, (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_1_SHIFT
) );
152 if (index
& _TNL_BIT_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
& _TNL_BITS_TEX_ANY
) {
165 for (i
= 0; i
< ctx
->Const
.MaxTextureUnits
; i
++) {
166 if (index
& _TNL_BIT_TEX(i
)) {
167 GLuint sz
= VB
->TexCoordPtr
[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
->tnl_index
!= index
||
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
->swtcl
.vertex_size
=
191 _tnl_install_attrs( ctx
,
192 rmesa
->swtcl
.vertex_attrs
,
193 rmesa
->swtcl
.vertex_attr_count
,
195 rmesa
->swtcl
.vertex_size
/= 4;
196 rmesa
->tnl_index
= index
;
201 static void r200RenderStart( GLcontext
*ctx
)
203 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
205 r200SetVertexFormat( ctx
);
207 if (rmesa
->dma
.flush
!= 0 &&
208 rmesa
->dma
.flush
!= flush_last_swtcl_prim
)
209 rmesa
->dma
.flush( rmesa
);
214 * Set vertex state for SW TCL. The primary purpose of this function is to
215 * determine in advance whether or not the hardware can / should do the
216 * projection divide or Mesa should do it.
218 void r200ChooseVertexState( GLcontext
*ctx
)
220 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
221 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
223 GLuint vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
224 GLuint vap
= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
];
226 /* HW perspective divide is a win, but tiny vertex formats are a
229 if ( ((tnl
->render_inputs
& _TNL_BITS_TEX_ANY
) == 0)
230 || (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
231 rmesa
->swtcl
.needproj
= GL_TRUE
;
232 vte
|= R200_VTX_XY_FMT
| R200_VTX_Z_FMT
;
233 vap
|= R200_VAP_FORCE_W_TO_ONE
;
236 rmesa
->swtcl
.needproj
= GL_FALSE
;
237 vte
&= ~(R200_VTX_XY_FMT
| R200_VTX_Z_FMT
);
238 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
241 _tnl_need_projected_coords( ctx
, rmesa
->swtcl
.needproj
);
243 if (vte
!= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
]) {
244 R200_STATECHANGE( rmesa
, vte
);
245 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = vte
;
248 if (vap
!= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
]) {
249 R200_STATECHANGE( rmesa
, vap
);
250 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] = vap
;
255 /* Flush vertices in the current dma region.
257 static void flush_last_swtcl_prim( r200ContextPtr rmesa
)
259 if (R200_DEBUG
& DEBUG_IOCTL
)
260 fprintf(stderr
, "%s\n", __FUNCTION__
);
262 rmesa
->dma
.flush
= 0;
264 if (rmesa
->dma
.current
.buf
) {
265 struct r200_dma_region
*current
= &rmesa
->dma
.current
;
266 GLuint current_offset
= (rmesa
->r200Screen
->gart_buffer_offset
+
267 current
->buf
->buf
->idx
* RADEON_BUFFER_SIZE
+
270 assert (!(rmesa
->swtcl
.hw_primitive
& R200_VF_PRIM_WALK_IND
));
272 assert (current
->start
+
273 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
276 if (rmesa
->dma
.current
.start
!= rmesa
->dma
.current
.ptr
) {
277 r200EnsureCmdBufSpace( rmesa
, VERT_AOS_BUFSZ
+
278 rmesa
->hw
.max_state_size
+ VBUF_BUFSZ
);
279 r200EmitVertexAOS( rmesa
,
280 rmesa
->swtcl
.vertex_size
,
283 r200EmitVbufPrim( rmesa
,
284 rmesa
->swtcl
.hw_primitive
,
285 rmesa
->swtcl
.numverts
);
288 rmesa
->swtcl
.numverts
= 0;
289 current
->start
= current
->ptr
;
294 /* Alloc space in the current dma region.
296 static __inline
void *r200AllocDmaLowVerts( r200ContextPtr rmesa
,
297 int nverts
, int vsize
)
299 GLuint bytes
= vsize
* nverts
;
301 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
302 r200RefillCurrentDmaRegion( rmesa
);
304 if (!rmesa
->dma
.flush
) {
305 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
306 rmesa
->dma
.flush
= flush_last_swtcl_prim
;
309 ASSERT( vsize
== rmesa
->swtcl
.vertex_size
* 4 );
310 ASSERT( rmesa
->dma
.flush
== flush_last_swtcl_prim
);
311 ASSERT( rmesa
->dma
.current
.start
+
312 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
313 rmesa
->dma
.current
.ptr
);
317 GLubyte
*head
= (GLubyte
*) (rmesa
->dma
.current
.address
+ rmesa
->dma
.current
.ptr
);
318 rmesa
->dma
.current
.ptr
+= bytes
;
319 rmesa
->swtcl
.numverts
+= nverts
;
326 /**************************************************************************/
329 static const GLuint reduced_hw_prim
[GL_POLYGON
+1] = {
334 R200_VF_PRIM_TRIANGLES
,
335 R200_VF_PRIM_TRIANGLES
,
336 R200_VF_PRIM_TRIANGLES
,
337 R200_VF_PRIM_TRIANGLES
,
338 R200_VF_PRIM_TRIANGLES
,
339 R200_VF_PRIM_TRIANGLES
342 static void r200RasterPrimitive( GLcontext
*ctx
, GLuint hwprim
);
343 static void r200RenderPrimitive( GLcontext
*ctx
, GLenum prim
);
344 static void r200ResetLineStipple( GLcontext
*ctx
);
346 /***********************************************************************
347 * Emit primitives as inline vertices *
348 ***********************************************************************/
350 #define HAVE_POINTS 1
352 #define HAVE_LINE_STRIPS 1
353 #define HAVE_TRIANGLES 1
354 #define HAVE_TRI_STRIPS 1
355 #define HAVE_TRI_STRIP_1 0
356 #define HAVE_TRI_FANS 1
358 #define HAVE_QUAD_STRIPS 0
359 #define HAVE_POLYGONS 1
364 #define CTX_ARG r200ContextPtr rmesa
365 #define CTX_ARG2 rmesa
366 #define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
367 #define ALLOC_VERTS( n, size ) r200AllocDmaLowVerts( rmesa, n, size * 4 )
369 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
370 const char *r200verts = (char *)rmesa->swtcl.verts;
371 #define VERT(x) (r200Vertex *)(r200verts + ((x) * vertsize * sizeof(int)))
372 #define VERTEX r200Vertex
373 #define DO_DEBUG_VERTS (1 && (R200_DEBUG & DEBUG_VERTS))
376 #define TAG(x) r200_##x
377 #include "tnl_dd/t_dd_triemit.h"
380 /***********************************************************************
381 * Macros for t_dd_tritmp.h to draw basic primitives *
382 ***********************************************************************/
384 #define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d )
385 #define TRI( a, b, c ) r200_triangle( rmesa, a, b, c )
386 #define LINE( a, b ) r200_line( rmesa, a, b )
387 #define POINT( a ) r200_point( rmesa, a )
389 /***********************************************************************
390 * Build render functions from dd templates *
391 ***********************************************************************/
393 #define R200_TWOSIDE_BIT 0x01
394 #define R200_UNFILLED_BIT 0x02
395 #define R200_MAX_TRIFUNC 0x04
399 tnl_points_func points
;
401 tnl_triangle_func triangle
;
403 } rast_tab
[R200_MAX_TRIFUNC
];
406 #define DO_FALLBACK 0
407 #define DO_UNFILLED (IND & R200_UNFILLED_BIT)
408 #define DO_TWOSIDE (IND & R200_TWOSIDE_BIT)
415 #define DO_FULL_QUAD 1
419 #define HAVE_BACK_COLORS 0
420 #define HAVE_HW_FLATSHADE 1
423 #define DEPTH_SCALE 1.0
424 #define UNFILLED_TRI unfilled_tri
425 #define UNFILLED_QUAD unfilled_quad
426 #define VERT_X(_v) _v->v.x
427 #define VERT_Y(_v) _v->v.y
428 #define VERT_Z(_v) _v->v.z
429 #define AREA_IS_CCW( a ) (a < 0)
430 #define GET_VERTEX(e) (rmesa->swtcl.verts + (e*rmesa->swtcl.vertex_size*sizeof(int)))
432 #define VERT_SET_RGBA( v, c ) \
434 r200_color_t *color = (r200_color_t *)&((v)->ui[coloroffset]); \
435 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
436 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
437 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
438 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
441 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
443 #define VERT_SET_SPEC( v, c ) \
446 r200_color_t *spec = (r200_color_t *)&((v)->ui[specoffset]); \
447 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
448 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
449 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
452 #define VERT_COPY_SPEC( v0, v1 ) \
455 r200_color_t *spec0 = (r200_color_t *)&((v0)->ui[specoffset]); \
456 r200_color_t *spec1 = (r200_color_t *)&((v1)->ui[specoffset]); \
457 spec0->red = spec1->red; \
458 spec0->green = spec1->green; \
459 spec0->blue = spec1->blue; \
463 /* These don't need LE32_TO_CPU() as they used to save and restore
464 * colors which are already in the correct format.
466 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
467 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
468 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
469 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
475 #define LOCAL_VARS(n) \
476 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
477 GLuint color[n], spec[n]; \
478 GLuint coloroffset = rmesa->swtcl.coloroffset; \
479 GLuint specoffset = rmesa->swtcl.specoffset; \
480 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
482 /***********************************************************************
483 * Helpers for rendering unfilled primitives *
484 ***********************************************************************/
486 #define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim[x] )
487 #define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
490 #include "tnl_dd/t_dd_unfilled.h"
494 /***********************************************************************
495 * Generate GL render functions *
496 ***********************************************************************/
501 #include "tnl_dd/t_dd_tritmp.h"
503 #define IND (R200_TWOSIDE_BIT)
504 #define TAG(x) x##_twoside
505 #include "tnl_dd/t_dd_tritmp.h"
507 #define IND (R200_UNFILLED_BIT)
508 #define TAG(x) x##_unfilled
509 #include "tnl_dd/t_dd_tritmp.h"
511 #define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT)
512 #define TAG(x) x##_twoside_unfilled
513 #include "tnl_dd/t_dd_tritmp.h"
516 static void init_rast_tab( void )
521 init_twoside_unfilled();
524 /**********************************************************************/
525 /* Render unclipped begin/end objects */
526 /**********************************************************************/
528 #define RENDER_POINTS( start, count ) \
529 for ( ; start < count ; start++) \
530 r200_point( rmesa, VERT(start) )
531 #define RENDER_LINE( v0, v1 ) \
532 r200_line( rmesa, VERT(v0), VERT(v1) )
533 #define RENDER_TRI( v0, v1, v2 ) \
534 r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
535 #define RENDER_QUAD( v0, v1, v2, v3 ) \
536 r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
537 #define INIT(x) do { \
538 r200RenderPrimitive( ctx, x ); \
542 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
543 const GLuint vertsize = rmesa->swtcl.vertex_size; \
544 const char *r200verts = (char *)rmesa->swtcl.verts; \
545 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
546 const GLboolean stipple = ctx->Line.StippleFlag; \
547 (void) elt; (void) stipple;
548 #define RESET_STIPPLE if ( stipple ) r200ResetLineStipple( ctx );
549 #define RESET_OCCLUSION
550 #define PRESERVE_VB_DEFS
552 #define TAG(x) r200_##x##_verts
553 #include "tnl/t_vb_rendertmp.h"
556 #define TAG(x) r200_##x##_elts
557 #define ELT(x) elt[x]
558 #include "tnl/t_vb_rendertmp.h"
562 /**********************************************************************/
563 /* Choose render functions */
564 /**********************************************************************/
566 void r200ChooseRenderState( GLcontext
*ctx
)
568 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
569 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
571 GLuint flags
= ctx
->_TriangleCaps
;
573 if (!rmesa
->TclFallback
|| rmesa
->Fallback
)
576 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= R200_TWOSIDE_BIT
;
577 if (flags
& DD_TRI_UNFILLED
) index
|= R200_UNFILLED_BIT
;
579 if (index
!= rmesa
->swtcl
.RenderIndex
) {
580 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
581 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
582 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
583 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
584 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
587 tnl
->Driver
.Render
.PrimTabVerts
= r200_render_tab_verts
;
588 tnl
->Driver
.Render
.PrimTabElts
= r200_render_tab_elts
;
589 tnl
->Driver
.Render
.ClippedPolygon
= r200_fast_clipped_poly
;
591 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
592 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
593 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
596 rmesa
->swtcl
.RenderIndex
= index
;
601 /**********************************************************************/
602 /* High level hooks for t_vb_render.c */
603 /**********************************************************************/
606 static void r200RasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
608 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
610 if (rmesa
->swtcl
.hw_primitive
!= hwprim
) {
611 R200_NEWPRIM( rmesa
);
612 rmesa
->swtcl
.hw_primitive
= hwprim
;
616 static void r200RenderPrimitive( GLcontext
*ctx
, GLenum prim
)
618 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
619 rmesa
->swtcl
.render_primitive
= prim
;
620 if (prim
< GL_TRIANGLES
|| !(ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
621 r200RasterPrimitive( ctx
, reduced_hw_prim
[prim
] );
624 static void r200RenderFinish( GLcontext
*ctx
)
628 static void r200ResetLineStipple( GLcontext
*ctx
)
630 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
631 R200_STATECHANGE( rmesa
, lin
);
635 /**********************************************************************/
636 /* Transition to/from hardware rasterization. */
637 /**********************************************************************/
639 static const char * const fallbackStrings
[] = {
641 "glDrawBuffer(GL_FRONT_AND_BACK)",
642 "glEnable(GL_STENCIL) without hw stencil buffer",
643 "glRenderMode(selection or feedback)",
645 "glBlendFunc(mode != ADD)",
647 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
651 static const char *getFallbackString(GLuint bit
)
658 return fallbackStrings
[i
];
662 void r200Fallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
664 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
665 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
666 GLuint oldfallback
= rmesa
->Fallback
;
669 rmesa
->Fallback
|= bit
;
670 if (oldfallback
== 0) {
671 R200_FIREVERTICES( rmesa
);
672 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_RASTER
, GL_TRUE
);
673 _swsetup_Wakeup( ctx
);
674 _tnl_need_projected_coords( ctx
, GL_TRUE
);
675 rmesa
->swtcl
.RenderIndex
= ~0;
676 if (R200_DEBUG
& DEBUG_FALLBACKS
) {
677 fprintf(stderr
, "R200 begin rasterization fallback: 0x%x %s\n",
678 bit
, getFallbackString(bit
));
683 rmesa
->Fallback
&= ~bit
;
684 if (oldfallback
== bit
) {
686 _swrast_flush( ctx
);
687 tnl
->Driver
.Render
.Start
= r200RenderStart
;
688 tnl
->Driver
.Render
.PrimitiveNotify
= r200RenderPrimitive
;
689 tnl
->Driver
.Render
.Finish
= r200RenderFinish
;
691 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
692 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
693 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
695 tnl
->Driver
.Render
.ResetLineStipple
= r200ResetLineStipple
;
696 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_RASTER
, GL_FALSE
);
697 if (rmesa
->TclFallback
) {
698 /* These are already done if rmesa->TclFallback goes to
699 * zero above. But not if it doesn't (R200_NO_TCL for
702 r200ChooseVertexState( ctx
);
703 r200ChooseRenderState( ctx
);
705 if (R200_DEBUG
& DEBUG_FALLBACKS
) {
706 fprintf(stderr
, "R200 end rasterization fallback: 0x%x %s\n",
707 bit
, getFallbackString(bit
));
717 * Cope with depth operations by drawing individual pixels as points.
720 * The way the vertex state is set in this routine is hokey. It seems to
721 * work, but it's very hackish. This whole routine is pretty hackish. If
722 * the bitmap is small enough, it seems like it would be faster to copy it
723 * to AGP memory and use it as a non-power-of-two texture (i.e.,
724 * NV_texture_rectangle).
727 r200PointsBitmap( GLcontext
*ctx
, GLint px
, GLint py
,
728 GLsizei width
, GLsizei height
,
729 const struct gl_pixelstore_attrib
*unpack
,
730 const GLubyte
*bitmap
)
732 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
733 const GLfloat
*rc
= ctx
->Current
.RasterColor
;
742 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_BITMAP
, 1 );
744 /* Choose tiny vertex format
747 const GLuint fmt_0
= R200_VTX_XY
| R200_VTX_Z0
| R200_VTX_W0
748 | (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
);
749 const GLuint fmt_1
= 0;
750 GLuint vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
751 GLuint vap
= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
];
753 vte
&= ~(R200_VTX_XY_FMT
| R200_VTX_Z_FMT
);
754 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
756 rmesa
->swtcl
.vertex_size
= 5;
758 if ( (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] != fmt_0
)
759 || (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] != fmt_1
) ) {
761 R200_STATECHANGE( rmesa
, vtx
);
762 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
763 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] = fmt_1
;
766 if (vte
!= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
]) {
767 R200_STATECHANGE( rmesa
, vte
);
768 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = vte
;
771 if (vap
!= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
]) {
772 R200_STATECHANGE( rmesa
, vap
);
773 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] = vap
;
777 /* Ready for point primitives:
779 r200RenderPrimitive( ctx
, GL_POINTS
);
781 /* Turn off the hw viewport transformation:
783 R200_STATECHANGE( rmesa
, vte
);
784 orig_vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
785 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] &= ~(R200_VPORT_X_SCALE_ENA
|
786 R200_VPORT_Y_SCALE_ENA
|
787 R200_VPORT_Z_SCALE_ENA
|
788 R200_VPORT_X_OFFSET_ENA
|
789 R200_VPORT_Y_OFFSET_ENA
|
790 R200_VPORT_Z_OFFSET_ENA
);
792 /* Turn off other stuff: Stipple?, texture?, blending?, etc.
796 /* Populate the vertex
798 * Incorporate FOG into RGBA
800 if (ctx
->Fog
.Enabled
) {
801 const GLfloat
*fc
= ctx
->Fog
.Color
;
805 if (ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORDINATE_EXT
)
806 f
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.Attrib
[VERT_ATTRIB_FOG
][0]);
808 f
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
810 color
[0] = f
* rc
[0] + (1.F
- f
) * fc
[0];
811 color
[1] = f
* rc
[1] + (1.F
- f
) * fc
[1];
812 color
[2] = f
* rc
[2] + (1.F
- f
) * fc
[2];
815 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.red
, color
[0]);
816 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.green
, color
[1]);
817 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.blue
, color
[2]);
818 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.alpha
, color
[3]);
821 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.red
, rc
[0]);
822 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.green
, rc
[1]);
823 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.blue
, rc
[2]);
824 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.alpha
, rc
[3]);
828 vert
.tv
.z
= ctx
->Current
.RasterPos
[2];
831 /* Update window height
833 LOCK_HARDWARE( rmesa
);
834 UNLOCK_HARDWARE( rmesa
);
835 h
= rmesa
->dri
.drawable
->h
+ rmesa
->dri
.drawable
->y
;
836 px
+= rmesa
->dri
.drawable
->x
;
838 /* Clipping handled by existing mechansims in r200_ioctl.c?
840 for (row
=0; row
<height
; row
++) {
841 const GLubyte
*src
= (const GLubyte
*)
842 _mesa_image_address( unpack
, bitmap
, width
, height
,
843 GL_COLOR_INDEX
, GL_BITMAP
, 0, row
, 0 );
845 if (unpack
->LsbFirst
) {
847 GLubyte mask
= 1U << (unpack
->SkipPixels
& 0x7);
848 for (col
=0; col
<width
; col
++) {
851 vert
.tv
.y
= h
- (py
+row
) - 1;
852 r200_point( rmesa
, &vert
);
855 mask
= ((mask
<< 1) & 0xff) | (mask
>> 7);
858 /* get ready for next row */
864 GLubyte mask
= 128U >> (unpack
->SkipPixels
& 0x7);
865 for (col
=0; col
<width
; col
++) {
868 vert
.tv
.y
= h
- (py
+row
) - 1;
869 r200_point( rmesa
, &vert
);
872 mask
= ((mask
<< 7) & 0xff) | (mask
>> 1);
874 /* get ready for next row */
880 /* Fire outstanding vertices, restore state
882 R200_STATECHANGE( rmesa
, vte
);
883 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = orig_vte
;
887 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_BITMAP
, 0 );
889 /* Need to restore vertexformat?
891 if (rmesa
->TclFallback
)
892 r200ChooseVertexState( ctx
);
896 void r200FlushVertices( GLcontext
*ctx
, GLuint flags
)
898 _tnl_FlushVertices( ctx
, flags
);
900 if (flags
& FLUSH_STORED_VERTICES
)
901 R200_NEWPRIM( R200_CONTEXT( ctx
) );
904 /**********************************************************************/
905 /* Initialization. */
906 /**********************************************************************/
908 void r200InitSwtcl( GLcontext
*ctx
)
910 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
911 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
912 static int firsttime
= 1;
919 tnl
->Driver
.Render
.Start
= r200RenderStart
;
920 tnl
->Driver
.Render
.Finish
= r200RenderFinish
;
921 tnl
->Driver
.Render
.PrimitiveNotify
= r200RenderPrimitive
;
922 tnl
->Driver
.Render
.ResetLineStipple
= r200ResetLineStipple
;
923 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
924 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
925 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
927 /* FIXME: what are these numbers? */
928 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
929 36 * sizeof(GLfloat
) );
931 rmesa
->swtcl
.verts
= (GLubyte
*)tnl
->clipspace
.vertex_buf
;
932 rmesa
->swtcl
.RenderIndex
= ~0;
933 rmesa
->swtcl
.render_primitive
= GL_TRIANGLES
;
934 rmesa
->swtcl
.hw_primitive
= 0;
938 void r200DestroySwtcl( GLcontext
*ctx
)
940 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
942 if (rmesa
->swtcl
.indexed_verts
.buf
)
943 r200ReleaseDmaRegion( rmesa
, &rmesa
->swtcl
.indexed_verts
, __FUNCTION__
);