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