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#include "main/imports.h"
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_R_MODE_NV:
634   case GL_POINT_SPRITE_COORD_ORIGIN: */
635   default:
636      fprintf(stderr, "bad pname parameter in r200PointParameter\n");
637      return;
638   }
639}
640
641/* =============================================================
642 * Line state
643 */
644static void r200LineWidth( struct gl_context *ctx, GLfloat widthf )
645{
646   r200ContextPtr rmesa = R200_CONTEXT(ctx);
647
648   R200_STATECHANGE( rmesa, lin );
649   R200_STATECHANGE( rmesa, set );
650
651   /* Line width is stored in U6.4 format.
652    * Same min/max limits for AA, non-AA lines.
653    */
654   rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff;
655   rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)
656      (CLAMP(widthf, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth) * 16.0);
657
658   if ( widthf > 1.0 ) {
659      rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_WIDELINE_ENABLE;
660   } else {
661      rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE;
662   }
663}
664
665static void r200LineStipple( struct gl_context *ctx, GLint factor, GLushort pattern )
666{
667   r200ContextPtr rmesa = R200_CONTEXT(ctx);
668
669   R200_STATECHANGE( rmesa, lin );
670   rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
671      ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
672}
673
674
675/* =============================================================
676 * Masks
677 */
678static void r200ColorMask( struct gl_context *ctx,
679			   GLboolean r, GLboolean g,
680			   GLboolean b, GLboolean a )
681{
682   r200ContextPtr rmesa = R200_CONTEXT(ctx);
683   GLuint mask;
684   struct radeon_renderbuffer *rrb;
685   GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
686
687   rrb = radeon_get_colorbuffer(&rmesa->radeon);
688   if (!rrb)
689     return;
690   mask = radeonPackColor( rrb->cpp,
691			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 0)*0xFF,
692			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 1)*0xFF,
693			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 2)*0xFF,
694			   GET_COLORMASK_BIT(ctx->Color.ColorMask, 0, 3)*0xFF );
695
696
697   if (!(r && g && b && a))
698      flag |= R200_PLANE_MASK_ENABLE;
699
700   if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
701      R200_STATECHANGE( rmesa, ctx );
702      rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
703   }
704
705   if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
706      R200_STATECHANGE( rmesa, msk );
707      rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
708   }
709}
710
711
712/* =============================================================
713 * Polygon state
714 */
715
716static void r200PolygonOffset( struct gl_context *ctx,
717			       GLfloat factor, GLfloat units, GLfloat clamp )
718{
719   r200ContextPtr rmesa = R200_CONTEXT(ctx);
720   const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
721   float_ui32_type constant =  { units * depthScale };
722   float_ui32_type factoru = { factor };
723
724/*    factor *= 2; */
725/*    constant *= 2; */
726
727/*    fprintf(stderr, "%s f:%f u:%f\n", __func__, factor, constant); */
728
729   R200_STATECHANGE( rmesa, zbs );
730   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR]   = factoru.ui32;
731   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
732}
733
734static void r200PolygonMode( struct gl_context *ctx, GLenum face, GLenum mode )
735{
736   r200ContextPtr rmesa = R200_CONTEXT(ctx);
737   GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
738                         ctx->Polygon.BackMode != GL_FILL);
739
740   /* Can't generally do unfilled via tcl, but some good special
741    * cases work.
742    */
743   TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, unfilled);
744   if (rmesa->radeon.TclFallback) {
745      r200ChooseRenderState( ctx );
746      r200ChooseVertexState( ctx );
747   }
748}
749
750
751/* =============================================================
752 * Rendering attributes
753 *
754 * We really don't want to recalculate all this every time we bind a
755 * texture.  These things shouldn't change all that often, so it makes
756 * sense to break them out of the core texture state update routines.
757 */
758
759/* Examine lighting and texture state to determine if separate specular
760 * should be enabled.
761 */
762static void r200UpdateSpecular( struct gl_context *ctx )
763{
764   r200ContextPtr rmesa = R200_CONTEXT(ctx);
765   uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
766
767   R200_STATECHANGE( rmesa, tcl );
768   R200_STATECHANGE( rmesa, vtx );
769
770   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
771   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
772   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
773   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
774   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
775
776   p &= ~R200_SPECULAR_ENABLE;
777
778   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
779
780
781   if (ctx->Light.Enabled &&
782       ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
783      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
784	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
785	  (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
786      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
787      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
788      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
789      p |=  R200_SPECULAR_ENABLE;
790      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
791	 ~R200_DIFFUSE_SPECULAR_COMBINE;
792   }
793   else if (ctx->Light.Enabled) {
794      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
795	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
796      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
797      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
798   } else if (ctx->Fog.ColorSumEnabled ) {
799      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
800	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
801	  (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
802      p |=  R200_SPECULAR_ENABLE;
803   } else {
804      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
805	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
806   }
807
808   if (ctx->Fog.Enabled) {
809      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
810	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
811      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
812   }
813
814   if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
815      R200_STATECHANGE( rmesa, ctx );
816      rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
817   }
818
819   /* Update vertex/render formats
820    */
821   if (rmesa->radeon.TclFallback) {
822      r200ChooseRenderState( ctx );
823      r200ChooseVertexState( ctx );
824   }
825}
826
827
828/* =============================================================
829 * Materials
830 */
831
832
833/* Update on colormaterial, material emmissive/ambient,
834 * lightmodel.globalambient
835 */
836static void update_global_ambient( struct gl_context *ctx )
837{
838   r200ContextPtr rmesa = R200_CONTEXT(ctx);
839   float *fcmd = (float *)R200_DB_STATE( glt );
840
841   /* Need to do more if both emmissive & ambient are PREMULT:
842    * I believe this is not nessary when using source_material. This condition thus
843    * will never happen currently, and the function has no dependencies on materials now
844    */
845   if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
846       ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
847	(3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
848   {
849      COPY_3V( &fcmd[GLT_RED],
850	       ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
851      ACC_SCALE_3V( &fcmd[GLT_RED],
852		   ctx->Light.Model.Ambient,
853		   ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
854   }
855   else
856   {
857      COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
858   }
859
860   R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
861}
862
863/* Update on change to
864 *    - light[p].colors
865 *    - light[p].enabled
866 */
867static void update_light_colors( struct gl_context *ctx, GLuint p )
868{
869   struct gl_light *l = &ctx->Light.Light[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], l->Ambient );
878      COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
879      COPY_4V( &fcmd[LIT_SPECULAR_RED], l->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         GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1122
1123         if (l->EyePosition[3] == 0.0) {
1124            COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1125            COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1126            fcmd[LIT_POSITION_W] = 0;
1127            fcmd[LIT_DIRECTION_W] = 0;
1128         } else {
1129            COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1130            fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0];
1131            fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1];
1132            fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2];
1133            fcmd[LIT_DIRECTION_W] = 0;
1134         }
1135
1136         R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1137      }
1138   }
1139}
1140
1141static void r200Lightfv( struct gl_context *ctx, GLenum light,
1142			   GLenum pname, const GLfloat *params )
1143{
1144   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1145   GLint p = light - GL_LIGHT0;
1146   struct gl_light *l = &ctx->Light.Light[p];
1147   GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1148
1149
1150   switch (pname) {
1151   case GL_AMBIENT:
1152   case GL_DIFFUSE:
1153   case GL_SPECULAR:
1154      update_light_colors( ctx, p );
1155      break;
1156
1157   case GL_SPOT_DIRECTION:
1158      /* picked up in update_light */
1159      break;
1160
1161   case GL_POSITION: {
1162      /* positions picked up in update_light, but can do flag here */
1163      GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1164      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1165
1166      R200_STATECHANGE(rmesa, tcl);
1167      if (l->EyePosition[3] != 0.0F)
1168	 rmesa->hw.tcl.cmd[idx] |= flag;
1169      else
1170	 rmesa->hw.tcl.cmd[idx] &= ~flag;
1171      break;
1172   }
1173
1174   case GL_SPOT_EXPONENT:
1175      R200_STATECHANGE(rmesa, lit[p]);
1176      fcmd[LIT_SPOT_EXPONENT] = params[0];
1177      break;
1178
1179   case GL_SPOT_CUTOFF: {
1180      GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1181      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1182
1183      R200_STATECHANGE(rmesa, lit[p]);
1184      fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1185
1186      R200_STATECHANGE(rmesa, tcl);
1187      if (l->SpotCutoff != 180.0F)
1188	 rmesa->hw.tcl.cmd[idx] |= flag;
1189      else
1190	 rmesa->hw.tcl.cmd[idx] &= ~flag;
1191
1192      break;
1193   }
1194
1195   case GL_CONSTANT_ATTENUATION:
1196      R200_STATECHANGE(rmesa, lit[p]);
1197      fcmd[LIT_ATTEN_CONST] = params[0];
1198      if ( params[0] == 0.0 )
1199	 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1200      else
1201	 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1202      break;
1203   case GL_LINEAR_ATTENUATION:
1204      R200_STATECHANGE(rmesa, lit[p]);
1205      fcmd[LIT_ATTEN_LINEAR] = params[0];
1206      break;
1207   case GL_QUADRATIC_ATTENUATION:
1208      R200_STATECHANGE(rmesa, lit[p]);
1209      fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1210      break;
1211   default:
1212      return;
1213   }
1214
1215   /* Set RANGE_ATTEN only when needed */
1216   switch (pname) {
1217   case GL_POSITION:
1218   case GL_CONSTANT_ATTENUATION:
1219   case GL_LINEAR_ATTENUATION:
1220   case GL_QUADRATIC_ATTENUATION: {
1221      GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1222      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1223      GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1224				  : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1225      GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1226				  : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1227
1228      if ( l->EyePosition[3] == 0.0F ||
1229	   ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1230	     fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1231	 /* Disable attenuation */
1232	 icmd[idx] &= ~atten_flag;
1233      } else {
1234	 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1235	    /* Enable only constant portion of attenuation calculation */
1236	    icmd[idx] |= ( atten_flag | atten_const_flag );
1237	 } else {
1238	    /* Enable full attenuation calculation */
1239	    icmd[idx] &= ~atten_const_flag;
1240	    icmd[idx] |= atten_flag;
1241	 }
1242      }
1243
1244      R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1245      break;
1246   }
1247   default:
1248     break;
1249   }
1250}
1251
1252static void r200UpdateLocalViewer ( struct gl_context *ctx )
1253{
1254/* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1255   GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1256   for these and only these modes). This means specular highlights may turn out
1257   wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1258   is not set, though it seems to happen rarely and the effect seems quite
1259   subtle. May need TCL fallback to fix it completely, though I'm not sure
1260   how you'd identify the cases where the specular highlights indeed will
1261   be wrong. Don't know if fglrx does something special in that case.
1262*/
1263   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1264   R200_STATECHANGE( rmesa, tcl );
1265   if (ctx->Light.Model.LocalViewer ||
1266       ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
1267      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1268   else
1269      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1270}
1271
1272static void r200LightModelfv( struct gl_context *ctx, GLenum pname,
1273				const GLfloat *param )
1274{
1275   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1276
1277   switch (pname) {
1278      case GL_LIGHT_MODEL_AMBIENT:
1279	 update_global_ambient( ctx );
1280	 break;
1281
1282      case GL_LIGHT_MODEL_LOCAL_VIEWER:
1283	 r200UpdateLocalViewer( ctx );
1284         break;
1285
1286      case GL_LIGHT_MODEL_TWO_SIDE:
1287	 R200_STATECHANGE( rmesa, tcl );
1288	 if (ctx->Light.Model.TwoSide)
1289	    rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1290	 else
1291	    rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1292	 if (rmesa->radeon.TclFallback) {
1293	    r200ChooseRenderState( ctx );
1294	    r200ChooseVertexState( ctx );
1295	 }
1296         break;
1297
1298      case GL_LIGHT_MODEL_COLOR_CONTROL:
1299	 r200UpdateSpecular(ctx);
1300         break;
1301
1302      default:
1303         break;
1304   }
1305}
1306
1307static void r200ShadeModel( struct gl_context *ctx, GLenum mode )
1308{
1309   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1310   GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1311
1312   s &= ~(R200_DIFFUSE_SHADE_MASK |
1313	  R200_ALPHA_SHADE_MASK |
1314	  R200_SPECULAR_SHADE_MASK |
1315	  R200_FOG_SHADE_MASK |
1316	  R200_DISC_FOG_SHADE_MASK);
1317
1318   switch ( mode ) {
1319   case GL_FLAT:
1320      s |= (R200_DIFFUSE_SHADE_FLAT |
1321	    R200_ALPHA_SHADE_FLAT |
1322	    R200_SPECULAR_SHADE_FLAT |
1323	    R200_FOG_SHADE_FLAT |
1324	    R200_DISC_FOG_SHADE_FLAT);
1325      break;
1326   case GL_SMOOTH:
1327      s |= (R200_DIFFUSE_SHADE_GOURAUD |
1328	    R200_ALPHA_SHADE_GOURAUD |
1329	    R200_SPECULAR_SHADE_GOURAUD |
1330	    R200_FOG_SHADE_GOURAUD |
1331	    R200_DISC_FOG_SHADE_GOURAUD);
1332      break;
1333   default:
1334      return;
1335   }
1336
1337   if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1338      R200_STATECHANGE( rmesa, set );
1339      rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1340   }
1341}
1342
1343
1344/* =============================================================
1345 * User clip planes
1346 */
1347
1348static void r200ClipPlane( struct gl_context *ctx, GLenum plane, const GLfloat *eq )
1349{
1350   GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1351   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1352   GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1353
1354   R200_STATECHANGE( rmesa, ucp[p] );
1355   rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1356   rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1357   rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1358   rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1359}
1360
1361static void r200UpdateClipPlanes( struct gl_context *ctx )
1362{
1363   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1364   GLbitfield mask = ctx->Transform.ClipPlanesEnabled;
1365
1366   while (mask) {
1367      const int p = u_bit_scan(&mask);
1368      GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1369
1370      R200_STATECHANGE( rmesa, ucp[p] );
1371      rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1372      rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1373      rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1374      rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1375   }
1376}
1377
1378
1379/* =============================================================
1380 * Stencil
1381 */
1382
1383static void
1384r200StencilFuncSeparate( struct gl_context *ctx, GLenum face, GLenum func,
1385                         GLint ref, GLuint mask )
1386{
1387   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1388   GLuint refmask = ((_mesa_get_stencil_ref(ctx, 0) << R200_STENCIL_REF_SHIFT) |
1389		     ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT));
1390
1391   R200_STATECHANGE( rmesa, ctx );
1392   R200_STATECHANGE( rmesa, msk );
1393
1394   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1395   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1396						   R200_STENCIL_VALUE_MASK);
1397
1398   switch ( ctx->Stencil.Function[0] ) {
1399   case GL_NEVER:
1400      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1401      break;
1402   case GL_LESS:
1403      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1404      break;
1405   case GL_EQUAL:
1406      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1407      break;
1408   case GL_LEQUAL:
1409      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1410      break;
1411   case GL_GREATER:
1412      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1413      break;
1414   case GL_NOTEQUAL:
1415      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1416      break;
1417   case GL_GEQUAL:
1418      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1419      break;
1420   case GL_ALWAYS:
1421      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1422      break;
1423   }
1424
1425   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1426}
1427
1428static void
1429r200StencilMaskSeparate( struct gl_context *ctx, GLenum face, GLuint mask )
1430{
1431   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1432
1433   R200_STATECHANGE( rmesa, msk );
1434   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1435   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1436      ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT);
1437}
1438
1439static void
1440r200StencilOpSeparate( struct gl_context *ctx, GLenum face, GLenum fail,
1441                       GLenum zfail, GLenum zpass )
1442{
1443   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1444
1445   R200_STATECHANGE( rmesa, ctx );
1446   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1447					       R200_STENCIL_ZFAIL_MASK |
1448					       R200_STENCIL_ZPASS_MASK);
1449
1450   switch ( ctx->Stencil.FailFunc[0] ) {
1451   case GL_KEEP:
1452      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1453      break;
1454   case GL_ZERO:
1455      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1456      break;
1457   case GL_REPLACE:
1458      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1459      break;
1460   case GL_INCR:
1461      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1462      break;
1463   case GL_DECR:
1464      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1465      break;
1466   case GL_INCR_WRAP_EXT:
1467      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1468      break;
1469   case GL_DECR_WRAP_EXT:
1470      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1471      break;
1472   case GL_INVERT:
1473      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1474      break;
1475   }
1476
1477   switch ( ctx->Stencil.ZFailFunc[0] ) {
1478   case GL_KEEP:
1479      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1480      break;
1481   case GL_ZERO:
1482      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1483      break;
1484   case GL_REPLACE:
1485      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1486      break;
1487   case GL_INCR:
1488      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1489      break;
1490   case GL_DECR:
1491      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1492      break;
1493   case GL_INCR_WRAP_EXT:
1494      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1495      break;
1496   case GL_DECR_WRAP_EXT:
1497      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1498      break;
1499   case GL_INVERT:
1500      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1501      break;
1502   }
1503
1504   switch ( ctx->Stencil.ZPassFunc[0] ) {
1505   case GL_KEEP:
1506      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1507      break;
1508   case GL_ZERO:
1509      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1510      break;
1511   case GL_REPLACE:
1512      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1513      break;
1514   case GL_INCR:
1515      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1516      break;
1517   case GL_DECR:
1518      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1519      break;
1520   case GL_INCR_WRAP_EXT:
1521      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1522      break;
1523   case GL_DECR_WRAP_EXT:
1524      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1525      break;
1526   case GL_INVERT:
1527      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1528      break;
1529   }
1530}
1531
1532
1533/* =============================================================
1534 * Window position and viewport transformation
1535 */
1536
1537/**
1538 * Called when window size or position changes or viewport or depth range
1539 * state is changed.  We update the hardware viewport state here.
1540 */
1541void r200UpdateWindow( struct gl_context *ctx )
1542{
1543   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1544   __DRIdrawable *dPriv = radeon_get_drawable(&rmesa->radeon);
1545   GLfloat xoffset = 0;
1546   GLfloat yoffset = dPriv ? (GLfloat) dPriv->h : 0;
1547   const GLboolean render_to_fbo = (ctx->DrawBuffer ? _mesa_is_user_fbo(ctx->DrawBuffer) : 0);
1548   float scale[3], translate[3];
1549   GLfloat y_scale, y_bias;
1550
1551   if (render_to_fbo) {
1552      y_scale = 1.0;
1553      y_bias = 0;
1554   } else {
1555      y_scale = -1.0;
1556      y_bias = yoffset;
1557   }
1558
1559   _mesa_get_viewport_xform(ctx, 0, scale, translate);
1560   float_ui32_type sx = { scale[0] };
1561   float_ui32_type sy = { scale[1] * y_scale };
1562   float_ui32_type sz = { scale[2] };
1563   float_ui32_type tx = { translate[0] + xoffset };
1564   float_ui32_type ty = { (translate[1] * y_scale) + y_bias };
1565   float_ui32_type tz = { translate[2] };
1566
1567   R200_STATECHANGE( rmesa, vpt );
1568
1569   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE]  = sx.ui32;
1570   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1571   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE]  = sy.ui32;
1572   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1573   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE]  = sz.ui32;
1574   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1575}
1576
1577void r200_vtbl_update_scissor( struct gl_context *ctx )
1578{
1579   r200ContextPtr r200 = R200_CONTEXT(ctx);
1580   unsigned x1, y1, x2, y2;
1581   struct radeon_renderbuffer *rrb;
1582
1583   R200_SET_STATE(r200, set, SET_RE_CNTL, R200_SCISSOR_ENABLE | r200->hw.set.cmd[SET_RE_CNTL]);
1584
1585   if (r200->radeon.state.scissor.enabled) {
1586      x1 = r200->radeon.state.scissor.rect.x1;
1587      y1 = r200->radeon.state.scissor.rect.y1;
1588      x2 = r200->radeon.state.scissor.rect.x2;
1589      y2 = r200->radeon.state.scissor.rect.y2;
1590   } else {
1591      rrb = radeon_get_colorbuffer(&r200->radeon);
1592      x1 = 0;
1593      y1 = 0;
1594      x2 = rrb->base.Base.Width - 1;
1595      y2 = rrb->base.Base.Height - 1;
1596   }
1597
1598   R200_SET_STATE(r200, sci, SCI_XY_1, x1 | (y1 << 16));
1599   R200_SET_STATE(r200, sci, SCI_XY_2, x2 | (y2 << 16));
1600}
1601
1602
1603static void r200Viewport(struct gl_context *ctx)
1604{
1605   /* Don't pipeline viewport changes, conflict with window offset
1606    * setting below.  Could apply deltas to rescue pipelined viewport
1607    * values, or keep the originals hanging around.
1608    */
1609   r200UpdateWindow( ctx );
1610
1611   radeon_viewport(ctx);
1612}
1613
1614static void r200DepthRange(struct gl_context *ctx)
1615{
1616   r200UpdateWindow( ctx );
1617}
1618
1619/* =============================================================
1620 * Miscellaneous
1621 */
1622
1623static void r200RenderMode( struct gl_context *ctx, GLenum mode )
1624{
1625   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1626   FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1627}
1628
1629static void r200LogicOpCode(struct gl_context *ctx, enum gl_logicop_mode opcode)
1630{
1631   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1632
1633   assert((unsigned) opcode <= 15);
1634
1635   R200_STATECHANGE( rmesa, msk );
1636   rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = opcode;
1637}
1638
1639/* =============================================================
1640 * State enable/disable
1641 */
1642
1643static void r200Enable( struct gl_context *ctx, GLenum cap, GLboolean state )
1644{
1645   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1646   GLuint p, flag;
1647
1648   if ( R200_DEBUG & RADEON_STATE )
1649      fprintf( stderr, "%s( %s = %s )\n", __func__,
1650	       _mesa_enum_to_string( cap ),
1651	       state ? "GL_TRUE" : "GL_FALSE" );
1652
1653   switch ( cap ) {
1654      /* Fast track this one...
1655       */
1656   case GL_TEXTURE_1D:
1657   case GL_TEXTURE_2D:
1658   case GL_TEXTURE_3D:
1659      break;
1660
1661   case GL_ALPHA_TEST:
1662      R200_STATECHANGE( rmesa, ctx );
1663      if (state) {
1664	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1665      } else {
1666	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1667      }
1668      break;
1669
1670   case GL_BLEND:
1671   case GL_COLOR_LOGIC_OP:
1672      r200_set_blend_state( ctx );
1673      break;
1674
1675   case GL_CLIP_PLANE0:
1676   case GL_CLIP_PLANE1:
1677   case GL_CLIP_PLANE2:
1678   case GL_CLIP_PLANE3:
1679   case GL_CLIP_PLANE4:
1680   case GL_CLIP_PLANE5:
1681      p = cap-GL_CLIP_PLANE0;
1682      R200_STATECHANGE( rmesa, tcl );
1683      if (state) {
1684	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1685	 r200ClipPlane( ctx, cap, NULL );
1686      }
1687      else {
1688	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1689      }
1690      break;
1691
1692   case GL_COLOR_MATERIAL:
1693      r200ColorMaterial( ctx, 0, 0 );
1694      r200UpdateMaterial( ctx );
1695      break;
1696
1697   case GL_CULL_FACE:
1698      r200CullFace( ctx, 0 );
1699      break;
1700
1701   case GL_DEPTH_TEST:
1702      R200_STATECHANGE(rmesa, ctx );
1703      if ( state ) {
1704	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_Z_ENABLE;
1705      } else {
1706	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1707      }
1708      break;
1709
1710   case GL_DITHER:
1711      R200_STATECHANGE(rmesa, ctx );
1712      if ( state ) {
1713	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_DITHER_ENABLE;
1714	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable;
1715      } else {
1716	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1717	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  rmesa->radeon.state.color.roundEnable;
1718      }
1719      break;
1720
1721   case GL_FOG:
1722      R200_STATECHANGE(rmesa, ctx );
1723      if ( state ) {
1724	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1725	 r200Fogfv( ctx, GL_FOG_MODE, NULL );
1726      } else {
1727	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1728	 R200_STATECHANGE(rmesa, tcl);
1729	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1730      }
1731      r200UpdateSpecular( ctx ); /* for PK_SPEC */
1732      if (rmesa->radeon.TclFallback)
1733	 r200ChooseVertexState( ctx );
1734      _mesa_allow_light_in_model( ctx, !state );
1735      break;
1736
1737   case GL_LIGHT0:
1738   case GL_LIGHT1:
1739   case GL_LIGHT2:
1740   case GL_LIGHT3:
1741   case GL_LIGHT4:
1742   case GL_LIGHT5:
1743   case GL_LIGHT6:
1744   case GL_LIGHT7:
1745      R200_STATECHANGE(rmesa, tcl);
1746      p = cap - GL_LIGHT0;
1747      if (p&1)
1748	 flag = (R200_LIGHT_1_ENABLE |
1749		 R200_LIGHT_1_ENABLE_AMBIENT |
1750		 R200_LIGHT_1_ENABLE_SPECULAR);
1751      else
1752	 flag = (R200_LIGHT_0_ENABLE |
1753		 R200_LIGHT_0_ENABLE_AMBIENT |
1754		 R200_LIGHT_0_ENABLE_SPECULAR);
1755
1756      if (state)
1757	 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1758      else
1759	 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1760
1761      /*
1762       */
1763      update_light_colors( ctx, p );
1764      break;
1765
1766   case GL_LIGHTING:
1767      r200UpdateSpecular(ctx);
1768      /* for reflection map fixup - might set recheck_texgen for all units too */
1769      rmesa->radeon.NewGLState |= _NEW_TEXTURE;
1770      break;
1771
1772   case GL_LINE_SMOOTH:
1773      R200_STATECHANGE( rmesa, ctx );
1774      if ( state ) {
1775	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  R200_ANTI_ALIAS_LINE;
1776      } else {
1777	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1778      }
1779      break;
1780
1781   case GL_LINE_STIPPLE:
1782      R200_STATECHANGE( rmesa, set );
1783      if ( state ) {
1784	 rmesa->hw.set.cmd[SET_RE_CNTL] |=  R200_PATTERN_ENABLE;
1785      } else {
1786	 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1787      }
1788      break;
1789
1790   case GL_NORMALIZE:
1791      R200_STATECHANGE( rmesa, tcl );
1792      if ( state ) {
1793	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_NORMALIZE_NORMALS;
1794      } else {
1795	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1796      }
1797      break;
1798
1799      /* Pointsize registers on r200 only work for point sprites, and point smooth
1800       * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1801       * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1802       * is enough to satisfy conform.
1803       */
1804   case GL_POINT_SMOOTH:
1805      break;
1806
1807      /* These don't really do anything, as we don't use the 3vtx
1808       * primitives yet.
1809       */
1810#if 0
1811   case GL_POLYGON_OFFSET_POINT:
1812      R200_STATECHANGE( rmesa, set );
1813      if ( state ) {
1814	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_POINT;
1815      } else {
1816	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1817      }
1818      break;
1819
1820   case GL_POLYGON_OFFSET_LINE:
1821      R200_STATECHANGE( rmesa, set );
1822      if ( state ) {
1823	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_LINE;
1824      } else {
1825	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1826      }
1827      break;
1828#endif
1829
1830   case GL_POINT_SPRITE_ARB:
1831      R200_STATECHANGE( rmesa, spr );
1832      if ( state ) {
1833	 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_GEN_TEX_MASK &
1834            (ctx->Point.CoordReplace << R200_PS_GEN_TEX_0_SHIFT);
1835      } else {
1836	 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
1837      }
1838      break;
1839
1840   case GL_POLYGON_OFFSET_FILL:
1841      R200_STATECHANGE( rmesa, set );
1842      if ( state ) {
1843	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_TRI;
1844      } else {
1845	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
1846      }
1847      break;
1848
1849   case GL_POLYGON_SMOOTH:
1850      R200_STATECHANGE( rmesa, ctx );
1851      if ( state ) {
1852	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  R200_ANTI_ALIAS_POLY;
1853      } else {
1854	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
1855      }
1856      break;
1857
1858   case GL_POLYGON_STIPPLE:
1859      R200_STATECHANGE(rmesa, set );
1860      if ( state ) {
1861	 rmesa->hw.set.cmd[SET_RE_CNTL] |=  R200_STIPPLE_ENABLE;
1862      } else {
1863	 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
1864      }
1865      break;
1866
1867   case GL_RESCALE_NORMAL_EXT: {
1868      GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1869      R200_STATECHANGE( rmesa, tcl );
1870      if ( tmp ) {
1871	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_RESCALE_NORMALS;
1872      } else {
1873	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
1874      }
1875      break;
1876   }
1877
1878   case GL_SCISSOR_TEST:
1879      radeon_firevertices(&rmesa->radeon);
1880      rmesa->radeon.state.scissor.enabled = state;
1881      radeonUpdateScissor( ctx );
1882      break;
1883
1884   case GL_STENCIL_TEST:
1885      {
1886	 GLboolean hw_stencil = GL_FALSE;
1887	 if (ctx->DrawBuffer) {
1888	    struct radeon_renderbuffer *rrbStencil
1889	       = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
1890	    hw_stencil = (rrbStencil && rrbStencil->bo);
1891	 }
1892
1893	 if (hw_stencil) {
1894	    R200_STATECHANGE( rmesa, ctx );
1895	    if ( state ) {
1896	       rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_STENCIL_ENABLE;
1897	    } else {
1898	       rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
1899	    }
1900	 } else {
1901	    FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
1902	 }
1903      }
1904      break;
1905
1906   case GL_TEXTURE_GEN_Q:
1907   case GL_TEXTURE_GEN_R:
1908   case GL_TEXTURE_GEN_S:
1909   case GL_TEXTURE_GEN_T:
1910      /* Picked up in r200UpdateTextureState.
1911       */
1912      rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
1913      break;
1914
1915   case GL_COLOR_SUM_EXT:
1916      r200UpdateSpecular ( ctx );
1917      break;
1918
1919   case GL_VERTEX_PROGRAM_ARB:
1920      if (!state) {
1921	 GLuint i;
1922	 rmesa->curr_vp_hw = NULL;
1923	 R200_STATECHANGE( rmesa, vap );
1924	 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
1925	 /* mark all tcl atoms (tcl vector state got overwritten) dirty
1926	    not sure about tcl scalar state - we need at least grd
1927	    with vert progs too.
1928	    ucp looks like it doesn't get overwritten (may even work
1929	    with vp for pos-invariant progs if we're lucky) */
1930	 R200_STATECHANGE( rmesa, mtl[0] );
1931	 R200_STATECHANGE( rmesa, mtl[1] );
1932	 R200_STATECHANGE( rmesa, fog );
1933	 R200_STATECHANGE( rmesa, glt );
1934	 R200_STATECHANGE( rmesa, eye );
1935	 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
1936	    R200_STATECHANGE( rmesa, mat[i] );
1937	 }
1938	 for (i = 0 ; i < 8; i++) {
1939	    R200_STATECHANGE( rmesa, lit[i] );
1940	 }
1941	 R200_STATECHANGE( rmesa, tcl );
1942	 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
1943	    if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
1944	       rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
1945	    }
1946/*	    else {
1947	       rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
1948	    }*/
1949	 }
1950	 /* ugly. Need to call everything which might change compsel. */
1951	 r200UpdateSpecular( ctx );
1952#if 0
1953	/* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
1954	   but without it doom3 locks up at always the same places. Why? */
1955	/* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
1956	   accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
1957	 r200UpdateTextureState( ctx );
1958	 /* if we call r200UpdateTextureState we need the code below because we are calling it with
1959	    non-current derived enabled values which may revert the state atoms for frag progs even when
1960	    they already got disabled... ugh
1961	    Should really figure out why we need to call r200UpdateTextureState in the first place */
1962	 GLuint unit;
1963	 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
1964	    R200_STATECHANGE( rmesa, pix[unit] );
1965	    R200_STATECHANGE( rmesa, tex[unit] );
1966	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
1967		~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
1968	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
1969	    /* need to guard this with drmSupportsFragmentShader? Should never get here if
1970	       we don't announce ATI_fs, right? */
1971	    rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
1972         }
1973	 R200_STATECHANGE( rmesa, cst );
1974	 R200_STATECHANGE( rmesa, tf );
1975	 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
1976#endif
1977      }
1978      else {
1979	 /* picked up later */
1980      }
1981      /* call functions which change hw state based on ARB_vp enabled or not. */
1982      r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
1983      r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
1984      break;
1985
1986   case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
1987      r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
1988      break;
1989
1990   case GL_FRAGMENT_SHADER_ATI:
1991      if ( !state ) {
1992	 /* restore normal tex env colors and make sure tex env combine will get updated
1993	    mark env atoms dirty (as their data was overwritten by afs even
1994	    if they didn't change) and restore tex coord routing */
1995	 GLuint unit;
1996	 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
1997	    R200_STATECHANGE( rmesa, pix[unit] );
1998	    R200_STATECHANGE( rmesa, tex[unit] );
1999	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2000		~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2001	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2002	    rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2003         }
2004	 R200_STATECHANGE( rmesa, cst );
2005	 R200_STATECHANGE( rmesa, tf );
2006	 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2007      }
2008      else {
2009	 /* need to mark this dirty as pix/tf atoms have overwritten the data
2010	    even if the data in the atoms didn't change */
2011	 R200_STATECHANGE( rmesa, atf );
2012	 R200_STATECHANGE( rmesa, afs[1] );
2013	 /* everything else picked up in r200UpdateTextureState hopefully */
2014      }
2015      break;
2016   default:
2017      return;
2018   }
2019}
2020
2021
2022void r200LightingSpaceChange( struct gl_context *ctx )
2023{
2024   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2025   GLboolean tmp;
2026
2027   if (R200_DEBUG & RADEON_STATE)
2028      fprintf(stderr, "%s %d BEFORE %x\n", __func__, ctx->_NeedEyeCoords,
2029	      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2030
2031   if (ctx->_NeedEyeCoords)
2032      tmp = ctx->Transform.RescaleNormals;
2033   else
2034      tmp = !ctx->Transform.RescaleNormals;
2035
2036   R200_STATECHANGE( rmesa, tcl );
2037   if ( tmp ) {
2038      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_RESCALE_NORMALS;
2039   } else {
2040      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2041   }
2042
2043   if (R200_DEBUG & RADEON_STATE)
2044      fprintf(stderr, "%s %d AFTER %x\n", __func__, ctx->_NeedEyeCoords,
2045	      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2046}
2047
2048/* =============================================================
2049 * Deferred state management - matrices, textures, other?
2050 */
2051
2052
2053
2054
2055static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2056{
2057   float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2058   int i;
2059
2060
2061   for (i = 0 ; i < 4 ; i++) {
2062      *dest++ = src[i];
2063      *dest++ = src[i+4];
2064      *dest++ = src[i+8];
2065      *dest++ = src[i+12];
2066   }
2067
2068   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2069}
2070
2071static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2072{
2073   float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2074   memcpy(dest, src, 16*sizeof(float));
2075   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2076}
2077
2078
2079static void update_texturematrix( struct gl_context *ctx )
2080{
2081   r200ContextPtr rmesa = R200_CONTEXT( ctx );
2082   GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2083   GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2084   int unit;
2085
2086   if (R200_DEBUG & RADEON_STATE)
2087      fprintf(stderr, "%s before COMPSEL: %x\n", __func__,
2088	      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2089
2090   rmesa->TexMatEnabled = 0;
2091   rmesa->TexMatCompSel = 0;
2092
2093   for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2094      if (!ctx->Texture.Unit[unit]._Current)
2095	 continue;
2096
2097      if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2098	 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2099				  R200_TEXMAT_0_ENABLE) << unit;
2100
2101	 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2102
2103	 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2104	    /* Need to preconcatenate any active texgen
2105	     * obj/eyeplane matrices:
2106	     */
2107	    _math_matrix_mul_matrix( &rmesa->tmpmat,
2108				     ctx->TextureMatrixStack[unit].Top,
2109				     &rmesa->TexGenMatrix[unit] );
2110	    upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2111	 }
2112	 else {
2113	    upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2114			   R200_MTX_TEX0+unit );
2115	 }
2116      }
2117      else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2118	 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2119			R200_MTX_TEX0+unit );
2120      }
2121   }
2122
2123   tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2124   if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2125      R200_STATECHANGE(rmesa, tcg);
2126      rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2127   }
2128
2129   compsel &= ~R200_OUTPUT_TEX_MASK;
2130   compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2131   if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2132      R200_STATECHANGE(rmesa, vtx);
2133      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2134   }
2135}
2136
2137GLboolean r200ValidateBuffers(struct gl_context *ctx)
2138{
2139   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2140   struct radeon_renderbuffer *rrb;
2141   struct radeon_dma_bo *dma_bo;
2142   int i, ret;
2143
2144	if (RADEON_DEBUG & RADEON_IOCTL)
2145		fprintf(stderr, "%s\n", __func__);
2146   radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs);
2147
2148   rrb = radeon_get_colorbuffer(&rmesa->radeon);
2149   /* color buffer */
2150   if (rrb && rrb->bo) {
2151     radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2152				       0, RADEON_GEM_DOMAIN_VRAM);
2153   }
2154
2155   /* depth buffer */
2156   rrb = radeon_get_depthbuffer(&rmesa->radeon);
2157   /* color buffer */
2158   if (rrb && rrb->bo) {
2159     radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2160				       0, RADEON_GEM_DOMAIN_VRAM);
2161   }
2162
2163   for (i = 0; i < ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTextureImageUnits; ++i) {
2164      radeonTexObj *t;
2165
2166      if (!ctx->Texture.Unit[i]._Current)
2167	 continue;
2168
2169      t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
2170      if (t->image_override && t->bo)
2171	radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo,
2172			   RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2173      else if (t->mt->bo)
2174	radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo,
2175			   RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2176   }
2177
2178   dma_bo = first_elem(&rmesa->radeon.dma.reserved);
2179   {
2180       ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, dma_bo->bo, RADEON_GEM_DOMAIN_GTT, 0);
2181       if (ret)
2182	   return GL_FALSE;
2183   }
2184   return GL_TRUE;
2185}
2186
2187GLboolean r200ValidateState( struct gl_context *ctx )
2188{
2189   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2190   GLuint new_state = rmesa->radeon.NewGLState;
2191
2192   if (new_state & _NEW_BUFFERS) {
2193      _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer);
2194      /* this updates the DrawBuffer's Width/Height if it's a FBO */
2195      _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
2196
2197      R200_STATECHANGE(rmesa, ctx);
2198   }
2199
2200   if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) {
2201      r200UpdateTextureState( ctx );
2202      new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
2203      r200UpdateLocalViewer( ctx );
2204   }
2205
2206   /* we need to do a space check here */
2207   if (!r200ValidateBuffers(ctx))
2208     return GL_FALSE;
2209
2210/* FIXME: don't really need most of these when vertex progs are enabled */
2211
2212   /* Need an event driven matrix update?
2213    */
2214   if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2215      upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2216
2217   /* Need these for lighting (shouldn't upload otherwise)
2218    */
2219   if (new_state & (_NEW_MODELVIEW)) {
2220      upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2221      upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2222   }
2223
2224   /* Does this need to be triggered on eg. modelview for
2225    * texgen-derived objplane/eyeplane matrices?
2226    */
2227   if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2228      update_texturematrix( ctx );
2229   }
2230
2231   if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2232      update_light( ctx );
2233   }
2234
2235   /* emit all active clip planes if projection matrix changes.
2236    */
2237   if (new_state & (_NEW_PROJECTION)) {
2238      if (ctx->Transform.ClipPlanesEnabled)
2239	 r200UpdateClipPlanes( ctx );
2240   }
2241
2242   if (new_state & (_NEW_PROGRAM|
2243                    _NEW_PROGRAM_CONSTANTS |
2244   /* need to test for pretty much anything due to possible parameter bindings */
2245	_NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
2246	_NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
2247	_NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
2248      if (_mesa_arb_vertex_program_enabled(ctx)) {
2249	 r200SetupVertexProg( ctx );
2250      }
2251      else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
2252   }
2253
2254   rmesa->radeon.NewGLState = 0;
2255   return GL_TRUE;
2256}
2257
2258
2259static void r200InvalidateState(struct gl_context *ctx)
2260{
2261   GLuint new_state = ctx->NewState;
2262
2263   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2264
2265   if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT))
2266      _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer);
2267
2268   _swrast_InvalidateState( ctx, new_state );
2269   _swsetup_InvalidateState( ctx, new_state );
2270   _tnl_InvalidateState( ctx, new_state );
2271   R200_CONTEXT(ctx)->radeon.NewGLState |= new_state;
2272
2273   if (new_state & _NEW_PROGRAM)
2274      rmesa->curr_vp_hw = NULL;
2275}
2276
2277/* A hack.  The r200 can actually cope just fine with materials
2278 * between begin/ends, so fix this.
2279 * Should map to inputs just like the generic vertex arrays for vertex progs.
2280 * In theory there could still be too many and we'd still need a fallback.
2281 */
2282static GLboolean check_material( struct gl_context *ctx )
2283{
2284   TNLcontext *tnl = TNL_CONTEXT(ctx);
2285   GLint i;
2286
2287   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2288	i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2289	i++)
2290      if (tnl->vb.AttribPtr[i] &&
2291	  tnl->vb.AttribPtr[i]->stride)
2292	 return GL_TRUE;
2293
2294   return GL_FALSE;
2295}
2296
2297static void r200WrapRunPipeline( struct gl_context *ctx )
2298{
2299   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2300   GLboolean has_material;
2301
2302   if (0)
2303      fprintf(stderr, "%s, newstate: %x\n", __func__, rmesa->radeon.NewGLState);
2304
2305   /* Validate state:
2306    */
2307   if (rmesa->radeon.NewGLState)
2308      if (!r200ValidateState( ctx ))
2309	 FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
2310
2311   has_material = !_mesa_arb_vertex_program_enabled(ctx) &&
2312                  ctx->Light.Enabled && check_material( ctx );
2313
2314   if (has_material) {
2315      TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2316   }
2317
2318   /* Run the pipeline.
2319    */
2320   _tnl_run_pipeline( ctx );
2321
2322   if (has_material) {
2323      TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2324   }
2325}
2326
2327
2328static void r200PolygonStipple( struct gl_context *ctx, const GLubyte *mask )
2329{
2330   r200ContextPtr r200 = R200_CONTEXT(ctx);
2331   GLint i;
2332
2333   radeon_firevertices(&r200->radeon);
2334
2335   radeon_print(RADEON_STATE, RADEON_TRACE,
2336		   "%s(%p) first 32 bits are %x.\n",
2337		   __func__,
2338		   ctx,
2339		   *(uint32_t*)mask);
2340
2341   R200_STATECHANGE(r200, stp);
2342
2343   /* Must flip pattern upside down.
2344    */
2345   for ( i = 31 ; i >= 0; i--) {
2346     r200->hw.stp.cmd[3 + i] = ((GLuint *) mask)[i];
2347   }
2348}
2349/* Initialize the driver's state functions.
2350 */
2351void r200InitStateFuncs( radeonContextPtr radeon, struct dd_function_table *functions )
2352{
2353   functions->UpdateState		= r200InvalidateState;
2354   functions->LightingSpaceChange	= r200LightingSpaceChange;
2355
2356   functions->DrawBuffer		= radeonDrawBuffer;
2357   functions->ReadBuffer		= radeonReadBuffer;
2358
2359   functions->CopyPixels                = _mesa_meta_CopyPixels;
2360   functions->DrawPixels                = _mesa_meta_DrawPixels;
2361   functions->ReadPixels                = radeonReadPixels;
2362
2363   functions->AlphaFunc			= r200AlphaFunc;
2364   functions->BlendColor		= r200BlendColor;
2365   functions->BlendEquationSeparate	= r200BlendEquationSeparate;
2366   functions->BlendFuncSeparate		= r200BlendFuncSeparate;
2367   functions->ClipPlane			= r200ClipPlane;
2368   functions->ColorMask			= r200ColorMask;
2369   functions->CullFace			= r200CullFace;
2370   functions->DepthFunc			= r200DepthFunc;
2371   functions->DepthMask			= r200DepthMask;
2372   functions->DepthRange		= r200DepthRange;
2373   functions->Enable			= r200Enable;
2374   functions->Fogfv			= r200Fogfv;
2375   functions->FrontFace			= r200FrontFace;
2376   functions->LightModelfv		= r200LightModelfv;
2377   functions->Lightfv			= r200Lightfv;
2378   functions->LineStipple		= r200LineStipple;
2379   functions->LineWidth			= r200LineWidth;
2380   functions->LogicOpcode		= r200LogicOpCode;
2381   functions->PolygonMode		= r200PolygonMode;
2382   functions->PolygonOffset		= r200PolygonOffset;
2383   functions->PolygonStipple		= r200PolygonStipple;
2384   functions->PointParameterfv		= r200PointParameter;
2385   functions->PointSize			= r200PointSize;
2386   functions->RenderMode		= r200RenderMode;
2387   functions->Scissor			= radeonScissor;
2388   functions->ShadeModel		= r200ShadeModel;
2389   functions->StencilFuncSeparate	= r200StencilFuncSeparate;
2390   functions->StencilMaskSeparate	= r200StencilMaskSeparate;
2391   functions->StencilOpSeparate		= r200StencilOpSeparate;
2392   functions->Viewport			= r200Viewport;
2393}
2394
2395
2396void r200InitTnlFuncs( struct gl_context *ctx )
2397{
2398   TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2399   TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2400}
2401