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