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