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 );
177 if ( rmesa
->tnl_index
!= index
||
178 (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] != fmt_0
) ||
179 (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] != fmt_1
) ) {
181 R200_STATECHANGE( rmesa
, vtx
);
182 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
183 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] = fmt_1
;
185 rmesa
->swtcl
.vertex_size
=
186 _tnl_install_attrs( ctx
,
187 rmesa
->swtcl
.vertex_attrs
,
188 rmesa
->swtcl
.vertex_attr_count
,
190 rmesa
->swtcl
.vertex_size
/= 4;
191 rmesa
->tnl_index
= index
;
196 static void r200RenderStart( GLcontext
*ctx
)
198 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
200 r200SetVertexFormat( ctx
);
202 if (rmesa
->dma
.flush
!= 0 &&
203 rmesa
->dma
.flush
!= flush_last_swtcl_prim
)
204 rmesa
->dma
.flush( rmesa
);
209 * Set vertex state for SW TCL. The primary purpose of this function is to
210 * determine in advance whether or not the hardware can / should do the
211 * projection divide or Mesa should do it.
213 void r200ChooseVertexState( GLcontext
*ctx
)
215 r200ContextPtr rmesa
= R200_CONTEXT( ctx
);
216 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
218 GLuint vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
219 GLuint vap
= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
];
221 /* HW perspective divide is a win, but tiny vertex formats are a
224 if ( ((tnl
->render_inputs
& _TNL_BITS_TEX_ANY
) == 0)
225 || (ctx
->_TriangleCaps
& (DD_TRI_LIGHT_TWOSIDE
|DD_TRI_UNFILLED
))) {
226 rmesa
->swtcl
.needproj
= GL_TRUE
;
227 vte
|= R200_VTX_XY_FMT
| R200_VTX_Z_FMT
;
228 vap
|= R200_VAP_FORCE_W_TO_ONE
;
231 rmesa
->swtcl
.needproj
= GL_FALSE
;
232 vte
&= ~(R200_VTX_XY_FMT
| R200_VTX_Z_FMT
);
233 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
236 _tnl_need_projected_coords( ctx
, rmesa
->swtcl
.needproj
);
238 if (vte
!= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
]) {
239 R200_STATECHANGE( rmesa
, vte
);
240 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = vte
;
243 if (vap
!= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
]) {
244 R200_STATECHANGE( rmesa
, vap
);
245 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] = vap
;
250 /* Flush vertices in the current dma region.
252 static void flush_last_swtcl_prim( r200ContextPtr rmesa
)
254 if (R200_DEBUG
& DEBUG_IOCTL
)
255 fprintf(stderr
, "%s\n", __FUNCTION__
);
257 rmesa
->dma
.flush
= 0;
259 if (rmesa
->dma
.current
.buf
) {
260 struct r200_dma_region
*current
= &rmesa
->dma
.current
;
261 GLuint current_offset
= (rmesa
->r200Screen
->gart_buffer_offset
+
262 current
->buf
->buf
->idx
* RADEON_BUFFER_SIZE
+
265 assert (!(rmesa
->swtcl
.hw_primitive
& R200_VF_PRIM_WALK_IND
));
267 assert (current
->start
+
268 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
271 if (rmesa
->dma
.current
.start
!= rmesa
->dma
.current
.ptr
) {
272 r200EnsureCmdBufSpace( rmesa
, VERT_AOS_BUFSZ
+
273 rmesa
->hw
.max_state_size
+ VBUF_BUFSZ
);
274 r200EmitVertexAOS( rmesa
,
275 rmesa
->swtcl
.vertex_size
,
278 r200EmitVbufPrim( rmesa
,
279 rmesa
->swtcl
.hw_primitive
,
280 rmesa
->swtcl
.numverts
);
283 rmesa
->swtcl
.numverts
= 0;
284 current
->start
= current
->ptr
;
289 /* Alloc space in the current dma region.
291 static __inline
void *r200AllocDmaLowVerts( r200ContextPtr rmesa
,
292 int nverts
, int vsize
)
294 GLuint bytes
= vsize
* nverts
;
296 if ( rmesa
->dma
.current
.ptr
+ bytes
> rmesa
->dma
.current
.end
)
297 r200RefillCurrentDmaRegion( rmesa
);
299 if (!rmesa
->dma
.flush
) {
300 rmesa
->glCtx
->Driver
.NeedFlush
|= FLUSH_STORED_VERTICES
;
301 rmesa
->dma
.flush
= flush_last_swtcl_prim
;
304 ASSERT( vsize
== rmesa
->swtcl
.vertex_size
* 4 );
305 ASSERT( rmesa
->dma
.flush
== flush_last_swtcl_prim
);
306 ASSERT( rmesa
->dma
.current
.start
+
307 rmesa
->swtcl
.numverts
* rmesa
->swtcl
.vertex_size
* 4 ==
308 rmesa
->dma
.current
.ptr
);
312 GLubyte
*head
= (GLubyte
*) (rmesa
->dma
.current
.address
+ rmesa
->dma
.current
.ptr
);
313 rmesa
->dma
.current
.ptr
+= bytes
;
314 rmesa
->swtcl
.numverts
+= nverts
;
321 /**************************************************************************/
324 static const GLuint reduced_hw_prim
[GL_POLYGON
+1] = {
329 R200_VF_PRIM_TRIANGLES
,
330 R200_VF_PRIM_TRIANGLES
,
331 R200_VF_PRIM_TRIANGLES
,
332 R200_VF_PRIM_TRIANGLES
,
333 R200_VF_PRIM_TRIANGLES
,
334 R200_VF_PRIM_TRIANGLES
337 static void r200RasterPrimitive( GLcontext
*ctx
, GLuint hwprim
);
338 static void r200RenderPrimitive( GLcontext
*ctx
, GLenum prim
);
339 static void r200ResetLineStipple( GLcontext
*ctx
);
341 /***********************************************************************
342 * Emit primitives as inline vertices *
343 ***********************************************************************/
345 #define HAVE_POINTS 1
347 #define HAVE_LINE_STRIPS 1
348 #define HAVE_TRIANGLES 1
349 #define HAVE_TRI_STRIPS 1
350 #define HAVE_TRI_STRIP_1 0
351 #define HAVE_TRI_FANS 1
353 #define HAVE_QUAD_STRIPS 0
354 #define HAVE_POLYGONS 1
359 #define CTX_ARG r200ContextPtr rmesa
360 #define CTX_ARG2 rmesa
361 #define GET_VERTEX_DWORDS() rmesa->swtcl.vertex_size
362 #define ALLOC_VERTS( n, size ) r200AllocDmaLowVerts( rmesa, n, size * 4 )
364 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
365 const char *r200verts = (char *)rmesa->swtcl.verts;
366 #define VERT(x) (r200Vertex *)(r200verts + ((x) * vertsize * sizeof(int)))
367 #define VERTEX r200Vertex
368 #define DO_DEBUG_VERTS (1 && (R200_DEBUG & DEBUG_VERTS))
371 #define TAG(x) r200_##x
372 #include "tnl_dd/t_dd_triemit.h"
375 /***********************************************************************
376 * Macros for t_dd_tritmp.h to draw basic primitives *
377 ***********************************************************************/
379 #define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d )
380 #define TRI( a, b, c ) r200_triangle( rmesa, a, b, c )
381 #define LINE( a, b ) r200_line( rmesa, a, b )
382 #define POINT( a ) r200_point( rmesa, a )
384 /***********************************************************************
385 * Build render functions from dd templates *
386 ***********************************************************************/
388 #define R200_TWOSIDE_BIT 0x01
389 #define R200_UNFILLED_BIT 0x02
390 #define R200_MAX_TRIFUNC 0x04
394 tnl_points_func points
;
396 tnl_triangle_func triangle
;
398 } rast_tab
[R200_MAX_TRIFUNC
];
401 #define DO_FALLBACK 0
402 #define DO_UNFILLED (IND & R200_UNFILLED_BIT)
403 #define DO_TWOSIDE (IND & R200_TWOSIDE_BIT)
410 #define DO_FULL_QUAD 1
414 #define HAVE_BACK_COLORS 0
415 #define HAVE_HW_FLATSHADE 1
418 #define DEPTH_SCALE 1.0
419 #define UNFILLED_TRI unfilled_tri
420 #define UNFILLED_QUAD unfilled_quad
421 #define VERT_X(_v) _v->v.x
422 #define VERT_Y(_v) _v->v.y
423 #define VERT_Z(_v) _v->v.z
424 #define AREA_IS_CCW( a ) (a < 0)
425 #define GET_VERTEX(e) (rmesa->swtcl.verts + (e*rmesa->swtcl.vertex_size*sizeof(int)))
427 #define VERT_SET_RGBA( v, c ) \
429 r200_color_t *color = (r200_color_t *)&((v)->ui[coloroffset]); \
430 UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]); \
431 UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]); \
432 UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]); \
433 UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]); \
436 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
438 #define VERT_SET_SPEC( v, c ) \
441 r200_color_t *spec = (r200_color_t *)&((v)->ui[specoffset]); \
442 UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]); \
443 UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]); \
444 UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]); \
447 #define VERT_COPY_SPEC( v0, v1 ) \
450 r200_color_t *spec0 = (r200_color_t *)&((v0)->ui[specoffset]); \
451 r200_color_t *spec1 = (r200_color_t *)&((v1)->ui[specoffset]); \
452 spec0->red = spec1->red; \
453 spec0->green = spec1->green; \
454 spec0->blue = spec1->blue; \
458 /* These don't need LE32_TO_CPU() as they used to save and restore
459 * colors which are already in the correct format.
461 #define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
462 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
463 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
464 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
470 #define LOCAL_VARS(n) \
471 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
472 GLuint color[n], spec[n]; \
473 GLuint coloroffset = rmesa->swtcl.coloroffset; \
474 GLuint specoffset = rmesa->swtcl.specoffset; \
475 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
477 /***********************************************************************
478 * Helpers for rendering unfilled primitives *
479 ***********************************************************************/
481 #define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim[x] )
482 #define RENDER_PRIMITIVE rmesa->swtcl.render_primitive
485 #include "tnl_dd/t_dd_unfilled.h"
489 /***********************************************************************
490 * Generate GL render functions *
491 ***********************************************************************/
496 #include "tnl_dd/t_dd_tritmp.h"
498 #define IND (R200_TWOSIDE_BIT)
499 #define TAG(x) x##_twoside
500 #include "tnl_dd/t_dd_tritmp.h"
502 #define IND (R200_UNFILLED_BIT)
503 #define TAG(x) x##_unfilled
504 #include "tnl_dd/t_dd_tritmp.h"
506 #define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT)
507 #define TAG(x) x##_twoside_unfilled
508 #include "tnl_dd/t_dd_tritmp.h"
511 static void init_rast_tab( void )
516 init_twoside_unfilled();
519 /**********************************************************************/
520 /* Render unclipped begin/end objects */
521 /**********************************************************************/
523 #define RENDER_POINTS( start, count ) \
524 for ( ; start < count ; start++) \
525 r200_point( rmesa, VERT(start) )
526 #define RENDER_LINE( v0, v1 ) \
527 r200_line( rmesa, VERT(v0), VERT(v1) )
528 #define RENDER_TRI( v0, v1, v2 ) \
529 r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
530 #define RENDER_QUAD( v0, v1, v2, v3 ) \
531 r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
532 #define INIT(x) do { \
533 r200RenderPrimitive( ctx, x ); \
537 r200ContextPtr rmesa = R200_CONTEXT(ctx); \
538 const GLuint vertsize = rmesa->swtcl.vertex_size; \
539 const char *r200verts = (char *)rmesa->swtcl.verts; \
540 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
541 const GLboolean stipple = ctx->Line.StippleFlag; \
542 (void) elt; (void) stipple;
543 #define RESET_STIPPLE if ( stipple ) r200ResetLineStipple( ctx );
544 #define RESET_OCCLUSION
545 #define PRESERVE_VB_DEFS
547 #define TAG(x) r200_##x##_verts
548 #include "tnl/t_vb_rendertmp.h"
551 #define TAG(x) r200_##x##_elts
552 #define ELT(x) elt[x]
553 #include "tnl/t_vb_rendertmp.h"
557 /**********************************************************************/
558 /* Choose render functions */
559 /**********************************************************************/
561 void r200ChooseRenderState( GLcontext
*ctx
)
563 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
564 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
566 GLuint flags
= ctx
->_TriangleCaps
;
568 if (!rmesa
->TclFallback
|| rmesa
->Fallback
)
571 if (flags
& DD_TRI_LIGHT_TWOSIDE
) index
|= R200_TWOSIDE_BIT
;
572 if (flags
& DD_TRI_UNFILLED
) index
|= R200_UNFILLED_BIT
;
574 if (index
!= rmesa
->swtcl
.RenderIndex
) {
575 tnl
->Driver
.Render
.Points
= rast_tab
[index
].points
;
576 tnl
->Driver
.Render
.Line
= rast_tab
[index
].line
;
577 tnl
->Driver
.Render
.ClippedLine
= rast_tab
[index
].line
;
578 tnl
->Driver
.Render
.Triangle
= rast_tab
[index
].triangle
;
579 tnl
->Driver
.Render
.Quad
= rast_tab
[index
].quad
;
582 tnl
->Driver
.Render
.PrimTabVerts
= r200_render_tab_verts
;
583 tnl
->Driver
.Render
.PrimTabElts
= r200_render_tab_elts
;
584 tnl
->Driver
.Render
.ClippedPolygon
= r200_fast_clipped_poly
;
586 tnl
->Driver
.Render
.PrimTabVerts
= _tnl_render_tab_verts
;
587 tnl
->Driver
.Render
.PrimTabElts
= _tnl_render_tab_elts
;
588 tnl
->Driver
.Render
.ClippedPolygon
= _tnl_RenderClippedPolygon
;
591 rmesa
->swtcl
.RenderIndex
= index
;
596 /**********************************************************************/
597 /* High level hooks for t_vb_render.c */
598 /**********************************************************************/
601 static void r200RasterPrimitive( GLcontext
*ctx
, GLuint hwprim
)
603 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
605 if (rmesa
->swtcl
.hw_primitive
!= hwprim
) {
606 R200_NEWPRIM( rmesa
);
607 rmesa
->swtcl
.hw_primitive
= hwprim
;
611 static void r200RenderPrimitive( GLcontext
*ctx
, GLenum prim
)
613 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
614 rmesa
->swtcl
.render_primitive
= prim
;
615 if (prim
< GL_TRIANGLES
|| !(ctx
->_TriangleCaps
& DD_TRI_UNFILLED
))
616 r200RasterPrimitive( ctx
, reduced_hw_prim
[prim
] );
619 static void r200RenderFinish( GLcontext
*ctx
)
623 static void r200ResetLineStipple( GLcontext
*ctx
)
625 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
626 R200_STATECHANGE( rmesa
, lin
);
630 /**********************************************************************/
631 /* Transition to/from hardware rasterization. */
632 /**********************************************************************/
634 static const char * const fallbackStrings
[] = {
636 "glDrawBuffer(GL_FRONT_AND_BACK)",
637 "glEnable(GL_STENCIL) without hw stencil buffer",
638 "glRenderMode(selection or feedback)",
640 "glBlendFunc(mode != ADD)",
642 "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
646 static const char *getFallbackString(GLuint bit
)
653 return fallbackStrings
[i
];
657 void r200Fallback( GLcontext
*ctx
, GLuint bit
, GLboolean mode
)
659 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
660 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
661 GLuint oldfallback
= rmesa
->Fallback
;
664 rmesa
->Fallback
|= bit
;
665 if (oldfallback
== 0) {
666 R200_FIREVERTICES( rmesa
);
667 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_RASTER
, GL_TRUE
);
668 _swsetup_Wakeup( ctx
);
669 _tnl_need_projected_coords( ctx
, GL_TRUE
);
670 rmesa
->swtcl
.RenderIndex
= ~0;
671 if (R200_DEBUG
& DEBUG_FALLBACKS
) {
672 fprintf(stderr
, "R200 begin rasterization fallback: 0x%x %s\n",
673 bit
, getFallbackString(bit
));
678 rmesa
->Fallback
&= ~bit
;
679 if (oldfallback
== bit
) {
681 _swrast_flush( ctx
);
682 tnl
->Driver
.Render
.Start
= r200RenderStart
;
683 tnl
->Driver
.Render
.PrimitiveNotify
= r200RenderPrimitive
;
684 tnl
->Driver
.Render
.Finish
= r200RenderFinish
;
686 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
687 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
688 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
690 tnl
->Driver
.Render
.ResetLineStipple
= r200ResetLineStipple
;
691 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_RASTER
, GL_FALSE
);
692 if (rmesa
->TclFallback
) {
693 /* These are already done if rmesa->TclFallback goes to
694 * zero above. But not if it doesn't (R200_NO_TCL for
697 r200ChooseVertexState( ctx
);
698 r200ChooseRenderState( ctx
);
700 if (R200_DEBUG
& DEBUG_FALLBACKS
) {
701 fprintf(stderr
, "R200 end rasterization fallback: 0x%x %s\n",
702 bit
, getFallbackString(bit
));
712 * Cope with depth operations by drawing individual pixels as points.
715 * The way the vertex state is set in this routine is hokey. It seems to
716 * work, but it's very hackish. This whole routine is pretty hackish. If
717 * the bitmap is small enough, it seems like it would be faster to copy it
718 * to AGP memory and use it as a non-power-of-two texture (i.e.,
719 * NV_texture_rectangle).
722 r200PointsBitmap( GLcontext
*ctx
, GLint px
, GLint py
,
723 GLsizei width
, GLsizei height
,
724 const struct gl_pixelstore_attrib
*unpack
,
725 const GLubyte
*bitmap
)
727 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
728 const GLfloat
*rc
= ctx
->Current
.RasterColor
;
737 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_BITMAP
, 1 );
739 /* Choose tiny vertex format
742 const GLuint fmt_0
= R200_VTX_XY
| R200_VTX_Z0
| R200_VTX_W0
743 | (R200_VTX_PK_RGBA
<< R200_VTX_COLOR_0_SHIFT
);
744 const GLuint fmt_1
= 0;
745 GLuint vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
746 GLuint vap
= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
];
748 vte
&= ~(R200_VTX_XY_FMT
| R200_VTX_Z_FMT
);
749 vap
&= ~R200_VAP_FORCE_W_TO_ONE
;
751 rmesa
->swtcl
.vertex_size
= 5;
753 if ( (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] != fmt_0
)
754 || (rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] != fmt_1
) ) {
756 R200_STATECHANGE( rmesa
, vtx
);
757 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_0
] = fmt_0
;
758 rmesa
->hw
.vtx
.cmd
[VTX_VTXFMT_1
] = fmt_1
;
761 if (vte
!= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
]) {
762 R200_STATECHANGE( rmesa
, vte
);
763 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = vte
;
766 if (vap
!= rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
]) {
767 R200_STATECHANGE( rmesa
, vap
);
768 rmesa
->hw
.vap
.cmd
[VAP_SE_VAP_CNTL
] = vap
;
772 /* Ready for point primitives:
774 r200RenderPrimitive( ctx
, GL_POINTS
);
776 /* Turn off the hw viewport transformation:
778 R200_STATECHANGE( rmesa
, vte
);
779 orig_vte
= rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
];
780 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] &= ~(R200_VPORT_X_SCALE_ENA
|
781 R200_VPORT_Y_SCALE_ENA
|
782 R200_VPORT_Z_SCALE_ENA
|
783 R200_VPORT_X_OFFSET_ENA
|
784 R200_VPORT_Y_OFFSET_ENA
|
785 R200_VPORT_Z_OFFSET_ENA
);
787 /* Turn off other stuff: Stipple?, texture?, blending?, etc.
791 /* Populate the vertex
793 * Incorporate FOG into RGBA
795 if (ctx
->Fog
.Enabled
) {
796 const GLfloat
*fc
= ctx
->Fog
.Color
;
800 if (ctx
->Fog
.FogCoordinateSource
== GL_FOG_COORDINATE_EXT
)
801 f
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.Attrib
[VERT_ATTRIB_FOG
][0]);
803 f
= _swrast_z_to_fogfactor(ctx
, ctx
->Current
.RasterDistance
);
805 color
[0] = f
* rc
[0] + (1.F
- f
) * fc
[0];
806 color
[1] = f
* rc
[1] + (1.F
- f
) * fc
[1];
807 color
[2] = f
* rc
[2] + (1.F
- f
) * fc
[2];
810 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.red
, color
[0]);
811 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.green
, color
[1]);
812 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.blue
, color
[2]);
813 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.alpha
, color
[3]);
816 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.red
, rc
[0]);
817 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.green
, rc
[1]);
818 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.blue
, rc
[2]);
819 UNCLAMPED_FLOAT_TO_CHAN(vert
.tv
.color
.alpha
, rc
[3]);
823 vert
.tv
.z
= ctx
->Current
.RasterPos
[2];
826 /* Update window height
828 LOCK_HARDWARE( rmesa
);
829 UNLOCK_HARDWARE( rmesa
);
830 h
= rmesa
->dri
.drawable
->h
+ rmesa
->dri
.drawable
->y
;
831 px
+= rmesa
->dri
.drawable
->x
;
833 /* Clipping handled by existing mechansims in r200_ioctl.c?
835 for (row
=0; row
<height
; row
++) {
836 const GLubyte
*src
= (const GLubyte
*)
837 _mesa_image_address( unpack
, bitmap
, width
, height
,
838 GL_COLOR_INDEX
, GL_BITMAP
, 0, row
, 0 );
840 if (unpack
->LsbFirst
) {
842 GLubyte mask
= 1U << (unpack
->SkipPixels
& 0x7);
843 for (col
=0; col
<width
; col
++) {
846 vert
.tv
.y
= h
- (py
+row
) - 1;
847 r200_point( rmesa
, &vert
);
850 mask
= ((mask
<< 1) & 0xff) | (mask
>> 7);
853 /* get ready for next row */
859 GLubyte mask
= 128U >> (unpack
->SkipPixels
& 0x7);
860 for (col
=0; col
<width
; col
++) {
863 vert
.tv
.y
= h
- (py
+row
) - 1;
864 r200_point( rmesa
, &vert
);
867 mask
= ((mask
<< 7) & 0xff) | (mask
>> 1);
869 /* get ready for next row */
875 /* Fire outstanding vertices, restore state
877 R200_STATECHANGE( rmesa
, vte
);
878 rmesa
->hw
.vte
.cmd
[VTE_SE_VTE_CNTL
] = orig_vte
;
882 TCL_FALLBACK( ctx
, R200_TCL_FALLBACK_BITMAP
, 0 );
884 /* Need to restore vertexformat?
886 if (rmesa
->TclFallback
)
887 r200ChooseVertexState( ctx
);
891 void r200FlushVertices( GLcontext
*ctx
, GLuint flags
)
893 _tnl_FlushVertices( ctx
, flags
);
895 if (flags
& FLUSH_STORED_VERTICES
)
896 R200_NEWPRIM( R200_CONTEXT( ctx
) );
899 /**********************************************************************/
900 /* Initialization. */
901 /**********************************************************************/
903 void r200InitSwtcl( GLcontext
*ctx
)
905 TNLcontext
*tnl
= TNL_CONTEXT(ctx
);
906 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
907 static int firsttime
= 1;
914 tnl
->Driver
.Render
.Start
= r200RenderStart
;
915 tnl
->Driver
.Render
.Finish
= r200RenderFinish
;
916 tnl
->Driver
.Render
.PrimitiveNotify
= r200RenderPrimitive
;
917 tnl
->Driver
.Render
.ResetLineStipple
= r200ResetLineStipple
;
918 tnl
->Driver
.Render
.BuildVertices
= _tnl_build_vertices
;
919 tnl
->Driver
.Render
.CopyPV
= _tnl_copy_pv
;
920 tnl
->Driver
.Render
.Interp
= _tnl_interp
;
922 /* FIXME: what are these numbers? */
923 _tnl_init_vertices( ctx
, ctx
->Const
.MaxArrayLockSize
+ 12,
924 36 * sizeof(GLfloat
) );
926 rmesa
->swtcl
.verts
= (GLubyte
*)tnl
->clipspace
.vertex_buf
;
927 rmesa
->swtcl
.RenderIndex
= ~0;
928 rmesa
->swtcl
.render_primitive
= GL_TRIANGLES
;
929 rmesa
->swtcl
.hw_primitive
= 0;
933 void r200DestroySwtcl( GLcontext
*ctx
)
935 r200ContextPtr rmesa
= R200_CONTEXT(ctx
);
937 if (rmesa
->swtcl
.indexed_verts
.buf
)
938 r200ReleaseDmaRegion( rmesa
, &rmesa
->swtcl
.indexed_verts
, __FUNCTION__
);