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