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