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