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