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