1/**************************************************************************
2
3Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
4
5The Weather Channel (TM) funded Tungsten Graphics to develop the
6initial release of the Radeon 8500 driver under the XFree86 license.
7This notice must be preserved.
8
9Permission is hereby granted, free of charge, to any person obtaining
10a copy of this software and associated documentation files (the
11"Software"), to deal in the Software without restriction, including
12without limitation the rights to use, copy, modify, merge, publish,
13distribute, sublicense, and/or sell copies of the Software, and to
14permit persons to whom the Software is furnished to do so, subject to
15the following conditions:
16
17The above copyright notice and this permission notice (including the
18next paragraph) shall be included in all copies or substantial
19portions of the Software.
20
21THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
25LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28
29**************************************************************************/
30
31/*
32 * Authors:
33 *   Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36#include "main/glheader.h"
37#include "main/imports.h"
38#include "main/api_arrayelt.h"
39#include "main/enums.h"
40#include "main/colormac.h"
41#include "main/light.h"
42#include "main/framebuffer.h"
43#include "main/fbobject.h"
44
45#include "swrast/swrast.h"
46#include "vbo/vbo.h"
47#include "tnl/tnl.h"
48#include "tnl/t_pipeline.h"
49#include "swrast_setup/swrast_setup.h"
50#include "drivers/common/meta.h"
51
52#include "radeon_common.h"
53#include "radeon_mipmap_tree.h"
54#include "r200_context.h"
55#include "r200_ioctl.h"
56#include "r200_state.h"
57#include "r200_tcl.h"
58#include "r200_tex.h"
59#include "r200_swtcl.h"
60#include "r200_vertprog.h"
61
62
63/* =============================================================
64 * Alpha blending
65 */
66
67static void r200AlphaFunc( struct gl_context *ctx, GLenum func, GLfloat ref )
68{
69   r200ContextPtr rmesa = R200_CONTEXT(ctx);
70   int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
71   GLubyte refByte;
72
73   CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
74
75   R200_STATECHANGE( rmesa, ctx );
76
77   pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK);
78   pp_misc |= (refByte & R200_REF_ALPHA_MASK);
79
80   switch ( func ) {
81   case GL_NEVER:
82      pp_misc |= R200_ALPHA_TEST_FAIL;
83      break;
84   case GL_LESS:
85      pp_misc |= R200_ALPHA_TEST_LESS;
86      break;
87   case GL_EQUAL:
88      pp_misc |= R200_ALPHA_TEST_EQUAL;
89      break;
90   case GL_LEQUAL:
91      pp_misc |= R200_ALPHA_TEST_LEQUAL;
92      break;
93   case GL_GREATER:
94      pp_misc |= R200_ALPHA_TEST_GREATER;
95      break;
96   case GL_NOTEQUAL:
97      pp_misc |= R200_ALPHA_TEST_NEQUAL;
98      break;
99   case GL_GEQUAL:
100      pp_misc |= R200_ALPHA_TEST_GEQUAL;
101      break;
102   case GL_ALWAYS:
103      pp_misc |= R200_ALPHA_TEST_PASS;
104      break;
105   }
106
107   rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
108}
109
110static void r200BlendColor( struct gl_context *ctx, const GLfloat cf[4] )
111{
112   GLubyte color[4];
113   r200ContextPtr rmesa = R200_CONTEXT(ctx);
114   R200_STATECHANGE( rmesa, ctx );
115   CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]);
116   CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]);
117   CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]);
118   CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]);
119   rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = radeonPackColor( 4, color[0], color[1], color[2], color[3] );
120}
121
122/**
123 * Calculate the hardware blend factor setting.  This same function is used
124 * for source and destination of both alpha and RGB.
125 *
126 * \returns
127 * The hardware register value for the specified blend factor.  This value
128 * will need to be shifted into the correct position for either source or
129 * destination factor.
130 *
131 * \todo
132 * Since the two cases where source and destination are handled differently
133 * are essentially error cases, they should never happen.  Determine if these
134 * cases can be removed.
135 */
136static int blend_factor( GLenum factor, GLboolean is_src )
137{
138   int func;
139
140   switch ( factor ) {
141   case GL_ZERO:
142      func = R200_BLEND_GL_ZERO;
143      break;
144   case GL_ONE:
145      func = R200_BLEND_GL_ONE;
146      break;
147   case GL_DST_COLOR:
148      func = R200_BLEND_GL_DST_COLOR;
149      break;
150   case GL_ONE_MINUS_DST_COLOR:
151      func = R200_BLEND_GL_ONE_MINUS_DST_COLOR;
152      break;
153   case GL_SRC_COLOR:
154      func = R200_BLEND_GL_SRC_COLOR;
155      break;
156   case GL_ONE_MINUS_SRC_COLOR:
157      func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR;
158      break;
159   case GL_SRC_ALPHA:
160      func = R200_BLEND_GL_SRC_ALPHA;
161      break;
162   case GL_ONE_MINUS_SRC_ALPHA:
163      func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA;
164      break;
165   case GL_DST_ALPHA:
166      func = R200_BLEND_GL_DST_ALPHA;
167      break;
168   case GL_ONE_MINUS_DST_ALPHA:
169      func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA;
170      break;
171   case GL_SRC_ALPHA_SATURATE:
172      func = (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : R200_BLEND_GL_ZERO;
173      break;
174   case GL_CONSTANT_COLOR:
175      func = R200_BLEND_GL_CONST_COLOR;
176      break;
177   case GL_ONE_MINUS_CONSTANT_COLOR:
178      func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR;
179      break;
180   case GL_CONSTANT_ALPHA:
181      func = R200_BLEND_GL_CONST_ALPHA;
182      break;
183   case GL_ONE_MINUS_CONSTANT_ALPHA:
184      func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA;
185      break;
186   default:
187      func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO;
188   }
189   return func;
190}
191
192/**
193 * Sets both the blend equation and the blend function.
194 * This is done in a single
195 * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX)
196 * change the interpretation of the blend function.
197 * Also, make sure that blend function and blend equation are set to their default
198 * value if color blending is not enabled, since at least blend equations GL_MIN
199 * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for
200 * unknown reasons.
201 */
202static void r200_set_blend_state( struct gl_context * ctx )
203{
204   r200ContextPtr rmesa = R200_CONTEXT(ctx);
205   GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &
206      ~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE);
207
208   int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
209      (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
210   int eqn = R200_COMB_FCN_ADD_CLAMP;
211   int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
212      (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT);
213   int eqnA = R200_COMB_FCN_ADD_CLAMP;
214
215   R200_STATECHANGE( rmesa, ctx );
216
217   if (ctx->Color.ColorLogicOpEnabled) {
218      rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] =  cntl | R200_ROP_ENABLE;
219      rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
220      rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
221      return;
222   } else if (ctx->Color.BlendEnabled) {
223      rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] =  cntl | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE;
224   }
225   else {
226      rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl;
227      rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func;
228      rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
229      return;
230   }
231
232   func = (blend_factor( ctx->Color.Blend[0].SrcRGB, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
233      (blend_factor( ctx->Color.Blend[0].DstRGB, GL_FALSE ) << R200_DST_BLEND_SHIFT);
234
235   switch(ctx->Color.Blend[0].EquationRGB) {
236   case GL_FUNC_ADD:
237      eqn = R200_COMB_FCN_ADD_CLAMP;
238      break;
239
240   case GL_FUNC_SUBTRACT:
241      eqn = R200_COMB_FCN_SUB_CLAMP;
242      break;
243
244   case GL_FUNC_REVERSE_SUBTRACT:
245      eqn = R200_COMB_FCN_RSUB_CLAMP;
246      break;
247
248   case GL_MIN:
249      eqn = R200_COMB_FCN_MIN;
250      func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
251         (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
252      break;
253
254   case GL_MAX:
255      eqn = R200_COMB_FCN_MAX;
256      func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
257         (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
258      break;
259
260   default:
261      fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n",
262         __FUNCTION__, __LINE__, ctx->Color.Blend[0].EquationRGB );
263      return;
264   }
265
266   funcA = (blend_factor( ctx->Color.Blend[0].SrcA, GL_TRUE ) << R200_SRC_BLEND_SHIFT) |
267      (blend_factor( ctx->Color.Blend[0].DstA, GL_FALSE ) << R200_DST_BLEND_SHIFT);
268
269   switch(ctx->Color.Blend[0].EquationA) {
270   case GL_FUNC_ADD:
271      eqnA = R200_COMB_FCN_ADD_CLAMP;
272      break;
273
274   case GL_FUNC_SUBTRACT:
275      eqnA = R200_COMB_FCN_SUB_CLAMP;
276      break;
277
278   case GL_FUNC_REVERSE_SUBTRACT:
279      eqnA = R200_COMB_FCN_RSUB_CLAMP;
280      break;
281
282   case GL_MIN:
283      eqnA = R200_COMB_FCN_MIN;
284      funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
285         (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
286      break;
287
288   case GL_MAX:
289      eqnA = R200_COMB_FCN_MAX;
290      funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) |
291         (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT);
292      break;
293
294   default:
295      fprintf( stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n",
296         __FUNCTION__, __LINE__, ctx->Color.Blend[0].EquationA );
297      return;
298   }
299
300   rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqnA | funcA;
301   rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func;
302
303}
304
305static void r200BlendEquationSeparate( struct gl_context *ctx,
306				       GLenum modeRGB, GLenum modeA )
307{
308      r200_set_blend_state( ctx );
309}
310
311static void r200BlendFuncSeparate( struct gl_context *ctx,
312				     GLenum sfactorRGB, GLenum dfactorRGB,
313				     GLenum sfactorA, GLenum dfactorA )
314{
315      r200_set_blend_state( ctx );
316}
317
318
319/* =============================================================
320 * Depth testing
321 */
322
323static void r200DepthFunc( struct gl_context *ctx, GLenum func )
324{
325   r200ContextPtr rmesa = R200_CONTEXT(ctx);
326
327   R200_STATECHANGE( rmesa, ctx );
328   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK;
329
330   switch ( ctx->Depth.Func ) {
331   case GL_NEVER:
332      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER;
333      break;
334   case GL_LESS:
335      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS;
336      break;
337   case GL_EQUAL:
338      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL;
339      break;
340   case GL_LEQUAL:
341      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL;
342      break;
343   case GL_GREATER:
344      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER;
345      break;
346   case GL_NOTEQUAL:
347      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL;
348      break;
349   case GL_GEQUAL:
350      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL;
351      break;
352   case GL_ALWAYS:
353      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS;
354      break;
355   }
356}
357
358static void r200DepthMask( struct gl_context *ctx, GLboolean flag )
359{
360   r200ContextPtr rmesa = R200_CONTEXT(ctx);
361   R200_STATECHANGE( rmesa, ctx );
362
363   if ( ctx->Depth.Mask ) {
364      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |=  R200_Z_WRITE_ENABLE;
365   } else {
366      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE;
367   }
368}
369
370
371/* =============================================================
372 * Fog
373 */
374
375
376static void r200Fogfv( struct gl_context *ctx, GLenum pname, const GLfloat *param )
377{
378   r200ContextPtr rmesa = R200_CONTEXT(ctx);
379   union { int i; float f; } c, d;
380   GLubyte col[4];
381   GLuint i;
382
383   c.i = rmesa->hw.fog.cmd[FOG_C];
384   d.i = rmesa->hw.fog.cmd[FOG_D];
385
386   switch (pname) {
387   case GL_FOG_MODE:
388      if (!ctx->Fog.Enabled)
389	 return;
390      R200_STATECHANGE(rmesa, tcl);
391      rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
392      switch (ctx->Fog.Mode) {
393      case GL_LINEAR:
394	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR;
395	 if (ctx->Fog.Start == ctx->Fog.End) {
396	    c.f = 1.0F;
397	    d.f = 1.0F;
398	 }
399	 else {
400	    c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
401	    d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
402	 }
403	 break;
404      case GL_EXP:
405	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP;
406	 c.f = 0.0;
407	 d.f = -ctx->Fog.Density;
408	 break;
409      case GL_EXP2:
410	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2;
411	 c.f = 0.0;
412	 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
413	 break;
414      default:
415	 return;
416      }
417      break;
418   case GL_FOG_DENSITY:
419      switch (ctx->Fog.Mode) {
420      case GL_EXP:
421	 c.f = 0.0;
422	 d.f = -ctx->Fog.Density;
423	 break;
424      case GL_EXP2:
425	 c.f = 0.0;
426	 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
427	 break;
428      default:
429	 break;
430      }
431      break;
432   case GL_FOG_START:
433   case GL_FOG_END:
434      if (ctx->Fog.Mode == GL_LINEAR) {
435	 if (ctx->Fog.Start == ctx->Fog.End) {
436	    c.f = 1.0F;
437	    d.f = 1.0F;
438	 } else {
439	    c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
440	    d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
441	 }
442      }
443      break;
444   case GL_FOG_COLOR:
445      R200_STATECHANGE( rmesa, ctx );
446      _mesa_unclamped_float_rgba_to_ubyte(col, ctx->Fog.Color );
447      i = radeonPackColor( 4, col[0], col[1], col[2], 0 );
448      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK;
449      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i;
450      break;
451   case GL_FOG_COORD_SRC: {
452      GLuint out_0 = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0];
453      GLuint fog   = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR];
454
455      fog &= ~R200_FOG_USE_MASK;
456      if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD || ctx->VertexProgram.Enabled) {
457	 fog   |= R200_FOG_USE_VTX_FOG;
458	 out_0 |= R200_VTX_DISCRETE_FOG;
459      }
460      else {
461	 fog   |=  R200_FOG_USE_SPEC_ALPHA;
462	 out_0 &= ~R200_VTX_DISCRETE_FOG;
463      }
464
465      if ( fog != rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] ) {
466	 R200_STATECHANGE( rmesa, ctx );
467	 rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog;
468      }
469
470      if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) {
471	 R200_STATECHANGE( rmesa, vtx );
472	 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0;
473      }
474
475      break;
476   }
477   default:
478      return;
479   }
480
481   if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
482      R200_STATECHANGE( rmesa, fog );
483      rmesa->hw.fog.cmd[FOG_C] = c.i;
484      rmesa->hw.fog.cmd[FOG_D] = d.i;
485   }
486}
487
488/* =============================================================
489 * Culling
490 */
491
492static void r200CullFace( struct gl_context *ctx, GLenum unused )
493{
494   r200ContextPtr rmesa = R200_CONTEXT(ctx);
495   GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
496   GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
497
498   s |= R200_FFACE_SOLID | R200_BFACE_SOLID;
499   t &= ~(R200_CULL_FRONT | R200_CULL_BACK);
500
501   if ( ctx->Polygon.CullFlag ) {
502      switch ( ctx->Polygon.CullFaceMode ) {
503      case GL_FRONT:
504	 s &= ~R200_FFACE_SOLID;
505	 t |= R200_CULL_FRONT;
506	 break;
507      case GL_BACK:
508	 s &= ~R200_BFACE_SOLID;
509	 t |= R200_CULL_BACK;
510	 break;
511      case GL_FRONT_AND_BACK:
512	 s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID);
513	 t |= (R200_CULL_FRONT | R200_CULL_BACK);
514	 break;
515      }
516   }
517
518   if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
519      R200_STATECHANGE(rmesa, set );
520      rmesa->hw.set.cmd[SET_SE_CNTL] = s;
521   }
522
523   if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
524      R200_STATECHANGE(rmesa, tcl );
525      rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
526   }
527}
528
529static void r200FrontFace( struct gl_context *ctx, GLenum mode )
530{
531   r200ContextPtr rmesa = R200_CONTEXT(ctx);
532   int cull_face = (mode == GL_CW) ? R200_FFACE_CULL_CW : R200_FFACE_CULL_CCW;
533
534   R200_STATECHANGE( rmesa, set );
535   rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK;
536
537   R200_STATECHANGE( rmesa, tcl );
538   rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW;
539
540   /* Winding is inverted when rendering to FBO */
541   if (ctx->DrawBuffer && _mesa_is_user_fbo(ctx->DrawBuffer))
542      cull_face = (mode == GL_CCW) ? R200_FFACE_CULL_CW : R200_FFACE_CULL_CCW;
543   rmesa->hw.set.cmd[SET_SE_CNTL] |= cull_face;
544
545   if ( mode == GL_CCW )
546      rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW;
547}
548
549/* =============================================================
550 * Point state
551 */
552static void r200PointSize( struct gl_context *ctx, GLfloat size )
553{
554   r200ContextPtr rmesa = R200_CONTEXT(ctx);
555   GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
556
557   radeon_print(RADEON_STATE, RADEON_TRACE,
558       "%s(%p) size: %f, fixed point result: %d.%d (%d/16)\n",
559       __func__, ctx, size,
560       ((GLuint)(ctx->Point.Size * 16.0))/16,
561       (((GLuint)(ctx->Point.Size * 16.0))&15)*100/16,
562       ((GLuint)(ctx->Point.Size * 16.0))&15);
563
564   R200_STATECHANGE( rmesa, cst );
565   R200_STATECHANGE( rmesa, ptp );
566   rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff;
567   rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0));
568/* this is the size param of the point size calculation (point size reg value
569   is not used when calculation is active). */
570   fcmd[PTP_VPORT_SCALE_PTSIZE] = ctx->Point.Size;
571}
572
573static void r200PointParameter( struct gl_context *ctx, GLenum pname, const GLfloat *params)
574{
575   r200ContextPtr rmesa = R200_CONTEXT(ctx);
576   GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
577
578   switch (pname) {
579   case GL_POINT_SIZE_MIN:
580   /* Can clamp both in tcl and setup - just set both (as does fglrx) */
581      R200_STATECHANGE( rmesa, lin );
582      R200_STATECHANGE( rmesa, ptp );
583      rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= 0xffff;
584      rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Point.MinSize * 16.0) << 16;
585      fcmd[PTP_CLAMP_MIN] = ctx->Point.MinSize;
586      break;
587   case GL_POINT_SIZE_MAX:
588      R200_STATECHANGE( rmesa, cst );
589      R200_STATECHANGE( rmesa, ptp );
590      rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= 0xffff;
591      rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= (GLuint)(ctx->Point.MaxSize * 16.0) << 16;
592      fcmd[PTP_CLAMP_MAX] = ctx->Point.MaxSize;
593      break;
594   case GL_POINT_DISTANCE_ATTENUATION:
595      R200_STATECHANGE( rmesa, vtx );
596      R200_STATECHANGE( rmesa, spr );
597      R200_STATECHANGE( rmesa, ptp );
598      GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd;
599      rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &=
600	 ~(R200_PS_MULT_MASK | R200_PS_LIN_ATT_ZERO | R200_PS_SE_SEL_STATE);
601      /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in
602	 r200ValidateState looks like overkill */
603      if (ctx->Point.Params[0] != 1.0 ||
604	  ctx->Point.Params[1] != 0.0 ||
605	  ctx->Point.Params[2] != 0.0 ||
606	  (ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled)) {
607	 /* all we care for vp would be the ps_se_sel_state setting */
608	 fcmd[PTP_ATT_CONST_QUAD] = ctx->Point.Params[2];
609	 fcmd[PTP_ATT_CONST_LIN] = ctx->Point.Params[1];
610	 fcmd[PTP_ATT_CONST_CON] = ctx->Point.Params[0];
611	 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_MULT_ATTENCONST;
612	 if (ctx->Point.Params[1] == 0.0)
613	    rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_LIN_ATT_ZERO;
614/* FIXME: setting this here doesn't look quite ok - we only want to do
615          that if we're actually drawing points probably */
616	 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_PT_SIZE;
617	 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= R200_VTX_POINT_SIZE;
618      }
619      else {
620	 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
621	    R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST;
622	 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_PT_SIZE;
623	 rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~R200_VTX_POINT_SIZE;
624      }
625      break;
626   case GL_POINT_FADE_THRESHOLD_SIZE:
627      /* don't support multisampling, so doesn't matter. */
628      break;
629   /* can't do these but don't need them.
630   case GL_POINT_SPRITE_R_MODE_NV:
631   case GL_POINT_SPRITE_COORD_ORIGIN: */
632   default:
633      fprintf(stderr, "bad pname parameter in r200PointParameter\n");
634      return;
635   }
636}
637
638/* =============================================================
639 * Line state
640 */
641static void r200LineWidth( struct gl_context *ctx, GLfloat widthf )
642{
643   r200ContextPtr rmesa = R200_CONTEXT(ctx);
644
645   R200_STATECHANGE( rmesa, lin );
646   R200_STATECHANGE( rmesa, set );
647
648   /* Line width is stored in U6.4 format.
649    * Same min/max limits for AA, non-AA lines.
650    */
651   rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
652   rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)
653      (CLAMP(widthf, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth) * 16.0);
654
655   if ( widthf > 1.0 ) {
656      rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_WIDELINE_ENABLE;
657   } else {
658      rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
659   }
660}
661
662static void r200LineStipple( struct gl_context *ctx, GLint factor, GLushort pattern )
663{
664   r200ContextPtr rmesa = R200_CONTEXT(ctx);
665
666   R200_STATECHANGE( rmesa, lin );
667   rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
668      ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
669}
670
671
672/* =============================================================
673 * Masks
674 */
675static void r200ColorMask( struct gl_context *ctx,
676			   GLboolean r, GLboolean g,
677			   GLboolean b, GLboolean a )
678{
679   r200ContextPtr rmesa = R200_CONTEXT(ctx);
680   GLuint mask;
681   struct radeon_renderbuffer *rrb;
682   GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
683
684   rrb = radeon_get_colorbuffer(&rmesa->radeon);
685   if (!rrb)
686     return;
687   mask = radeonPackColor( rrb->cpp,
688			   ctx->Color.ColorMask[0][RCOMP],
689			   ctx->Color.ColorMask[0][GCOMP],
690			   ctx->Color.ColorMask[0][BCOMP],
691			   ctx->Color.ColorMask[0][ACOMP] );
692
693
694   if (!(r && g && b && a))
695      flag |= R200_PLANE_MASK_ENABLE;
696
697   if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
698      R200_STATECHANGE( rmesa, ctx );
699      rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
700   }
701
702   if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
703      R200_STATECHANGE( rmesa, msk );
704      rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
705   }
706}
707
708
709/* =============================================================
710 * Polygon state
711 */
712
713static void r200PolygonOffset( struct gl_context *ctx,
714			       GLfloat factor, GLfloat units )
715{
716   r200ContextPtr rmesa = R200_CONTEXT(ctx);
717   const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
718   float_ui32_type constant =  { units * depthScale };
719   float_ui32_type factoru = { factor };
720
721/*    factor *= 2; */
722/*    constant *= 2; */
723
724/*    fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
725
726   R200_STATECHANGE( rmesa, zbs );
727   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR]   = factoru.ui32;
728   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
729}
730
731static void r200PolygonMode( struct gl_context *ctx, GLenum face, GLenum mode )
732{
733   r200ContextPtr rmesa = R200_CONTEXT(ctx);
734   GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
735
736   /* Can't generally do unfilled via tcl, but some good special
737    * cases work.
738    */
739   TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
740   if (rmesa->radeon.TclFallback) {
741      r200ChooseRenderState( ctx );
742      r200ChooseVertexState( ctx );
743   }
744}
745
746
747/* =============================================================
748 * Rendering attributes
749 *
750 * We really don't want to recalculate all this every time we bind a
751 * texture.  These things shouldn't change all that often, so it makes
752 * sense to break them out of the core texture state update routines.
753 */
754
755/* Examine lighting and texture state to determine if separate specular
756 * should be enabled.
757 */
758static void r200UpdateSpecular( struct gl_context *ctx )
759{
760   r200ContextPtr rmesa = R200_CONTEXT(ctx);
761   uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
762
763   R200_STATECHANGE( rmesa, tcl );
764   R200_STATECHANGE( rmesa, vtx );
765
766   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
767   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
768   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
769   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
770   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
771
772   p &= ~R200_SPECULAR_ENABLE;
773
774   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
775
776
777   if (ctx->Light.Enabled &&
778       ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
779      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
780	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
781	  (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
782      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
783      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
784      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
785      p |=  R200_SPECULAR_ENABLE;
786      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
787	 ~R200_DIFFUSE_SPECULAR_COMBINE;
788   }
789   else if (ctx->Light.Enabled) {
790      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
791	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
792      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
793      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
794   } else if (ctx->Fog.ColorSumEnabled ) {
795      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
796	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
797	  (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
798      p |=  R200_SPECULAR_ENABLE;
799   } else {
800      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
801	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
802   }
803
804   if (ctx->Fog.Enabled) {
805      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
806	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
807      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
808   }
809
810   if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
811      R200_STATECHANGE( rmesa, ctx );
812      rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
813   }
814
815   /* Update vertex/render formats
816    */
817   if (rmesa->radeon.TclFallback) {
818      r200ChooseRenderState( ctx );
819      r200ChooseVertexState( ctx );
820   }
821}
822
823
824/* =============================================================
825 * Materials
826 */
827
828
829/* Update on colormaterial, material emmissive/ambient,
830 * lightmodel.globalambient
831 */
832static void update_global_ambient( struct gl_context *ctx )
833{
834   r200ContextPtr rmesa = R200_CONTEXT(ctx);
835   float *fcmd = (float *)R200_DB_STATE( glt );
836
837   /* Need to do more if both emmissive & ambient are PREMULT:
838    * I believe this is not nessary when using source_material. This condition thus
839    * will never happen currently, and the function has no dependencies on materials now
840    */
841   if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
842       ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
843	(3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
844   {
845      COPY_3V( &fcmd[GLT_RED],
846	       ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
847      ACC_SCALE_3V( &fcmd[GLT_RED],
848		   ctx->Light.Model.Ambient,
849		   ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
850   }
851   else
852   {
853      COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
854   }
855
856   R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
857}
858
859/* Update on change to
860 *    - light[p].colors
861 *    - light[p].enabled
862 */
863static void update_light_colors( struct gl_context *ctx, GLuint p )
864{
865   struct gl_light *l = &ctx->Light.Light[p];
866
867/*     fprintf(stderr, "%s\n", __FUNCTION__); */
868
869   if (l->Enabled) {
870      r200ContextPtr rmesa = R200_CONTEXT(ctx);
871      float *fcmd = (float *)R200_DB_STATE( lit[p] );
872
873      COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
874      COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
875      COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
876
877      R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
878   }
879}
880
881static void r200ColorMaterial( struct gl_context *ctx, GLenum face, GLenum mode )
882{
883      r200ContextPtr rmesa = R200_CONTEXT(ctx);
884      GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
885      light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
886			   (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
887			   (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
888		   (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
889		   (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
890		   (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) |
891		   (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
892		   (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT));
893
894   if (ctx->Light.ColorMaterialEnabled) {
895      GLuint mask = ctx->Light._ColorMaterialBitmask;
896
897      if (mask & MAT_BIT_FRONT_EMISSION) {
898	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
899			     R200_FRONT_EMISSIVE_SOURCE_SHIFT);
900      }
901      else
902	 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
903			     R200_FRONT_EMISSIVE_SOURCE_SHIFT);
904
905      if (mask & MAT_BIT_FRONT_AMBIENT) {
906	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
907			     R200_FRONT_AMBIENT_SOURCE_SHIFT);
908      }
909      else
910         light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
911			     R200_FRONT_AMBIENT_SOURCE_SHIFT);
912
913      if (mask & MAT_BIT_FRONT_DIFFUSE) {
914	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
915			     R200_FRONT_DIFFUSE_SOURCE_SHIFT);
916      }
917      else
918         light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
919			     R200_FRONT_DIFFUSE_SOURCE_SHIFT);
920
921      if (mask & MAT_BIT_FRONT_SPECULAR) {
922	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
923			     R200_FRONT_SPECULAR_SOURCE_SHIFT);
924      }
925      else {
926         light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
927			     R200_FRONT_SPECULAR_SOURCE_SHIFT);
928      }
929
930      if (mask & MAT_BIT_BACK_EMISSION) {
931	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
932			     R200_BACK_EMISSIVE_SOURCE_SHIFT);
933      }
934
935      else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
936			     R200_BACK_EMISSIVE_SOURCE_SHIFT);
937
938      if (mask & MAT_BIT_BACK_AMBIENT) {
939	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
940			     R200_BACK_AMBIENT_SOURCE_SHIFT);
941      }
942      else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
943			     R200_BACK_AMBIENT_SOURCE_SHIFT);
944
945      if (mask & MAT_BIT_BACK_DIFFUSE) {
946	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
947			     R200_BACK_DIFFUSE_SOURCE_SHIFT);
948   }
949      else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
950			     R200_BACK_DIFFUSE_SOURCE_SHIFT);
951
952      if (mask & MAT_BIT_BACK_SPECULAR) {
953	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
954			     R200_BACK_SPECULAR_SOURCE_SHIFT);
955      }
956      else {
957         light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
958			     R200_BACK_SPECULAR_SOURCE_SHIFT);
959      }
960      }
961   else {
962       /* Default to SOURCE_MATERIAL:
963        */
964     light_model_ctl1 |=
965        (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
966        (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
967        (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
968        (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
969        (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
970        (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) |
971        (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
972        (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT);
973   }
974
975   if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
976      R200_STATECHANGE( rmesa, tcl );
977      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
978   }
979
980
981}
982
983void r200UpdateMaterial( struct gl_context *ctx )
984{
985   r200ContextPtr rmesa = R200_CONTEXT(ctx);
986   GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
987   GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
988   GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] );
989   GLuint mask = ~0;
990
991   /* Might be possible and faster to update everything unconditionally? */
992   if (ctx->Light.ColorMaterialEnabled)
993      mask &= ~ctx->Light._ColorMaterialBitmask;
994
995   if (R200_DEBUG & RADEON_STATE)
996      fprintf(stderr, "%s\n", __FUNCTION__);
997
998   if (mask & MAT_BIT_FRONT_EMISSION) {
999      fcmd[MTL_EMMISSIVE_RED]   = mat[MAT_ATTRIB_FRONT_EMISSION][0];
1000      fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
1001      fcmd[MTL_EMMISSIVE_BLUE]  = mat[MAT_ATTRIB_FRONT_EMISSION][2];
1002      fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
1003   }
1004   if (mask & MAT_BIT_FRONT_AMBIENT) {
1005      fcmd[MTL_AMBIENT_RED]     = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
1006      fcmd[MTL_AMBIENT_GREEN]   = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
1007      fcmd[MTL_AMBIENT_BLUE]    = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
1008      fcmd[MTL_AMBIENT_ALPHA]   = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
1009   }
1010   if (mask & MAT_BIT_FRONT_DIFFUSE) {
1011      fcmd[MTL_DIFFUSE_RED]     = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
1012      fcmd[MTL_DIFFUSE_GREEN]   = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
1013      fcmd[MTL_DIFFUSE_BLUE]    = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
1014      fcmd[MTL_DIFFUSE_ALPHA]   = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
1015   }
1016   if (mask & MAT_BIT_FRONT_SPECULAR) {
1017      fcmd[MTL_SPECULAR_RED]    = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
1018      fcmd[MTL_SPECULAR_GREEN]  = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
1019      fcmd[MTL_SPECULAR_BLUE]   = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
1020      fcmd[MTL_SPECULAR_ALPHA]  = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
1021   }
1022   if (mask & MAT_BIT_FRONT_SHININESS) {
1023      fcmd[MTL_SHININESS]       = mat[MAT_ATTRIB_FRONT_SHININESS][0];
1024   }
1025
1026   if (mask & MAT_BIT_BACK_EMISSION) {
1027      fcmd2[MTL_EMMISSIVE_RED]   = mat[MAT_ATTRIB_BACK_EMISSION][0];
1028      fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1];
1029      fcmd2[MTL_EMMISSIVE_BLUE]  = mat[MAT_ATTRIB_BACK_EMISSION][2];
1030      fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3];
1031   }
1032   if (mask & MAT_BIT_BACK_AMBIENT) {
1033      fcmd2[MTL_AMBIENT_RED]     = mat[MAT_ATTRIB_BACK_AMBIENT][0];
1034      fcmd2[MTL_AMBIENT_GREEN]   = mat[MAT_ATTRIB_BACK_AMBIENT][1];
1035      fcmd2[MTL_AMBIENT_BLUE]    = mat[MAT_ATTRIB_BACK_AMBIENT][2];
1036      fcmd2[MTL_AMBIENT_ALPHA]   = mat[MAT_ATTRIB_BACK_AMBIENT][3];
1037   }
1038   if (mask & MAT_BIT_BACK_DIFFUSE) {
1039      fcmd2[MTL_DIFFUSE_RED]     = mat[MAT_ATTRIB_BACK_DIFFUSE][0];
1040      fcmd2[MTL_DIFFUSE_GREEN]   = mat[MAT_ATTRIB_BACK_DIFFUSE][1];
1041      fcmd2[MTL_DIFFUSE_BLUE]    = mat[MAT_ATTRIB_BACK_DIFFUSE][2];
1042      fcmd2[MTL_DIFFUSE_ALPHA]   = mat[MAT_ATTRIB_BACK_DIFFUSE][3];
1043   }
1044   if (mask & MAT_BIT_BACK_SPECULAR) {
1045      fcmd2[MTL_SPECULAR_RED]    = mat[MAT_ATTRIB_BACK_SPECULAR][0];
1046      fcmd2[MTL_SPECULAR_GREEN]  = mat[MAT_ATTRIB_BACK_SPECULAR][1];
1047      fcmd2[MTL_SPECULAR_BLUE]   = mat[MAT_ATTRIB_BACK_SPECULAR][2];
1048      fcmd2[MTL_SPECULAR_ALPHA]  = mat[MAT_ATTRIB_BACK_SPECULAR][3];
1049   }
1050   if (mask & MAT_BIT_BACK_SHININESS) {
1051      fcmd2[MTL_SHININESS]       = mat[MAT_ATTRIB_BACK_SHININESS][0];
1052   }
1053
1054   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] );
1055   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] );
1056
1057   /* currently material changes cannot trigger a global ambient change, I believe this is correct
1058    update_global_ambient( ctx ); */
1059}
1060
1061/* _NEW_LIGHT
1062 * _NEW_MODELVIEW
1063 * _MESA_NEW_NEED_EYE_COORDS
1064 *
1065 * Uses derived state from mesa:
1066 *       _VP_inf_norm
1067 *       _h_inf_norm
1068 *       _Position
1069 *       _NormSpotDirection
1070 *       _ModelViewInvScale
1071 *       _NeedEyeCoords
1072 *       _EyeZDir
1073 *
1074 * which are calculated in light.c and are correct for the current
1075 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1076 * and _MESA_NEW_NEED_EYE_COORDS.
1077 */
1078static void update_light( struct gl_context *ctx )
1079{
1080   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1081
1082   /* Have to check these, or have an automatic shortcircuit mechanism
1083    * to remove noop statechanges. (Or just do a better job on the
1084    * front end).
1085    */
1086   {
1087      GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
1088
1089      if (ctx->_NeedEyeCoords)
1090	 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1091      else
1092	 tmp |= R200_LIGHT_IN_MODELSPACE;
1093
1094      if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1095      {
1096	 R200_STATECHANGE( rmesa, tcl );
1097	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1098      }
1099   }
1100
1101   {
1102      GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1103      fcmd[EYE_X] = ctx->_EyeZDir[0];
1104      fcmd[EYE_Y] = ctx->_EyeZDir[1];
1105      fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1106      fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1107      R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1108   }
1109
1110
1111
1112   if (ctx->Light.Enabled) {
1113      GLint p;
1114      for (p = 0 ; p < MAX_LIGHTS; p++) {
1115	 if (ctx->Light.Light[p].Enabled) {
1116	    struct gl_light *l = &ctx->Light.Light[p];
1117	    GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1118
1119	    if (l->EyePosition[3] == 0.0) {
1120	       COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1121	       COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1122	       fcmd[LIT_POSITION_W] = 0;
1123	       fcmd[LIT_DIRECTION_W] = 0;
1124	    } else {
1125	       COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1126	       fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0];
1127	       fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1];
1128	       fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2];
1129	       fcmd[LIT_DIRECTION_W] = 0;
1130	    }
1131
1132	    R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1133	 }
1134      }
1135   }
1136}
1137
1138static void r200Lightfv( struct gl_context *ctx, GLenum light,
1139			   GLenum pname, const GLfloat *params )
1140{
1141   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1142   GLint p = light - GL_LIGHT0;
1143   struct gl_light *l = &ctx->Light.Light[p];
1144   GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1145
1146
1147   switch (pname) {
1148   case GL_AMBIENT:
1149   case GL_DIFFUSE:
1150   case GL_SPECULAR:
1151      update_light_colors( ctx, p );
1152      break;
1153
1154   case GL_SPOT_DIRECTION:
1155      /* picked up in update_light */
1156      break;
1157
1158   case GL_POSITION: {
1159      /* positions picked up in update_light, but can do flag here */
1160      GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1161      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1162
1163      R200_STATECHANGE(rmesa, tcl);
1164      if (l->EyePosition[3] != 0.0F)
1165	 rmesa->hw.tcl.cmd[idx] |= flag;
1166      else
1167	 rmesa->hw.tcl.cmd[idx] &= ~flag;
1168      break;
1169   }
1170
1171   case GL_SPOT_EXPONENT:
1172      R200_STATECHANGE(rmesa, lit[p]);
1173      fcmd[LIT_SPOT_EXPONENT] = params[0];
1174      break;
1175
1176   case GL_SPOT_CUTOFF: {
1177      GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1178      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1179
1180      R200_STATECHANGE(rmesa, lit[p]);
1181      fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1182
1183      R200_STATECHANGE(rmesa, tcl);
1184      if (l->SpotCutoff != 180.0F)
1185	 rmesa->hw.tcl.cmd[idx] |= flag;
1186      else
1187	 rmesa->hw.tcl.cmd[idx] &= ~flag;
1188
1189      break;
1190   }
1191
1192   case GL_CONSTANT_ATTENUATION:
1193      R200_STATECHANGE(rmesa, lit[p]);
1194      fcmd[LIT_ATTEN_CONST] = params[0];
1195      if ( params[0] == 0.0 )
1196	 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1197      else
1198	 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1199      break;
1200   case GL_LINEAR_ATTENUATION:
1201      R200_STATECHANGE(rmesa, lit[p]);
1202      fcmd[LIT_ATTEN_LINEAR] = params[0];
1203      break;
1204   case GL_QUADRATIC_ATTENUATION:
1205      R200_STATECHANGE(rmesa, lit[p]);
1206      fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1207      break;
1208   default:
1209      return;
1210   }
1211
1212   /* Set RANGE_ATTEN only when needed */
1213   switch (pname) {
1214   case GL_POSITION:
1215   case GL_CONSTANT_ATTENUATION:
1216   case GL_LINEAR_ATTENUATION:
1217   case GL_QUADRATIC_ATTENUATION: {
1218      GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1219      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1220      GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1221				  : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1222      GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1223				  : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1224
1225      if ( l->EyePosition[3] == 0.0F ||
1226	   ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1227	     fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1228	 /* Disable attenuation */
1229	 icmd[idx] &= ~atten_flag;
1230      } else {
1231	 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1232	    /* Enable only constant portion of attenuation calculation */
1233	    icmd[idx] |= ( atten_flag | atten_const_flag );
1234	 } else {
1235	    /* Enable full attenuation calculation */
1236	    icmd[idx] &= ~atten_const_flag;
1237	    icmd[idx] |= atten_flag;
1238	 }
1239      }
1240
1241      R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1242      break;
1243   }
1244   default:
1245     break;
1246   }
1247}
1248
1249static void r200UpdateLocalViewer ( struct gl_context *ctx )
1250{
1251/* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1252   GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1253   for these and only these modes). This means specular highlights may turn out
1254   wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1255   is not set, though it seems to happen rarely and the effect seems quite
1256   subtle. May need TCL fallback to fix it completely, though I'm not sure
1257   how you'd identify the cases where the specular highlights indeed will
1258   be wrong. Don't know if fglrx does something special in that case.
1259*/
1260   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1261   R200_STATECHANGE( rmesa, tcl );
1262   if (ctx->Light.Model.LocalViewer ||
1263       ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
1264      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1265   else
1266      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1267}
1268
1269static void r200LightModelfv( struct gl_context *ctx, GLenum pname,
1270				const GLfloat *param )
1271{
1272   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1273
1274   switch (pname) {
1275      case GL_LIGHT_MODEL_AMBIENT:
1276	 update_global_ambient( ctx );
1277	 break;
1278
1279      case GL_LIGHT_MODEL_LOCAL_VIEWER:
1280	 r200UpdateLocalViewer( ctx );
1281         break;
1282
1283      case GL_LIGHT_MODEL_TWO_SIDE:
1284	 R200_STATECHANGE( rmesa, tcl );
1285	 if (ctx->Light.Model.TwoSide)
1286	    rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1287	 else
1288	    rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1289	 if (rmesa->radeon.TclFallback) {
1290	    r200ChooseRenderState( ctx );
1291	    r200ChooseVertexState( ctx );
1292	 }
1293         break;
1294
1295      case GL_LIGHT_MODEL_COLOR_CONTROL:
1296	 r200UpdateSpecular(ctx);
1297         break;
1298
1299      default:
1300         break;
1301   }
1302}
1303
1304static void r200ShadeModel( struct gl_context *ctx, GLenum mode )
1305{
1306   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1307   GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1308
1309   s &= ~(R200_DIFFUSE_SHADE_MASK |
1310	  R200_ALPHA_SHADE_MASK |
1311	  R200_SPECULAR_SHADE_MASK |
1312	  R200_FOG_SHADE_MASK |
1313	  R200_DISC_FOG_SHADE_MASK);
1314
1315   switch ( mode ) {
1316   case GL_FLAT:
1317      s |= (R200_DIFFUSE_SHADE_FLAT |
1318	    R200_ALPHA_SHADE_FLAT |
1319	    R200_SPECULAR_SHADE_FLAT |
1320	    R200_FOG_SHADE_FLAT |
1321	    R200_DISC_FOG_SHADE_FLAT);
1322      break;
1323   case GL_SMOOTH:
1324      s |= (R200_DIFFUSE_SHADE_GOURAUD |
1325	    R200_ALPHA_SHADE_GOURAUD |
1326	    R200_SPECULAR_SHADE_GOURAUD |
1327	    R200_FOG_SHADE_GOURAUD |
1328	    R200_DISC_FOG_SHADE_GOURAUD);
1329      break;
1330   default:
1331      return;
1332   }
1333
1334   if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1335      R200_STATECHANGE( rmesa, set );
1336      rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1337   }
1338}
1339
1340
1341/* =============================================================
1342 * User clip planes
1343 */
1344
1345static void r200ClipPlane( struct gl_context *ctx, GLenum plane, const GLfloat *eq )
1346{
1347   GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1348   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1349   GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1350
1351   R200_STATECHANGE( rmesa, ucp[p] );
1352   rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1353   rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1354   rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1355   rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1356}
1357
1358static void r200UpdateClipPlanes( struct gl_context *ctx )
1359{
1360   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1361   GLuint p;
1362
1363   for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1364      if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1365	 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1366
1367	 R200_STATECHANGE( rmesa, ucp[p] );
1368	 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1369	 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1370	 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1371	 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1372      }
1373   }
1374}
1375
1376
1377/* =============================================================
1378 * Stencil
1379 */
1380
1381static void
1382r200StencilFuncSeparate( struct gl_context *ctx, GLenum face, GLenum func,
1383                         GLint ref, GLuint mask )
1384{
1385   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1386   GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R200_STENCIL_REF_SHIFT) |
1387		     ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT));
1388
1389   R200_STATECHANGE( rmesa, ctx );
1390   R200_STATECHANGE( rmesa, msk );
1391
1392   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1393   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1394						   R200_STENCIL_VALUE_MASK);
1395
1396   switch ( ctx->Stencil.Function[0] ) {
1397   case GL_NEVER:
1398      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1399      break;
1400   case GL_LESS:
1401      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1402      break;
1403   case GL_EQUAL:
1404      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1405      break;
1406   case GL_LEQUAL:
1407      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1408      break;
1409   case GL_GREATER:
1410      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1411      break;
1412   case GL_NOTEQUAL:
1413      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1414      break;
1415   case GL_GEQUAL:
1416      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1417      break;
1418   case GL_ALWAYS:
1419      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1420      break;
1421   }
1422
1423   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1424}
1425
1426static void
1427r200StencilMaskSeparate( struct gl_context *ctx, GLenum face, GLuint mask )
1428{
1429   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1430
1431   R200_STATECHANGE( rmesa, msk );
1432   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1433   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1434      ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT);
1435}
1436
1437static void
1438r200StencilOpSeparate( struct gl_context *ctx, GLenum face, GLenum fail,
1439                       GLenum zfail, GLenum zpass )
1440{
1441   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1442
1443   R200_STATECHANGE( rmesa, ctx );
1444   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1445					       R200_STENCIL_ZFAIL_MASK |
1446					       R200_STENCIL_ZPASS_MASK);
1447
1448   switch ( ctx->Stencil.FailFunc[0] ) {
1449   case GL_KEEP:
1450      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1451      break;
1452   case GL_ZERO:
1453      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1454      break;
1455   case GL_REPLACE:
1456      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1457      break;
1458   case GL_INCR:
1459      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1460      break;
1461   case GL_DECR:
1462      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1463      break;
1464   case GL_INCR_WRAP_EXT:
1465      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1466      break;
1467   case GL_DECR_WRAP_EXT:
1468      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1469      break;
1470   case GL_INVERT:
1471      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1472      break;
1473   }
1474
1475   switch ( ctx->Stencil.ZFailFunc[0] ) {
1476   case GL_KEEP:
1477      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1478      break;
1479   case GL_ZERO:
1480      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1481      break;
1482   case GL_REPLACE:
1483      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1484      break;
1485   case GL_INCR:
1486      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1487      break;
1488   case GL_DECR:
1489      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1490      break;
1491   case GL_INCR_WRAP_EXT:
1492      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1493      break;
1494   case GL_DECR_WRAP_EXT:
1495      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1496      break;
1497   case GL_INVERT:
1498      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1499      break;
1500   }
1501
1502   switch ( ctx->Stencil.ZPassFunc[0] ) {
1503   case GL_KEEP:
1504      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1505      break;
1506   case GL_ZERO:
1507      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1508      break;
1509   case GL_REPLACE:
1510      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1511      break;
1512   case GL_INCR:
1513      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1514      break;
1515   case GL_DECR:
1516      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1517      break;
1518   case GL_INCR_WRAP_EXT:
1519      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1520      break;
1521   case GL_DECR_WRAP_EXT:
1522      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1523      break;
1524   case GL_INVERT:
1525      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1526      break;
1527   }
1528}
1529
1530
1531/* =============================================================
1532 * Window position and viewport transformation
1533 */
1534
1535/**
1536 * Called when window size or position changes or viewport or depth range
1537 * state is changed.  We update the hardware viewport state here.
1538 */
1539void r200UpdateWindow( struct gl_context *ctx )
1540{
1541   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1542   __DRIdrawable *dPriv = radeon_get_drawable(&rmesa->radeon);
1543   GLfloat xoffset = 0;
1544   GLfloat yoffset = dPriv ? (GLfloat) dPriv->h : 0;
1545   const GLfloat *v = ctx->Viewport._WindowMap.m;
1546   const GLboolean render_to_fbo = (ctx->DrawBuffer ? _mesa_is_user_fbo(ctx->DrawBuffer) : 0);
1547   const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
1548   GLfloat y_scale, y_bias;
1549
1550   if (render_to_fbo) {
1551      y_scale = 1.0;
1552      y_bias = 0;
1553   } else {
1554      y_scale = -1.0;
1555      y_bias = yoffset;
1556   }
1557
1558   float_ui32_type sx = { v[MAT_SX] };
1559   float_ui32_type tx = { v[MAT_TX] + xoffset };
1560   float_ui32_type sy = { v[MAT_SY] * y_scale };
1561   float_ui32_type ty = { (v[MAT_TY] * y_scale) + y_bias };
1562   float_ui32_type sz = { v[MAT_SZ] * depthScale };
1563   float_ui32_type tz = { v[MAT_TZ] * depthScale };
1564
1565   R200_STATECHANGE( rmesa, vpt );
1566
1567   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE]  = sx.ui32;
1568   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1569   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE]  = sy.ui32;
1570   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1571   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE]  = sz.ui32;
1572   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1573}
1574
1575void r200_vtbl_update_scissor( struct gl_context *ctx )
1576{
1577   r200ContextPtr r200 = R200_CONTEXT(ctx);
1578   unsigned x1, y1, x2, y2;
1579   struct radeon_renderbuffer *rrb;
1580
1581   R200_SET_STATE(r200, set, SET_RE_CNTL, R200_SCISSOR_ENABLE | r200->hw.set.cmd[SET_RE_CNTL]);
1582
1583   if (r200->radeon.state.scissor.enabled) {
1584      x1 = r200->radeon.state.scissor.rect.x1;
1585      y1 = r200->radeon.state.scissor.rect.y1;
1586      x2 = r200->radeon.state.scissor.rect.x2;
1587      y2 = r200->radeon.state.scissor.rect.y2;
1588   } else {
1589      rrb = radeon_get_colorbuffer(&r200->radeon);
1590      x1 = 0;
1591      y1 = 0;
1592      x2 = rrb->base.Base.Width - 1;
1593      y2 = rrb->base.Base.Height - 1;
1594   }
1595
1596   R200_SET_STATE(r200, sci, SCI_XY_1, x1 | (y1 << 16));
1597   R200_SET_STATE(r200, sci, SCI_XY_2, x2 | (y2 << 16));
1598}
1599
1600
1601static void r200Viewport( struct gl_context *ctx, GLint x, GLint y,
1602			    GLsizei width, GLsizei height )
1603{
1604   /* Don't pipeline viewport changes, conflict with window offset
1605    * setting below.  Could apply deltas to rescue pipelined viewport
1606    * values, or keep the originals hanging around.
1607    */
1608   r200UpdateWindow( ctx );
1609
1610   radeon_viewport(ctx, x, y, width, height);
1611}
1612
1613static void r200DepthRange( struct gl_context *ctx, GLclampd nearval,
1614			      GLclampd farval )
1615{
1616   r200UpdateWindow( ctx );
1617}
1618
1619void r200UpdateViewportOffset( struct gl_context *ctx )
1620{
1621   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1622   __DRIdrawable *dPriv = radeon_get_drawable(&rmesa->radeon);
1623   GLfloat xoffset = (GLfloat)0;
1624   GLfloat yoffset = (GLfloat)dPriv->h;
1625   const GLfloat *v = ctx->Viewport._WindowMap.m;
1626
1627   float_ui32_type tx;
1628   float_ui32_type ty;
1629
1630   tx.f = v[MAT_TX] + xoffset;
1631   ty.f = (- v[MAT_TY]) + yoffset;
1632
1633   if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 ||
1634	rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 )
1635   {
1636      /* Note: this should also modify whatever data the context reset
1637       * code uses...
1638       */
1639      R200_STATECHANGE( rmesa, vpt );
1640      rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1641      rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1642
1643      /* update polygon stipple x/y screen offset */
1644      {
1645         GLuint stx, sty;
1646         GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1647
1648         m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1649                R200_STIPPLE_Y_OFFSET_MASK);
1650
1651         /* add magic offsets, then invert */
1652         stx = 31 - ((-1) & R200_STIPPLE_COORD_MASK);
1653         sty = 31 - ((dPriv->h - 1)
1654                     & R200_STIPPLE_COORD_MASK);
1655
1656         m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1657               (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1658
1659         if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1660            R200_STATECHANGE( rmesa, msc );
1661	    rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1662         }
1663      }
1664   }
1665
1666   radeonUpdateScissor( ctx );
1667}
1668
1669
1670
1671/* =============================================================
1672 * Miscellaneous
1673 */
1674
1675static void r200RenderMode( struct gl_context *ctx, GLenum mode )
1676{
1677   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1678   FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1679}
1680
1681
1682static GLuint r200_rop_tab[] = {
1683   R200_ROP_CLEAR,
1684   R200_ROP_AND,
1685   R200_ROP_AND_REVERSE,
1686   R200_ROP_COPY,
1687   R200_ROP_AND_INVERTED,
1688   R200_ROP_NOOP,
1689   R200_ROP_XOR,
1690   R200_ROP_OR,
1691   R200_ROP_NOR,
1692   R200_ROP_EQUIV,
1693   R200_ROP_INVERT,
1694   R200_ROP_OR_REVERSE,
1695   R200_ROP_COPY_INVERTED,
1696   R200_ROP_OR_INVERTED,
1697   R200_ROP_NAND,
1698   R200_ROP_SET,
1699};
1700
1701static void r200LogicOpCode( struct gl_context *ctx, GLenum opcode )
1702{
1703   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1704   GLuint rop = (GLuint)opcode - GL_CLEAR;
1705
1706   ASSERT( rop < 16 );
1707
1708   R200_STATECHANGE( rmesa, msk );
1709   rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1710}
1711
1712/* =============================================================
1713 * State enable/disable
1714 */
1715
1716static void r200Enable( struct gl_context *ctx, GLenum cap, GLboolean state )
1717{
1718   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1719   GLuint p, flag;
1720
1721   if ( R200_DEBUG & RADEON_STATE )
1722      fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1723	       _mesa_lookup_enum_by_nr( cap ),
1724	       state ? "GL_TRUE" : "GL_FALSE" );
1725
1726   switch ( cap ) {
1727      /* Fast track this one...
1728       */
1729   case GL_TEXTURE_1D:
1730   case GL_TEXTURE_2D:
1731   case GL_TEXTURE_3D:
1732      break;
1733
1734   case GL_ALPHA_TEST:
1735      R200_STATECHANGE( rmesa, ctx );
1736      if (state) {
1737	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1738      } else {
1739	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1740      }
1741      break;
1742
1743   case GL_BLEND:
1744   case GL_COLOR_LOGIC_OP:
1745      r200_set_blend_state( ctx );
1746      break;
1747
1748   case GL_CLIP_PLANE0:
1749   case GL_CLIP_PLANE1:
1750   case GL_CLIP_PLANE2:
1751   case GL_CLIP_PLANE3:
1752   case GL_CLIP_PLANE4:
1753   case GL_CLIP_PLANE5:
1754      p = cap-GL_CLIP_PLANE0;
1755      R200_STATECHANGE( rmesa, tcl );
1756      if (state) {
1757	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1758	 r200ClipPlane( ctx, cap, NULL );
1759      }
1760      else {
1761	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1762      }
1763      break;
1764
1765   case GL_COLOR_MATERIAL:
1766      r200ColorMaterial( ctx, 0, 0 );
1767      r200UpdateMaterial( ctx );
1768      break;
1769
1770   case GL_CULL_FACE:
1771      r200CullFace( ctx, 0 );
1772      break;
1773
1774   case GL_DEPTH_TEST:
1775      R200_STATECHANGE(rmesa, ctx );
1776      if ( state ) {
1777	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_Z_ENABLE;
1778      } else {
1779	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1780      }
1781      break;
1782
1783   case GL_DITHER:
1784      R200_STATECHANGE(rmesa, ctx );
1785      if ( state ) {
1786	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_DITHER_ENABLE;
1787	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable;
1788      } else {
1789	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1790	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  rmesa->radeon.state.color.roundEnable;
1791      }
1792      break;
1793
1794   case GL_FOG:
1795      R200_STATECHANGE(rmesa, ctx );
1796      if ( state ) {
1797	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1798	 r200Fogfv( ctx, GL_FOG_MODE, NULL );
1799      } else {
1800	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1801	 R200_STATECHANGE(rmesa, tcl);
1802	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1803      }
1804      r200UpdateSpecular( ctx ); /* for PK_SPEC */
1805      if (rmesa->radeon.TclFallback)
1806	 r200ChooseVertexState( ctx );
1807      _mesa_allow_light_in_model( ctx, !state );
1808      break;
1809
1810   case GL_LIGHT0:
1811   case GL_LIGHT1:
1812   case GL_LIGHT2:
1813   case GL_LIGHT3:
1814   case GL_LIGHT4:
1815   case GL_LIGHT5:
1816   case GL_LIGHT6:
1817   case GL_LIGHT7:
1818      R200_STATECHANGE(rmesa, tcl);
1819      p = cap - GL_LIGHT0;
1820      if (p&1)
1821	 flag = (R200_LIGHT_1_ENABLE |
1822		 R200_LIGHT_1_ENABLE_AMBIENT |
1823		 R200_LIGHT_1_ENABLE_SPECULAR);
1824      else
1825	 flag = (R200_LIGHT_0_ENABLE |
1826		 R200_LIGHT_0_ENABLE_AMBIENT |
1827		 R200_LIGHT_0_ENABLE_SPECULAR);
1828
1829      if (state)
1830	 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1831      else
1832	 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1833
1834      /*
1835       */
1836      update_light_colors( ctx, p );
1837      break;
1838
1839   case GL_LIGHTING:
1840      r200UpdateSpecular(ctx);
1841      /* for reflection map fixup - might set recheck_texgen for all units too */
1842      rmesa->radeon.NewGLState |= _NEW_TEXTURE;
1843      break;
1844
1845   case GL_LINE_SMOOTH:
1846      R200_STATECHANGE( rmesa, ctx );
1847      if ( state ) {
1848	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  R200_ANTI_ALIAS_LINE;
1849      } else {
1850	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1851      }
1852      break;
1853
1854   case GL_LINE_STIPPLE:
1855      R200_STATECHANGE( rmesa, set );
1856      if ( state ) {
1857	 rmesa->hw.set.cmd[SET_RE_CNTL] |=  R200_PATTERN_ENABLE;
1858      } else {
1859	 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1860      }
1861      break;
1862
1863   case GL_NORMALIZE:
1864      R200_STATECHANGE( rmesa, tcl );
1865      if ( state ) {
1866	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_NORMALIZE_NORMALS;
1867      } else {
1868	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1869      }
1870      break;
1871
1872      /* Pointsize registers on r200 only work for point sprites, and point smooth
1873       * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1874       * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1875       * is enough to satisfy conform.
1876       */
1877   case GL_POINT_SMOOTH:
1878      break;
1879
1880      /* These don't really do anything, as we don't use the 3vtx
1881       * primitives yet.
1882       */
1883#if 0
1884   case GL_POLYGON_OFFSET_POINT:
1885      R200_STATECHANGE( rmesa, set );
1886      if ( state ) {
1887	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_POINT;
1888      } else {
1889	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1890      }
1891      break;
1892
1893   case GL_POLYGON_OFFSET_LINE:
1894      R200_STATECHANGE( rmesa, set );
1895      if ( state ) {
1896	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_LINE;
1897      } else {
1898	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1899      }
1900      break;
1901#endif
1902
1903   case GL_POINT_SPRITE_ARB:
1904      R200_STATECHANGE( rmesa, spr );
1905      if ( state ) {
1906	 int i;
1907	 for (i = 0; i < 6; i++) {
1908	    rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
1909		ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i);
1910	 }
1911      } else {
1912	 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
1913      }
1914      break;
1915
1916   case GL_POLYGON_OFFSET_FILL:
1917      R200_STATECHANGE( rmesa, set );
1918      if ( state ) {
1919	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_TRI;
1920      } else {
1921	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
1922      }
1923      break;
1924
1925   case GL_POLYGON_SMOOTH:
1926      R200_STATECHANGE( rmesa, ctx );
1927      if ( state ) {
1928	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  R200_ANTI_ALIAS_POLY;
1929      } else {
1930	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
1931      }
1932      break;
1933
1934   case GL_POLYGON_STIPPLE:
1935      R200_STATECHANGE(rmesa, set );
1936      if ( state ) {
1937	 rmesa->hw.set.cmd[SET_RE_CNTL] |=  R200_STIPPLE_ENABLE;
1938      } else {
1939	 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
1940      }
1941      break;
1942
1943   case GL_RESCALE_NORMAL_EXT: {
1944      GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1945      R200_STATECHANGE( rmesa, tcl );
1946      if ( tmp ) {
1947	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_RESCALE_NORMALS;
1948      } else {
1949	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1950      }
1951      break;
1952   }
1953
1954   case GL_SCISSOR_TEST:
1955      radeon_firevertices(&rmesa->radeon);
1956      rmesa->radeon.state.scissor.enabled = state;
1957      radeonUpdateScissor( ctx );
1958      break;
1959
1960   case GL_STENCIL_TEST:
1961      {
1962	 GLboolean hw_stencil = GL_FALSE;
1963	 if (ctx->DrawBuffer) {
1964	    struct radeon_renderbuffer *rrbStencil
1965	       = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
1966	    hw_stencil = (rrbStencil && rrbStencil->bo);
1967	 }
1968
1969	 if (hw_stencil) {
1970	    R200_STATECHANGE( rmesa, ctx );
1971	    if ( state ) {
1972	       rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_STENCIL_ENABLE;
1973	    } else {
1974	       rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
1975	    }
1976	 } else {
1977	    FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
1978	 }
1979      }
1980      break;
1981
1982   case GL_TEXTURE_GEN_Q:
1983   case GL_TEXTURE_GEN_R:
1984   case GL_TEXTURE_GEN_S:
1985   case GL_TEXTURE_GEN_T:
1986      /* Picked up in r200UpdateTextureState.
1987       */
1988      rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1989      break;
1990
1991   case GL_COLOR_SUM_EXT:
1992      r200UpdateSpecular ( ctx );
1993      break;
1994
1995   case GL_VERTEX_PROGRAM_ARB:
1996      if (!state) {
1997	 GLuint i;
1998	 rmesa->curr_vp_hw = NULL;
1999	 R200_STATECHANGE( rmesa, vap );
2000	 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
2001	 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2002	    not sure about tcl scalar state - we need at least grd
2003	    with vert progs too.
2004	    ucp looks like it doesn't get overwritten (may even work
2005	    with vp for pos-invariant progs if we're lucky) */
2006	 R200_STATECHANGE( rmesa, mtl[0] );
2007	 R200_STATECHANGE( rmesa, mtl[1] );
2008	 R200_STATECHANGE( rmesa, fog );
2009	 R200_STATECHANGE( rmesa, glt );
2010	 R200_STATECHANGE( rmesa, eye );
2011	 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
2012	    R200_STATECHANGE( rmesa, mat[i] );
2013	 }
2014	 for (i = 0 ; i < 8; i++) {
2015	    R200_STATECHANGE( rmesa, lit[i] );
2016	 }
2017	 R200_STATECHANGE( rmesa, tcl );
2018	 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
2019	    if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
2020	       rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
2021	    }
2022/*	    else {
2023	       rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2024	    }*/
2025	 }
2026	 /* ugly. Need to call everything which might change compsel. */
2027	 r200UpdateSpecular( ctx );
2028#if 0
2029	/* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2030	   but without it doom3 locks up at always the same places. Why? */
2031	/* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2032	   accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2033	 r200UpdateTextureState( ctx );
2034	 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2035	    non-current derived enabled values which may revert the state atoms for frag progs even when
2036	    they already got disabled... ugh
2037	    Should really figure out why we need to call r200UpdateTextureState in the first place */
2038	 GLuint unit;
2039	 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2040	    R200_STATECHANGE( rmesa, pix[unit] );
2041	    R200_STATECHANGE( rmesa, tex[unit] );
2042	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2043		~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2044	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2045	    /* need to guard this with drmSupportsFragmentShader? Should never get here if
2046	       we don't announce ATI_fs, right? */
2047	    rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2048         }
2049	 R200_STATECHANGE( rmesa, cst );
2050	 R200_STATECHANGE( rmesa, tf );
2051	 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2052#endif
2053      }
2054      else {
2055	 /* picked up later */
2056      }
2057      /* call functions which change hw state based on ARB_vp enabled or not. */
2058      r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2059      r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
2060      break;
2061
2062   case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
2063      r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2064      break;
2065
2066   case GL_FRAGMENT_SHADER_ATI:
2067      if ( !state ) {
2068	 /* restore normal tex env colors and make sure tex env combine will get updated
2069	    mark env atoms dirty (as their data was overwritten by afs even
2070	    if they didn't change) and restore tex coord routing */
2071	 GLuint unit;
2072	 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2073	    R200_STATECHANGE( rmesa, pix[unit] );
2074	    R200_STATECHANGE( rmesa, tex[unit] );
2075	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2076		~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2077	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2078	    rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2079         }
2080	 R200_STATECHANGE( rmesa, cst );
2081	 R200_STATECHANGE( rmesa, tf );
2082	 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2083      }
2084      else {
2085	 /* need to mark this dirty as pix/tf atoms have overwritten the data
2086	    even if the data in the atoms didn't change */
2087	 R200_STATECHANGE( rmesa, atf );
2088	 R200_STATECHANGE( rmesa, afs[1] );
2089	 /* everything else picked up in r200UpdateTextureState hopefully */
2090      }
2091      break;
2092   default:
2093      return;
2094   }
2095}
2096
2097
2098void r200LightingSpaceChange( struct gl_context *ctx )
2099{
2100   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2101   GLboolean tmp;
2102
2103   if (R200_DEBUG & RADEON_STATE)
2104      fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2105	      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2106
2107   if (ctx->_NeedEyeCoords)
2108      tmp = ctx->Transform.RescaleNormals;
2109   else
2110      tmp = !ctx->Transform.RescaleNormals;
2111
2112   R200_STATECHANGE( rmesa, tcl );
2113   if ( tmp ) {
2114      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_RESCALE_NORMALS;
2115   } else {
2116      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2117   }
2118
2119   if (R200_DEBUG & RADEON_STATE)
2120      fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2121	      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2122}
2123
2124/* =============================================================
2125 * Deferred state management - matrices, textures, other?
2126 */
2127
2128
2129
2130
2131static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2132{
2133   float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2134   int i;
2135
2136
2137   for (i = 0 ; i < 4 ; i++) {
2138      *dest++ = src[i];
2139      *dest++ = src[i+4];
2140      *dest++ = src[i+8];
2141      *dest++ = src[i+12];
2142   }
2143
2144   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2145}
2146
2147static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2148{
2149   float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2150   memcpy(dest, src, 16*sizeof(float));
2151   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2152}
2153
2154
2155static void update_texturematrix( struct gl_context *ctx )
2156{
2157   r200ContextPtr rmesa = R200_CONTEXT( ctx );
2158   GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2159   GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2160   int unit;
2161
2162   if (R200_DEBUG & RADEON_STATE)
2163      fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
2164	      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2165
2166   rmesa->TexMatEnabled = 0;
2167   rmesa->TexMatCompSel = 0;
2168
2169   for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2170      if (!ctx->Texture.Unit[unit]._ReallyEnabled)
2171	 continue;
2172
2173      if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2174	 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2175				  R200_TEXMAT_0_ENABLE) << unit;
2176
2177	 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2178
2179	 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2180	    /* Need to preconcatenate any active texgen
2181	     * obj/eyeplane matrices:
2182	     */
2183	    _math_matrix_mul_matrix( &rmesa->tmpmat,
2184				     ctx->TextureMatrixStack[unit].Top,
2185				     &rmesa->TexGenMatrix[unit] );
2186	    upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2187	 }
2188	 else {
2189	    upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2190			   R200_MTX_TEX0+unit );
2191	 }
2192      }
2193      else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2194	 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2195			R200_MTX_TEX0+unit );
2196      }
2197   }
2198
2199   tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2200   if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2201      R200_STATECHANGE(rmesa, tcg);
2202      rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2203   }
2204
2205   compsel &= ~R200_OUTPUT_TEX_MASK;
2206   compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2207   if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2208      R200_STATECHANGE(rmesa, vtx);
2209      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2210   }
2211}
2212
2213static GLboolean r200ValidateBuffers(struct gl_context *ctx)
2214{
2215   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2216   struct radeon_renderbuffer *rrb;
2217   struct radeon_dma_bo *dma_bo;
2218   int i, ret;
2219
2220	if (RADEON_DEBUG & RADEON_IOCTL)
2221		fprintf(stderr, "%s\n", __FUNCTION__);
2222   radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs);
2223
2224   rrb = radeon_get_colorbuffer(&rmesa->radeon);
2225   /* color buffer */
2226   if (rrb && rrb->bo) {
2227     radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2228				       0, RADEON_GEM_DOMAIN_VRAM);
2229   }
2230
2231   /* depth buffer */
2232   rrb = radeon_get_depthbuffer(&rmesa->radeon);
2233   /* color buffer */
2234   if (rrb && rrb->bo) {
2235     radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2236				       0, RADEON_GEM_DOMAIN_VRAM);
2237   }
2238
2239   for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
2240      radeonTexObj *t;
2241
2242      if (!ctx->Texture.Unit[i]._ReallyEnabled)
2243	 continue;
2244
2245      t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
2246      if (t->image_override && t->bo)
2247	radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo,
2248			   RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2249      else if (t->mt->bo)
2250	radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo,
2251			   RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2252   }
2253
2254   dma_bo = first_elem(&rmesa->radeon.dma.reserved);
2255   {
2256       ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, dma_bo->bo, RADEON_GEM_DOMAIN_GTT, 0);
2257       if (ret)
2258	   return GL_FALSE;
2259   }
2260   return GL_TRUE;
2261}
2262
2263GLboolean r200ValidateState( struct gl_context *ctx )
2264{
2265   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2266   GLuint new_state = rmesa->radeon.NewGLState;
2267
2268   if (new_state & _NEW_BUFFERS) {
2269      _mesa_update_framebuffer(ctx);
2270      /* this updates the DrawBuffer's Width/Height if it's a FBO */
2271      _mesa_update_draw_buffer_bounds(ctx);
2272
2273      R200_STATECHANGE(rmesa, ctx);
2274   }
2275
2276   if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) {
2277      r200UpdateTextureState( ctx );
2278      new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
2279      r200UpdateLocalViewer( ctx );
2280   }
2281
2282   /* we need to do a space check here */
2283   if (!r200ValidateBuffers(ctx))
2284     return GL_FALSE;
2285
2286/* FIXME: don't really need most of these when vertex progs are enabled */
2287
2288   /* Need an event driven matrix update?
2289    */
2290   if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2291      upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2292
2293   /* Need these for lighting (shouldn't upload otherwise)
2294    */
2295   if (new_state & (_NEW_MODELVIEW)) {
2296      upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2297      upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2298   }
2299
2300   /* Does this need to be triggered on eg. modelview for
2301    * texgen-derived objplane/eyeplane matrices?
2302    */
2303   if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2304      update_texturematrix( ctx );
2305   }
2306
2307   if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2308      update_light( ctx );
2309   }
2310
2311   /* emit all active clip planes if projection matrix changes.
2312    */
2313   if (new_state & (_NEW_PROJECTION)) {
2314      if (ctx->Transform.ClipPlanesEnabled)
2315	 r200UpdateClipPlanes( ctx );
2316   }
2317
2318   if (new_state & (_NEW_PROGRAM|
2319                    _NEW_PROGRAM_CONSTANTS |
2320   /* need to test for pretty much anything due to possible parameter bindings */
2321	_NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
2322	_NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
2323	_NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
2324      if (ctx->VertexProgram._Enabled) {
2325	 r200SetupVertexProg( ctx );
2326      }
2327      else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
2328   }
2329
2330   rmesa->radeon.NewGLState = 0;
2331   return GL_TRUE;
2332}
2333
2334
2335static void r200InvalidateState( struct gl_context *ctx, GLuint new_state )
2336{
2337   _swrast_InvalidateState( ctx, new_state );
2338   _swsetup_InvalidateState( ctx, new_state );
2339   _vbo_InvalidateState( ctx, new_state );
2340   _tnl_InvalidateState( ctx, new_state );
2341   _ae_invalidate_state( ctx, new_state );
2342   R200_CONTEXT(ctx)->radeon.NewGLState |= new_state;
2343}
2344
2345/* A hack.  The r200 can actually cope just fine with materials
2346 * between begin/ends, so fix this.
2347 * Should map to inputs just like the generic vertex arrays for vertex progs.
2348 * In theory there could still be too many and we'd still need a fallback.
2349 */
2350static GLboolean check_material( struct gl_context *ctx )
2351{
2352   TNLcontext *tnl = TNL_CONTEXT(ctx);
2353   GLint i;
2354
2355   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2356	i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2357	i++)
2358      if (tnl->vb.AttribPtr[i] &&
2359	  tnl->vb.AttribPtr[i]->stride)
2360	 return GL_TRUE;
2361
2362   return GL_FALSE;
2363}
2364
2365static void r200WrapRunPipeline( struct gl_context *ctx )
2366{
2367   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2368   GLboolean has_material;
2369
2370   if (0)
2371      fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->radeon.NewGLState);
2372
2373   /* Validate state:
2374    */
2375   if (rmesa->radeon.NewGLState)
2376      if (!r200ValidateState( ctx ))
2377	 FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
2378
2379   has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx );
2380
2381   if (has_material) {
2382      TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2383   }
2384
2385   /* Run the pipeline.
2386    */
2387   _tnl_run_pipeline( ctx );
2388
2389   if (has_material) {
2390      TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2391   }
2392}
2393
2394
2395static void r200PolygonStipple( struct gl_context *ctx, const GLubyte *mask )
2396{
2397   r200ContextPtr r200 = R200_CONTEXT(ctx);
2398   GLint i;
2399
2400   radeon_firevertices(&r200->radeon);
2401
2402   radeon_print(RADEON_STATE, RADEON_TRACE,
2403		   "%s(%p) first 32 bits are %x.\n",
2404		   __func__,
2405		   ctx,
2406		   *(uint32_t*)mask);
2407
2408   R200_STATECHANGE(r200, stp);
2409
2410   /* Must flip pattern upside down.
2411    */
2412   for ( i = 31 ; i >= 0; i--) {
2413     r200->hw.stp.cmd[3 + i] = ((GLuint *) mask)[i];
2414   }
2415}
2416/* Initialize the driver's state functions.
2417 */
2418void r200InitStateFuncs( radeonContextPtr radeon, struct dd_function_table *functions )
2419{
2420   functions->UpdateState		= r200InvalidateState;
2421   functions->LightingSpaceChange	= r200LightingSpaceChange;
2422
2423   functions->DrawBuffer		= radeonDrawBuffer;
2424   functions->ReadBuffer		= radeonReadBuffer;
2425
2426   functions->CopyPixels                = _mesa_meta_CopyPixels;
2427   functions->DrawPixels                = _mesa_meta_DrawPixels;
2428   functions->ReadPixels                = radeonReadPixels;
2429
2430   functions->AlphaFunc			= r200AlphaFunc;
2431   functions->BlendColor		= r200BlendColor;
2432   functions->BlendEquationSeparate	= r200BlendEquationSeparate;
2433   functions->BlendFuncSeparate		= r200BlendFuncSeparate;
2434   functions->ClipPlane			= r200ClipPlane;
2435   functions->ColorMask			= r200ColorMask;
2436   functions->CullFace			= r200CullFace;
2437   functions->DepthFunc			= r200DepthFunc;
2438   functions->DepthMask			= r200DepthMask;
2439   functions->DepthRange		= r200DepthRange;
2440   functions->Enable			= r200Enable;
2441   functions->Fogfv			= r200Fogfv;
2442   functions->FrontFace			= r200FrontFace;
2443   functions->Hint			= NULL;
2444   functions->LightModelfv		= r200LightModelfv;
2445   functions->Lightfv			= r200Lightfv;
2446   functions->LineStipple		= r200LineStipple;
2447   functions->LineWidth			= r200LineWidth;
2448   functions->LogicOpcode		= r200LogicOpCode;
2449   functions->PolygonMode		= r200PolygonMode;
2450   functions->PolygonOffset		= r200PolygonOffset;
2451   functions->PolygonStipple		= r200PolygonStipple;
2452   functions->PointParameterfv		= r200PointParameter;
2453   functions->PointSize			= r200PointSize;
2454   functions->RenderMode		= r200RenderMode;
2455   functions->Scissor			= radeonScissor;
2456   functions->ShadeModel		= r200ShadeModel;
2457   functions->StencilFuncSeparate	= r200StencilFuncSeparate;
2458   functions->StencilMaskSeparate	= r200StencilMaskSeparate;
2459   functions->StencilOpSeparate		= r200StencilOpSeparate;
2460   functions->Viewport			= r200Viewport;
2461}
2462
2463
2464void r200InitTnlFuncs( struct gl_context *ctx )
2465{
2466   TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2467   TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2468}
2469