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