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