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