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