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