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