r200_state.c revision 504d01b275169f019d375b4a8b5e935b9fd108d3
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;
713   struct radeon_renderbuffer *rrb;
714   GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE;
715
716   rrb = radeon_get_colorbuffer(&rmesa->radeon);
717   if (!rrb)
718     return;
719   mask = radeonPackColor( rrb->cpp,
720			   ctx->Color.ColorMask[RCOMP],
721			   ctx->Color.ColorMask[GCOMP],
722			   ctx->Color.ColorMask[BCOMP],
723			   ctx->Color.ColorMask[ACOMP] );
724
725
726   if (!(r && g && b && a))
727      flag |= R200_PLANE_MASK_ENABLE;
728
729   if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) {
730      R200_STATECHANGE( rmesa, ctx );
731      rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag;
732   }
733
734   if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
735      R200_STATECHANGE( rmesa, msk );
736      rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
737   }
738}
739
740
741/* =============================================================
742 * Polygon state
743 */
744
745static void r200PolygonOffset( GLcontext *ctx,
746			       GLfloat factor, GLfloat units )
747{
748   r200ContextPtr rmesa = R200_CONTEXT(ctx);
749   const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
750   float_ui32_type constant =  { units * depthScale };
751   float_ui32_type factoru = { factor };
752
753/*    factor *= 2; */
754/*    constant *= 2; */
755
756/*    fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */
757
758   R200_STATECHANGE( rmesa, zbs );
759   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR]   = factoru.ui32;
760   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
761}
762
763static void r200PolygonStipple( GLcontext *ctx, const GLubyte *mask )
764{
765   r200ContextPtr rmesa = R200_CONTEXT(ctx);
766   GLuint i;
767   drm_radeon_stipple_t stipple;
768
769   /* Must flip pattern upside down.
770    */
771   for ( i = 0 ; i < 32 ; i++ ) {
772      rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
773   }
774
775   /* TODO: push this into cmd mechanism
776    */
777   radeon_firevertices(&rmesa->radeon);
778   LOCK_HARDWARE( &rmesa->radeon );
779
780   /* FIXME: Use window x,y offsets into stipple RAM.
781    */
782   stipple.mask = rmesa->state.stipple.mask;
783   drmCommandWrite( rmesa->radeon.dri.fd, DRM_RADEON_STIPPLE,
784                    &stipple, sizeof(stipple) );
785   UNLOCK_HARDWARE( &rmesa->radeon );
786}
787
788static void r200PolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
789{
790   r200ContextPtr rmesa = R200_CONTEXT(ctx);
791   GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
792
793   /* Can't generally do unfilled via tcl, but some good special
794    * cases work.
795    */
796   TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, flag);
797   if (rmesa->radeon.TclFallback) {
798      r200ChooseRenderState( ctx );
799      r200ChooseVertexState( ctx );
800   }
801}
802
803
804/* =============================================================
805 * Rendering attributes
806 *
807 * We really don't want to recalculate all this every time we bind a
808 * texture.  These things shouldn't change all that often, so it makes
809 * sense to break them out of the core texture state update routines.
810 */
811
812/* Examine lighting and texture state to determine if separate specular
813 * should be enabled.
814 */
815static void r200UpdateSpecular( GLcontext *ctx )
816{
817   r200ContextPtr rmesa = R200_CONTEXT(ctx);
818   uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
819
820   R200_STATECHANGE( rmesa, tcl );
821   R200_STATECHANGE( rmesa, vtx );
822
823   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_0_SHIFT);
824   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3<<R200_VTX_COLOR_1_SHIFT);
825   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0;
826   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1;
827   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE;
828
829   p &= ~R200_SPECULAR_ENABLE;
830
831   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE;
832
833
834   if (ctx->Light.Enabled &&
835       ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
836      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
837	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
838	  (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
839      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
840      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
841      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
842      p |=  R200_SPECULAR_ENABLE;
843      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &=
844	 ~R200_DIFFUSE_SPECULAR_COMBINE;
845   }
846   else if (ctx->Light.Enabled) {
847      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
848	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
849      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0;
850      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE;
851   } else if (ctx->Fog.ColorSumEnabled ) {
852      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
853	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) |
854	  (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
855      p |=  R200_SPECULAR_ENABLE;
856   } else {
857      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
858	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT));
859   }
860
861   if (ctx->Fog.Enabled) {
862      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |=
863	 ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT));
864      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1;
865   }
866
867   if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
868      R200_STATECHANGE( rmesa, ctx );
869      rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
870   }
871
872   /* Update vertex/render formats
873    */
874   if (rmesa->radeon.TclFallback) {
875      r200ChooseRenderState( ctx );
876      r200ChooseVertexState( ctx );
877   }
878}
879
880
881/* =============================================================
882 * Materials
883 */
884
885
886/* Update on colormaterial, material emmissive/ambient,
887 * lightmodel.globalambient
888 */
889static void update_global_ambient( GLcontext *ctx )
890{
891   r200ContextPtr rmesa = R200_CONTEXT(ctx);
892   float *fcmd = (float *)R200_DB_STATE( glt );
893
894   /* Need to do more if both emmissive & ambient are PREMULT:
895    * I believe this is not nessary when using source_material. This condition thus
896    * will never happen currently, and the function has no dependencies on materials now
897    */
898   if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] &
899       ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
900	(3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0)
901   {
902      COPY_3V( &fcmd[GLT_RED],
903	       ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
904      ACC_SCALE_3V( &fcmd[GLT_RED],
905		   ctx->Light.Model.Ambient,
906		   ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
907   }
908   else
909   {
910      COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
911   }
912
913   R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
914}
915
916/* Update on change to
917 *    - light[p].colors
918 *    - light[p].enabled
919 */
920static void update_light_colors( GLcontext *ctx, GLuint p )
921{
922   struct gl_light *l = &ctx->Light.Light[p];
923
924/*     fprintf(stderr, "%s\n", __FUNCTION__); */
925
926   if (l->Enabled) {
927      r200ContextPtr rmesa = R200_CONTEXT(ctx);
928      float *fcmd = (float *)R200_DB_STATE( lit[p] );
929
930      COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
931      COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
932      COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
933
934      R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
935   }
936}
937
938static void r200ColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
939{
940      r200ContextPtr rmesa = R200_CONTEXT(ctx);
941      GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1];
942      light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
943			   (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
944			   (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
945		   (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
946		   (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
947		   (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) |
948		   (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
949		   (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT));
950
951   if (ctx->Light.ColorMaterialEnabled) {
952      GLuint mask = ctx->Light.ColorMaterialBitmask;
953
954      if (mask & MAT_BIT_FRONT_EMISSION) {
955	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
956			     R200_FRONT_EMISSIVE_SOURCE_SHIFT);
957      }
958      else
959	 light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
960			     R200_FRONT_EMISSIVE_SOURCE_SHIFT);
961
962      if (mask & MAT_BIT_FRONT_AMBIENT) {
963	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
964			     R200_FRONT_AMBIENT_SOURCE_SHIFT);
965      }
966      else
967         light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
968			     R200_FRONT_AMBIENT_SOURCE_SHIFT);
969
970      if (mask & MAT_BIT_FRONT_DIFFUSE) {
971	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
972			     R200_FRONT_DIFFUSE_SOURCE_SHIFT);
973      }
974      else
975         light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
976			     R200_FRONT_DIFFUSE_SOURCE_SHIFT);
977
978      if (mask & MAT_BIT_FRONT_SPECULAR) {
979	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
980			     R200_FRONT_SPECULAR_SOURCE_SHIFT);
981      }
982      else {
983         light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 <<
984			     R200_FRONT_SPECULAR_SOURCE_SHIFT);
985      }
986
987      if (mask & MAT_BIT_BACK_EMISSION) {
988	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
989			     R200_BACK_EMISSIVE_SOURCE_SHIFT);
990      }
991
992      else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
993			     R200_BACK_EMISSIVE_SOURCE_SHIFT);
994
995      if (mask & MAT_BIT_BACK_AMBIENT) {
996	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
997			     R200_BACK_AMBIENT_SOURCE_SHIFT);
998      }
999      else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1000			     R200_BACK_AMBIENT_SOURCE_SHIFT);
1001
1002      if (mask & MAT_BIT_BACK_DIFFUSE) {
1003	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1004			     R200_BACK_DIFFUSE_SOURCE_SHIFT);
1005   }
1006      else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1007			     R200_BACK_DIFFUSE_SOURCE_SHIFT);
1008
1009      if (mask & MAT_BIT_BACK_SPECULAR) {
1010	 light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 <<
1011			     R200_BACK_SPECULAR_SOURCE_SHIFT);
1012      }
1013      else {
1014         light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 <<
1015			     R200_BACK_SPECULAR_SOURCE_SHIFT);
1016      }
1017      }
1018   else {
1019       /* Default to SOURCE_MATERIAL:
1020        */
1021     light_model_ctl1 |=
1022        (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) |
1023        (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) |
1024        (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) |
1025        (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) |
1026        (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) |
1027        (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) |
1028        (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) |
1029        (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT);
1030   }
1031
1032   if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) {
1033      R200_STATECHANGE( rmesa, tcl );
1034      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1;
1035   }
1036
1037
1038}
1039
1040void r200UpdateMaterial( GLcontext *ctx )
1041{
1042   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1043   GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
1044   GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] );
1045   GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] );
1046   GLuint mask = ~0;
1047
1048   /* Might be possible and faster to update everything unconditionally? */
1049   if (ctx->Light.ColorMaterialEnabled)
1050      mask &= ~ctx->Light.ColorMaterialBitmask;
1051
1052   if (R200_DEBUG & DEBUG_STATE)
1053      fprintf(stderr, "%s\n", __FUNCTION__);
1054
1055   if (mask & MAT_BIT_FRONT_EMISSION) {
1056      fcmd[MTL_EMMISSIVE_RED]   = mat[MAT_ATTRIB_FRONT_EMISSION][0];
1057      fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
1058      fcmd[MTL_EMMISSIVE_BLUE]  = mat[MAT_ATTRIB_FRONT_EMISSION][2];
1059      fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
1060   }
1061   if (mask & MAT_BIT_FRONT_AMBIENT) {
1062      fcmd[MTL_AMBIENT_RED]     = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
1063      fcmd[MTL_AMBIENT_GREEN]   = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
1064      fcmd[MTL_AMBIENT_BLUE]    = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
1065      fcmd[MTL_AMBIENT_ALPHA]   = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
1066   }
1067   if (mask & MAT_BIT_FRONT_DIFFUSE) {
1068      fcmd[MTL_DIFFUSE_RED]     = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
1069      fcmd[MTL_DIFFUSE_GREEN]   = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
1070      fcmd[MTL_DIFFUSE_BLUE]    = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
1071      fcmd[MTL_DIFFUSE_ALPHA]   = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
1072   }
1073   if (mask & MAT_BIT_FRONT_SPECULAR) {
1074      fcmd[MTL_SPECULAR_RED]    = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
1075      fcmd[MTL_SPECULAR_GREEN]  = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
1076      fcmd[MTL_SPECULAR_BLUE]   = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
1077      fcmd[MTL_SPECULAR_ALPHA]  = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
1078   }
1079   if (mask & MAT_BIT_FRONT_SHININESS) {
1080      fcmd[MTL_SHININESS]       = mat[MAT_ATTRIB_FRONT_SHININESS][0];
1081   }
1082
1083   if (mask & MAT_BIT_BACK_EMISSION) {
1084      fcmd2[MTL_EMMISSIVE_RED]   = mat[MAT_ATTRIB_BACK_EMISSION][0];
1085      fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1];
1086      fcmd2[MTL_EMMISSIVE_BLUE]  = mat[MAT_ATTRIB_BACK_EMISSION][2];
1087      fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3];
1088   }
1089   if (mask & MAT_BIT_BACK_AMBIENT) {
1090      fcmd2[MTL_AMBIENT_RED]     = mat[MAT_ATTRIB_BACK_AMBIENT][0];
1091      fcmd2[MTL_AMBIENT_GREEN]   = mat[MAT_ATTRIB_BACK_AMBIENT][1];
1092      fcmd2[MTL_AMBIENT_BLUE]    = mat[MAT_ATTRIB_BACK_AMBIENT][2];
1093      fcmd2[MTL_AMBIENT_ALPHA]   = mat[MAT_ATTRIB_BACK_AMBIENT][3];
1094   }
1095   if (mask & MAT_BIT_BACK_DIFFUSE) {
1096      fcmd2[MTL_DIFFUSE_RED]     = mat[MAT_ATTRIB_BACK_DIFFUSE][0];
1097      fcmd2[MTL_DIFFUSE_GREEN]   = mat[MAT_ATTRIB_BACK_DIFFUSE][1];
1098      fcmd2[MTL_DIFFUSE_BLUE]    = mat[MAT_ATTRIB_BACK_DIFFUSE][2];
1099      fcmd2[MTL_DIFFUSE_ALPHA]   = mat[MAT_ATTRIB_BACK_DIFFUSE][3];
1100   }
1101   if (mask & MAT_BIT_BACK_SPECULAR) {
1102      fcmd2[MTL_SPECULAR_RED]    = mat[MAT_ATTRIB_BACK_SPECULAR][0];
1103      fcmd2[MTL_SPECULAR_GREEN]  = mat[MAT_ATTRIB_BACK_SPECULAR][1];
1104      fcmd2[MTL_SPECULAR_BLUE]   = mat[MAT_ATTRIB_BACK_SPECULAR][2];
1105      fcmd2[MTL_SPECULAR_ALPHA]  = mat[MAT_ATTRIB_BACK_SPECULAR][3];
1106   }
1107   if (mask & MAT_BIT_BACK_SHININESS) {
1108      fcmd2[MTL_SHININESS]       = mat[MAT_ATTRIB_BACK_SHININESS][0];
1109   }
1110
1111   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] );
1112   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] );
1113
1114   /* currently material changes cannot trigger a global ambient change, I believe this is correct
1115    update_global_ambient( ctx ); */
1116}
1117
1118/* _NEW_LIGHT
1119 * _NEW_MODELVIEW
1120 * _MESA_NEW_NEED_EYE_COORDS
1121 *
1122 * Uses derived state from mesa:
1123 *       _VP_inf_norm
1124 *       _h_inf_norm
1125 *       _Position
1126 *       _NormSpotDirection
1127 *       _ModelViewInvScale
1128 *       _NeedEyeCoords
1129 *       _EyeZDir
1130 *
1131 * which are calculated in light.c and are correct for the current
1132 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
1133 * and _MESA_NEW_NEED_EYE_COORDS.
1134 */
1135static void update_light( GLcontext *ctx )
1136{
1137   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1138
1139   /* Have to check these, or have an automatic shortcircuit mechanism
1140    * to remove noop statechanges. (Or just do a better job on the
1141    * front end).
1142    */
1143   {
1144      GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0];
1145
1146      if (ctx->_NeedEyeCoords)
1147	 tmp &= ~R200_LIGHT_IN_MODELSPACE;
1148      else
1149	 tmp |= R200_LIGHT_IN_MODELSPACE;
1150
1151      if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0])
1152      {
1153	 R200_STATECHANGE( rmesa, tcl );
1154	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp;
1155      }
1156   }
1157
1158   {
1159      GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye );
1160      fcmd[EYE_X] = ctx->_EyeZDir[0];
1161      fcmd[EYE_Y] = ctx->_EyeZDir[1];
1162      fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1163      fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1164      R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1165   }
1166
1167
1168
1169   if (ctx->Light.Enabled) {
1170      GLint p;
1171      for (p = 0 ; p < MAX_LIGHTS; p++) {
1172	 if (ctx->Light.Light[p].Enabled) {
1173	    struct gl_light *l = &ctx->Light.Light[p];
1174	    GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] );
1175
1176	    if (l->EyePosition[3] == 0.0) {
1177	       COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1178	       COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1179	       fcmd[LIT_POSITION_W] = 0;
1180	       fcmd[LIT_DIRECTION_W] = 0;
1181	    } else {
1182	       COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1183	       fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0];
1184	       fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1];
1185	       fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2];
1186	       fcmd[LIT_DIRECTION_W] = 0;
1187	    }
1188
1189	    R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1190	 }
1191      }
1192   }
1193}
1194
1195static void r200Lightfv( GLcontext *ctx, GLenum light,
1196			   GLenum pname, const GLfloat *params )
1197{
1198   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1199   GLint p = light - GL_LIGHT0;
1200   struct gl_light *l = &ctx->Light.Light[p];
1201   GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1202
1203
1204   switch (pname) {
1205   case GL_AMBIENT:
1206   case GL_DIFFUSE:
1207   case GL_SPECULAR:
1208      update_light_colors( ctx, p );
1209      break;
1210
1211   case GL_SPOT_DIRECTION:
1212      /* picked up in update_light */
1213      break;
1214
1215   case GL_POSITION: {
1216      /* positions picked up in update_light, but can do flag here */
1217      GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL;
1218      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1219
1220      R200_STATECHANGE(rmesa, tcl);
1221      if (l->EyePosition[3] != 0.0F)
1222	 rmesa->hw.tcl.cmd[idx] |= flag;
1223      else
1224	 rmesa->hw.tcl.cmd[idx] &= ~flag;
1225      break;
1226   }
1227
1228   case GL_SPOT_EXPONENT:
1229      R200_STATECHANGE(rmesa, lit[p]);
1230      fcmd[LIT_SPOT_EXPONENT] = params[0];
1231      break;
1232
1233   case GL_SPOT_CUTOFF: {
1234      GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT;
1235      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1236
1237      R200_STATECHANGE(rmesa, lit[p]);
1238      fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1239
1240      R200_STATECHANGE(rmesa, tcl);
1241      if (l->SpotCutoff != 180.0F)
1242	 rmesa->hw.tcl.cmd[idx] |= flag;
1243      else
1244	 rmesa->hw.tcl.cmd[idx] &= ~flag;
1245
1246      break;
1247   }
1248
1249   case GL_CONSTANT_ATTENUATION:
1250      R200_STATECHANGE(rmesa, lit[p]);
1251      fcmd[LIT_ATTEN_CONST] = params[0];
1252      if ( params[0] == 0.0 )
1253	 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1254      else
1255	 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1256      break;
1257   case GL_LINEAR_ATTENUATION:
1258      R200_STATECHANGE(rmesa, lit[p]);
1259      fcmd[LIT_ATTEN_LINEAR] = params[0];
1260      break;
1261   case GL_QUADRATIC_ATTENUATION:
1262      R200_STATECHANGE(rmesa, lit[p]);
1263      fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1264      break;
1265   default:
1266      return;
1267   }
1268
1269   /* Set RANGE_ATTEN only when needed */
1270   switch (pname) {
1271   case GL_POSITION:
1272   case GL_CONSTANT_ATTENUATION:
1273   case GL_LINEAR_ATTENUATION:
1274   case GL_QUADRATIC_ATTENUATION: {
1275      GLuint *icmd = (GLuint *)R200_DB_STATE( tcl );
1276      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1277      GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN
1278				  : R200_LIGHT_0_ENABLE_RANGE_ATTEN;
1279      GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN
1280				  : R200_LIGHT_0_CONSTANT_RANGE_ATTEN;
1281
1282      if ( l->EyePosition[3] == 0.0F ||
1283	   ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1284	     fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1285	 /* Disable attenuation */
1286	 icmd[idx] &= ~atten_flag;
1287      } else {
1288	 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1289	    /* Enable only constant portion of attenuation calculation */
1290	    icmd[idx] |= ( atten_flag | atten_const_flag );
1291	 } else {
1292	    /* Enable full attenuation calculation */
1293	    icmd[idx] &= ~atten_const_flag;
1294	    icmd[idx] |= atten_flag;
1295	 }
1296      }
1297
1298      R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1299      break;
1300   }
1301   default:
1302     break;
1303   }
1304}
1305
1306static void r200UpdateLocalViewer ( GLcontext *ctx )
1307{
1308/* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and
1309   GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that
1310   for these and only these modes). This means specular highlights may turn out
1311   wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER
1312   is not set, though it seems to happen rarely and the effect seems quite
1313   subtle. May need TCL fallback to fix it completely, though I'm not sure
1314   how you'd identify the cases where the specular highlights indeed will
1315   be wrong. Don't know if fglrx does something special in that case.
1316*/
1317   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1318   R200_STATECHANGE( rmesa, tcl );
1319   if (ctx->Light.Model.LocalViewer ||
1320       ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
1321      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER;
1322   else
1323      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER;
1324}
1325
1326static void r200LightModelfv( GLcontext *ctx, GLenum pname,
1327				const GLfloat *param )
1328{
1329   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1330
1331   switch (pname) {
1332      case GL_LIGHT_MODEL_AMBIENT:
1333	 update_global_ambient( ctx );
1334	 break;
1335
1336      case GL_LIGHT_MODEL_LOCAL_VIEWER:
1337	 r200UpdateLocalViewer( ctx );
1338         break;
1339
1340      case GL_LIGHT_MODEL_TWO_SIDE:
1341	 R200_STATECHANGE( rmesa, tcl );
1342	 if (ctx->Light.Model.TwoSide)
1343	    rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE;
1344	 else
1345	    rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE);
1346	 if (rmesa->radeon.TclFallback) {
1347	    r200ChooseRenderState( ctx );
1348	    r200ChooseVertexState( ctx );
1349	 }
1350         break;
1351
1352      case GL_LIGHT_MODEL_COLOR_CONTROL:
1353	 r200UpdateSpecular(ctx);
1354         break;
1355
1356      default:
1357         break;
1358   }
1359}
1360
1361static void r200ShadeModel( GLcontext *ctx, GLenum mode )
1362{
1363   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1364   GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1365
1366   s &= ~(R200_DIFFUSE_SHADE_MASK |
1367	  R200_ALPHA_SHADE_MASK |
1368	  R200_SPECULAR_SHADE_MASK |
1369	  R200_FOG_SHADE_MASK |
1370	  R200_DISC_FOG_SHADE_MASK);
1371
1372   switch ( mode ) {
1373   case GL_FLAT:
1374      s |= (R200_DIFFUSE_SHADE_FLAT |
1375	    R200_ALPHA_SHADE_FLAT |
1376	    R200_SPECULAR_SHADE_FLAT |
1377	    R200_FOG_SHADE_FLAT |
1378	    R200_DISC_FOG_SHADE_FLAT);
1379      break;
1380   case GL_SMOOTH:
1381      s |= (R200_DIFFUSE_SHADE_GOURAUD |
1382	    R200_ALPHA_SHADE_GOURAUD |
1383	    R200_SPECULAR_SHADE_GOURAUD |
1384	    R200_FOG_SHADE_GOURAUD |
1385	    R200_DISC_FOG_SHADE_GOURAUD);
1386      break;
1387   default:
1388      return;
1389   }
1390
1391   if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1392      R200_STATECHANGE( rmesa, set );
1393      rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1394   }
1395}
1396
1397
1398/* =============================================================
1399 * User clip planes
1400 */
1401
1402static void r200ClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1403{
1404   GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1405   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1406   GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1407
1408   R200_STATECHANGE( rmesa, ucp[p] );
1409   rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1410   rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1411   rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1412   rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1413}
1414
1415static void r200UpdateClipPlanes( GLcontext *ctx )
1416{
1417   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1418   GLuint p;
1419
1420   for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1421      if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1422	 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1423
1424	 R200_STATECHANGE( rmesa, ucp[p] );
1425	 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1426	 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1427	 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1428	 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1429      }
1430   }
1431}
1432
1433
1434/* =============================================================
1435 * Stencil
1436 */
1437
1438static void
1439r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
1440                         GLint ref, GLuint mask )
1441{
1442   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1443   GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << R200_STENCIL_REF_SHIFT) |
1444		     ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT));
1445
1446   R200_STATECHANGE( rmesa, ctx );
1447   R200_STATECHANGE( rmesa, msk );
1448
1449   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1450   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1451						   R200_STENCIL_VALUE_MASK);
1452
1453   switch ( ctx->Stencil.Function[0] ) {
1454   case GL_NEVER:
1455      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1456      break;
1457   case GL_LESS:
1458      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1459      break;
1460   case GL_EQUAL:
1461      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1462      break;
1463   case GL_LEQUAL:
1464      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1465      break;
1466   case GL_GREATER:
1467      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1468      break;
1469   case GL_NOTEQUAL:
1470      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1471      break;
1472   case GL_GEQUAL:
1473      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1474      break;
1475   case GL_ALWAYS:
1476      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1477      break;
1478   }
1479
1480   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1481}
1482
1483static void
1484r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
1485{
1486   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1487
1488   R200_STATECHANGE( rmesa, msk );
1489   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1490   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1491      ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT);
1492}
1493
1494static void
1495r200StencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
1496                       GLenum zfail, GLenum zpass )
1497{
1498   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1499
1500   R200_STATECHANGE( rmesa, ctx );
1501   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1502					       R200_STENCIL_ZFAIL_MASK |
1503					       R200_STENCIL_ZPASS_MASK);
1504
1505   switch ( ctx->Stencil.FailFunc[0] ) {
1506   case GL_KEEP:
1507      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1508      break;
1509   case GL_ZERO:
1510      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1511      break;
1512   case GL_REPLACE:
1513      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1514      break;
1515   case GL_INCR:
1516      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1517      break;
1518   case GL_DECR:
1519      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1520      break;
1521   case GL_INCR_WRAP_EXT:
1522      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1523      break;
1524   case GL_DECR_WRAP_EXT:
1525      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1526      break;
1527   case GL_INVERT:
1528      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1529      break;
1530   }
1531
1532   switch ( ctx->Stencil.ZFailFunc[0] ) {
1533   case GL_KEEP:
1534      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1535      break;
1536   case GL_ZERO:
1537      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1538      break;
1539   case GL_REPLACE:
1540      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1541      break;
1542   case GL_INCR:
1543      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1544      break;
1545   case GL_DECR:
1546      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1547      break;
1548   case GL_INCR_WRAP_EXT:
1549      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1550      break;
1551   case GL_DECR_WRAP_EXT:
1552      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1553      break;
1554   case GL_INVERT:
1555      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1556      break;
1557   }
1558
1559   switch ( ctx->Stencil.ZPassFunc[0] ) {
1560   case GL_KEEP:
1561      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1562      break;
1563   case GL_ZERO:
1564      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1565      break;
1566   case GL_REPLACE:
1567      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1568      break;
1569   case GL_INCR:
1570      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1571      break;
1572   case GL_DECR:
1573      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1574      break;
1575   case GL_INCR_WRAP_EXT:
1576      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1577      break;
1578   case GL_DECR_WRAP_EXT:
1579      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1580      break;
1581   case GL_INVERT:
1582      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1583      break;
1584   }
1585}
1586
1587static void r200ClearStencil( GLcontext *ctx, GLint s )
1588{
1589   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1590
1591   rmesa->radeon.state.stencil.clear =
1592      ((GLuint) (ctx->Stencil.Clear & 0xff) |
1593       (0xff << R200_STENCIL_MASK_SHIFT) |
1594       ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT));
1595}
1596
1597
1598/* =============================================================
1599 * Window position and viewport transformation
1600 */
1601
1602/*
1603 * To correctly position primitives:
1604 */
1605#define SUBPIXEL_X 0.125
1606#define SUBPIXEL_Y 0.125
1607
1608
1609/**
1610 * Called when window size or position changes or viewport or depth range
1611 * state is changed.  We update the hardware viewport state here.
1612 */
1613void r200UpdateWindow( GLcontext *ctx )
1614{
1615   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1616   __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
1617   GLfloat xoffset = dPriv ? (GLfloat) dPriv->x : 0;
1618   GLfloat yoffset = dPriv ? (GLfloat) dPriv->y + dPriv->h : 0;
1619   const GLfloat *v = ctx->Viewport._WindowMap.m;
1620   const GLboolean render_to_fbo = (ctx->DrawBuffer ? (ctx->DrawBuffer->Name != 0) : 0);
1621   const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
1622   GLfloat y_scale, y_bias;
1623
1624   if (render_to_fbo) {
1625      y_scale = 1.0;
1626      y_bias = 0;
1627   } else {
1628      y_scale = -1.0;
1629      y_bias = yoffset;
1630   }
1631
1632   float_ui32_type sx = { v[MAT_SX] };
1633   float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
1634   float_ui32_type sy = { v[MAT_SY] * y_scale };
1635   float_ui32_type ty = { (v[MAT_TY] * y_scale) + y_bias + SUBPIXEL_Y };
1636   float_ui32_type sz = { v[MAT_SZ] * depthScale };
1637   float_ui32_type tz = { v[MAT_TZ] * depthScale };
1638
1639   R200_STATECHANGE( rmesa, vpt );
1640
1641   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE]  = sx.ui32;
1642   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1643   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE]  = sy.ui32;
1644   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1645   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE]  = sz.ui32;
1646   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1647}
1648
1649
1650
1651static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1652			    GLsizei width, GLsizei height )
1653{
1654   /* Don't pipeline viewport changes, conflict with window offset
1655    * setting below.  Could apply deltas to rescue pipelined viewport
1656    * values, or keep the originals hanging around.
1657    */
1658   r200UpdateWindow( ctx );
1659
1660   radeon_viewport(ctx, x, y, width, height);
1661}
1662
1663static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1664			      GLclampd farval )
1665{
1666   r200UpdateWindow( ctx );
1667}
1668
1669void r200UpdateViewportOffset( GLcontext *ctx )
1670{
1671   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1672   __DRIdrawablePrivate *dPriv = radeon_get_drawable(&rmesa->radeon);
1673   GLfloat xoffset = (GLfloat)dPriv->x;
1674   GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1675   const GLfloat *v = ctx->Viewport._WindowMap.m;
1676
1677   float_ui32_type tx;
1678   float_ui32_type ty;
1679
1680   tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X;
1681   ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1682
1683   if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 ||
1684	rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 )
1685   {
1686      /* Note: this should also modify whatever data the context reset
1687       * code uses...
1688       */
1689      R200_STATECHANGE( rmesa, vpt );
1690      rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1691      rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1692
1693      /* update polygon stipple x/y screen offset */
1694      {
1695         GLuint stx, sty;
1696         GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1697
1698         m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1699                R200_STIPPLE_Y_OFFSET_MASK);
1700
1701         /* add magic offsets, then invert */
1702         stx = 31 - ((dPriv->x - 1) & R200_STIPPLE_COORD_MASK);
1703         sty = 31 - ((dPriv->y + dPriv->h - 1)
1704                     & R200_STIPPLE_COORD_MASK);
1705
1706         m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1707               (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1708
1709         if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1710            R200_STATECHANGE( rmesa, msc );
1711	    rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1712         }
1713      }
1714   }
1715
1716   radeonUpdateScissor( ctx );
1717}
1718
1719
1720
1721/* =============================================================
1722 * Miscellaneous
1723 */
1724
1725static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1726{
1727   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1728   GLubyte color[4];
1729   struct radeon_renderbuffer *rrb;
1730
1731   rrb = radeon_get_colorbuffer(&rmesa->radeon);
1732   if (!rrb)
1733     return;
1734   CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1735   CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1736   CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1737   CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1738   rmesa->radeon.state.color.clear = radeonPackColor( rrb->cpp,
1739                                             color[0], color[1],
1740                                             color[2], color[3] );
1741}
1742
1743
1744static void r200RenderMode( GLcontext *ctx, GLenum mode )
1745{
1746   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1747   FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1748}
1749
1750
1751static GLuint r200_rop_tab[] = {
1752   R200_ROP_CLEAR,
1753   R200_ROP_AND,
1754   R200_ROP_AND_REVERSE,
1755   R200_ROP_COPY,
1756   R200_ROP_AND_INVERTED,
1757   R200_ROP_NOOP,
1758   R200_ROP_XOR,
1759   R200_ROP_OR,
1760   R200_ROP_NOR,
1761   R200_ROP_EQUIV,
1762   R200_ROP_INVERT,
1763   R200_ROP_OR_REVERSE,
1764   R200_ROP_COPY_INVERTED,
1765   R200_ROP_OR_INVERTED,
1766   R200_ROP_NAND,
1767   R200_ROP_SET,
1768};
1769
1770static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1771{
1772   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1773   GLuint rop = (GLuint)opcode - GL_CLEAR;
1774
1775   ASSERT( rop < 16 );
1776
1777   R200_STATECHANGE( rmesa, msk );
1778   rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1779}
1780
1781/* =============================================================
1782 * State enable/disable
1783 */
1784
1785static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1786{
1787   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1788   GLuint p, flag;
1789
1790   if ( R200_DEBUG & DEBUG_STATE )
1791      fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1792	       _mesa_lookup_enum_by_nr( cap ),
1793	       state ? "GL_TRUE" : "GL_FALSE" );
1794
1795   switch ( cap ) {
1796      /* Fast track this one...
1797       */
1798   case GL_TEXTURE_1D:
1799   case GL_TEXTURE_2D:
1800   case GL_TEXTURE_3D:
1801      break;
1802
1803   case GL_ALPHA_TEST:
1804      R200_STATECHANGE( rmesa, ctx );
1805      if (state) {
1806	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1807      } else {
1808	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1809      }
1810      break;
1811
1812   case GL_BLEND:
1813   case GL_COLOR_LOGIC_OP:
1814      r200_set_blend_state( ctx );
1815      break;
1816
1817   case GL_CLIP_PLANE0:
1818   case GL_CLIP_PLANE1:
1819   case GL_CLIP_PLANE2:
1820   case GL_CLIP_PLANE3:
1821   case GL_CLIP_PLANE4:
1822   case GL_CLIP_PLANE5:
1823      p = cap-GL_CLIP_PLANE0;
1824      R200_STATECHANGE( rmesa, tcl );
1825      if (state) {
1826	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1827	 r200ClipPlane( ctx, cap, NULL );
1828      }
1829      else {
1830	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1831      }
1832      break;
1833
1834   case GL_COLOR_MATERIAL:
1835      r200ColorMaterial( ctx, 0, 0 );
1836      r200UpdateMaterial( ctx );
1837      break;
1838
1839   case GL_CULL_FACE:
1840      r200CullFace( ctx, 0 );
1841      break;
1842
1843   case GL_DEPTH_TEST:
1844      R200_STATECHANGE(rmesa, ctx );
1845      if ( state ) {
1846	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_Z_ENABLE;
1847      } else {
1848	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1849      }
1850      break;
1851
1852   case GL_DITHER:
1853      R200_STATECHANGE(rmesa, ctx );
1854      if ( state ) {
1855	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_DITHER_ENABLE;
1856	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable;
1857      } else {
1858	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1859	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  rmesa->radeon.state.color.roundEnable;
1860      }
1861      break;
1862
1863   case GL_FOG:
1864      R200_STATECHANGE(rmesa, ctx );
1865      if ( state ) {
1866	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1867	 r200Fogfv( ctx, GL_FOG_MODE, NULL );
1868      } else {
1869	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1870	 R200_STATECHANGE(rmesa, tcl);
1871	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1872      }
1873      r200UpdateSpecular( ctx ); /* for PK_SPEC */
1874      if (rmesa->radeon.TclFallback)
1875	 r200ChooseVertexState( ctx );
1876      _mesa_allow_light_in_model( ctx, !state );
1877      break;
1878
1879   case GL_LIGHT0:
1880   case GL_LIGHT1:
1881   case GL_LIGHT2:
1882   case GL_LIGHT3:
1883   case GL_LIGHT4:
1884   case GL_LIGHT5:
1885   case GL_LIGHT6:
1886   case GL_LIGHT7:
1887      R200_STATECHANGE(rmesa, tcl);
1888      p = cap - GL_LIGHT0;
1889      if (p&1)
1890	 flag = (R200_LIGHT_1_ENABLE |
1891		 R200_LIGHT_1_ENABLE_AMBIENT |
1892		 R200_LIGHT_1_ENABLE_SPECULAR);
1893      else
1894	 flag = (R200_LIGHT_0_ENABLE |
1895		 R200_LIGHT_0_ENABLE_AMBIENT |
1896		 R200_LIGHT_0_ENABLE_SPECULAR);
1897
1898      if (state)
1899	 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1900      else
1901	 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1902
1903      /*
1904       */
1905      update_light_colors( ctx, p );
1906      break;
1907
1908   case GL_LIGHTING:
1909      r200UpdateSpecular(ctx);
1910      /* for reflection map fixup - might set recheck_texgen for all units too */
1911      rmesa->radeon.NewGLState |= _NEW_TEXTURE;
1912      break;
1913
1914   case GL_LINE_SMOOTH:
1915      R200_STATECHANGE( rmesa, ctx );
1916      if ( state ) {
1917	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  R200_ANTI_ALIAS_LINE;
1918      } else {
1919	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1920      }
1921      break;
1922
1923   case GL_LINE_STIPPLE:
1924      R200_STATECHANGE( rmesa, set );
1925      if ( state ) {
1926	 rmesa->hw.set.cmd[SET_RE_CNTL] |=  R200_PATTERN_ENABLE;
1927      } else {
1928	 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1929      }
1930      break;
1931
1932   case GL_NORMALIZE:
1933      R200_STATECHANGE( rmesa, tcl );
1934      if ( state ) {
1935	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_NORMALIZE_NORMALS;
1936      } else {
1937	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1938      }
1939      break;
1940
1941      /* Pointsize registers on r200 only work for point sprites, and point smooth
1942       * doesn't work for point sprites (and isn't needed for 1.0 sized aa points).
1943       * In any case, setting pointmin == pointsizemax == 1.0 for aa points
1944       * is enough to satisfy conform.
1945       */
1946   case GL_POINT_SMOOTH:
1947      break;
1948
1949      /* These don't really do anything, as we don't use the 3vtx
1950       * primitives yet.
1951       */
1952#if 0
1953   case GL_POLYGON_OFFSET_POINT:
1954      R200_STATECHANGE( rmesa, set );
1955      if ( state ) {
1956	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_POINT;
1957      } else {
1958	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
1959      }
1960      break;
1961
1962   case GL_POLYGON_OFFSET_LINE:
1963      R200_STATECHANGE( rmesa, set );
1964      if ( state ) {
1965	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_LINE;
1966      } else {
1967	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
1968      }
1969      break;
1970#endif
1971
1972   case GL_POINT_SPRITE_ARB:
1973      R200_STATECHANGE( rmesa, spr );
1974      if ( state ) {
1975	 int i;
1976	 for (i = 0; i < 6; i++) {
1977	    rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |=
1978		ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i);
1979	 }
1980      } else {
1981	 rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK;
1982      }
1983      break;
1984
1985   case GL_POLYGON_OFFSET_FILL:
1986      R200_STATECHANGE( rmesa, set );
1987      if ( state ) {
1988	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_TRI;
1989      } else {
1990	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
1991      }
1992      break;
1993
1994   case GL_POLYGON_SMOOTH:
1995      R200_STATECHANGE( rmesa, ctx );
1996      if ( state ) {
1997	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  R200_ANTI_ALIAS_POLY;
1998      } else {
1999	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
2000      }
2001      break;
2002
2003   case GL_POLYGON_STIPPLE:
2004      R200_STATECHANGE(rmesa, set );
2005      if ( state ) {
2006	 rmesa->hw.set.cmd[SET_RE_CNTL] |=  R200_STIPPLE_ENABLE;
2007      } else {
2008	 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
2009      }
2010      break;
2011
2012   case GL_RESCALE_NORMAL_EXT: {
2013      GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
2014      R200_STATECHANGE( rmesa, tcl );
2015      if ( tmp ) {
2016	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_RESCALE_NORMALS;
2017      } else {
2018	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2019      }
2020      break;
2021   }
2022
2023   case GL_SCISSOR_TEST:
2024      radeon_firevertices(&rmesa->radeon);
2025      rmesa->radeon.state.scissor.enabled = state;
2026      radeonUpdateScissor( ctx );
2027      break;
2028
2029   case GL_STENCIL_TEST:
2030      {
2031	 GLboolean hw_stencil = GL_FALSE;
2032	 if (ctx->DrawBuffer) {
2033	    struct radeon_renderbuffer *rrbStencil
2034	       = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL);
2035	    hw_stencil = (rrbStencil && rrbStencil->bo);
2036	 }
2037
2038	 if (hw_stencil) {
2039	    R200_STATECHANGE( rmesa, ctx );
2040	    if ( state ) {
2041	       rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_STENCIL_ENABLE;
2042	    } else {
2043	       rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
2044	    }
2045	 } else {
2046	    FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
2047	 }
2048      }
2049      break;
2050
2051   case GL_TEXTURE_GEN_Q:
2052   case GL_TEXTURE_GEN_R:
2053   case GL_TEXTURE_GEN_S:
2054   case GL_TEXTURE_GEN_T:
2055      /* Picked up in r200UpdateTextureState.
2056       */
2057      rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
2058      break;
2059
2060   case GL_COLOR_SUM_EXT:
2061      r200UpdateSpecular ( ctx );
2062      break;
2063
2064   case GL_VERTEX_PROGRAM_ARB:
2065      if (!state) {
2066	 GLuint i;
2067	 rmesa->curr_vp_hw = NULL;
2068	 R200_STATECHANGE( rmesa, vap );
2069	 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE;
2070	 /* mark all tcl atoms (tcl vector state got overwritten) dirty
2071	    not sure about tcl scalar state - we need at least grd
2072	    with vert progs too.
2073	    ucp looks like it doesn't get overwritten (may even work
2074	    with vp for pos-invariant progs if we're lucky) */
2075	 R200_STATECHANGE( rmesa, mtl[0] );
2076	 R200_STATECHANGE( rmesa, mtl[1] );
2077	 R200_STATECHANGE( rmesa, fog );
2078	 R200_STATECHANGE( rmesa, glt );
2079	 R200_STATECHANGE( rmesa, eye );
2080	 for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) {
2081	    R200_STATECHANGE( rmesa, mat[i] );
2082	 }
2083	 for (i = 0 ; i < 8; i++) {
2084	    R200_STATECHANGE( rmesa, lit[i] );
2085	 }
2086	 R200_STATECHANGE( rmesa, tcl );
2087	 for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) {
2088	    if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
2089	       rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i);
2090	    }
2091/*	    else {
2092	       rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i);
2093	    }*/
2094	 }
2095	 /* ugly. Need to call everything which might change compsel. */
2096	 r200UpdateSpecular( ctx );
2097#if 0
2098	/* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM),
2099	   but without it doom3 locks up at always the same places. Why? */
2100	/* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before
2101	   accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */
2102	 r200UpdateTextureState( ctx );
2103	 /* if we call r200UpdateTextureState we need the code below because we are calling it with
2104	    non-current derived enabled values which may revert the state atoms for frag progs even when
2105	    they already got disabled... ugh
2106	    Should really figure out why we need to call r200UpdateTextureState in the first place */
2107	 GLuint unit;
2108	 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2109	    R200_STATECHANGE( rmesa, pix[unit] );
2110	    R200_STATECHANGE( rmesa, tex[unit] );
2111	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2112		~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2113	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2114	    /* need to guard this with drmSupportsFragmentShader? Should never get here if
2115	       we don't announce ATI_fs, right? */
2116	    rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2117         }
2118	 R200_STATECHANGE( rmesa, cst );
2119	 R200_STATECHANGE( rmesa, tf );
2120	 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2121#endif
2122      }
2123      else {
2124	 /* picked up later */
2125      }
2126      /* call functions which change hw state based on ARB_vp enabled or not. */
2127      r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2128      r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL );
2129      break;
2130
2131   case GL_VERTEX_PROGRAM_POINT_SIZE_ARB:
2132      r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL );
2133      break;
2134
2135   case GL_FRAGMENT_SHADER_ATI:
2136      if ( !state ) {
2137	 /* restore normal tex env colors and make sure tex env combine will get updated
2138	    mark env atoms dirty (as their data was overwritten by afs even
2139	    if they didn't change) and restore tex coord routing */
2140	 GLuint unit;
2141	 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2142	    R200_STATECHANGE( rmesa, pix[unit] );
2143	    R200_STATECHANGE( rmesa, tex[unit] );
2144	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2145		~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2146	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2147	    /* need to guard this with drmSupportsFragmentShader? Should never get here if
2148	       we don't announce ATI_fs, right? */
2149	    rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2150         }
2151	 R200_STATECHANGE( rmesa, cst );
2152	 R200_STATECHANGE( rmesa, tf );
2153	 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2154      }
2155      else {
2156	 /* need to mark this dirty as pix/tf atoms have overwritten the data
2157	    even if the data in the atoms didn't change */
2158	 R200_STATECHANGE( rmesa, atf );
2159	 R200_STATECHANGE( rmesa, afs[1] );
2160	 /* everything else picked up in r200UpdateTextureState hopefully */
2161      }
2162      break;
2163   default:
2164      return;
2165   }
2166}
2167
2168
2169void r200LightingSpaceChange( GLcontext *ctx )
2170{
2171   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2172   GLboolean tmp;
2173
2174   if (R200_DEBUG & DEBUG_STATE)
2175      fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2176	      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2177
2178   if (ctx->_NeedEyeCoords)
2179      tmp = ctx->Transform.RescaleNormals;
2180   else
2181      tmp = !ctx->Transform.RescaleNormals;
2182
2183   R200_STATECHANGE( rmesa, tcl );
2184   if ( tmp ) {
2185      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_RESCALE_NORMALS;
2186   } else {
2187      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2188   }
2189
2190   if (R200_DEBUG & DEBUG_STATE)
2191      fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2192	      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2193}
2194
2195/* =============================================================
2196 * Deferred state management - matrices, textures, other?
2197 */
2198
2199
2200
2201
2202static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2203{
2204   float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2205   int i;
2206
2207
2208   for (i = 0 ; i < 4 ; i++) {
2209      *dest++ = src[i];
2210      *dest++ = src[i+4];
2211      *dest++ = src[i+8];
2212      *dest++ = src[i+12];
2213   }
2214
2215   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2216}
2217
2218static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2219{
2220   float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2221   memcpy(dest, src, 16*sizeof(float));
2222   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2223}
2224
2225
2226static void update_texturematrix( GLcontext *ctx )
2227{
2228   r200ContextPtr rmesa = R200_CONTEXT( ctx );
2229   GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2230   GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2231   int unit;
2232
2233   if (R200_DEBUG & DEBUG_STATE)
2234      fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
2235	      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2236
2237   rmesa->TexMatEnabled = 0;
2238   rmesa->TexMatCompSel = 0;
2239
2240   for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2241      if (!ctx->Texture.Unit[unit]._ReallyEnabled)
2242	 continue;
2243
2244      if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2245	 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2246				  R200_TEXMAT_0_ENABLE) << unit;
2247
2248	 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2249
2250	 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2251	    /* Need to preconcatenate any active texgen
2252	     * obj/eyeplane matrices:
2253	     */
2254	    _math_matrix_mul_matrix( &rmesa->tmpmat,
2255				     ctx->TextureMatrixStack[unit].Top,
2256				     &rmesa->TexGenMatrix[unit] );
2257	    upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2258	 }
2259	 else {
2260	    upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2261			   R200_MTX_TEX0+unit );
2262	 }
2263      }
2264      else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2265	 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2266			R200_MTX_TEX0+unit );
2267      }
2268   }
2269
2270   tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2271   if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2272      R200_STATECHANGE(rmesa, tcg);
2273      rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2274   }
2275
2276   compsel &= ~R200_OUTPUT_TEX_MASK;
2277   compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2278   if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2279      R200_STATECHANGE(rmesa, vtx);
2280      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2281   }
2282}
2283
2284static GLboolean r200ValidateBuffers(GLcontext *ctx)
2285{
2286   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2287   struct radeon_renderbuffer *rrb;
2288   int i, ret;
2289
2290   radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs);
2291
2292   rrb = radeon_get_colorbuffer(&rmesa->radeon);
2293   /* color buffer */
2294   if (rrb && rrb->bo) {
2295     radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2296				       0, RADEON_GEM_DOMAIN_VRAM);
2297   }
2298
2299   /* depth buffer */
2300   rrb = radeon_get_depthbuffer(&rmesa->radeon);
2301   /* color buffer */
2302   if (rrb && rrb->bo) {
2303     radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo,
2304				       0, RADEON_GEM_DOMAIN_VRAM);
2305   }
2306
2307   for (i = 0; i < ctx->Const.MaxTextureImageUnits; ++i) {
2308      radeonTexObj *t;
2309
2310      if (!ctx->Texture.Unit[i]._ReallyEnabled)
2311	 continue;
2312
2313      t = radeon_tex_obj(ctx->Texture.Unit[i]._Current);
2314      if (t->image_override && t->bo)
2315	radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo,
2316			   RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2317      else if (t->mt->bo)
2318	radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo,
2319			   RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0);
2320   }
2321
2322   ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, rmesa->radeon.dma.current, RADEON_GEM_DOMAIN_GTT, 0);
2323   if (ret)
2324       return GL_FALSE;
2325   return GL_TRUE;
2326}
2327
2328GLboolean r200ValidateState( GLcontext *ctx )
2329{
2330   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2331   GLuint new_state = rmesa->radeon.NewGLState;
2332
2333   if (new_state & _NEW_BUFFERS) {
2334      _mesa_update_framebuffer(ctx);
2335      /* this updates the DrawBuffer's Width/Height if it's a FBO */
2336      _mesa_update_draw_buffer_bounds(ctx);
2337
2338      R200_STATECHANGE(rmesa, ctx);
2339   }
2340
2341   if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) {
2342      r200UpdateTextureState( ctx );
2343      new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */
2344      r200UpdateLocalViewer( ctx );
2345   }
2346
2347   /* we need to do a space check here */
2348   if (!r200ValidateBuffers(ctx))
2349     return GL_FALSE;
2350
2351/* FIXME: don't really need most of these when vertex progs are enabled */
2352
2353   /* Need an event driven matrix update?
2354    */
2355   if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2356      upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2357
2358   /* Need these for lighting (shouldn't upload otherwise)
2359    */
2360   if (new_state & (_NEW_MODELVIEW)) {
2361      upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2362      upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2363   }
2364
2365   /* Does this need to be triggered on eg. modelview for
2366    * texgen-derived objplane/eyeplane matrices?
2367    */
2368   if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2369      update_texturematrix( ctx );
2370   }
2371
2372   if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2373      update_light( ctx );
2374   }
2375
2376   /* emit all active clip planes if projection matrix changes.
2377    */
2378   if (new_state & (_NEW_PROJECTION)) {
2379      if (ctx->Transform.ClipPlanesEnabled)
2380	 r200UpdateClipPlanes( ctx );
2381   }
2382
2383   if (new_state & (_NEW_PROGRAM|
2384                    _NEW_PROGRAM_CONSTANTS |
2385   /* need to test for pretty much anything due to possible parameter bindings */
2386	_NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM|
2387	_NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX|
2388	_NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) {
2389      if (ctx->VertexProgram._Enabled) {
2390	 r200SetupVertexProg( ctx );
2391      }
2392      else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0);
2393   }
2394
2395   rmesa->radeon.NewGLState = 0;
2396   return GL_TRUE;
2397}
2398
2399
2400static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2401{
2402   _swrast_InvalidateState( ctx, new_state );
2403   _swsetup_InvalidateState( ctx, new_state );
2404   _vbo_InvalidateState( ctx, new_state );
2405   _tnl_InvalidateState( ctx, new_state );
2406   _ae_invalidate_state( ctx, new_state );
2407   R200_CONTEXT(ctx)->radeon.NewGLState |= new_state;
2408}
2409
2410/* A hack.  The r200 can actually cope just fine with materials
2411 * between begin/ends, so fix this.
2412 * Should map to inputs just like the generic vertex arrays for vertex progs.
2413 * In theory there could still be too many and we'd still need a fallback.
2414 */
2415static GLboolean check_material( GLcontext *ctx )
2416{
2417   TNLcontext *tnl = TNL_CONTEXT(ctx);
2418   GLint i;
2419
2420   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2421	i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2422	i++)
2423      if (tnl->vb.AttribPtr[i] &&
2424	  tnl->vb.AttribPtr[i]->stride)
2425	 return GL_TRUE;
2426
2427   return GL_FALSE;
2428}
2429
2430static void r200WrapRunPipeline( GLcontext *ctx )
2431{
2432   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2433   GLboolean has_material;
2434
2435   if (0)
2436      fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->radeon.NewGLState);
2437
2438   /* Validate state:
2439    */
2440   if (rmesa->radeon.NewGLState)
2441      if (!r200ValidateState( ctx ))
2442	 FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE);
2443
2444   has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx );
2445
2446   if (has_material) {
2447      TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2448   }
2449
2450   /* Run the pipeline.
2451    */
2452   _tnl_run_pipeline( ctx );
2453
2454   if (has_material) {
2455      TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2456   }
2457}
2458
2459
2460/* Initialize the driver's state functions.
2461 */
2462void r200InitStateFuncs( struct dd_function_table *functions )
2463{
2464   functions->UpdateState		= r200InvalidateState;
2465   functions->LightingSpaceChange	= r200LightingSpaceChange;
2466
2467   functions->DrawBuffer		= radeonDrawBuffer;
2468   functions->ReadBuffer		= radeonReadBuffer;
2469
2470   functions->AlphaFunc			= r200AlphaFunc;
2471   functions->BlendColor		= r200BlendColor;
2472   functions->BlendEquationSeparate	= r200BlendEquationSeparate;
2473   functions->BlendFuncSeparate		= r200BlendFuncSeparate;
2474   functions->ClearColor		= r200ClearColor;
2475   functions->ClearDepth		= r200ClearDepth;
2476   functions->ClearIndex		= NULL;
2477   functions->ClearStencil		= r200ClearStencil;
2478   functions->ClipPlane			= r200ClipPlane;
2479   functions->ColorMask			= r200ColorMask;
2480   functions->CullFace			= r200CullFace;
2481   functions->DepthFunc			= r200DepthFunc;
2482   functions->DepthMask			= r200DepthMask;
2483   functions->DepthRange		= r200DepthRange;
2484   functions->Enable			= r200Enable;
2485   functions->Fogfv			= r200Fogfv;
2486   functions->FrontFace			= r200FrontFace;
2487   functions->Hint			= NULL;
2488   functions->IndexMask			= NULL;
2489   functions->LightModelfv		= r200LightModelfv;
2490   functions->Lightfv			= r200Lightfv;
2491   functions->LineStipple		= r200LineStipple;
2492   functions->LineWidth			= r200LineWidth;
2493   functions->LogicOpcode		= r200LogicOpCode;
2494   functions->PolygonMode		= r200PolygonMode;
2495   functions->PolygonOffset		= r200PolygonOffset;
2496   functions->PolygonStipple		= r200PolygonStipple;
2497   functions->PointParameterfv		= r200PointParameter;
2498   functions->PointSize			= r200PointSize;
2499   functions->RenderMode		= r200RenderMode;
2500   functions->Scissor			= radeonScissor;
2501   functions->ShadeModel		= r200ShadeModel;
2502   functions->StencilFuncSeparate	= r200StencilFuncSeparate;
2503   functions->StencilMaskSeparate	= r200StencilMaskSeparate;
2504   functions->StencilOpSeparate		= r200StencilOpSeparate;
2505   functions->Viewport			= r200Viewport;
2506}
2507
2508
2509void r200InitTnlFuncs( GLcontext *ctx )
2510{
2511   TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2512   TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2513}
2514