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