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