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