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