r200_state.c revision a400a1e4045e2478032bc5b8ae0b794964b24bae
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
44#include "swrast/swrast.h"
45#include "array_cache/acache.h"
46#include "tnl/tnl.h"
47#include "tnl/t_pipeline.h"
48#include "swrast_setup/swrast_setup.h"
49
50#include "r200_context.h"
51#include "r200_ioctl.h"
52#include "r200_state.h"
53#include "r200_tcl.h"
54#include "r200_tex.h"
55#include "r200_swtcl.h"
56#include "r200_vtxfmt.h"
57
58#include "drirenderbuffer.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
1438r200StencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
1439                         GLint ref, GLuint mask )
1440{
1441   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1442   GLuint refmask = ((ctx->Stencil.Ref[0] << R200_STENCIL_REF_SHIFT) |
1443		     (ctx->Stencil.ValueMask[0] << R200_STENCIL_MASK_SHIFT));
1444
1445   R200_STATECHANGE( rmesa, ctx );
1446   R200_STATECHANGE( rmesa, msk );
1447
1448   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK;
1449   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK|
1450						   R200_STENCIL_VALUE_MASK);
1451
1452   switch ( ctx->Stencil.Function[0] ) {
1453   case GL_NEVER:
1454      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER;
1455      break;
1456   case GL_LESS:
1457      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS;
1458      break;
1459   case GL_EQUAL:
1460      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL;
1461      break;
1462   case GL_LEQUAL:
1463      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL;
1464      break;
1465   case GL_GREATER:
1466      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER;
1467      break;
1468   case GL_NOTEQUAL:
1469      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL;
1470      break;
1471   case GL_GEQUAL:
1472      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL;
1473      break;
1474   case GL_ALWAYS:
1475      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS;
1476      break;
1477   }
1478
1479   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1480}
1481
1482static void
1483r200StencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
1484{
1485   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1486
1487   R200_STATECHANGE( rmesa, msk );
1488   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK;
1489   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1490      (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT);
1491}
1492
1493static void
1494r200StencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
1495                       GLenum zfail, GLenum zpass )
1496{
1497   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1498
1499   R200_STATECHANGE( rmesa, ctx );
1500   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK |
1501					       R200_STENCIL_ZFAIL_MASK |
1502					       R200_STENCIL_ZPASS_MASK);
1503
1504   switch ( ctx->Stencil.FailFunc[0] ) {
1505   case GL_KEEP:
1506      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP;
1507      break;
1508   case GL_ZERO:
1509      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO;
1510      break;
1511   case GL_REPLACE:
1512      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE;
1513      break;
1514   case GL_INCR:
1515      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC;
1516      break;
1517   case GL_DECR:
1518      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC;
1519      break;
1520   case GL_INCR_WRAP_EXT:
1521      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP;
1522      break;
1523   case GL_DECR_WRAP_EXT:
1524      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP;
1525      break;
1526   case GL_INVERT:
1527      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT;
1528      break;
1529   }
1530
1531   switch ( ctx->Stencil.ZFailFunc[0] ) {
1532   case GL_KEEP:
1533      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP;
1534      break;
1535   case GL_ZERO:
1536      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO;
1537      break;
1538   case GL_REPLACE:
1539      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE;
1540      break;
1541   case GL_INCR:
1542      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC;
1543      break;
1544   case GL_DECR:
1545      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC;
1546      break;
1547   case GL_INCR_WRAP_EXT:
1548      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP;
1549      break;
1550   case GL_DECR_WRAP_EXT:
1551      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP;
1552      break;
1553   case GL_INVERT:
1554      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT;
1555      break;
1556   }
1557
1558   switch ( ctx->Stencil.ZPassFunc[0] ) {
1559   case GL_KEEP:
1560      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP;
1561      break;
1562   case GL_ZERO:
1563      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO;
1564      break;
1565   case GL_REPLACE:
1566      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE;
1567      break;
1568   case GL_INCR:
1569      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC;
1570      break;
1571   case GL_DECR:
1572      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC;
1573      break;
1574   case GL_INCR_WRAP_EXT:
1575      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP;
1576      break;
1577   case GL_DECR_WRAP_EXT:
1578      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP;
1579      break;
1580   case GL_INVERT:
1581      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT;
1582      break;
1583   }
1584}
1585
1586static void r200ClearStencil( GLcontext *ctx, GLint s )
1587{
1588   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1589
1590   rmesa->state.stencil.clear =
1591      ((GLuint) ctx->Stencil.Clear |
1592       (0xff << R200_STENCIL_MASK_SHIFT) |
1593       (ctx->Stencil.WriteMask[0] << R200_STENCIL_WRITEMASK_SHIFT));
1594}
1595
1596
1597/* =============================================================
1598 * Window position and viewport transformation
1599 */
1600
1601/*
1602 * To correctly position primitives:
1603 */
1604#define SUBPIXEL_X 0.125
1605#define SUBPIXEL_Y 0.125
1606
1607void r200UpdateWindow( GLcontext *ctx )
1608{
1609   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1610   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1611   GLfloat xoffset = (GLfloat)dPriv->x;
1612   GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1613   const GLfloat *v = ctx->Viewport._WindowMap.m;
1614
1615   GLfloat sx = v[MAT_SX];
1616   GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
1617   GLfloat sy = - v[MAT_SY];
1618   GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1619   GLfloat sz = v[MAT_SZ] * rmesa->state.depth.scale;
1620   GLfloat tz = v[MAT_TZ] * rmesa->state.depth.scale;
1621
1622   R200_FIREVERTICES( rmesa );
1623   R200_STATECHANGE( rmesa, vpt );
1624
1625   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE]  = *(GLuint *)&sx;
1626   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1627   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE]  = *(GLuint *)&sy;
1628   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1629   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE]  = *(GLuint *)&sz;
1630   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = *(GLuint *)&tz;
1631}
1632
1633
1634
1635static void r200Viewport( GLcontext *ctx, GLint x, GLint y,
1636			    GLsizei width, GLsizei height )
1637{
1638   /* Don't pipeline viewport changes, conflict with window offset
1639    * setting below.  Could apply deltas to rescue pipelined viewport
1640    * values, or keep the originals hanging around.
1641    */
1642   R200_FIREVERTICES( R200_CONTEXT(ctx) );
1643   r200UpdateWindow( ctx );
1644}
1645
1646static void r200DepthRange( GLcontext *ctx, GLclampd nearval,
1647			      GLclampd farval )
1648{
1649   r200UpdateWindow( ctx );
1650}
1651
1652void r200UpdateViewportOffset( GLcontext *ctx )
1653{
1654   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1655   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1656   GLfloat xoffset = (GLfloat)dPriv->x;
1657   GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1658   const GLfloat *v = ctx->Viewport._WindowMap.m;
1659
1660   GLfloat tx = v[MAT_TX] + xoffset + SUBPIXEL_X;
1661   GLfloat ty = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1662
1663   if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != *(GLuint *)&tx ||
1664	rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != *(GLuint *)&ty )
1665   {
1666      /* Note: this should also modify whatever data the context reset
1667       * code uses...
1668       */
1669      rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = *(GLuint *)&tx;
1670      rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = *(GLuint *)&ty;
1671
1672      /* update polygon stipple x/y screen offset */
1673      {
1674         GLuint stx, sty;
1675         GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1676
1677         m &= ~(R200_STIPPLE_X_OFFSET_MASK |
1678                R200_STIPPLE_Y_OFFSET_MASK);
1679
1680         /* add magic offsets, then invert */
1681         stx = 31 - ((rmesa->dri.drawable->x - 1) & R200_STIPPLE_COORD_MASK);
1682         sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1683                     & R200_STIPPLE_COORD_MASK);
1684
1685         m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) |
1686               (sty << R200_STIPPLE_Y_OFFSET_SHIFT));
1687
1688         if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1689            R200_STATECHANGE( rmesa, msc );
1690	    rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1691         }
1692      }
1693   }
1694
1695   r200UpdateScissor( ctx );
1696}
1697
1698
1699
1700/* =============================================================
1701 * Miscellaneous
1702 */
1703
1704static void r200ClearColor( GLcontext *ctx, const GLfloat c[4] )
1705{
1706   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1707   GLubyte color[4];
1708   CLAMPED_FLOAT_TO_UBYTE(color[0], c[0]);
1709   CLAMPED_FLOAT_TO_UBYTE(color[1], c[1]);
1710   CLAMPED_FLOAT_TO_UBYTE(color[2], c[2]);
1711   CLAMPED_FLOAT_TO_UBYTE(color[3], c[3]);
1712   rmesa->state.color.clear = r200PackColor( rmesa->r200Screen->cpp,
1713                                             color[0], color[1],
1714                                             color[2], color[3] );
1715}
1716
1717
1718static void r200RenderMode( GLcontext *ctx, GLenum mode )
1719{
1720   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1721   FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1722}
1723
1724
1725static GLuint r200_rop_tab[] = {
1726   R200_ROP_CLEAR,
1727   R200_ROP_AND,
1728   R200_ROP_AND_REVERSE,
1729   R200_ROP_COPY,
1730   R200_ROP_AND_INVERTED,
1731   R200_ROP_NOOP,
1732   R200_ROP_XOR,
1733   R200_ROP_OR,
1734   R200_ROP_NOR,
1735   R200_ROP_EQUIV,
1736   R200_ROP_INVERT,
1737   R200_ROP_OR_REVERSE,
1738   R200_ROP_COPY_INVERTED,
1739   R200_ROP_OR_INVERTED,
1740   R200_ROP_NAND,
1741   R200_ROP_SET,
1742};
1743
1744static void r200LogicOpCode( GLcontext *ctx, GLenum opcode )
1745{
1746   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1747   GLuint rop = (GLuint)opcode - GL_CLEAR;
1748
1749   ASSERT( rop < 16 );
1750
1751   R200_STATECHANGE( rmesa, msk );
1752   rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop];
1753}
1754
1755
1756void r200SetCliprects( r200ContextPtr rmesa, GLenum mode )
1757{
1758   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1759
1760   switch ( mode ) {
1761   case GL_FRONT_LEFT:
1762      rmesa->numClipRects = dPriv->numClipRects;
1763      rmesa->pClipRects = dPriv->pClipRects;
1764      break;
1765   case GL_BACK_LEFT:
1766      /* Can't ignore 2d windows if we are page flipping.
1767       */
1768      if ( dPriv->numBackClipRects == 0 || rmesa->doPageFlip ) {
1769	 rmesa->numClipRects = dPriv->numClipRects;
1770	 rmesa->pClipRects = dPriv->pClipRects;
1771      }
1772      else {
1773	 rmesa->numClipRects = dPriv->numBackClipRects;
1774	 rmesa->pClipRects = dPriv->pBackClipRects;
1775      }
1776      break;
1777   default:
1778      fprintf(stderr, "bad mode in r200SetCliprects\n");
1779      return;
1780   }
1781
1782   if (rmesa->state.scissor.enabled)
1783      r200RecalcScissorRects( rmesa );
1784}
1785
1786
1787static void r200DrawBuffer( GLcontext *ctx, GLenum mode )
1788{
1789   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1790
1791   if (R200_DEBUG & DEBUG_DRI)
1792      fprintf(stderr, "%s %s\n", __FUNCTION__,
1793	      _mesa_lookup_enum_by_nr( mode ));
1794
1795   R200_FIREVERTICES(rmesa);	/* don't pipeline cliprect changes */
1796
1797   /*
1798    * _ColorDrawBufferMask is easier to cope with than <mode>.
1799    * Check for software fallback, update cliprects.
1800    */
1801   switch ( ctx->DrawBuffer->_ColorDrawBufferMask[0] ) {
1802   case BUFFER_BIT_FRONT_LEFT:
1803      FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1804      r200SetCliprects( rmesa, GL_FRONT_LEFT );
1805      break;
1806   case BUFFER_BIT_BACK_LEFT:
1807      FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_FALSE );
1808      r200SetCliprects( rmesa, GL_BACK_LEFT );
1809      break;
1810   default:
1811      /* GL_NONE or GL_FRONT_AND_BACK or stereo left&right, etc */
1812      FALLBACK( rmesa, R200_FALLBACK_DRAW_BUFFER, GL_TRUE );
1813      return;
1814   }
1815
1816   /* We'll set the drawing engine's offset/pitch parameters later
1817    * when we update other state.
1818    */
1819}
1820
1821
1822static void r200ReadBuffer( GLcontext *ctx, GLenum mode )
1823{
1824   /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1825}
1826
1827/* =============================================================
1828 * State enable/disable
1829 */
1830
1831static void r200Enable( GLcontext *ctx, GLenum cap, GLboolean state )
1832{
1833   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1834   GLuint p, flag;
1835
1836   if ( R200_DEBUG & DEBUG_STATE )
1837      fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1838	       _mesa_lookup_enum_by_nr( cap ),
1839	       state ? "GL_TRUE" : "GL_FALSE" );
1840
1841   switch ( cap ) {
1842      /* Fast track this one...
1843       */
1844   case GL_TEXTURE_1D:
1845   case GL_TEXTURE_2D:
1846   case GL_TEXTURE_3D:
1847      break;
1848
1849   case GL_ALPHA_TEST:
1850      R200_STATECHANGE( rmesa, ctx );
1851      if (state) {
1852	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE;
1853      } else {
1854	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE;
1855      }
1856      break;
1857
1858   case GL_BLEND:
1859   case GL_COLOR_LOGIC_OP:
1860      r200_set_blend_state( ctx );
1861      break;
1862
1863   case GL_CLIP_PLANE0:
1864   case GL_CLIP_PLANE1:
1865   case GL_CLIP_PLANE2:
1866   case GL_CLIP_PLANE3:
1867   case GL_CLIP_PLANE4:
1868   case GL_CLIP_PLANE5:
1869      p = cap-GL_CLIP_PLANE0;
1870      R200_STATECHANGE( rmesa, tcl );
1871      if (state) {
1872	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0<<p);
1873	 r200ClipPlane( ctx, cap, NULL );
1874      }
1875      else {
1876	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0<<p);
1877      }
1878      break;
1879
1880   case GL_COLOR_MATERIAL:
1881      r200ColorMaterial( ctx, 0, 0 );
1882      r200UpdateMaterial( ctx );
1883      break;
1884
1885   case GL_CULL_FACE:
1886      r200CullFace( ctx, 0 );
1887      break;
1888
1889   case GL_DEPTH_TEST:
1890      R200_STATECHANGE(rmesa, ctx );
1891      if ( state ) {
1892	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_Z_ENABLE;
1893      } else {
1894	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE;
1895      }
1896      break;
1897
1898   case GL_DITHER:
1899      R200_STATECHANGE(rmesa, ctx );
1900      if ( state ) {
1901	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_DITHER_ENABLE;
1902	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
1903      } else {
1904	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE;
1905	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  rmesa->state.color.roundEnable;
1906      }
1907      break;
1908
1909   case GL_FOG:
1910      R200_STATECHANGE(rmesa, ctx );
1911      if ( state ) {
1912	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE;
1913	 r200Fogfv( ctx, GL_FOG_MODE, NULL );
1914      } else {
1915	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE;
1916	 R200_STATECHANGE(rmesa, tcl);
1917	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK;
1918      }
1919      r200UpdateSpecular( ctx ); /* for PK_SPEC */
1920      if (rmesa->TclFallback)
1921	 r200ChooseVertexState( ctx );
1922      _mesa_allow_light_in_model( ctx, !state );
1923      break;
1924
1925   case GL_LIGHT0:
1926   case GL_LIGHT1:
1927   case GL_LIGHT2:
1928   case GL_LIGHT3:
1929   case GL_LIGHT4:
1930   case GL_LIGHT5:
1931   case GL_LIGHT6:
1932   case GL_LIGHT7:
1933      R200_STATECHANGE(rmesa, tcl);
1934      p = cap - GL_LIGHT0;
1935      if (p&1)
1936	 flag = (R200_LIGHT_1_ENABLE |
1937		 R200_LIGHT_1_ENABLE_AMBIENT |
1938		 R200_LIGHT_1_ENABLE_SPECULAR);
1939      else
1940	 flag = (R200_LIGHT_0_ENABLE |
1941		 R200_LIGHT_0_ENABLE_AMBIENT |
1942		 R200_LIGHT_0_ENABLE_SPECULAR);
1943
1944      if (state)
1945	 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1946      else
1947	 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1948
1949      /*
1950       */
1951      update_light_colors( ctx, p );
1952      break;
1953
1954   case GL_LIGHTING:
1955      r200UpdateSpecular(ctx);
1956      break;
1957
1958   case GL_LINE_SMOOTH:
1959      R200_STATECHANGE( rmesa, ctx );
1960      if ( state ) {
1961	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  R200_ANTI_ALIAS_LINE;
1962      } else {
1963	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE;
1964      }
1965      break;
1966
1967   case GL_LINE_STIPPLE:
1968      R200_STATECHANGE( rmesa, set );
1969      if ( state ) {
1970	 rmesa->hw.set.cmd[SET_RE_CNTL] |=  R200_PATTERN_ENABLE;
1971      } else {
1972	 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE;
1973      }
1974      break;
1975
1976   case GL_NORMALIZE:
1977      R200_STATECHANGE( rmesa, tcl );
1978      if ( state ) {
1979	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_NORMALIZE_NORMALS;
1980      } else {
1981	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS;
1982      }
1983      break;
1984
1985      /* Pointsize registers on r200 don't seem to do anything.  Maybe
1986       * have to pass pointsizes as vertex parameters?  In any case,
1987       * setting pointmin == pointsizemax == 1.0, and doing nothing
1988       * for aa is enough to satisfy conform.
1989       */
1990   case GL_POINT_SMOOTH:
1991      break;
1992
1993      /* These don't really do anything, as we don't use the 3vtx
1994       * primitives yet.
1995       */
1996#if 0
1997   case GL_POLYGON_OFFSET_POINT:
1998      R200_STATECHANGE( rmesa, set );
1999      if ( state ) {
2000	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_POINT;
2001      } else {
2002	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT;
2003      }
2004      break;
2005
2006   case GL_POLYGON_OFFSET_LINE:
2007      R200_STATECHANGE( rmesa, set );
2008      if ( state ) {
2009	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_LINE;
2010      } else {
2011	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE;
2012      }
2013      break;
2014#endif
2015
2016   case GL_POLYGON_OFFSET_FILL:
2017      R200_STATECHANGE( rmesa, set );
2018      if ( state ) {
2019	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  R200_ZBIAS_ENABLE_TRI;
2020      } else {
2021	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI;
2022      }
2023      break;
2024
2025   case GL_POLYGON_SMOOTH:
2026      R200_STATECHANGE( rmesa, ctx );
2027      if ( state ) {
2028	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  R200_ANTI_ALIAS_POLY;
2029      } else {
2030	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY;
2031      }
2032      break;
2033
2034   case GL_POLYGON_STIPPLE:
2035      R200_STATECHANGE(rmesa, set );
2036      if ( state ) {
2037	 rmesa->hw.set.cmd[SET_RE_CNTL] |=  R200_STIPPLE_ENABLE;
2038      } else {
2039	 rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE;
2040      }
2041      break;
2042
2043   case GL_RESCALE_NORMAL_EXT: {
2044      GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
2045      R200_STATECHANGE( rmesa, tcl );
2046      if ( tmp ) {
2047	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_RESCALE_NORMALS;
2048      } else {
2049	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2050      }
2051      break;
2052   }
2053
2054   case GL_SCISSOR_TEST:
2055      R200_FIREVERTICES( rmesa );
2056      rmesa->state.scissor.enabled = state;
2057      r200UpdateScissor( ctx );
2058      break;
2059
2060   case GL_STENCIL_TEST:
2061      if ( rmesa->state.stencil.hwBuffer ) {
2062	 R200_STATECHANGE( rmesa, ctx );
2063	 if ( state ) {
2064	    rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  R200_STENCIL_ENABLE;
2065	 } else {
2066	    rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE;
2067	 }
2068      } else {
2069	 FALLBACK( rmesa, R200_FALLBACK_STENCIL, state );
2070      }
2071      break;
2072
2073   case GL_TEXTURE_GEN_Q:
2074   case GL_TEXTURE_GEN_R:
2075   case GL_TEXTURE_GEN_S:
2076   case GL_TEXTURE_GEN_T:
2077      /* Picked up in r200UpdateTextureState.
2078       */
2079      rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
2080      break;
2081
2082   case GL_COLOR_SUM_EXT:
2083      r200UpdateSpecular ( ctx );
2084      break;
2085
2086   case GL_VERTEX_PROGRAM_ARB:
2087      TCL_FALLBACK(rmesa->glCtx, R200_TCL_FALLBACK_VERTEX_PROGRAM, state);
2088      break;
2089
2090   case GL_FRAGMENT_SHADER_ATI:
2091      if ( !state ) {
2092	 /* restore normal tex env colors and make sure tex env combine will get updated
2093	    mark env atoms dirty (as their data was overwritten by afs even
2094	    if they didn't change) and restore tex coord routing */
2095	 GLuint unit;
2096	 for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) {
2097	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &=
2098		~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE);
2099	    rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT;
2100	    /* need to guard this with drmSupportsFragmentShader? Should never get here if
2101	       we don't announce ATI_fs, right? */
2102	    rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0;
2103	    R200_STATECHANGE( rmesa, pix[unit] );
2104	    R200_STATECHANGE( rmesa, tex[unit] );
2105         }
2106	 rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0;
2107	 R200_STATECHANGE( rmesa, cst );
2108	 R200_STATECHANGE( rmesa, tf );
2109      }
2110      else {
2111	 /* need to mark this dirty as pix/tf atoms have overwritten the data
2112	    even if the data in the atoms didn't change */
2113	 R200_STATECHANGE( rmesa, atf );
2114	 R200_STATECHANGE( rmesa, afs[1] );
2115	 /* everything else picked up in r200UpdateTextureState hopefully */
2116      }
2117      break;
2118   default:
2119      return;
2120   }
2121}
2122
2123
2124void r200LightingSpaceChange( GLcontext *ctx )
2125{
2126   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2127   GLboolean tmp;
2128
2129   if (R200_DEBUG & DEBUG_STATE)
2130      fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2131	      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2132
2133   if (ctx->_NeedEyeCoords)
2134      tmp = ctx->Transform.RescaleNormals;
2135   else
2136      tmp = !ctx->Transform.RescaleNormals;
2137
2138   R200_STATECHANGE( rmesa, tcl );
2139   if ( tmp ) {
2140      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |=  R200_RESCALE_NORMALS;
2141   } else {
2142      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS;
2143   }
2144
2145   if (R200_DEBUG & DEBUG_STATE)
2146      fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2147	      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]);
2148}
2149
2150/* =============================================================
2151 * Deferred state management - matrices, textures, other?
2152 */
2153
2154
2155
2156
2157static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx )
2158{
2159   float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2160   int i;
2161
2162
2163   for (i = 0 ; i < 4 ; i++) {
2164      *dest++ = src[i];
2165      *dest++ = src[i+4];
2166      *dest++ = src[i+8];
2167      *dest++ = src[i+12];
2168   }
2169
2170   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2171}
2172
2173static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx )
2174{
2175   float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0;
2176   memcpy(dest, src, 16*sizeof(float));
2177   R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2178}
2179
2180
2181static void update_texturematrix( GLcontext *ctx )
2182{
2183   r200ContextPtr rmesa = R200_CONTEXT( ctx );
2184   GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0];
2185   GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL];
2186   int unit;
2187
2188   if (R200_DEBUG & DEBUG_STATE)
2189      fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__,
2190	      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]);
2191
2192   rmesa->TexMatEnabled = 0;
2193   rmesa->TexMatCompSel = 0;
2194
2195   for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2196      if (!ctx->Texture.Unit[unit]._ReallyEnabled)
2197	 continue;
2198
2199      if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2200	 rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE|
2201				  R200_TEXMAT_0_ENABLE) << unit;
2202
2203	 rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit;
2204
2205	 if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2206	    /* Need to preconcatenate any active texgen
2207	     * obj/eyeplane matrices:
2208	     */
2209	    _math_matrix_mul_matrix( &rmesa->tmpmat,
2210				     ctx->TextureMatrixStack[unit].Top,
2211				     &rmesa->TexGenMatrix[unit] );
2212	    upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit );
2213	 }
2214	 else {
2215	    upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m,
2216			   R200_MTX_TEX0+unit );
2217	 }
2218      }
2219      else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) {
2220	 upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m,
2221			R200_MTX_TEX0+unit );
2222      }
2223   }
2224
2225   tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled);
2226   if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) {
2227      R200_STATECHANGE(rmesa, tcg);
2228      rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc;
2229   }
2230
2231   compsel &= ~R200_OUTPUT_TEX_MASK;
2232   compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel;
2233   if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) {
2234      R200_STATECHANGE(rmesa, vtx);
2235      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel;
2236   }
2237}
2238
2239
2240
2241/**
2242 * Tell the card where to render (offset, pitch).
2243 * Effected by glDrawBuffer, etc
2244 */
2245void
2246r200UpdateDrawBuffer(GLcontext *ctx)
2247{
2248   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2249   struct gl_framebuffer *fb = ctx->DrawBuffer;
2250   driRenderbuffer *drb;
2251
2252   if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_FRONT_LEFT) {
2253      /* draw to front */
2254      drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
2255   }
2256   else if (fb->_ColorDrawBufferMask[0] == BUFFER_BIT_BACK_LEFT) {
2257      /* draw to back */
2258      drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
2259   }
2260   else {
2261      /* drawing to multiple buffers, or none */
2262      return;
2263   }
2264
2265   assert(drb);
2266   assert(drb->flippedPitch);
2267
2268   R200_STATECHANGE( rmesa, ctx );
2269
2270   /* Note: we used the (possibly) page-flipped values */
2271   rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
2272     = ((drb->flippedOffset + rmesa->r200Screen->fbLocation)
2273	& R200_COLOROFFSET_MASK);
2274   rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
2275   if (rmesa->sarea->tiling_enabled) {
2276      rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= R200_COLOR_TILE_ENABLE;
2277   }
2278}
2279
2280
2281
2282void r200ValidateState( GLcontext *ctx )
2283{
2284   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2285   GLuint new_state = rmesa->NewGLState;
2286
2287   if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
2288     r200UpdateDrawBuffer(ctx);
2289   }
2290
2291   if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM)) {
2292      r200UpdateTextureState( ctx );
2293      new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2294   }
2295
2296   /* Need an event driven matrix update?
2297    */
2298   if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2299      upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP );
2300
2301   /* Need these for lighting (shouldn't upload otherwise)
2302    */
2303   if (new_state & (_NEW_MODELVIEW)) {
2304      upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV );
2305      upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV );
2306   }
2307
2308   /* Does this need to be triggered on eg. modelview for
2309    * texgen-derived objplane/eyeplane matrices?
2310    */
2311   if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) {
2312      update_texturematrix( ctx );
2313   }
2314
2315   if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2316      update_light( ctx );
2317   }
2318
2319   /* emit all active clip planes if projection matrix changes.
2320    */
2321   if (new_state & (_NEW_PROJECTION)) {
2322      if (ctx->Transform.ClipPlanesEnabled)
2323	 r200UpdateClipPlanes( ctx );
2324   }
2325
2326
2327   rmesa->NewGLState = 0;
2328}
2329
2330
2331static void r200InvalidateState( GLcontext *ctx, GLuint new_state )
2332{
2333   _swrast_InvalidateState( ctx, new_state );
2334   _swsetup_InvalidateState( ctx, new_state );
2335   _ac_InvalidateState( ctx, new_state );
2336   _tnl_InvalidateState( ctx, new_state );
2337   _ae_invalidate_state( ctx, new_state );
2338   R200_CONTEXT(ctx)->NewGLState |= new_state;
2339   r200VtxfmtInvalidate( ctx );
2340}
2341
2342/* A hack.  The r200 can actually cope just fine with materials
2343 * between begin/ends, so fix this. But how ?
2344 */
2345static GLboolean check_material( GLcontext *ctx )
2346{
2347   TNLcontext *tnl = TNL_CONTEXT(ctx);
2348   GLint i;
2349
2350   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2351	i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2352	i++)
2353      if (tnl->vb.AttribPtr[i] &&
2354	  tnl->vb.AttribPtr[i]->stride)
2355	 return GL_TRUE;
2356
2357   return GL_FALSE;
2358}
2359
2360static void r200WrapRunPipeline( GLcontext *ctx )
2361{
2362   r200ContextPtr rmesa = R200_CONTEXT(ctx);
2363   GLboolean has_material;
2364
2365   if (0)
2366      fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2367
2368   /* Validate state:
2369    */
2370   if (rmesa->NewGLState)
2371      r200ValidateState( ctx );
2372
2373   has_material = (ctx->Light.Enabled && check_material( ctx ));
2374
2375   if (has_material) {
2376      TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE );
2377   }
2378
2379   /* Run the pipeline.
2380    */
2381   _tnl_run_pipeline( ctx );
2382
2383   if (has_material) {
2384      TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE );
2385   }
2386}
2387
2388
2389/* Initialize the driver's state functions.
2390 */
2391void r200InitStateFuncs( struct dd_function_table *functions )
2392{
2393   functions->UpdateState		= r200InvalidateState;
2394   functions->LightingSpaceChange	= r200LightingSpaceChange;
2395
2396   functions->DrawBuffer		= r200DrawBuffer;
2397   functions->ReadBuffer		= r200ReadBuffer;
2398
2399   functions->AlphaFunc			= r200AlphaFunc;
2400   functions->BlendColor		= r200BlendColor;
2401   functions->BlendEquationSeparate	= r200BlendEquationSeparate;
2402   functions->BlendFuncSeparate		= r200BlendFuncSeparate;
2403   functions->ClearColor		= r200ClearColor;
2404   functions->ClearDepth		= r200ClearDepth;
2405   functions->ClearIndex		= NULL;
2406   functions->ClearStencil		= r200ClearStencil;
2407   functions->ClipPlane			= r200ClipPlane;
2408   functions->ColorMask			= r200ColorMask;
2409   functions->CullFace			= r200CullFace;
2410   functions->DepthFunc			= r200DepthFunc;
2411   functions->DepthMask			= r200DepthMask;
2412   functions->DepthRange		= r200DepthRange;
2413   functions->Enable			= r200Enable;
2414   functions->Fogfv			= r200Fogfv;
2415   functions->FrontFace			= r200FrontFace;
2416   functions->Hint			= NULL;
2417   functions->IndexMask			= NULL;
2418   functions->LightModelfv		= r200LightModelfv;
2419   functions->Lightfv			= r200Lightfv;
2420   functions->LineStipple		= r200LineStipple;
2421   functions->LineWidth			= r200LineWidth;
2422   functions->LogicOpcode		= r200LogicOpCode;
2423   functions->PolygonMode		= r200PolygonMode;
2424   functions->PolygonOffset		= r200PolygonOffset;
2425   functions->PolygonStipple		= r200PolygonStipple;
2426   functions->PointSize			= r200PointSize;
2427   functions->RenderMode		= r200RenderMode;
2428   functions->Scissor			= r200Scissor;
2429   functions->ShadeModel		= r200ShadeModel;
2430   functions->StencilFuncSeparate	= r200StencilFuncSeparate;
2431   functions->StencilMaskSeparate	= r200StencilMaskSeparate;
2432   functions->StencilOpSeparate		= r200StencilOpSeparate;
2433   functions->Viewport			= r200Viewport;
2434
2435   /* Swrast hooks for imaging extensions:
2436    */
2437   functions->CopyColorTable		= _swrast_CopyColorTable;
2438   functions->CopyColorSubTable		= _swrast_CopyColorSubTable;
2439   functions->CopyConvolutionFilter1D	= _swrast_CopyConvolutionFilter1D;
2440   functions->CopyConvolutionFilter2D	= _swrast_CopyConvolutionFilter2D;
2441}
2442
2443
2444void r200InitTnlFuncs( GLcontext *ctx )
2445{
2446   TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial;
2447   TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline;
2448}
2449