1/*
2Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
3
4The Weather Channel (TM) funded Tungsten Graphics to develop the
5initial release of the Radeon 8500 driver under the XFree86 license.
6This notice must be preserved.
7
8Permission is hereby granted, free of charge, to any person obtaining
9a copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sublicense, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice (including the
17next paragraph) shall be included in all copies or substantial
18portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28**************************************************************************/
29
30/*
31 * Authors:
32 *   Keith Whitwell <keithw@vmware.com>
33 */
34
35#include "main/glheader.h"
36#include "main/mtypes.h"
37#include "main/enums.h"
38#include "main/image.h"
39
40#include "main/macros.h"
41#include "main/state.h"
42
43#include "swrast/s_context.h"
44#include "swrast/s_fog.h"
45#include "swrast_setup/swrast_setup.h"
46#include "tnl/tnl.h"
47#include "tnl/t_context.h"
48#include "tnl/t_pipeline.h"
49
50#include "r200_context.h"
51#include "r200_ioctl.h"
52#include "r200_state.h"
53#include "r200_swtcl.h"
54#include "r200_tcl.h"
55
56
57/***********************************************************************
58 *                         Initialization
59 ***********************************************************************/
60
61#define EMIT_ATTR( ATTR, STYLE, F0 )					\
62do {									\
63   rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = (ATTR);	\
64   rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = (STYLE);	\
65   rmesa->radeon.swtcl.vertex_attr_count++;					\
66   fmt_0 |= F0;								\
67} while (0)
68
69#define EMIT_PAD( N )							\
70do {									\
71   rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = 0;		\
72   rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = EMIT_PAD;	\
73   rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].offset = (N);		\
74   rmesa->radeon.swtcl.vertex_attr_count++;					\
75} while (0)
76
77static void r200SetVertexFormat( struct gl_context *ctx )
78{
79   r200ContextPtr rmesa = R200_CONTEXT( ctx );
80   TNLcontext *tnl = TNL_CONTEXT(ctx);
81   struct vertex_buffer *VB = &tnl->vb;
82   GLbitfield64 index_bitset = tnl->render_inputs_bitset;
83   int fmt_0 = 0;
84   int fmt_1 = 0;
85   int offset = 0;
86
87   /* Important:
88    */
89   if ( VB->NdcPtr != NULL ) {
90      VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
91   }
92   else {
93      VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr;
94   }
95
96   assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL );
97   rmesa->radeon.swtcl.vertex_attr_count = 0;
98
99   /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
100    * build up a hardware vertex.
101    */
102   if ( !rmesa->swtcl.needproj ||
103        (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) ) {
104      /* need w coord for projected textures */
105      EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 );
106      offset = 4;
107   }
108   else {
109      EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F, R200_VTX_XY | R200_VTX_Z0 );
110      offset = 3;
111   }
112
113   if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE)) {
114      EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, R200_VTX_POINT_SIZE );
115      offset += 1;
116   }
117
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) );
121#else
122   EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ABGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
123#endif
124   offset += 1;
125
126   rmesa->swtcl.specoffset = 0;
127   if (index_bitset &
128       (BITFIELD64_BIT(_TNL_ATTRIB_COLOR1) | BITFIELD64_BIT(_TNL_ATTRIB_FOG))) {
129
130#if MESA_LITTLE_ENDIAN
131      if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) {
132	 rmesa->swtcl.specoffset = offset;
133	 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
134      }
135      else {
136	 EMIT_PAD( 3 );
137      }
138
139      if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) {
140	 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
141      }
142      else {
143	 EMIT_PAD( 1 );
144      }
145#else
146      if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) {
147	 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
148      }
149      else {
150	 EMIT_PAD( 1 );
151      }
152
153      if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) {
154	 rmesa->swtcl.specoffset = offset;
155	 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
156      }
157      else {
158	 EMIT_PAD( 3 );
159      }
160#endif
161   }
162
163   if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) {
164      int i;
165
166      for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
167	 if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) {
168	    GLuint sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size;
169
170	    fmt_1 |= sz << (3 * i);
171	    EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_1F + sz - 1, 0 );
172	 }
173      }
174   }
175
176   if ( (rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK)
177      != R200_FOG_USE_SPEC_ALPHA ) {
178      R200_STATECHANGE( rmesa, ctx );
179      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK;
180      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_SPEC_ALPHA;
181   }
182
183   if (rmesa->radeon.tnl_index_bitset != index_bitset ||
184	(rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) ||
185	(rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
186      R200_NEWPRIM(rmesa);
187      R200_STATECHANGE( rmesa, vtx );
188      rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
189      rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
190
191      rmesa->radeon.swtcl.vertex_size =
192	  _tnl_install_attrs( ctx,
193			      rmesa->radeon.swtcl.vertex_attrs,
194			      rmesa->radeon.swtcl.vertex_attr_count,
195			      NULL, 0 );
196      rmesa->radeon.swtcl.vertex_size /= 4;
197      rmesa->radeon.tnl_index_bitset = index_bitset;
198   }
199}
200
201static void r200_predict_emit_size( r200ContextPtr rmesa )
202{
203   if (RADEON_DEBUG & RADEON_VERTS)
204      fprintf(stderr, "%s\n", __func__);
205   const int vertex_array_size = 7;
206   const int prim_size = 3;
207   if (!rmesa->radeon.swtcl.emit_prediction) {
208      const int state_size = radeonCountStateEmitSize(&rmesa->radeon);
209      if (rcommonEnsureCmdBufSpace(&rmesa->radeon,
210	       state_size +
211	       vertex_array_size + prim_size,
212	       __func__))
213	 rmesa->radeon.swtcl.emit_prediction = radeonCountStateEmitSize(&rmesa->radeon);
214      else
215	 rmesa->radeon.swtcl.emit_prediction = state_size;
216      rmesa->radeon.swtcl.emit_prediction += vertex_array_size + prim_size
217	 + rmesa->radeon.cmdbuf.cs->cdw;
218   }
219}
220
221
222static void r200RenderStart( struct gl_context *ctx )
223{
224   r200SetVertexFormat( ctx );
225   if (RADEON_DEBUG & RADEON_VERTS)
226      fprintf(stderr, "%s\n", __func__);
227}
228
229
230/**
231 * Set vertex state for SW TCL.  The primary purpose of this function is to
232 * determine in advance whether or not the hardware can / should do the
233 * projection divide or Mesa should do it.
234 */
235void r200ChooseVertexState( struct gl_context *ctx )
236{
237   r200ContextPtr rmesa = R200_CONTEXT( ctx );
238   TNLcontext *tnl = TNL_CONTEXT(ctx);
239   GLuint vte;
240   GLuint vap;
241   GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
242                         ctx->Polygon.BackMode != GL_FILL);
243   GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
244
245   /* We must ensure that we don't do _tnl_need_projected_coords while in a
246    * rasterization fallback.  As this function will be called again when we
247    * leave a rasterization fallback, we can just skip it for now.
248    */
249   if (rmesa->radeon.Fallback != 0)
250      return;
251
252   vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
253   vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
254
255   /* HW perspective divide is a win, but tiny vertex formats are a
256    * bigger one.
257    */
258   if ((0 == (tnl->render_inputs_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)))
259       || twosided
260       || unfilled) {
261      rmesa->swtcl.needproj = GL_TRUE;
262      vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT;
263      vte &= ~R200_VTX_W0_FMT;
264      if (tnl->render_inputs_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) {
265	 vap &= ~R200_VAP_FORCE_W_TO_ONE;
266      }
267      else {
268	 vap |= R200_VAP_FORCE_W_TO_ONE;
269      }
270   }
271   else {
272      rmesa->swtcl.needproj = GL_FALSE;
273      vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
274      vte |= R200_VTX_W0_FMT;
275      vap &= ~R200_VAP_FORCE_W_TO_ONE;
276   }
277
278   _tnl_need_projected_coords( ctx, rmesa->swtcl.needproj );
279
280   if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
281      R200_STATECHANGE( rmesa, vte );
282      rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
283   }
284
285   if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
286      R200_STATECHANGE( rmesa, vap );
287      rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
288   }
289}
290
291void r200_swtcl_flush(struct gl_context *ctx, uint32_t current_offset)
292{
293   r200ContextPtr rmesa = R200_CONTEXT(ctx);
294   if (RADEON_DEBUG & RADEON_VERTS)
295      fprintf(stderr, "%s\n", __func__);
296
297
298   radeonEmitState(&rmesa->radeon);
299   r200EmitVertexAOS( rmesa,
300		      rmesa->radeon.swtcl.vertex_size,
301		      rmesa->radeon.swtcl.bo,
302		      current_offset);
303
304
305   r200EmitVbufPrim( rmesa,
306		     rmesa->radeon.swtcl.hw_primitive,
307		     rmesa->radeon.swtcl.numverts);
308   if ( rmesa->radeon.swtcl.emit_prediction < rmesa->radeon.cmdbuf.cs->cdw )
309      WARN_ONCE("Rendering was %d commands larger than predicted size."
310	    " We might overflow  command buffer.\n",
311	    rmesa->radeon.cmdbuf.cs->cdw - rmesa->radeon.swtcl.emit_prediction );
312
313   rmesa->radeon.swtcl.emit_prediction = 0;
314
315}
316
317/**************************************************************************/
318
319
320static inline GLuint reduced_hw_prim( struct gl_context *ctx, GLuint prim)
321{
322   switch (prim) {
323   case GL_POINTS:
324      return ((!ctx->Point.SmoothFlag) ?
325	 R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS);
326   case GL_LINES:
327   FALLTHROUGH;
328   case GL_LINE_LOOP:
329   FALLTHROUGH;
330   case GL_LINE_STRIP:
331      return R200_VF_PRIM_LINES;
332   default:
333   /* all others reduced to triangles */
334      return R200_VF_PRIM_TRIANGLES;
335   }
336}
337
338
339static void r200RasterPrimitive( struct gl_context *ctx, GLuint hwprim );
340static void r200RenderPrimitive( struct gl_context *ctx, GLenum prim );
341static void r200ResetLineStipple( struct gl_context *ctx );
342
343/***********************************************************************
344 *                    Emit primitives as inline vertices               *
345 ***********************************************************************/
346
347#define HAVE_POINTS      1
348#define HAVE_LINES       1
349#define HAVE_LINE_STRIPS 1
350#define HAVE_TRIANGLES   1
351#define HAVE_TRI_STRIPS  1
352#define HAVE_TRI_FANS    1
353#define HAVE_QUADS       0
354#define HAVE_QUAD_STRIPS 0
355#define HAVE_POLYGONS    1
356#define HAVE_ELTS        0
357
358static void* r200_alloc_verts( r200ContextPtr rmesa, GLuint n, GLuint size)
359{
360   void *rv;
361   do {
362      r200_predict_emit_size( rmesa );
363      rv = rcommonAllocDmaLowVerts( &rmesa->radeon, n, size * 4 );
364   } while(!rv);
365   return rv;
366}
367
368#undef LOCAL_VARS
369#undef ALLOC_VERTS
370#define CTX_ARG r200ContextPtr rmesa
371#define GET_VERTEX_DWORDS() rmesa->radeon.swtcl.vertex_size
372#define ALLOC_VERTS( n, size ) r200_alloc_verts(rmesa, n, size)
373#define LOCAL_VARS						\
374   r200ContextPtr rmesa = R200_CONTEXT(ctx);		\
375   const char *r200verts = (char *)rmesa->radeon.swtcl.verts;
376#define VERT(x) (radeonVertex *)(r200verts + ((x) * vertsize * sizeof(int)))
377#define VERTEX radeonVertex
378#define DO_DEBUG_VERTS (1 && (R200_DEBUG & RADEON_VERTS))
379
380#undef TAG
381#define TAG(x) r200_##x
382#include "tnl_dd/t_dd_triemit.h"
383
384
385/***********************************************************************
386 *          Macros for t_dd_tritmp.h to draw basic primitives          *
387 ***********************************************************************/
388
389#define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d )
390#define TRI( a, b, c )     r200_triangle( rmesa, a, b, c )
391#define LINE( a, b )       r200_line( rmesa, a, b )
392#define POINT( a )         r200_point( rmesa, a )
393
394/***********************************************************************
395 *              Build render functions from dd templates               *
396 ***********************************************************************/
397
398#define R200_TWOSIDE_BIT	0x01
399#define R200_UNFILLED_BIT	0x02
400#define R200_MAX_TRIFUNC	0x04
401
402
403static struct {
404   tnl_points_func	        points;
405   tnl_line_func		line;
406   tnl_triangle_func	triangle;
407   tnl_quad_func		quad;
408} rast_tab[R200_MAX_TRIFUNC];
409
410
411#define DO_FALLBACK  0
412#define DO_UNFILLED ((IND & R200_UNFILLED_BIT) != 0)
413#define DO_TWOSIDE  ((IND & R200_TWOSIDE_BIT) != 0)
414#define DO_FLAT      0
415#define DO_OFFSET     0
416#define DO_TRI       1
417#define DO_QUAD      1
418#define DO_LINE      1
419#define DO_POINTS    1
420#define DO_FULL_QUAD 1
421
422#define HAVE_SPEC   1
423#define HAVE_BACK_COLORS  0
424#define HAVE_HW_FLATSHADE 1
425#define TAB rast_tab
426
427#define DEPTH_SCALE 1.0
428#define UNFILLED_TRI unfilled_tri
429#define UNFILLED_QUAD unfilled_quad
430#define VERT_X(_v) _v->v.x
431#define VERT_Y(_v) _v->v.y
432#define VERT_Z(_v) _v->v.z
433#define AREA_IS_CCW( a ) (a < 0)
434#define GET_VERTEX(e) (rmesa->radeon.swtcl.verts + (e*rmesa->radeon.swtcl.vertex_size*sizeof(int)))
435
436#define VERT_SET_RGBA( v, c )  					\
437do {								\
438   radeon_color_t *color = (radeon_color_t *)&((v)->ui[coloroffset]);	\
439   UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]);		\
440   UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]);		\
441   UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]);		\
442   UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]);		\
443} while (0)
444
445#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
446
447#define VERT_SET_SPEC( v, c )					\
448do {								\
449   if (specoffset) {						\
450      radeon_color_t *spec = (radeon_color_t *)&((v)->ui[specoffset]);	\
451      UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]);	\
452      UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]);	\
453      UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]);	\
454   }								\
455} while (0)
456#define VERT_COPY_SPEC( v0, v1 )			\
457do {							\
458   if (specoffset) {					\
459      radeon_color_t *spec0 = (radeon_color_t *)&((v0)->ui[specoffset]);	\
460      radeon_color_t *spec1 = (radeon_color_t *)&((v1)->ui[specoffset]);	\
461      spec0->red   = spec1->red;	\
462      spec0->green = spec1->green;	\
463      spec0->blue  = spec1->blue; 	\
464   }							\
465} while (0)
466
467/* These don't need LE32_TO_CPU() as they used to save and restore
468 * colors which are already in the correct format.
469 */
470#define VERT_SAVE_RGBA( idx )    color[idx] = v[idx]->ui[coloroffset]
471#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
472#define VERT_SAVE_SPEC( idx )    if (specoffset) spec[idx] = v[idx]->ui[specoffset]
473#define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
474
475#undef LOCAL_VARS
476#undef TAG
477#undef INIT
478
479#define LOCAL_VARS(n)							\
480   r200ContextPtr rmesa = R200_CONTEXT(ctx);			\
481   GLuint color[n] = {0}, spec[n] = {0};						\
482   GLuint coloroffset = rmesa->swtcl.coloroffset;	\
483   GLuint specoffset = rmesa->swtcl.specoffset;			\
484   (void) color; (void) spec; (void) coloroffset; (void) specoffset;
485
486/***********************************************************************
487 *                Helpers for rendering unfilled primitives            *
488 ***********************************************************************/
489
490#define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim(ctx, x) )
491#define RENDER_PRIMITIVE rmesa->radeon.swtcl.render_primitive
492#undef TAG
493#define TAG(x) x
494#include "tnl_dd/t_dd_unfilled.h"
495#undef IND
496
497
498/***********************************************************************
499 *                      Generate GL render functions                   *
500 ***********************************************************************/
501
502
503#define IND (0)
504#define TAG(x) x
505#include "tnl_dd/t_dd_tritmp.h"
506
507#define IND (R200_TWOSIDE_BIT)
508#define TAG(x) x##_twoside
509#include "tnl_dd/t_dd_tritmp.h"
510
511#define IND (R200_UNFILLED_BIT)
512#define TAG(x) x##_unfilled
513#include "tnl_dd/t_dd_tritmp.h"
514
515#define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT)
516#define TAG(x) x##_twoside_unfilled
517#include "tnl_dd/t_dd_tritmp.h"
518
519
520static void init_rast_tab( void )
521{
522   init();
523   init_twoside();
524   init_unfilled();
525   init_twoside_unfilled();
526}
527
528/**********************************************************************/
529/*               Render unclipped begin/end objects                   */
530/**********************************************************************/
531
532#define RENDER_POINTS( start, count )		\
533   for ( ; start < count ; start++)		\
534      r200_point( rmesa, VERT(start) )
535#define RENDER_LINE( v0, v1 ) \
536   r200_line( rmesa, VERT(v0), VERT(v1) )
537#define RENDER_TRI( v0, v1, v2 )  \
538   r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
539#define RENDER_QUAD( v0, v1, v2, v3 ) \
540   r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
541#define INIT(x) do {					\
542   r200RenderPrimitive( ctx, x );			\
543} while (0)
544#undef LOCAL_VARS
545#define LOCAL_VARS						\
546   r200ContextPtr rmesa = R200_CONTEXT(ctx);		\
547   const GLuint vertsize = rmesa->radeon.swtcl.vertex_size;		\
548   const char *r200verts = (char *)rmesa->radeon.swtcl.verts;		\
549   const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;	\
550   const GLboolean stipple = ctx->Line.StippleFlag;		\
551   (void) elt; (void) stipple;
552#define RESET_STIPPLE	if ( stipple ) r200ResetLineStipple( ctx );
553#define RESET_OCCLUSION
554#define PRESERVE_VB_DEFS
555#define ELT(x) (x)
556#define TAG(x) r200_##x##_verts
557#include "tnl/t_vb_rendertmp.h"
558#undef ELT
559#undef TAG
560#define TAG(x) r200_##x##_elts
561#define ELT(x) elt[x]
562#include "tnl/t_vb_rendertmp.h"
563
564
565
566/**********************************************************************/
567/*                    Choose render functions                         */
568/**********************************************************************/
569
570void r200ChooseRenderState( struct gl_context *ctx )
571{
572   TNLcontext *tnl = TNL_CONTEXT(ctx);
573   r200ContextPtr rmesa = R200_CONTEXT(ctx);
574   GLuint index = 0;
575   GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
576                         ctx->Polygon.BackMode != GL_FILL);
577   GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
578
579   if (!rmesa->radeon.TclFallback || rmesa->radeon.Fallback)
580      return;
581
582   if (twosided)
583      index |= R200_TWOSIDE_BIT;
584   if (unfilled)
585      index |= R200_UNFILLED_BIT;
586
587   if (index != rmesa->radeon.swtcl.RenderIndex) {
588      tnl->Driver.Render.Points = rast_tab[index].points;
589      tnl->Driver.Render.Line = rast_tab[index].line;
590      tnl->Driver.Render.ClippedLine = rast_tab[index].line;
591      tnl->Driver.Render.Triangle = rast_tab[index].triangle;
592      tnl->Driver.Render.Quad = rast_tab[index].quad;
593
594      if (index == 0) {
595	 tnl->Driver.Render.PrimTabVerts = r200_render_tab_verts;
596	 tnl->Driver.Render.PrimTabElts = r200_render_tab_elts;
597	 tnl->Driver.Render.ClippedPolygon = r200_fast_clipped_poly;
598      } else {
599	 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
600	 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
601	 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
602      }
603
604      rmesa->radeon.swtcl.RenderIndex = index;
605   }
606}
607
608
609/**********************************************************************/
610/*                 High level hooks for t_vb_render.c                 */
611/**********************************************************************/
612
613
614static void r200RasterPrimitive( struct gl_context *ctx, GLuint hwprim )
615{
616   r200ContextPtr rmesa = R200_CONTEXT(ctx);
617
618   radeon_prepare_render(&rmesa->radeon);
619   if (rmesa->radeon.NewGLState)
620      r200ValidateState( ctx );
621
622
623   if (rmesa->radeon.swtcl.hw_primitive != hwprim) {
624      /* need to disable perspective-correct texturing for point sprites */
625      if ((hwprim & 0xf) == R200_VF_PRIM_POINT_SPRITES && ctx->Point.PointSprite) {
626	 if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) {
627	    R200_STATECHANGE( rmesa, set );
628	    rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE;
629	 }
630      }
631      else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) {
632	 R200_STATECHANGE( rmesa, set );
633	 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE;
634      }
635      R200_NEWPRIM( rmesa );
636      rmesa->radeon.swtcl.hw_primitive = hwprim;
637   }
638}
639
640static void r200RenderPrimitive( struct gl_context *ctx, GLenum prim )
641{
642   r200ContextPtr rmesa = R200_CONTEXT(ctx);
643   GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
644                         ctx->Polygon.BackMode != GL_FILL);
645
646   rmesa->radeon.swtcl.render_primitive = prim;
647   if (prim < GL_TRIANGLES || !unfilled)
648      r200RasterPrimitive( ctx, reduced_hw_prim(ctx, prim) );
649}
650
651static void r200RenderFinish( struct gl_context *ctx )
652{
653}
654
655static void r200ResetLineStipple( struct gl_context *ctx )
656{
657   r200ContextPtr rmesa = R200_CONTEXT(ctx);
658   R200_STATECHANGE( rmesa, lin );
659}
660
661
662/**********************************************************************/
663/*           Transition to/from hardware rasterization.               */
664/**********************************************************************/
665
666static const char * const fallbackStrings[] = {
667   "Texture mode",
668   "glDrawBuffer(GL_FRONT_AND_BACK)",
669   "glEnable(GL_STENCIL) without hw stencil buffer",
670   "glRenderMode(selection or feedback)",
671   "R200_NO_RAST",
672   "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
673};
674
675
676static const char *getFallbackString(GLuint bit)
677{
678   int i = 0;
679   while (bit > 1) {
680      i++;
681      bit >>= 1;
682   }
683   return fallbackStrings[i];
684}
685
686
687void r200Fallback( struct gl_context *ctx, GLuint bit, GLboolean mode )
688{
689   r200ContextPtr rmesa = R200_CONTEXT(ctx);
690   TNLcontext *tnl = TNL_CONTEXT(ctx);
691   GLuint oldfallback = rmesa->radeon.Fallback;
692
693   if (mode) {
694      rmesa->radeon.Fallback |= bit;
695      if (oldfallback == 0) {
696	 radeon_firevertices(&rmesa->radeon);
697	 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_TRUE );
698	 _swsetup_Wakeup( ctx );
699	 rmesa->radeon.swtcl.RenderIndex = ~0;
700         if (R200_DEBUG & RADEON_FALLBACKS) {
701            fprintf(stderr, "R200 begin rasterization fallback: 0x%x %s\n",
702                    bit, getFallbackString(bit));
703         }
704      }
705   }
706   else {
707      rmesa->radeon.Fallback &= ~bit;
708      if (oldfallback == bit) {
709
710	 _swrast_flush( ctx );
711	 tnl->Driver.Render.Start = r200RenderStart;
712	 tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
713	 tnl->Driver.Render.Finish = r200RenderFinish;
714
715	 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
716	 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
717	 tnl->Driver.Render.Interp = _tnl_interp;
718
719	 tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
720	 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_FALSE );
721	 if (rmesa->radeon.TclFallback) {
722	    /* These are already done if rmesa->radeon.TclFallback goes to
723	     * zero above. But not if it doesn't (R200_NO_TCL for
724	     * example?)
725	     */
726	    _tnl_invalidate_vertex_state( ctx, ~0 );
727	    _tnl_invalidate_vertices( ctx, ~0 );
728	    rmesa->radeon.tnl_index_bitset = 0;
729	    r200ChooseVertexState( ctx );
730	    r200ChooseRenderState( ctx );
731	 }
732         if (R200_DEBUG & RADEON_FALLBACKS) {
733            fprintf(stderr, "R200 end rasterization fallback: 0x%x %s\n",
734                    bit, getFallbackString(bit));
735         }
736      }
737   }
738}
739
740
741
742
743/**
744 * Cope with depth operations by drawing individual pixels as points.
745 *
746 * \todo
747 * The way the vertex state is set in this routine is hokey.  It seems to
748 * work, but it's very hackish.  This whole routine is pretty hackish.  If
749 * the bitmap is small enough, it seems like it would be faster to copy it
750 * to AGP memory and use it as a non-power-of-two texture (i.e.,
751 * NV_texture_rectangle).
752 */
753void
754r200PointsBitmap( struct gl_context *ctx, GLint px, GLint py,
755		  GLsizei width, GLsizei height,
756		  const struct gl_pixelstore_attrib *unpack,
757		  const GLubyte *bitmap )
758{
759   r200ContextPtr rmesa = R200_CONTEXT(ctx);
760   const GLfloat *rc = ctx->Current.RasterColor;
761   GLint row, col;
762   radeonVertex vert;
763   GLuint orig_vte;
764   GLuint h;
765
766
767   /* Turn off tcl.
768    */
769   TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 1 );
770
771   /* Choose tiny vertex format
772    */
773   {
774      const GLuint fmt_0 = R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0
775	  | (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT);
776      const GLuint fmt_1 = 0;
777      GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
778      GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
779
780      vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
781      vte |= R200_VTX_W0_FMT;
782      vap &= ~R200_VAP_FORCE_W_TO_ONE;
783
784      rmesa->radeon.swtcl.vertex_size = 5;
785
786      if ( (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0)
787	   || (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
788	 R200_NEWPRIM(rmesa);
789	 R200_STATECHANGE( rmesa, vtx );
790	 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
791	 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
792      }
793
794      if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
795	 R200_STATECHANGE( rmesa, vte );
796	 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
797      }
798
799      if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
800	 R200_STATECHANGE( rmesa, vap );
801	 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
802      }
803   }
804
805   /* Ready for point primitives:
806    */
807   r200RenderPrimitive( ctx, GL_POINTS );
808
809   /* Turn off the hw viewport transformation:
810    */
811   R200_STATECHANGE( rmesa, vte );
812   orig_vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
813   rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VPORT_X_SCALE_ENA |
814					   R200_VPORT_Y_SCALE_ENA |
815					   R200_VPORT_Z_SCALE_ENA |
816					   R200_VPORT_X_OFFSET_ENA |
817					   R200_VPORT_Y_OFFSET_ENA |
818					   R200_VPORT_Z_OFFSET_ENA);
819
820   /* Turn off other stuff:  Stipple?, texture?, blending?, etc.
821    */
822
823
824   /* Populate the vertex
825    *
826    * Incorporate FOG into RGBA
827    */
828   if (ctx->Fog.Enabled) {
829      const GLfloat *fc = ctx->Fog.Color;
830      GLfloat color[4];
831      GLfloat f;
832
833      if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
834         f = _swrast_z_to_fogfactor(ctx, ctx->Current.Attrib[VERT_ATTRIB_FOG][0]);
835      else
836         f = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
837
838      color[0] = f * rc[0] + (1.F - f) * fc[0];
839      color[1] = f * rc[1] + (1.F - f) * fc[1];
840      color[2] = f * rc[2] + (1.F - f) * fc[2];
841      color[3] = rc[3];
842
843      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red,   color[0]);
844      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, color[1]);
845      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue,  color[2]);
846      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, color[3]);
847   }
848   else {
849      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red,   rc[0]);
850      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, rc[1]);
851      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue,  rc[2]);
852      UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, rc[3]);
853   }
854
855
856   vert.tv.z = ctx->Current.RasterPos[2];
857
858
859   /* Update window height
860    */
861   h = radeon_get_drawable(&rmesa->radeon)->h;
862
863   /* Clipping handled by existing mechansims in r200_ioctl.c?
864    */
865   for (row=0; row<height; row++) {
866      const GLubyte *src = (const GLubyte *)
867	 _mesa_image_address2d(unpack, bitmap, width, height,
868                               GL_COLOR_INDEX, GL_BITMAP, row, 0 );
869
870      if (unpack->LsbFirst) {
871         /* Lsb first */
872         GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
873         for (col=0; col<width; col++) {
874            if (*src & mask) {
875	       vert.tv.x = px+col;
876	       vert.tv.y = h - (py+row) - 1;
877	       r200_point( rmesa, &vert );
878            }
879	    src += (mask >> 7);
880	    mask = ((mask << 1) & 0xff) | (mask >> 7);
881         }
882
883         /* get ready for next row */
884         if (mask != 1)
885            src++;
886      }
887      else {
888         /* Msb first */
889         GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
890         for (col=0; col<width; col++) {
891            if (*src & mask) {
892	       vert.tv.x = px+col;
893	       vert.tv.y = h - (py+row) - 1;
894	       r200_point( rmesa, &vert );
895            }
896	    src += mask & 1;
897	    mask = ((mask << 7) & 0xff) | (mask >> 1);
898         }
899         /* get ready for next row */
900         if (mask != 128)
901            src++;
902      }
903   }
904
905   /* Fire outstanding vertices, restore state
906    */
907   R200_STATECHANGE( rmesa, vte );
908   rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = orig_vte;
909
910   /* Unfallback
911    */
912   TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 0 );
913
914   /* Need to restore vertexformat?
915    */
916   if (rmesa->radeon.TclFallback)
917      r200ChooseVertexState( ctx );
918}
919
920
921
922/**********************************************************************/
923/*                            Initialization.                         */
924/**********************************************************************/
925
926void r200InitSwtcl( struct gl_context *ctx )
927{
928   TNLcontext *tnl = TNL_CONTEXT(ctx);
929   r200ContextPtr rmesa = R200_CONTEXT(ctx);
930   static int firsttime = 1;
931
932   if (firsttime) {
933      init_rast_tab();
934      firsttime = 0;
935   }
936   rmesa->radeon.swtcl.emit_prediction = 0;
937
938   tnl->Driver.Render.Start = r200RenderStart;
939   tnl->Driver.Render.Finish = r200RenderFinish;
940   tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
941   tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
942   tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
943   tnl->Driver.Render.CopyPV = _tnl_copy_pv;
944   tnl->Driver.Render.Interp = _tnl_interp;
945
946   /* FIXME: what are these numbers? */
947   _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
948		       36 * sizeof(GLfloat) );
949
950   rmesa->radeon.swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
951   rmesa->radeon.swtcl.RenderIndex = ~0;
952   rmesa->radeon.swtcl.render_primitive = GL_TRIANGLES;
953   rmesa->radeon.swtcl.hw_primitive = 0;
954}
955
956