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