OSDN Git Service

d43e14581e931faa03cc3eb30bd398731e5ef78b
[android-x86/external-mesa.git] / src / mesa / drivers / dri / r200 / r200_tcl.c
1 /*
2 Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
3
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28 **************************************************************************/
29
30 /*
31  * Authors:
32  *   Keith Whitwell <keith@tungstengraphics.com>
33  */
34
35 #include "main/glheader.h"
36 #include "main/imports.h"
37 #include "main/mtypes.h"
38 #include "main/enums.h"
39 #include "main/colormac.h"
40 #include "main/light.h"
41
42 #include "vbo/vbo.h"
43 #include "tnl/tnl.h"
44 #include "tnl/t_pipeline.h"
45
46 #include "r200_context.h"
47 #include "r200_state.h"
48 #include "r200_ioctl.h"
49 #include "r200_tcl.h"
50 #include "r200_swtcl.h"
51 #include "r200_maos.h"
52
53 #include "radeon_common_context.h"
54
55
56
57 #define HAVE_POINTS      1
58 #define HAVE_LINES       1
59 #define HAVE_LINE_LOOP   0
60 #define HAVE_LINE_STRIPS 1
61 #define HAVE_TRIANGLES   1
62 #define HAVE_TRI_STRIPS  1
63 #define HAVE_TRI_STRIP_1 0
64 #define HAVE_TRI_FANS    1
65 #define HAVE_QUADS       1
66 #define HAVE_QUAD_STRIPS 1
67 #define HAVE_POLYGONS    1
68 #define HAVE_ELTS        1
69
70
71 #define HW_POINTS           ((ctx->Point.PointSprite || \
72                                 ((ctx->_TriangleCaps & (DD_POINT_SIZE | DD_POINT_ATTEN)) && \
73                                 !(ctx->_TriangleCaps & (DD_POINT_SMOOTH)))) ? \
74                                 R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS)
75 #define HW_LINES            R200_VF_PRIM_LINES
76 #define HW_LINE_LOOP        0
77 #define HW_LINE_STRIP       R200_VF_PRIM_LINE_STRIP
78 #define HW_TRIANGLES        R200_VF_PRIM_TRIANGLES
79 #define HW_TRIANGLE_STRIP_0 R200_VF_PRIM_TRIANGLE_STRIP
80 #define HW_TRIANGLE_STRIP_1 0
81 #define HW_TRIANGLE_FAN     R200_VF_PRIM_TRIANGLE_FAN
82 #define HW_QUADS            R200_VF_PRIM_QUADS
83 #define HW_QUAD_STRIP       R200_VF_PRIM_QUAD_STRIP
84 #define HW_POLYGON          R200_VF_PRIM_POLYGON
85
86
87 static GLboolean discrete_prim[0x10] = {
88    0,                           /* 0 none */
89    1,                           /* 1 points */
90    1,                           /* 2 lines */
91    0,                           /* 3 line_strip */
92    1,                           /* 4 tri_list */
93    0,                           /* 5 tri_fan */
94    0,                           /* 6 tri_strip */
95    0,                           /* 7 tri_w_flags */
96    1,                           /* 8 rect list (unused) */
97    1,                           /* 9 3vert point */
98    1,                           /* a 3vert line */
99    0,                           /* b point sprite */
100    0,                           /* c line loop */
101    1,                           /* d quads */
102    0,                           /* e quad strip */
103    0,                           /* f polygon */
104 };
105    
106
107 #define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx)
108 #define ELT_TYPE  GLushort
109
110 #define ELT_INIT(prim, hw_prim) \
111    r200TclPrimitive( ctx, prim, hw_prim | R200_VF_PRIM_WALK_IND )
112
113 #define GET_MESA_ELTS() TNL_CONTEXT(ctx)->vb.Elts
114
115
116 /* Don't really know how many elts will fit in what's left of cmdbuf,
117  * as there is state to emit, etc:
118  */
119
120 /* Testing on isosurf shows a maximum around here.  Don't know if it's
121  * the card or driver or kernel module that is causing the behaviour.
122  */
123 #define GET_MAX_HW_ELTS() 300
124
125 #define RESET_STIPPLE() do {                    \
126    R200_STATECHANGE( rmesa, lin );              \
127    radeonEmitState(&rmesa->radeon);                     \
128 } while (0)
129
130 #define AUTO_STIPPLE( mode )  do {              \
131    R200_STATECHANGE( rmesa, lin );              \
132    if (mode)                                    \
133       rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \
134          R200_LINE_PATTERN_AUTO_RESET;  \
135    else                                         \
136       rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \
137          ~R200_LINE_PATTERN_AUTO_RESET; \
138    radeonEmitState(&rmesa->radeon);                     \
139 } while (0)
140
141
142 #define ALLOC_ELTS(nr)  r200AllocElts( rmesa, nr )
143
144 static GLushort *r200AllocElts( r200ContextPtr rmesa, GLuint nr ) 
145 {
146    if (rmesa->radeon.dma.flush == r200FlushElts &&
147        rmesa->tcl.elt_used + nr*2 < R200_ELT_BUF_SZ) {
148
149       GLushort *dest = (GLushort *)(rmesa->radeon.tcl.elt_dma_bo->ptr +
150                                     rmesa->radeon.tcl.elt_dma_offset + rmesa->tcl.elt_used);
151
152       rmesa->tcl.elt_used += nr*2;
153
154       return dest;
155    }
156    else {
157       if (rmesa->radeon.dma.flush)
158          rmesa->radeon.dma.flush( rmesa->radeon.glCtx );
159
160       r200EmitAOS( rmesa,
161                    rmesa->radeon.tcl.aos_count, 0 );
162
163       r200EmitMaxVtxIndex(rmesa, rmesa->radeon.tcl.aos[0].count);
164       return r200AllocEltsOpenEnded( rmesa, rmesa->tcl.hw_primitive, nr );
165    }
166 }
167
168
169 #define CLOSE_ELTS()                            \
170 do {                                            \
171    if (0) R200_NEWPRIM( rmesa );                \
172 }                                               \
173 while (0)
174
175
176 /* TODO: Try to extend existing primitive if both are identical,
177  * discrete and there are no intervening state changes.  (Somewhat
178  * duplicates changes to DrawArrays code)
179  */
180 static void r200EmitPrim( GLcontext *ctx, 
181                           GLenum prim, 
182                           GLuint hwprim, 
183                           GLuint start, 
184                           GLuint count) 
185 {
186    r200ContextPtr rmesa = R200_CONTEXT( ctx );
187    r200TclPrimitive( ctx, prim, hwprim );
188    
189    //   fprintf(stderr,"Emit prim %d\n", rmesa->radeon.tcl.aos_count);
190
191    r200EmitAOS( rmesa,
192                 rmesa->radeon.tcl.aos_count,
193                 start );
194    
195    /* Why couldn't this packet have taken an offset param?
196     */
197    r200EmitVbufPrim( rmesa,
198                      rmesa->tcl.hw_primitive,
199                      count - start );
200 }
201
202 #define EMIT_PRIM(ctx, prim, hwprim, start, count) do {         \
203    r200EmitPrim( ctx, prim, hwprim, start, count );             \
204    (void) rmesa; } while (0)
205
206 #define MAX_CONVERSION_SIZE 40
207 /* Try & join small primitives
208  */
209 #if 0
210 #define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) 0
211 #else
212 #define PREFER_DISCRETE_ELT_PRIM( NR, PRIM )                    \
213   ((NR) < 20 ||                                                 \
214    ((NR) < 40 &&                                                \
215     rmesa->tcl.hw_primitive == (PRIM|                           \
216                             R200_VF_TCL_OUTPUT_VTX_ENABLE|      \
217                                 R200_VF_PRIM_WALK_IND)))
218 #endif
219
220 #ifdef MESA_BIG_ENDIAN
221 /* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */
222 #define EMIT_ELT(dest, offset, x) do {                          \
223         int off = offset + ( ( (GLuint)dest & 0x2 ) >> 1 );     \
224         GLushort *des = (GLushort *)( (GLuint)dest & ~0x2 );    \
225         (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x);     \
226         (void)rmesa; } while (0)
227 #else
228 #define EMIT_ELT(dest, offset, x) do {                          \
229         (dest)[offset] = (GLushort) (x);                        \
230         (void)rmesa; } while (0)
231 #endif
232
233 #define EMIT_TWO_ELTS(dest, offset, x, y)  *(GLuint *)((dest)+offset) = ((y)<<16)|(x);
234
235
236
237 #define TAG(x) tcl_##x
238 #include "tnl_dd/t_dd_dmatmp2.h"
239
240 /**********************************************************************/
241 /*                          External entrypoints                     */
242 /**********************************************************************/
243
244 void r200EmitPrimitive( GLcontext *ctx, 
245                           GLuint first,
246                           GLuint last,
247                           GLuint flags )
248 {
249    tcl_render_tab_verts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
250 }
251
252 void r200EmitEltPrimitive( GLcontext *ctx, 
253                              GLuint first,
254                              GLuint last,
255                              GLuint flags )
256 {
257    tcl_render_tab_elts[flags&PRIM_MODE_MASK]( ctx, first, last, flags );
258 }
259
260 void r200TclPrimitive( GLcontext *ctx, 
261                          GLenum prim,
262                          int hw_prim )
263 {
264    r200ContextPtr rmesa = R200_CONTEXT(ctx);
265    GLuint newprim = hw_prim | R200_VF_TCL_OUTPUT_VTX_ENABLE;
266
267    if (newprim != rmesa->tcl.hw_primitive ||
268        !discrete_prim[hw_prim&0xf]) {
269       /* need to disable perspective-correct texturing for point sprites */
270       if ((prim & PRIM_MODE_MASK) == GL_POINTS && ctx->Point.PointSprite) {
271          if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) {
272             R200_STATECHANGE( rmesa, set );
273             rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE;
274          }
275       }
276       else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) {
277          R200_STATECHANGE( rmesa, set );
278          rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE;
279       }
280       R200_NEWPRIM( rmesa );
281       rmesa->tcl.hw_primitive = newprim;
282    }
283 }
284
285
286 /**********************************************************************/
287 /*             Fog blend factor computation for hw tcl                */
288 /*             same calculation used as in t_vb_fog.c                 */
289 /**********************************************************************/
290
291 #define FOG_EXP_TABLE_SIZE 256
292 #define FOG_MAX (10.0)
293 #define EXP_FOG_MAX .0006595
294 #define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
295 static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
296
297 #if 1
298 #define NEG_EXP( result, narg )                                         \
299 do {                                                                    \
300    GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR));                       \
301    GLint k = (GLint) f;                                                 \
302    if (k > FOG_EXP_TABLE_SIZE-2)                                        \
303       result = (GLfloat) EXP_FOG_MAX;                                   \
304    else                                                                 \
305       result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]);      \
306 } while (0)
307 #else
308 #define NEG_EXP( result, narg )                                 \
309 do {                                                            \
310    result = exp(-narg);                                         \
311 } while (0)
312 #endif
313
314
315 /**
316  * Initialize the exp_table[] lookup table for approximating exp().
317  */
318 void
319 r200InitStaticFogData( void )
320 {
321    GLfloat f = 0.0F;
322    GLint i = 0;
323    for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
324       exp_table[i] = (GLfloat) exp(-f);
325    }
326 }
327
328
329 /**
330  * Compute per-vertex fog blend factors from fog coordinates by
331  * evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function.
332  * Fog coordinates are distances from the eye (typically between the
333  * near and far clip plane distances).
334  * Note the fog (eye Z) coords may be negative so we use ABS(z) below.
335  * Fog blend factors are in the range [0,1].
336  */
337 float
338 r200ComputeFogBlendFactor( GLcontext *ctx, GLfloat fogcoord )
339 {
340    GLfloat end  = ctx->Fog.End;
341    GLfloat d, temp;
342    const GLfloat z = FABSF(fogcoord);
343
344    switch (ctx->Fog.Mode) {
345    case GL_LINEAR:
346       if (ctx->Fog.Start == ctx->Fog.End)
347          d = 1.0F;
348       else
349          d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
350       temp = (end - z) * d;
351       return CLAMP(temp, 0.0F, 1.0F);
352       break;
353    case GL_EXP:
354       d = ctx->Fog.Density;
355       NEG_EXP( temp, d * z );
356       return temp;
357       break;
358    case GL_EXP2:
359       d = ctx->Fog.Density*ctx->Fog.Density;
360       NEG_EXP( temp, d * z * z );
361       return temp;
362       break;
363    default:
364       _mesa_problem(ctx, "Bad fog mode in make_fog_coord");
365       return 0;
366    }
367 }
368
369 /**
370  * Predict total emit size for next rendering operation so there is no flush in middle of rendering
371  * Prediction has to aim towards the best possible value that is worse than worst case scenario
372  */
373 static GLuint r200EnsureEmitSize( GLcontext * ctx , GLubyte* vimap_rev )
374 {
375   r200ContextPtr rmesa = R200_CONTEXT(ctx);
376   TNLcontext *tnl = TNL_CONTEXT(ctx);
377   struct vertex_buffer *VB = &tnl->vb;
378   GLuint space_required;
379   GLuint state_size;
380   GLuint nr_aos = 0;
381   int i;
382   /* predict number of aos to emit */
383   for (i = 0; i < 15; ++i)
384   {
385     if (vimap_rev[i] != 255)
386     {
387       ++nr_aos;
388     }
389   }
390
391   {
392     /* count the prediction for state size */
393     space_required = 0;
394     state_size = radeonCountStateEmitSize( &rmesa->radeon );
395     /* vtx may be changed in r200EmitArrays so account for it if not dirty */
396     if (!rmesa->hw.vtx.dirty)
397       state_size += rmesa->hw.vtx.check(rmesa->radeon.glCtx, &rmesa->hw.vtx);
398     /* predict size for elements */
399     for (i = 0; i < VB->PrimitiveCount; ++i)
400     {
401       if (!VB->Primitive[i].count)
402         continue;
403       /* If primitive.count is less than MAX_CONVERSION_SIZE
404          rendering code may decide convert to elts.
405          In that case we have to make pessimistic prediction.
406          and use larger of 2 paths. */
407       const GLuint elt_count =(VB->Primitive[i].count/GET_MAX_HW_ELTS() + 1);
408       const GLuint elts = ELTS_BUFSZ(nr_aos) * elt_count;
409       const GLuint index = INDEX_BUFSZ * elt_count;
410       const GLuint vbuf = VBUF_BUFSZ;
411       if ( (!VB->Elts && VB->Primitive[i].count >= MAX_CONVERSION_SIZE)
412           || vbuf > index + elts)
413         space_required += vbuf;
414       else
415         space_required += index + elts;
416       space_required += AOS_BUFSZ(nr_aos);
417     }
418   }
419
420   radeon_print(RADEON_RENDER,RADEON_VERBOSE,
421       "%s space %u, aos %d\n",
422       __func__, space_required, AOS_BUFSZ(nr_aos) );
423   /* flush the buffer in case we need more than is left. */
424   if (rcommonEnsureCmdBufSpace(&rmesa->radeon, space_required + state_size, __FUNCTION__))
425     return space_required + radeonCountStateEmitSize( &rmesa->radeon );
426   else
427     return space_required + state_size;
428 }
429
430
431 /**********************************************************************/
432 /*                          Render pipeline stage                     */
433 /**********************************************************************/
434
435
436 /* TCL render.
437  */
438 static GLboolean r200_run_tcl_render( GLcontext *ctx,
439                                       struct tnl_pipeline_stage *stage )
440 {
441    r200ContextPtr rmesa = R200_CONTEXT(ctx);
442    TNLcontext *tnl = TNL_CONTEXT(ctx);
443    struct vertex_buffer *VB = &tnl->vb;
444    GLuint i;
445    GLubyte *vimap_rev;
446 /* use hw fixed order for simplicity, pos 0, weight 1, normal 2, fog 3, 
447    color0 - color3 4-7, texcoord0 - texcoord5 8-13, pos 1 14. Must not use
448    more than 12 of those at the same time. */
449    GLubyte map_rev_fixed[15] = {255, 255, 255, 255, 255, 255, 255, 255,
450                             255, 255, 255, 255, 255, 255, 255};
451
452
453    /* TODO: separate this from the swtnl pipeline 
454     */
455    if (rmesa->radeon.TclFallback)
456       return GL_TRUE;   /* fallback to software t&l */
457
458    radeon_print(RADEON_RENDER, RADEON_NORMAL, "%s\n", __FUNCTION__);
459
460    if (VB->Count == 0)
461       return GL_FALSE;
462
463    /* Validate state:
464     */
465    if (rmesa->radeon.NewGLState)
466       if (!r200ValidateState( ctx ))
467          return GL_TRUE; /* fallback to sw t&l */
468
469    if (!ctx->VertexProgram._Enabled) {
470    /* NOTE: inputs != tnl->render_inputs - these are the untransformed
471     * inputs.
472     */
473       map_rev_fixed[0] = VERT_ATTRIB_POS;
474       /* technically there is no reason we always need VA_COLOR0. In theory
475          could disable it depending on lighting, color materials, texturing... */
476       map_rev_fixed[4] = VERT_ATTRIB_COLOR0;
477
478       if (ctx->Light.Enabled) {
479          map_rev_fixed[2] = VERT_ATTRIB_NORMAL;
480       }
481
482       /* this also enables VA_COLOR1 when using separate specular
483          lighting model, which is unnecessary.
484          FIXME: OTOH, we're missing the case where a ATI_fragment_shader accesses
485          the secondary color (if lighting is disabled). The chip seems
486          misconfigured for that though elsewhere (tcl output, might lock up) */
487       if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) {
488          map_rev_fixed[5] = VERT_ATTRIB_COLOR1;
489       }
490
491       if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) {
492          map_rev_fixed[3] = VERT_ATTRIB_FOG;
493       }
494
495       for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) {
496          if (ctx->Texture.Unit[i]._ReallyEnabled) {
497             if (rmesa->TexGenNeedNormals[i]) {
498                map_rev_fixed[2] = VERT_ATTRIB_NORMAL;
499             }
500             map_rev_fixed[8 + i] = VERT_ATTRIB_TEX0 + i;
501          }
502       }
503       vimap_rev = &map_rev_fixed[0];
504    }
505    else {
506       /* vtx_tcl_output_vtxfmt_0/1 need to match configuration of "fragment
507          part", since using some vertex interpolator later which is not in
508          out_vtxfmt0/1 will lock up. It seems to be ok to write in vertex
509          prog to a not enabled output however, so just don't mess with it.
510          We only need to change compsel. */
511       GLuint out_compsel = 0;
512       const GLbitfield64 vp_out =
513          rmesa->curr_vp_hw->mesa_program.Base.OutputsWritten;
514
515       vimap_rev = &rmesa->curr_vp_hw->inputmap_rev[0];
516       assert(vp_out & BITFIELD64_BIT(VERT_RESULT_HPOS));
517       out_compsel = R200_OUTPUT_XYZW;
518       if (vp_out & BITFIELD64_BIT(VERT_RESULT_COL0)) {
519          out_compsel |= R200_OUTPUT_COLOR_0;
520       }
521       if (vp_out & BITFIELD64_BIT(VERT_RESULT_COL1)) {
522          out_compsel |= R200_OUTPUT_COLOR_1;
523       }
524       if (vp_out & BITFIELD64_BIT(VERT_RESULT_FOGC)) {
525          out_compsel |= R200_OUTPUT_DISCRETE_FOG;
526       }
527       if (vp_out & BITFIELD64_BIT(VERT_RESULT_PSIZ)) {
528          out_compsel |= R200_OUTPUT_PT_SIZE;
529       }
530       for (i = VERT_RESULT_TEX0; i < VERT_RESULT_TEX6; i++) {
531          if (vp_out & BITFIELD64_BIT(i)) {
532             out_compsel |= R200_OUTPUT_TEX_0 << (i - VERT_RESULT_TEX0);
533          }
534       }
535       if (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] != out_compsel) {
536          R200_STATECHANGE( rmesa, vtx );
537          rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = out_compsel;
538       }
539    }
540
541    /* Do the actual work:
542     */
543    radeonReleaseArrays( ctx, ~0 /* stage->changed_inputs */ );
544    GLuint emit_end = r200EnsureEmitSize( ctx, vimap_rev )
545      + rmesa->radeon.cmdbuf.cs->cdw;
546    r200EmitArrays( ctx, vimap_rev );
547
548    for (i = 0 ; i < VB->PrimitiveCount ; i++)
549    {
550       GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
551       GLuint start = VB->Primitive[i].start;
552       GLuint length = VB->Primitive[i].count;
553
554       if (!length)
555          continue;
556
557       if (VB->Elts)
558          r200EmitEltPrimitive( ctx, start, start+length, prim );
559       else
560          r200EmitPrimitive( ctx, start, start+length, prim );
561    }
562    if ( emit_end < rmesa->radeon.cmdbuf.cs->cdw )
563      WARN_ONCE("Rendering was %d commands larger than predicted size."
564          " We might overflow  command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end);
565
566    return GL_FALSE;             /* finished the pipe */
567 }
568
569
570
571 /* Initial state for tcl stage.  
572  */
573 const struct tnl_pipeline_stage _r200_tcl_stage =
574 {
575    "r200 render",
576    NULL,                        /*  private */
577    NULL,
578    NULL,
579    NULL,
580    r200_run_tcl_render  /* run */
581 };
582
583
584
585 /**********************************************************************/
586 /*                 Validate state at pipeline start                   */
587 /**********************************************************************/
588
589
590 /*-----------------------------------------------------------------------
591  * Manage TCL fallbacks
592  */
593
594
595 static void transition_to_swtnl( GLcontext *ctx )
596 {
597    r200ContextPtr rmesa = R200_CONTEXT(ctx);
598    TNLcontext *tnl = TNL_CONTEXT(ctx);
599
600    R200_NEWPRIM( rmesa );
601
602    r200ChooseVertexState( ctx );
603    r200ChooseRenderState( ctx );
604
605    _mesa_validate_all_lighting_tables( ctx ); 
606
607    tnl->Driver.NotifyMaterialChange = 
608       _mesa_validate_all_lighting_tables;
609
610    radeonReleaseArrays( ctx, ~0 );
611
612    /* Still using the D3D based hardware-rasterizer from the radeon;
613     * need to put the card into D3D mode to make it work:
614     */
615    R200_STATECHANGE( rmesa, vap );
616    rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~(R200_VAP_TCL_ENABLE|R200_VAP_PROG_VTX_SHADER_ENABLE);
617 }
618
619 static void transition_to_hwtnl( GLcontext *ctx )
620 {
621    r200ContextPtr rmesa = R200_CONTEXT(ctx);
622    TNLcontext *tnl = TNL_CONTEXT(ctx);
623
624    _tnl_need_projected_coords( ctx, GL_FALSE );
625
626    r200UpdateMaterial( ctx );
627
628    tnl->Driver.NotifyMaterialChange = r200UpdateMaterial;
629
630    if ( rmesa->radeon.dma.flush )                       
631       rmesa->radeon.dma.flush( rmesa->radeon.glCtx );   
632
633    rmesa->radeon.dma.flush = NULL;
634    
635    R200_STATECHANGE( rmesa, vap );
636    rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_TCL_ENABLE;
637    rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_FORCE_W_TO_ONE;
638
639    if (ctx->VertexProgram._Enabled) {
640       rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_PROG_VTX_SHADER_ENABLE;
641    }
642
643    if ( ((rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK)
644       == R200_FOG_USE_SPEC_ALPHA) &&
645       (ctx->Fog.FogCoordinateSource == GL_FOG_COORD )) {
646       R200_STATECHANGE( rmesa, ctx );
647       rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK;
648       rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_VTX_FOG;
649    }
650
651    R200_STATECHANGE( rmesa, vte );
652    rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VTX_XY_FMT|R200_VTX_Z_FMT);
653    rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] |= R200_VTX_W0_FMT;
654
655    if (R200_DEBUG & RADEON_FALLBACKS)
656       fprintf(stderr, "R200 end tcl fallback\n");
657 }
658
659
660 static char *fallbackStrings[] = {
661    "Rasterization fallback",
662    "Unfilled triangles",
663    "Twosided lighting, differing materials",
664    "Materials in VB (maybe between begin/end)",
665    "Texgen unit 0",
666    "Texgen unit 1",
667    "Texgen unit 2",
668    "Texgen unit 3",
669    "Texgen unit 4",
670    "Texgen unit 5",
671    "User disable",
672    "Bitmap as points",
673    "Vertex program"
674 };
675
676
677 static char *getFallbackString(GLuint bit)
678 {
679    int i = 0;
680    while (bit > 1) {
681       i++;
682       bit >>= 1;
683    }
684    return fallbackStrings[i];
685 }
686
687
688
689 void r200TclFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
690 {
691         r200ContextPtr rmesa = R200_CONTEXT(ctx);
692         GLuint oldfallback = rmesa->radeon.TclFallback;
693
694         if (mode) {
695                 if (oldfallback == 0) {
696                         /* We have to flush before transition */
697                         if ( rmesa->radeon.dma.flush )
698                                 rmesa->radeon.dma.flush( rmesa->radeon.glCtx );
699
700                         if (R200_DEBUG & RADEON_FALLBACKS)
701                                 fprintf(stderr, "R200 begin tcl fallback %s\n",
702                                                 getFallbackString( bit ));
703                         rmesa->radeon.TclFallback |= bit;
704                         transition_to_swtnl( ctx );
705                 } else
706                         rmesa->radeon.TclFallback |= bit;
707         } else {
708                 if (oldfallback == bit) {
709                         /* We have to flush before transition */
710                         if ( rmesa->radeon.dma.flush )
711                                 rmesa->radeon.dma.flush( rmesa->radeon.glCtx );
712
713                         if (R200_DEBUG & RADEON_FALLBACKS)
714                                 fprintf(stderr, "R200 end tcl fallback %s\n",
715                                                 getFallbackString( bit ));
716                         rmesa->radeon.TclFallback &= ~bit;
717                         transition_to_hwtnl( ctx );
718                 } else
719                         rmesa->radeon.TclFallback &= ~bit;
720         }
721 }