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