radeon_state.c revision ecadb51bbcb972a79f3ed79e65a7986b9396e757
1/* $XFree86: xc/lib/GL/mesa/src/drv/radeon/radeon_state.c,v 1.8 2002/12/16 16:18:58 dawes Exp $ */
2/**************************************************************************
3
4Copyright 2000, 2001 VA Linux Systems Inc., Fremont, California.
5
6All Rights Reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining
9a copy of this software and associated documentation files (the
10"Software"), to deal in the Software without restriction, including
11without limitation the rights to use, copy, modify, merge, publish,
12distribute, sublicense, and/or sell copies of the Software, and to
13permit persons to whom the Software is furnished to do so, subject to
14the following conditions:
15
16The above copyright notice and this permission notice (including the
17next paragraph) shall be included in all copies or substantial
18portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27
28**************************************************************************/
29
30/*
31 * Authors:
32 *   Gareth Hughes <gareth@valinux.com>
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/light.h"
41#include "main/state.h"
42#include "main/context.h"
43#include "main/framebuffer.h"
44
45#include "vbo/vbo.h"
46#include "tnl/tnl.h"
47#include "tnl/t_pipeline.h"
48#include "swrast_setup/swrast_setup.h"
49
50#include "radeon_context.h"
51#include "radeon_ioctl.h"
52#include "radeon_state.h"
53#include "radeon_tcl.h"
54#include "radeon_tex.h"
55#include "radeon_swtcl.h"
56#include "drirenderbuffer.h"
57
58static void radeonUpdateSpecular( GLcontext *ctx );
59
60/* =============================================================
61 * Alpha blending
62 */
63
64static void radeonAlphaFunc( GLcontext *ctx, GLenum func, GLfloat ref )
65{
66   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
67   int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC];
68   GLubyte refByte;
69
70   CLAMPED_FLOAT_TO_UBYTE(refByte, ref);
71
72   RADEON_STATECHANGE( rmesa, ctx );
73
74   pp_misc &= ~(RADEON_ALPHA_TEST_OP_MASK | RADEON_REF_ALPHA_MASK);
75   pp_misc |= (refByte & RADEON_REF_ALPHA_MASK);
76
77   switch ( func ) {
78   case GL_NEVER:
79      pp_misc |= RADEON_ALPHA_TEST_FAIL;
80      break;
81   case GL_LESS:
82      pp_misc |= RADEON_ALPHA_TEST_LESS;
83      break;
84   case GL_EQUAL:
85      pp_misc |= RADEON_ALPHA_TEST_EQUAL;
86      break;
87   case GL_LEQUAL:
88      pp_misc |= RADEON_ALPHA_TEST_LEQUAL;
89      break;
90   case GL_GREATER:
91      pp_misc |= RADEON_ALPHA_TEST_GREATER;
92      break;
93   case GL_NOTEQUAL:
94      pp_misc |= RADEON_ALPHA_TEST_NEQUAL;
95      break;
96   case GL_GEQUAL:
97      pp_misc |= RADEON_ALPHA_TEST_GEQUAL;
98      break;
99   case GL_ALWAYS:
100      pp_misc |= RADEON_ALPHA_TEST_PASS;
101      break;
102   }
103
104   rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc;
105}
106
107static void radeonBlendEquationSeparate( GLcontext *ctx,
108					 GLenum modeRGB, GLenum modeA )
109{
110   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
111   GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] & ~RADEON_COMB_FCN_MASK;
112   GLboolean fallback = GL_FALSE;
113
114   assert( modeRGB == modeA );
115
116   switch ( modeRGB ) {
117   case GL_FUNC_ADD:
118   case GL_LOGIC_OP:
119      b |= RADEON_COMB_FCN_ADD_CLAMP;
120      break;
121
122   case GL_FUNC_SUBTRACT:
123      b |= RADEON_COMB_FCN_SUB_CLAMP;
124      break;
125
126   default:
127      if (ctx->Color.BlendEnabled)
128	 fallback = GL_TRUE;
129      else
130	 b |= RADEON_COMB_FCN_ADD_CLAMP;
131      break;
132   }
133
134   FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, fallback );
135   if ( !fallback ) {
136      RADEON_STATECHANGE( rmesa, ctx );
137      rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
138      if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled
139	    && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) {
140	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_ROP_ENABLE;
141      } else {
142	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
143      }
144   }
145}
146
147static void radeonBlendFuncSeparate( GLcontext *ctx,
148				     GLenum sfactorRGB, GLenum dfactorRGB,
149				     GLenum sfactorA, GLenum dfactorA )
150{
151   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
152   GLuint b = rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] &
153      ~(RADEON_SRC_BLEND_MASK | RADEON_DST_BLEND_MASK);
154   GLboolean fallback = GL_FALSE;
155
156   switch ( ctx->Color.BlendSrcRGB ) {
157   case GL_ZERO:
158      b |= RADEON_SRC_BLEND_GL_ZERO;
159      break;
160   case GL_ONE:
161      b |= RADEON_SRC_BLEND_GL_ONE;
162      break;
163   case GL_DST_COLOR:
164      b |= RADEON_SRC_BLEND_GL_DST_COLOR;
165      break;
166   case GL_ONE_MINUS_DST_COLOR:
167      b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_COLOR;
168      break;
169   case GL_SRC_COLOR:
170      b |= RADEON_SRC_BLEND_GL_SRC_COLOR;
171      break;
172   case GL_ONE_MINUS_SRC_COLOR:
173      b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_COLOR;
174      break;
175   case GL_SRC_ALPHA:
176      b |= RADEON_SRC_BLEND_GL_SRC_ALPHA;
177      break;
178   case GL_ONE_MINUS_SRC_ALPHA:
179      b |= RADEON_SRC_BLEND_GL_ONE_MINUS_SRC_ALPHA;
180      break;
181   case GL_DST_ALPHA:
182      b |= RADEON_SRC_BLEND_GL_DST_ALPHA;
183      break;
184   case GL_ONE_MINUS_DST_ALPHA:
185      b |= RADEON_SRC_BLEND_GL_ONE_MINUS_DST_ALPHA;
186      break;
187   case GL_SRC_ALPHA_SATURATE:
188      b |= RADEON_SRC_BLEND_GL_SRC_ALPHA_SATURATE;
189      break;
190   case GL_CONSTANT_COLOR:
191   case GL_ONE_MINUS_CONSTANT_COLOR:
192   case GL_CONSTANT_ALPHA:
193   case GL_ONE_MINUS_CONSTANT_ALPHA:
194      if (ctx->Color.BlendEnabled)
195	 fallback = GL_TRUE;
196      else
197	 b |= RADEON_SRC_BLEND_GL_ONE;
198      break;
199   default:
200      break;
201   }
202
203   switch ( ctx->Color.BlendDstRGB ) {
204   case GL_ZERO:
205      b |= RADEON_DST_BLEND_GL_ZERO;
206      break;
207   case GL_ONE:
208      b |= RADEON_DST_BLEND_GL_ONE;
209      break;
210   case GL_SRC_COLOR:
211      b |= RADEON_DST_BLEND_GL_SRC_COLOR;
212      break;
213   case GL_ONE_MINUS_SRC_COLOR:
214      b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_COLOR;
215      break;
216   case GL_SRC_ALPHA:
217      b |= RADEON_DST_BLEND_GL_SRC_ALPHA;
218      break;
219   case GL_ONE_MINUS_SRC_ALPHA:
220      b |= RADEON_DST_BLEND_GL_ONE_MINUS_SRC_ALPHA;
221      break;
222   case GL_DST_COLOR:
223      b |= RADEON_DST_BLEND_GL_DST_COLOR;
224      break;
225   case GL_ONE_MINUS_DST_COLOR:
226      b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_COLOR;
227      break;
228   case GL_DST_ALPHA:
229      b |= RADEON_DST_BLEND_GL_DST_ALPHA;
230      break;
231   case GL_ONE_MINUS_DST_ALPHA:
232      b |= RADEON_DST_BLEND_GL_ONE_MINUS_DST_ALPHA;
233      break;
234   case GL_CONSTANT_COLOR:
235   case GL_ONE_MINUS_CONSTANT_COLOR:
236   case GL_CONSTANT_ALPHA:
237   case GL_ONE_MINUS_CONSTANT_ALPHA:
238      if (ctx->Color.BlendEnabled)
239	 fallback = GL_TRUE;
240      else
241	 b |= RADEON_DST_BLEND_GL_ZERO;
242      break;
243   default:
244      break;
245   }
246
247   FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, fallback );
248   if ( !fallback ) {
249      RADEON_STATECHANGE( rmesa, ctx );
250      rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCNTL] = b;
251   }
252}
253
254
255/* =============================================================
256 * Depth testing
257 */
258
259static void radeonDepthFunc( GLcontext *ctx, GLenum func )
260{
261   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
262
263   RADEON_STATECHANGE( rmesa, ctx );
264   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_TEST_MASK;
265
266   switch ( ctx->Depth.Func ) {
267   case GL_NEVER:
268      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEVER;
269      break;
270   case GL_LESS:
271      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LESS;
272      break;
273   case GL_EQUAL:
274      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_EQUAL;
275      break;
276   case GL_LEQUAL:
277      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_LEQUAL;
278      break;
279   case GL_GREATER:
280      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GREATER;
281      break;
282   case GL_NOTEQUAL:
283      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_NEQUAL;
284      break;
285   case GL_GEQUAL:
286      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_GEQUAL;
287      break;
288   case GL_ALWAYS:
289      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_Z_TEST_ALWAYS;
290      break;
291   }
292}
293
294
295static void radeonDepthMask( GLcontext *ctx, GLboolean flag )
296{
297   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
298   RADEON_STATECHANGE( rmesa, ctx );
299
300   if ( ctx->Depth.Mask ) {
301      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |=  RADEON_Z_WRITE_ENABLE;
302   } else {
303      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_Z_WRITE_ENABLE;
304   }
305}
306
307static void radeonClearDepth( GLcontext *ctx, GLclampd d )
308{
309   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
310   GLuint format = (rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &
311		    RADEON_DEPTH_FORMAT_MASK);
312
313   switch ( format ) {
314   case RADEON_DEPTH_FORMAT_16BIT_INT_Z:
315      rmesa->state.depth.clear = d * 0x0000ffff;
316      break;
317   case RADEON_DEPTH_FORMAT_24BIT_INT_Z:
318      rmesa->state.depth.clear = d * 0x00ffffff;
319      break;
320   }
321}
322
323
324/* =============================================================
325 * Fog
326 */
327
328
329static void radeonFogfv( GLcontext *ctx, GLenum pname, const GLfloat *param )
330{
331   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
332   union { int i; float f; } c, d;
333   GLchan col[4];
334
335   switch (pname) {
336   case GL_FOG_MODE:
337      if (!ctx->Fog.Enabled)
338	 return;
339      RADEON_STATECHANGE(rmesa, tcl);
340      rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
341      switch (ctx->Fog.Mode) {
342      case GL_LINEAR:
343	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_LINEAR;
344	 break;
345      case GL_EXP:
346	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP;
347	 break;
348      case GL_EXP2:
349	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_TCL_FOG_EXP2;
350	 break;
351      default:
352	 return;
353      }
354   /* fallthrough */
355   case GL_FOG_DENSITY:
356   case GL_FOG_START:
357   case GL_FOG_END:
358      if (!ctx->Fog.Enabled)
359	 return;
360      c.i = rmesa->hw.fog.cmd[FOG_C];
361      d.i = rmesa->hw.fog.cmd[FOG_D];
362      switch (ctx->Fog.Mode) {
363      case GL_EXP:
364	 c.f = 0.0;
365	 /* While this is the opposite sign from the DDK, it makes the fog test
366	  * pass, and matches r200.
367	  */
368	 d.f = -ctx->Fog.Density;
369	 break;
370      case GL_EXP2:
371	 c.f = 0.0;
372	 d.f = -(ctx->Fog.Density * ctx->Fog.Density);
373	 break;
374      case GL_LINEAR:
375	 if (ctx->Fog.Start == ctx->Fog.End) {
376	    c.f = 1.0F;
377	    d.f = 1.0F;
378	 } else {
379	    c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start);
380	    /* While this is the opposite sign from the DDK, it makes the fog
381	     * test pass, and matches r200.
382	     */
383	    d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start);
384	 }
385	 break;
386      default:
387	 break;
388      }
389      if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) {
390	 RADEON_STATECHANGE( rmesa, fog );
391	 rmesa->hw.fog.cmd[FOG_C] = c.i;
392	 rmesa->hw.fog.cmd[FOG_D] = d.i;
393      }
394      break;
395   case GL_FOG_COLOR:
396      RADEON_STATECHANGE( rmesa, ctx );
397      UNCLAMPED_FLOAT_TO_RGB_CHAN( col, ctx->Fog.Color );
398      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~RADEON_FOG_COLOR_MASK;
399      rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |=
400	 radeonPackColor( 4, col[0], col[1], col[2], 0 );
401      break;
402   case GL_FOG_COORD_SRC:
403      radeonUpdateSpecular( ctx );
404      break;
405   default:
406      return;
407   }
408}
409
410
411/* =============================================================
412 * Scissoring
413 */
414
415
416static GLboolean intersect_rect( drm_clip_rect_t *out,
417				 drm_clip_rect_t *a,
418				 drm_clip_rect_t *b )
419{
420   *out = *a;
421   if ( b->x1 > out->x1 ) out->x1 = b->x1;
422   if ( b->y1 > out->y1 ) out->y1 = b->y1;
423   if ( b->x2 < out->x2 ) out->x2 = b->x2;
424   if ( b->y2 < out->y2 ) out->y2 = b->y2;
425   if ( out->x1 >= out->x2 ) return GL_FALSE;
426   if ( out->y1 >= out->y2 ) return GL_FALSE;
427   return GL_TRUE;
428}
429
430
431void radeonRecalcScissorRects( radeonContextPtr rmesa )
432{
433   drm_clip_rect_t *out;
434   int i;
435
436   /* Grow cliprect store?
437    */
438   if (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
439      while (rmesa->state.scissor.numAllocedClipRects < rmesa->numClipRects) {
440	 rmesa->state.scissor.numAllocedClipRects += 1;	/* zero case */
441	 rmesa->state.scissor.numAllocedClipRects *= 2;
442      }
443
444      if (rmesa->state.scissor.pClipRects)
445	 FREE(rmesa->state.scissor.pClipRects);
446
447      rmesa->state.scissor.pClipRects =
448	 MALLOC( rmesa->state.scissor.numAllocedClipRects *
449		 sizeof(drm_clip_rect_t) );
450
451      if ( rmesa->state.scissor.pClipRects == NULL ) {
452	 rmesa->state.scissor.numAllocedClipRects = 0;
453	 return;
454      }
455   }
456
457   out = rmesa->state.scissor.pClipRects;
458   rmesa->state.scissor.numClipRects = 0;
459
460   for ( i = 0 ; i < rmesa->numClipRects ;  i++ ) {
461      if ( intersect_rect( out,
462			   &rmesa->pClipRects[i],
463			   &rmesa->state.scissor.rect ) ) {
464	 rmesa->state.scissor.numClipRects++;
465	 out++;
466      }
467   }
468}
469
470
471static void radeonUpdateScissor( GLcontext *ctx )
472{
473   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
474
475   if ( rmesa->dri.drawable ) {
476      __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
477
478      int x = ctx->Scissor.X;
479      int y = dPriv->h - ctx->Scissor.Y - ctx->Scissor.Height;
480      int w = ctx->Scissor.X + ctx->Scissor.Width - 1;
481      int h = dPriv->h - ctx->Scissor.Y - 1;
482
483      rmesa->state.scissor.rect.x1 = x + dPriv->x;
484      rmesa->state.scissor.rect.y1 = y + dPriv->y;
485      rmesa->state.scissor.rect.x2 = w + dPriv->x + 1;
486      rmesa->state.scissor.rect.y2 = h + dPriv->y + 1;
487
488      radeonRecalcScissorRects( rmesa );
489   }
490}
491
492
493static void radeonScissor( GLcontext *ctx,
494			   GLint x, GLint y, GLsizei w, GLsizei h )
495{
496   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
497
498   if ( ctx->Scissor.Enabled ) {
499      RADEON_FIREVERTICES( rmesa );	/* don't pipeline cliprect changes */
500      radeonUpdateScissor( ctx );
501   }
502
503}
504
505
506/* =============================================================
507 * Culling
508 */
509
510static void radeonCullFace( GLcontext *ctx, GLenum unused )
511{
512   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
513   GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
514   GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL];
515
516   s |= RADEON_FFACE_SOLID | RADEON_BFACE_SOLID;
517   t &= ~(RADEON_CULL_FRONT | RADEON_CULL_BACK);
518
519   if ( ctx->Polygon.CullFlag ) {
520      switch ( ctx->Polygon.CullFaceMode ) {
521      case GL_FRONT:
522	 s &= ~RADEON_FFACE_SOLID;
523	 t |= RADEON_CULL_FRONT;
524	 break;
525      case GL_BACK:
526	 s &= ~RADEON_BFACE_SOLID;
527	 t |= RADEON_CULL_BACK;
528	 break;
529      case GL_FRONT_AND_BACK:
530	 s &= ~(RADEON_FFACE_SOLID | RADEON_BFACE_SOLID);
531	 t |= (RADEON_CULL_FRONT | RADEON_CULL_BACK);
532	 break;
533      }
534   }
535
536   if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
537      RADEON_STATECHANGE(rmesa, set );
538      rmesa->hw.set.cmd[SET_SE_CNTL] = s;
539   }
540
541   if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) {
542      RADEON_STATECHANGE(rmesa, tcl );
543      rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t;
544   }
545}
546
547static void radeonFrontFace( GLcontext *ctx, GLenum mode )
548{
549   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
550
551   RADEON_STATECHANGE( rmesa, set );
552   rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_FFACE_CULL_DIR_MASK;
553
554   RADEON_STATECHANGE( rmesa, tcl );
555   rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_CULL_FRONT_IS_CCW;
556
557   switch ( mode ) {
558   case GL_CW:
559      rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CW;
560      break;
561   case GL_CCW:
562      rmesa->hw.set.cmd[SET_SE_CNTL] |= RADEON_FFACE_CULL_CCW;
563      rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_CULL_FRONT_IS_CCW;
564      break;
565   }
566}
567
568
569/* =============================================================
570 * Line state
571 */
572static void radeonLineWidth( GLcontext *ctx, GLfloat widthf )
573{
574   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
575
576   RADEON_STATECHANGE( rmesa, lin );
577   RADEON_STATECHANGE( rmesa, set );
578
579   /* Line width is stored in U6.4 format.
580    */
581   rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] = (GLuint)(widthf * 16.0);
582   if ( widthf > 1.0 ) {
583      rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_WIDELINE_ENABLE;
584   } else {
585      rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_WIDELINE_ENABLE;
586   }
587}
588
589static void radeonLineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
590{
591   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
592
593   RADEON_STATECHANGE( rmesa, lin );
594   rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] =
595      ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern));
596}
597
598
599/* =============================================================
600 * Masks
601 */
602static void radeonColorMask( GLcontext *ctx,
603			     GLboolean r, GLboolean g,
604			     GLboolean b, GLboolean a )
605{
606   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
607   GLuint mask = radeonPackColor( rmesa->radeonScreen->cpp,
608				  ctx->Color.ColorMask[RCOMP],
609				  ctx->Color.ColorMask[GCOMP],
610				  ctx->Color.ColorMask[BCOMP],
611				  ctx->Color.ColorMask[ACOMP] );
612
613   if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) {
614      RADEON_STATECHANGE( rmesa, msk );
615      rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask;
616   }
617}
618
619
620/* =============================================================
621 * Polygon state
622 */
623
624static void radeonPolygonOffset( GLcontext *ctx,
625				 GLfloat factor, GLfloat units )
626{
627   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
628   float_ui32_type constant =  { units * rmesa->state.depth.scale };
629   float_ui32_type factoru = { factor };
630
631   RADEON_STATECHANGE( rmesa, zbs );
632   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR]   = factoru.ui32;
633   rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32;
634}
635
636static void radeonPolygonStipple( GLcontext *ctx, const GLubyte *mask )
637{
638   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
639   GLuint i;
640   drm_radeon_stipple_t stipple;
641
642   /* Must flip pattern upside down.
643    */
644   for ( i = 0 ; i < 32 ; i++ ) {
645      rmesa->state.stipple.mask[31 - i] = ((GLuint *) mask)[i];
646   }
647
648   /* TODO: push this into cmd mechanism
649    */
650   RADEON_FIREVERTICES( rmesa );
651   LOCK_HARDWARE( rmesa );
652
653   /* FIXME: Use window x,y offsets into stipple RAM.
654    */
655   stipple.mask = rmesa->state.stipple.mask;
656   drmCommandWrite( rmesa->dri.fd, DRM_RADEON_STIPPLE,
657                    &stipple, sizeof(drm_radeon_stipple_t) );
658   UNLOCK_HARDWARE( rmesa );
659}
660
661static void radeonPolygonMode( GLcontext *ctx, GLenum face, GLenum mode )
662{
663   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
664   GLboolean flag = (ctx->_TriangleCaps & DD_TRI_UNFILLED) != 0;
665
666   /* Can't generally do unfilled via tcl, but some good special
667    * cases work.
668    */
669   TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_UNFILLED, flag);
670   if (rmesa->TclFallback) {
671      radeonChooseRenderState( ctx );
672      radeonChooseVertexState( ctx );
673   }
674}
675
676
677/* =============================================================
678 * Rendering attributes
679 *
680 * We really don't want to recalculate all this every time we bind a
681 * texture.  These things shouldn't change all that often, so it makes
682 * sense to break them out of the core texture state update routines.
683 */
684
685/* Examine lighting and texture state to determine if separate specular
686 * should be enabled.
687 */
688static void radeonUpdateSpecular( GLcontext *ctx )
689{
690   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
691   u_int32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL];
692   GLuint flag = 0;
693
694   RADEON_STATECHANGE( rmesa, tcl );
695
696   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_SPECULAR;
697   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &= ~RADEON_TCL_COMPUTE_DIFFUSE;
698   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_SPEC;
699   rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] &= ~RADEON_TCL_VTX_PK_DIFFUSE;
700   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LIGHTING_ENABLE;
701
702   p &= ~RADEON_SPECULAR_ENABLE;
703
704   rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_DIFFUSE_SPECULAR_COMBINE;
705
706
707   if (ctx->Light.Enabled &&
708       ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) {
709      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
710      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
711      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
712      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
713      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
714      p |=  RADEON_SPECULAR_ENABLE;
715      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &=
716	 ~RADEON_DIFFUSE_SPECULAR_COMBINE;
717   }
718   else if (ctx->Light.Enabled) {
719      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_DIFFUSE;
720      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
721      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
722   } else if (ctx->Fog.ColorSumEnabled ) {
723      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
724      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
725      p |= RADEON_SPECULAR_ENABLE;
726   } else {
727      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_DIFFUSE;
728   }
729
730   if (ctx->Fog.Enabled) {
731      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXFMT] |= RADEON_TCL_VTX_PK_SPEC;
732      if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH) {
733	 rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] |= RADEON_TCL_COMPUTE_SPECULAR;
734      /* Bizzare: have to leave lighting enabled to get fog. */
735	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LIGHTING_ENABLE;
736      }
737      else {
738      /* cannot do tcl fog factor calculation with fog coord source
739       * (send precomputed factors). Cannot use precomputed fog
740       * factors together with tcl spec light (need tcl fallback) */
741	 flag = (rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] &
742	    RADEON_TCL_COMPUTE_SPECULAR) != 0;
743      }
744   }
745
746   TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_FOGCOORDSPEC, flag);
747
748   if (NEED_SECONDARY_COLOR(ctx)) {
749      assert( (p & RADEON_SPECULAR_ENABLE) != 0 );
750   } else {
751      assert( (p & RADEON_SPECULAR_ENABLE) == 0 );
752   }
753
754   if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) {
755      RADEON_STATECHANGE( rmesa, ctx );
756      rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p;
757   }
758
759   /* Update vertex/render formats
760    */
761   if (rmesa->TclFallback) {
762      radeonChooseRenderState( ctx );
763      radeonChooseVertexState( ctx );
764   }
765}
766
767
768/* =============================================================
769 * Materials
770 */
771
772
773/* Update on colormaterial, material emmissive/ambient,
774 * lightmodel.globalambient
775 */
776static void update_global_ambient( GLcontext *ctx )
777{
778   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
779   float *fcmd = (float *)RADEON_DB_STATE( glt );
780
781   /* Need to do more if both emmissive & ambient are PREMULT:
782    * Hope this is not needed for MULT
783    */
784   if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &
785       ((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
786	(3 << RADEON_AMBIENT_SOURCE_SHIFT))) == 0)
787   {
788      COPY_3V( &fcmd[GLT_RED],
789	       ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]);
790      ACC_SCALE_3V( &fcmd[GLT_RED],
791		   ctx->Light.Model.Ambient,
792		   ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]);
793   }
794   else
795   {
796      COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient );
797   }
798
799   RADEON_DB_STATECHANGE(rmesa, &rmesa->hw.glt);
800}
801
802/* Update on change to
803 *    - light[p].colors
804 *    - light[p].enabled
805 */
806static void update_light_colors( GLcontext *ctx, GLuint p )
807{
808   struct gl_light *l = &ctx->Light.Light[p];
809
810/*     fprintf(stderr, "%s\n", __FUNCTION__); */
811
812   if (l->Enabled) {
813      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
814      float *fcmd = (float *)RADEON_DB_STATE( lit[p] );
815
816      COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient );
817      COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse );
818      COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular );
819
820      RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
821   }
822}
823
824/* Also fallback for asym colormaterial mode in twoside lighting...
825 */
826static void check_twoside_fallback( GLcontext *ctx )
827{
828   GLboolean fallback = GL_FALSE;
829   GLint i;
830
831   if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
832      if (ctx->Light.ColorMaterialEnabled &&
833	  (ctx->Light.ColorMaterialBitmask & BACK_MATERIAL_BITS) !=
834	  ((ctx->Light.ColorMaterialBitmask & FRONT_MATERIAL_BITS)<<1))
835	 fallback = GL_TRUE;
836      else {
837	 for (i = MAT_ATTRIB_FRONT_AMBIENT; i < MAT_ATTRIB_FRONT_INDEXES; i+=2)
838	    if (memcmp( ctx->Light.Material.Attrib[i],
839			ctx->Light.Material.Attrib[i+1],
840			sizeof(GLfloat)*4) != 0) {
841	       fallback = GL_TRUE;
842	       break;
843	    }
844      }
845   }
846
847   TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_LIGHT_TWOSIDE, fallback );
848}
849
850
851static void radeonColorMaterial( GLcontext *ctx, GLenum face, GLenum mode )
852{
853      radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
854      GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
855
856      light_model_ctl1 &= ~((3 << RADEON_EMISSIVE_SOURCE_SHIFT) |
857			   (3 << RADEON_AMBIENT_SOURCE_SHIFT) |
858			   (3 << RADEON_DIFFUSE_SOURCE_SHIFT) |
859			   (3 << RADEON_SPECULAR_SOURCE_SHIFT));
860
861   if (ctx->Light.ColorMaterialEnabled) {
862      GLuint mask = ctx->Light.ColorMaterialBitmask;
863
864      if (mask & MAT_BIT_FRONT_EMISSION) {
865	 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
866			     RADEON_EMISSIVE_SOURCE_SHIFT);
867      }
868      else {
869	 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
870			     RADEON_EMISSIVE_SOURCE_SHIFT);
871      }
872
873      if (mask & MAT_BIT_FRONT_AMBIENT) {
874	 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
875			     RADEON_AMBIENT_SOURCE_SHIFT);
876      }
877      else {
878	 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
879			     RADEON_AMBIENT_SOURCE_SHIFT);
880      }
881
882      if (mask & MAT_BIT_FRONT_DIFFUSE) {
883	 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
884			     RADEON_DIFFUSE_SOURCE_SHIFT);
885      }
886      else {
887	 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
888			     RADEON_DIFFUSE_SOURCE_SHIFT);
889      }
890
891      if (mask & MAT_BIT_FRONT_SPECULAR) {
892	 light_model_ctl1 |= (RADEON_LM_SOURCE_VERTEX_DIFFUSE <<
893			     RADEON_SPECULAR_SOURCE_SHIFT);
894      }
895      else {
896	 light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT <<
897			     RADEON_SPECULAR_SOURCE_SHIFT);
898      }
899   }
900   else {
901   /* Default to MULT:
902    */
903      light_model_ctl1 |= (RADEON_LM_SOURCE_STATE_MULT << RADEON_EMISSIVE_SOURCE_SHIFT) |
904		   (RADEON_LM_SOURCE_STATE_MULT << RADEON_AMBIENT_SOURCE_SHIFT) |
905		   (RADEON_LM_SOURCE_STATE_MULT << RADEON_DIFFUSE_SOURCE_SHIFT) |
906		   (RADEON_LM_SOURCE_STATE_MULT << RADEON_SPECULAR_SOURCE_SHIFT);
907   }
908
909      if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]) {
910	 RADEON_STATECHANGE( rmesa, tcl );
911	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = light_model_ctl1;
912   }
913}
914
915void radeonUpdateMaterial( GLcontext *ctx )
916{
917   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
918   GLfloat (*mat)[4] = ctx->Light.Material.Attrib;
919   GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( mtl );
920   GLuint mask = ~0;
921
922   if (ctx->Light.ColorMaterialEnabled)
923      mask &= ~ctx->Light.ColorMaterialBitmask;
924
925   if (RADEON_DEBUG & DEBUG_STATE)
926      fprintf(stderr, "%s\n", __FUNCTION__);
927
928
929   if (mask & MAT_BIT_FRONT_EMISSION) {
930      fcmd[MTL_EMMISSIVE_RED]   = mat[MAT_ATTRIB_FRONT_EMISSION][0];
931      fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1];
932      fcmd[MTL_EMMISSIVE_BLUE]  = mat[MAT_ATTRIB_FRONT_EMISSION][2];
933      fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3];
934   }
935   if (mask & MAT_BIT_FRONT_AMBIENT) {
936      fcmd[MTL_AMBIENT_RED]     = mat[MAT_ATTRIB_FRONT_AMBIENT][0];
937      fcmd[MTL_AMBIENT_GREEN]   = mat[MAT_ATTRIB_FRONT_AMBIENT][1];
938      fcmd[MTL_AMBIENT_BLUE]    = mat[MAT_ATTRIB_FRONT_AMBIENT][2];
939      fcmd[MTL_AMBIENT_ALPHA]   = mat[MAT_ATTRIB_FRONT_AMBIENT][3];
940   }
941   if (mask & MAT_BIT_FRONT_DIFFUSE) {
942      fcmd[MTL_DIFFUSE_RED]     = mat[MAT_ATTRIB_FRONT_DIFFUSE][0];
943      fcmd[MTL_DIFFUSE_GREEN]   = mat[MAT_ATTRIB_FRONT_DIFFUSE][1];
944      fcmd[MTL_DIFFUSE_BLUE]    = mat[MAT_ATTRIB_FRONT_DIFFUSE][2];
945      fcmd[MTL_DIFFUSE_ALPHA]   = mat[MAT_ATTRIB_FRONT_DIFFUSE][3];
946   }
947   if (mask & MAT_BIT_FRONT_SPECULAR) {
948      fcmd[MTL_SPECULAR_RED]    = mat[MAT_ATTRIB_FRONT_SPECULAR][0];
949      fcmd[MTL_SPECULAR_GREEN]  = mat[MAT_ATTRIB_FRONT_SPECULAR][1];
950      fcmd[MTL_SPECULAR_BLUE]   = mat[MAT_ATTRIB_FRONT_SPECULAR][2];
951      fcmd[MTL_SPECULAR_ALPHA]  = mat[MAT_ATTRIB_FRONT_SPECULAR][3];
952   }
953   if (mask & MAT_BIT_FRONT_SHININESS) {
954      fcmd[MTL_SHININESS]       = mat[MAT_ATTRIB_FRONT_SHININESS][0];
955   }
956
957   RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mtl );
958
959   check_twoside_fallback( ctx );
960/*   update_global_ambient( ctx );*/
961}
962
963/* _NEW_LIGHT
964 * _NEW_MODELVIEW
965 * _MESA_NEW_NEED_EYE_COORDS
966 *
967 * Uses derived state from mesa:
968 *       _VP_inf_norm
969 *       _h_inf_norm
970 *       _Position
971 *       _NormDirection
972 *       _ModelViewInvScale
973 *       _NeedEyeCoords
974 *       _EyeZDir
975 *
976 * which are calculated in light.c and are correct for the current
977 * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW
978 * and _MESA_NEW_NEED_EYE_COORDS.
979 */
980static void update_light( GLcontext *ctx )
981{
982   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
983
984   /* Have to check these, or have an automatic shortcircuit mechanism
985    * to remove noop statechanges. (Or just do a better job on the
986    * front end).
987    */
988   {
989      GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL];
990
991      if (ctx->_NeedEyeCoords)
992	 tmp &= ~RADEON_LIGHT_IN_MODELSPACE;
993      else
994	 tmp |= RADEON_LIGHT_IN_MODELSPACE;
995
996
997      /* Leave this test disabled: (unexplained q3 lockup) (even with
998         new packets)
999      */
1000      if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL])
1001      {
1002	 RADEON_STATECHANGE( rmesa, tcl );
1003	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] = tmp;
1004      }
1005   }
1006
1007   {
1008      GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( eye );
1009      fcmd[EYE_X] = ctx->_EyeZDir[0];
1010      fcmd[EYE_Y] = ctx->_EyeZDir[1];
1011      fcmd[EYE_Z] = - ctx->_EyeZDir[2];
1012      fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale;
1013      RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.eye );
1014   }
1015
1016
1017
1018   if (ctx->Light.Enabled) {
1019      GLint p;
1020      for (p = 0 ; p < MAX_LIGHTS; p++) {
1021	 if (ctx->Light.Light[p].Enabled) {
1022	    struct gl_light *l = &ctx->Light.Light[p];
1023	    GLfloat *fcmd = (GLfloat *)RADEON_DB_STATE( lit[p] );
1024
1025	    if (l->EyePosition[3] == 0.0) {
1026	       COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm );
1027	       COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm );
1028	       fcmd[LIT_POSITION_W] = 0;
1029	       fcmd[LIT_DIRECTION_W] = 0;
1030	    } else {
1031	       COPY_4V( &fcmd[LIT_POSITION_X], l->_Position );
1032	       fcmd[LIT_DIRECTION_X] = -l->_NormDirection[0];
1033	       fcmd[LIT_DIRECTION_Y] = -l->_NormDirection[1];
1034	       fcmd[LIT_DIRECTION_Z] = -l->_NormDirection[2];
1035	       fcmd[LIT_DIRECTION_W] = 0;
1036	    }
1037
1038	    RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] );
1039	 }
1040      }
1041   }
1042}
1043
1044static void radeonLightfv( GLcontext *ctx, GLenum light,
1045			   GLenum pname, const GLfloat *params )
1046{
1047   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1048   GLint p = light - GL_LIGHT0;
1049   struct gl_light *l = &ctx->Light.Light[p];
1050   GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd;
1051
1052
1053   switch (pname) {
1054   case GL_AMBIENT:
1055   case GL_DIFFUSE:
1056   case GL_SPECULAR:
1057      update_light_colors( ctx, p );
1058      break;
1059
1060   case GL_SPOT_DIRECTION:
1061      /* picked up in update_light */
1062      break;
1063
1064   case GL_POSITION: {
1065      /* positions picked up in update_light, but can do flag here */
1066      GLuint flag;
1067      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1068
1069      /* FIXME: Set RANGE_ATTEN only when needed */
1070      if (p&1)
1071	 flag = RADEON_LIGHT_1_IS_LOCAL;
1072      else
1073	 flag = RADEON_LIGHT_0_IS_LOCAL;
1074
1075      RADEON_STATECHANGE(rmesa, tcl);
1076      if (l->EyePosition[3] != 0.0F)
1077	 rmesa->hw.tcl.cmd[idx] |= flag;
1078      else
1079	 rmesa->hw.tcl.cmd[idx] &= ~flag;
1080      break;
1081   }
1082
1083   case GL_SPOT_EXPONENT:
1084      RADEON_STATECHANGE(rmesa, lit[p]);
1085      fcmd[LIT_SPOT_EXPONENT] = params[0];
1086      break;
1087
1088   case GL_SPOT_CUTOFF: {
1089      GLuint flag = (p&1) ? RADEON_LIGHT_1_IS_SPOT : RADEON_LIGHT_0_IS_SPOT;
1090      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1091
1092      RADEON_STATECHANGE(rmesa, lit[p]);
1093      fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff;
1094
1095      RADEON_STATECHANGE(rmesa, tcl);
1096      if (l->SpotCutoff != 180.0F)
1097	 rmesa->hw.tcl.cmd[idx] |= flag;
1098      else
1099	 rmesa->hw.tcl.cmd[idx] &= ~flag;
1100
1101      break;
1102   }
1103
1104   case GL_CONSTANT_ATTENUATION:
1105      RADEON_STATECHANGE(rmesa, lit[p]);
1106      fcmd[LIT_ATTEN_CONST] = params[0];
1107      if ( params[0] == 0.0 )
1108	 fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX;
1109      else
1110	 fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0];
1111      break;
1112   case GL_LINEAR_ATTENUATION:
1113      RADEON_STATECHANGE(rmesa, lit[p]);
1114      fcmd[LIT_ATTEN_LINEAR] = params[0];
1115      break;
1116   case GL_QUADRATIC_ATTENUATION:
1117      RADEON_STATECHANGE(rmesa, lit[p]);
1118      fcmd[LIT_ATTEN_QUADRATIC] = params[0];
1119      break;
1120   default:
1121      return;
1122   }
1123
1124   /* Set RANGE_ATTEN only when needed */
1125   switch (pname) {
1126   case GL_POSITION:
1127   case GL_CONSTANT_ATTENUATION:
1128   case GL_LINEAR_ATTENUATION:
1129   case GL_QUADRATIC_ATTENUATION:
1130   {
1131      GLuint *icmd = (GLuint *)RADEON_DB_STATE( tcl );
1132      GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2;
1133      GLuint atten_flag = ( p&1 ) ? RADEON_LIGHT_1_ENABLE_RANGE_ATTEN
1134				  : RADEON_LIGHT_0_ENABLE_RANGE_ATTEN;
1135      GLuint atten_const_flag = ( p&1 ) ? RADEON_LIGHT_1_CONSTANT_RANGE_ATTEN
1136				  : RADEON_LIGHT_0_CONSTANT_RANGE_ATTEN;
1137
1138      if ( l->EyePosition[3] == 0.0F ||
1139	   ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) &&
1140	     fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) {
1141	 /* Disable attenuation */
1142	 icmd[idx] &= ~atten_flag;
1143      } else {
1144	 if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) {
1145	    /* Enable only constant portion of attenuation calculation */
1146	    icmd[idx] |= ( atten_flag | atten_const_flag );
1147	 } else {
1148	    /* Enable full attenuation calculation */
1149	    icmd[idx] &= ~atten_const_flag;
1150	    icmd[idx] |= atten_flag;
1151	 }
1152      }
1153
1154      RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.tcl );
1155      break;
1156   }
1157   default:
1158      break;
1159   }
1160}
1161
1162
1163
1164
1165static void radeonLightModelfv( GLcontext *ctx, GLenum pname,
1166				const GLfloat *param )
1167{
1168   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1169
1170   switch (pname) {
1171      case GL_LIGHT_MODEL_AMBIENT:
1172	 update_global_ambient( ctx );
1173	 break;
1174
1175      case GL_LIGHT_MODEL_LOCAL_VIEWER:
1176	 RADEON_STATECHANGE( rmesa, tcl );
1177	 if (ctx->Light.Model.LocalViewer)
1178	    rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |= RADEON_LOCAL_VIEWER;
1179	 else
1180	    rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_LOCAL_VIEWER;
1181         break;
1182
1183      case GL_LIGHT_MODEL_TWO_SIDE:
1184	 RADEON_STATECHANGE( rmesa, tcl );
1185	 if (ctx->Light.Model.TwoSide)
1186	    rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= RADEON_LIGHT_TWOSIDE;
1187	 else
1188	    rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_LIGHT_TWOSIDE;
1189
1190	 check_twoside_fallback( ctx );
1191
1192	 if (rmesa->TclFallback) {
1193	    radeonChooseRenderState( ctx );
1194	    radeonChooseVertexState( ctx );
1195	 }
1196         break;
1197
1198      case GL_LIGHT_MODEL_COLOR_CONTROL:
1199	 radeonUpdateSpecular(ctx);
1200         break;
1201
1202      default:
1203         break;
1204   }
1205}
1206
1207static void radeonShadeModel( GLcontext *ctx, GLenum mode )
1208{
1209   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1210   GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL];
1211
1212   s &= ~(RADEON_DIFFUSE_SHADE_MASK |
1213	  RADEON_ALPHA_SHADE_MASK |
1214	  RADEON_SPECULAR_SHADE_MASK |
1215	  RADEON_FOG_SHADE_MASK);
1216
1217   switch ( mode ) {
1218   case GL_FLAT:
1219      s |= (RADEON_DIFFUSE_SHADE_FLAT |
1220	    RADEON_ALPHA_SHADE_FLAT |
1221	    RADEON_SPECULAR_SHADE_FLAT |
1222	    RADEON_FOG_SHADE_FLAT);
1223      break;
1224   case GL_SMOOTH:
1225      s |= (RADEON_DIFFUSE_SHADE_GOURAUD |
1226	    RADEON_ALPHA_SHADE_GOURAUD |
1227	    RADEON_SPECULAR_SHADE_GOURAUD |
1228	    RADEON_FOG_SHADE_GOURAUD);
1229      break;
1230   default:
1231      return;
1232   }
1233
1234   if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) {
1235      RADEON_STATECHANGE( rmesa, set );
1236      rmesa->hw.set.cmd[SET_SE_CNTL] = s;
1237   }
1238}
1239
1240
1241/* =============================================================
1242 * User clip planes
1243 */
1244
1245static void radeonClipPlane( GLcontext *ctx, GLenum plane, const GLfloat *eq )
1246{
1247   GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0;
1248   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1249   GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1250
1251   RADEON_STATECHANGE( rmesa, ucp[p] );
1252   rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1253   rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1254   rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1255   rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1256}
1257
1258static void radeonUpdateClipPlanes( GLcontext *ctx )
1259{
1260   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1261   GLuint p;
1262
1263   for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
1264      if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
1265	 GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p];
1266
1267	 RADEON_STATECHANGE( rmesa, ucp[p] );
1268	 rmesa->hw.ucp[p].cmd[UCP_X] = ip[0];
1269	 rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1];
1270	 rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2];
1271	 rmesa->hw.ucp[p].cmd[UCP_W] = ip[3];
1272      }
1273   }
1274}
1275
1276
1277/* =============================================================
1278 * Stencil
1279 */
1280
1281static void
1282radeonStencilFuncSeparate( GLcontext *ctx, GLenum face, GLenum func,
1283                           GLint ref, GLuint mask )
1284{
1285   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1286   GLuint refmask = (((ctx->Stencil.Ref[0] & 0xff) << RADEON_STENCIL_REF_SHIFT) |
1287		     ((ctx->Stencil.ValueMask[0] & 0xff) << RADEON_STENCIL_MASK_SHIFT));
1288
1289   RADEON_STATECHANGE( rmesa, ctx );
1290   RADEON_STATECHANGE( rmesa, msk );
1291
1292   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~RADEON_STENCIL_TEST_MASK;
1293   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(RADEON_STENCIL_REF_MASK|
1294						   RADEON_STENCIL_VALUE_MASK);
1295
1296   switch ( ctx->Stencil.Function[0] ) {
1297   case GL_NEVER:
1298      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEVER;
1299      break;
1300   case GL_LESS:
1301      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LESS;
1302      break;
1303   case GL_EQUAL:
1304      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_EQUAL;
1305      break;
1306   case GL_LEQUAL:
1307      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_LEQUAL;
1308      break;
1309   case GL_GREATER:
1310      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GREATER;
1311      break;
1312   case GL_NOTEQUAL:
1313      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_NEQUAL;
1314      break;
1315   case GL_GEQUAL:
1316      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_GEQUAL;
1317      break;
1318   case GL_ALWAYS:
1319      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_TEST_ALWAYS;
1320      break;
1321   }
1322
1323   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask;
1324}
1325
1326static void
1327radeonStencilMaskSeparate( GLcontext *ctx, GLenum face, GLuint mask )
1328{
1329   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1330
1331   RADEON_STATECHANGE( rmesa, msk );
1332   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~RADEON_STENCIL_WRITE_MASK;
1333   rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |=
1334      ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT);
1335}
1336
1337static void radeonStencilOpSeparate( GLcontext *ctx, GLenum face, GLenum fail,
1338                                     GLenum zfail, GLenum zpass )
1339{
1340   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1341
1342   /* radeon 7200 have stencil bug, DEC and INC_WRAP will actually both do DEC_WRAP,
1343      and DEC_WRAP (and INVERT) will do INVERT. No way to get correct INC_WRAP and DEC,
1344      but DEC_WRAP can be fixed by using DEC and INC_WRAP at least use INC. */
1345
1346   GLuint tempRADEON_STENCIL_FAIL_DEC_WRAP;
1347   GLuint tempRADEON_STENCIL_FAIL_INC_WRAP;
1348   GLuint tempRADEON_STENCIL_ZFAIL_DEC_WRAP;
1349   GLuint tempRADEON_STENCIL_ZFAIL_INC_WRAP;
1350   GLuint tempRADEON_STENCIL_ZPASS_DEC_WRAP;
1351   GLuint tempRADEON_STENCIL_ZPASS_INC_WRAP;
1352
1353   if (rmesa->radeonScreen->chip_flags & RADEON_CHIPSET_BROKEN_STENCIL) {
1354      tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC;
1355      tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC;
1356      tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC;
1357      tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC;
1358      tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC;
1359      tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC;
1360   }
1361   else {
1362      tempRADEON_STENCIL_FAIL_DEC_WRAP = RADEON_STENCIL_FAIL_DEC_WRAP;
1363      tempRADEON_STENCIL_FAIL_INC_WRAP = RADEON_STENCIL_FAIL_INC_WRAP;
1364      tempRADEON_STENCIL_ZFAIL_DEC_WRAP = RADEON_STENCIL_ZFAIL_DEC_WRAP;
1365      tempRADEON_STENCIL_ZFAIL_INC_WRAP = RADEON_STENCIL_ZFAIL_INC_WRAP;
1366      tempRADEON_STENCIL_ZPASS_DEC_WRAP = RADEON_STENCIL_ZPASS_DEC_WRAP;
1367      tempRADEON_STENCIL_ZPASS_INC_WRAP = RADEON_STENCIL_ZPASS_INC_WRAP;
1368   }
1369
1370   RADEON_STATECHANGE( rmesa, ctx );
1371   rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(RADEON_STENCIL_FAIL_MASK |
1372					       RADEON_STENCIL_ZFAIL_MASK |
1373					       RADEON_STENCIL_ZPASS_MASK);
1374
1375   switch ( ctx->Stencil.FailFunc[0] ) {
1376   case GL_KEEP:
1377      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_KEEP;
1378      break;
1379   case GL_ZERO:
1380      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_ZERO;
1381      break;
1382   case GL_REPLACE:
1383      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_REPLACE;
1384      break;
1385   case GL_INCR:
1386      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INC;
1387      break;
1388   case GL_DECR:
1389      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_DEC;
1390      break;
1391   case GL_INCR_WRAP:
1392      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_INC_WRAP;
1393      break;
1394   case GL_DECR_WRAP:
1395      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_FAIL_DEC_WRAP;
1396      break;
1397   case GL_INVERT:
1398      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_FAIL_INVERT;
1399      break;
1400   }
1401
1402   switch ( ctx->Stencil.ZFailFunc[0] ) {
1403   case GL_KEEP:
1404      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_KEEP;
1405      break;
1406   case GL_ZERO:
1407      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_ZERO;
1408      break;
1409   case GL_REPLACE:
1410      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_REPLACE;
1411      break;
1412   case GL_INCR:
1413      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INC;
1414      break;
1415   case GL_DECR:
1416      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_DEC;
1417      break;
1418   case GL_INCR_WRAP:
1419      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_INC_WRAP;
1420      break;
1421   case GL_DECR_WRAP:
1422      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZFAIL_DEC_WRAP;
1423      break;
1424   case GL_INVERT:
1425      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZFAIL_INVERT;
1426      break;
1427   }
1428
1429   switch ( ctx->Stencil.ZPassFunc[0] ) {
1430   case GL_KEEP:
1431      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_KEEP;
1432      break;
1433   case GL_ZERO:
1434      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_ZERO;
1435      break;
1436   case GL_REPLACE:
1437      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_REPLACE;
1438      break;
1439   case GL_INCR:
1440      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INC;
1441      break;
1442   case GL_DECR:
1443      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_DEC;
1444      break;
1445   case GL_INCR_WRAP:
1446      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_INC_WRAP;
1447      break;
1448   case GL_DECR_WRAP:
1449      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= tempRADEON_STENCIL_ZPASS_DEC_WRAP;
1450      break;
1451   case GL_INVERT:
1452      rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= RADEON_STENCIL_ZPASS_INVERT;
1453      break;
1454   }
1455}
1456
1457static void radeonClearStencil( GLcontext *ctx, GLint s )
1458{
1459   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1460
1461   rmesa->state.stencil.clear =
1462      ((GLuint) (ctx->Stencil.Clear & 0xff) |
1463       (0xff << RADEON_STENCIL_MASK_SHIFT) |
1464       ((ctx->Stencil.WriteMask[0] & 0xff) << RADEON_STENCIL_WRITEMASK_SHIFT));
1465}
1466
1467
1468/* =============================================================
1469 * Window position and viewport transformation
1470 */
1471
1472/*
1473 * To correctly position primitives:
1474 */
1475#define SUBPIXEL_X 0.125
1476#define SUBPIXEL_Y 0.125
1477
1478
1479/**
1480 * Called when window size or position changes or viewport or depth range
1481 * state is changed.  We update the hardware viewport state here.
1482 */
1483void radeonUpdateWindow( GLcontext *ctx )
1484{
1485   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1486   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1487   GLfloat xoffset = (GLfloat)dPriv->x;
1488   GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1489   const GLfloat *v = ctx->Viewport._WindowMap.m;
1490
1491   float_ui32_type sx = { v[MAT_SX] };
1492   float_ui32_type tx = { v[MAT_TX] + xoffset + SUBPIXEL_X };
1493   float_ui32_type sy = { - v[MAT_SY] };
1494   float_ui32_type ty = { (- v[MAT_TY]) + yoffset + SUBPIXEL_Y };
1495   float_ui32_type sz = { v[MAT_SZ] * rmesa->state.depth.scale };
1496   float_ui32_type tz = { v[MAT_TZ] * rmesa->state.depth.scale };
1497
1498   RADEON_FIREVERTICES( rmesa );
1499   RADEON_STATECHANGE( rmesa, vpt );
1500
1501   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE]  = sx.ui32;
1502   rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1503   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE]  = sy.ui32;
1504   rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1505   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE]  = sz.ui32;
1506   rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32;
1507}
1508
1509
1510static void radeonViewport( GLcontext *ctx, GLint x, GLint y,
1511			    GLsizei width, GLsizei height )
1512{
1513   /* Don't pipeline viewport changes, conflict with window offset
1514    * setting below.  Could apply deltas to rescue pipelined viewport
1515    * values, or keep the originals hanging around.
1516    */
1517   radeonUpdateWindow( ctx );
1518}
1519
1520static void radeonDepthRange( GLcontext *ctx, GLclampd nearval,
1521			      GLclampd farval )
1522{
1523   radeonUpdateWindow( ctx );
1524}
1525
1526void radeonUpdateViewportOffset( GLcontext *ctx )
1527{
1528   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1529   __DRIdrawablePrivate *dPriv = rmesa->dri.drawable;
1530   GLfloat xoffset = (GLfloat)dPriv->x;
1531   GLfloat yoffset = (GLfloat)dPriv->y + dPriv->h;
1532   const GLfloat *v = ctx->Viewport._WindowMap.m;
1533
1534   float_ui32_type tx;
1535   float_ui32_type ty;
1536
1537   tx.f = v[MAT_TX] + xoffset + SUBPIXEL_X;
1538   ty.f = (- v[MAT_TY]) + yoffset + SUBPIXEL_Y;
1539
1540   if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 ||
1541	rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 )
1542   {
1543      /* Note: this should also modify whatever data the context reset
1544       * code uses...
1545       */
1546      RADEON_STATECHANGE( rmesa, vpt );
1547      rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32;
1548      rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32;
1549
1550      /* update polygon stipple x/y screen offset */
1551      {
1552         GLuint stx, sty;
1553         GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC];
1554
1555         m &= ~(RADEON_STIPPLE_X_OFFSET_MASK |
1556                RADEON_STIPPLE_Y_OFFSET_MASK);
1557
1558         /* add magic offsets, then invert */
1559         stx = 31 - ((rmesa->dri.drawable->x - 1) & RADEON_STIPPLE_COORD_MASK);
1560         sty = 31 - ((rmesa->dri.drawable->y + rmesa->dri.drawable->h - 1)
1561                     & RADEON_STIPPLE_COORD_MASK);
1562
1563         m |= ((stx << RADEON_STIPPLE_X_OFFSET_SHIFT) |
1564               (sty << RADEON_STIPPLE_Y_OFFSET_SHIFT));
1565
1566         if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) {
1567            RADEON_STATECHANGE( rmesa, msc );
1568	    rmesa->hw.msc.cmd[MSC_RE_MISC] = m;
1569         }
1570      }
1571   }
1572
1573   radeonUpdateScissor( ctx );
1574}
1575
1576
1577
1578/* =============================================================
1579 * Miscellaneous
1580 */
1581
1582static void radeonClearColor( GLcontext *ctx, const GLfloat color[4] )
1583{
1584   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1585   GLubyte c[4];
1586   CLAMPED_FLOAT_TO_UBYTE(c[0], color[0]);
1587   CLAMPED_FLOAT_TO_UBYTE(c[1], color[1]);
1588   CLAMPED_FLOAT_TO_UBYTE(c[2], color[2]);
1589   CLAMPED_FLOAT_TO_UBYTE(c[3], color[3]);
1590   rmesa->state.color.clear = radeonPackColor( rmesa->radeonScreen->cpp,
1591					       c[0], c[1], c[2], c[3] );
1592}
1593
1594
1595static void radeonRenderMode( GLcontext *ctx, GLenum mode )
1596{
1597   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1598   FALLBACK( rmesa, RADEON_FALLBACK_RENDER_MODE, (mode != GL_RENDER) );
1599}
1600
1601
1602static GLuint radeon_rop_tab[] = {
1603   RADEON_ROP_CLEAR,
1604   RADEON_ROP_AND,
1605   RADEON_ROP_AND_REVERSE,
1606   RADEON_ROP_COPY,
1607   RADEON_ROP_AND_INVERTED,
1608   RADEON_ROP_NOOP,
1609   RADEON_ROP_XOR,
1610   RADEON_ROP_OR,
1611   RADEON_ROP_NOR,
1612   RADEON_ROP_EQUIV,
1613   RADEON_ROP_INVERT,
1614   RADEON_ROP_OR_REVERSE,
1615   RADEON_ROP_COPY_INVERTED,
1616   RADEON_ROP_OR_INVERTED,
1617   RADEON_ROP_NAND,
1618   RADEON_ROP_SET,
1619};
1620
1621static void radeonLogicOpCode( GLcontext *ctx, GLenum opcode )
1622{
1623   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1624   GLuint rop = (GLuint)opcode - GL_CLEAR;
1625
1626   ASSERT( rop < 16 );
1627
1628   RADEON_STATECHANGE( rmesa, msk );
1629   rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = radeon_rop_tab[rop];
1630}
1631
1632
1633/**
1634 * Set up the cliprects for either front or back-buffer drawing.
1635 */
1636void radeonSetCliprects( radeonContextPtr rmesa )
1637{
1638   __DRIdrawablePrivate *const drawable = rmesa->dri.drawable;
1639   __DRIdrawablePrivate *const readable = rmesa->dri.readable;
1640   GLframebuffer *const draw_fb = (GLframebuffer*) drawable->driverPrivate;
1641   GLframebuffer *const read_fb = (GLframebuffer*) readable->driverPrivate;
1642
1643   if (draw_fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
1644      /* Can't ignore 2d windows if we are page flipping.
1645       */
1646      if ( drawable->numBackClipRects == 0 || rmesa->doPageFlip ) {
1647	 rmesa->numClipRects = drawable->numClipRects;
1648	 rmesa->pClipRects = drawable->pClipRects;
1649      }
1650      else {
1651	 rmesa->numClipRects = drawable->numBackClipRects;
1652	 rmesa->pClipRects = drawable->pBackClipRects;
1653      }
1654   }
1655   else {
1656      /* front buffer (or none, or multiple buffers */
1657      rmesa->numClipRects = drawable->numClipRects;
1658      rmesa->pClipRects = drawable->pClipRects;
1659   }
1660
1661   if ((draw_fb->Width != drawable->w) || (draw_fb->Height != drawable->h)) {
1662      _mesa_resize_framebuffer(rmesa->glCtx, draw_fb,
1663			       drawable->w, drawable->h);
1664      draw_fb->Initialized = GL_TRUE;
1665   }
1666
1667   if (drawable != readable) {
1668      if ((read_fb->Width != readable->w) || (read_fb->Height != readable->h)) {
1669	 _mesa_resize_framebuffer(rmesa->glCtx, read_fb,
1670				  readable->w, readable->h);
1671	 read_fb->Initialized = GL_TRUE;
1672      }
1673   }
1674
1675   if (rmesa->state.scissor.enabled)
1676      radeonRecalcScissorRects( rmesa );
1677
1678   rmesa->lastStamp = drawable->lastStamp;
1679}
1680
1681
1682/**
1683 * Called via glDrawBuffer.
1684 */
1685static void radeonDrawBuffer( GLcontext *ctx, GLenum mode )
1686{
1687   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1688
1689   if (RADEON_DEBUG & DEBUG_DRI)
1690      fprintf(stderr, "%s %s\n", __FUNCTION__,
1691	      _mesa_lookup_enum_by_nr( mode ));
1692
1693   RADEON_FIREVERTICES(rmesa);	/* don't pipeline cliprect changes */
1694
1695   if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) {
1696      /* 0 (GL_NONE) buffers or multiple color drawing buffers */
1697      FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
1698      return;
1699   }
1700
1701   switch ( ctx->DrawBuffer->_ColorDrawBufferIndexes[0] ) {
1702   case BUFFER_FRONT_LEFT:
1703   case BUFFER_BACK_LEFT:
1704      FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_FALSE );
1705      break;
1706   default:
1707      FALLBACK( rmesa, RADEON_FALLBACK_DRAW_BUFFER, GL_TRUE );
1708      return;
1709   }
1710
1711   radeonSetCliprects( rmesa );
1712
1713   /* We'll set the drawing engine's offset/pitch parameters later
1714    * when we update other state.
1715    */
1716}
1717
1718static void radeonReadBuffer( GLcontext *ctx, GLenum mode )
1719{
1720   /* nothing, until we implement h/w glRead/CopyPixels or CopyTexImage */
1721}
1722
1723
1724/* =============================================================
1725 * State enable/disable
1726 */
1727
1728static void radeonEnable( GLcontext *ctx, GLenum cap, GLboolean state )
1729{
1730   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
1731   GLuint p, flag;
1732
1733   if ( RADEON_DEBUG & DEBUG_STATE )
1734      fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__,
1735	       _mesa_lookup_enum_by_nr( cap ),
1736	       state ? "GL_TRUE" : "GL_FALSE" );
1737
1738   switch ( cap ) {
1739      /* Fast track this one...
1740       */
1741   case GL_TEXTURE_1D:
1742   case GL_TEXTURE_2D:
1743   case GL_TEXTURE_3D:
1744      break;
1745
1746   case GL_ALPHA_TEST:
1747      RADEON_STATECHANGE( rmesa, ctx );
1748      if (state) {
1749	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_ALPHA_TEST_ENABLE;
1750      } else {
1751	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ALPHA_TEST_ENABLE;
1752      }
1753      break;
1754
1755   case GL_BLEND:
1756      RADEON_STATECHANGE( rmesa, ctx );
1757      if (state) {
1758	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_ALPHA_BLEND_ENABLE;
1759      } else {
1760	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ALPHA_BLEND_ENABLE;
1761      }
1762      if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled
1763	    && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) {
1764	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_ROP_ENABLE;
1765      } else {
1766	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
1767      }
1768
1769      /* Catch a possible fallback:
1770       */
1771      if (state) {
1772	 ctx->Driver.BlendEquationSeparate( ctx,
1773					    ctx->Color.BlendEquationRGB,
1774					    ctx->Color.BlendEquationA );
1775	 ctx->Driver.BlendFuncSeparate( ctx, ctx->Color.BlendSrcRGB,
1776					ctx->Color.BlendDstRGB,
1777					ctx->Color.BlendSrcA,
1778					ctx->Color.BlendDstA );
1779      }
1780      else {
1781	 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_FUNC, GL_FALSE );
1782	 FALLBACK( rmesa, RADEON_FALLBACK_BLEND_EQ, GL_FALSE );
1783      }
1784      break;
1785
1786   case GL_CLIP_PLANE0:
1787   case GL_CLIP_PLANE1:
1788   case GL_CLIP_PLANE2:
1789   case GL_CLIP_PLANE3:
1790   case GL_CLIP_PLANE4:
1791   case GL_CLIP_PLANE5:
1792      p = cap-GL_CLIP_PLANE0;
1793      RADEON_STATECHANGE( rmesa, tcl );
1794      if (state) {
1795	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (RADEON_UCP_ENABLE_0<<p);
1796	 radeonClipPlane( ctx, cap, NULL );
1797      }
1798      else {
1799	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(RADEON_UCP_ENABLE_0<<p);
1800      }
1801      break;
1802
1803   case GL_COLOR_MATERIAL:
1804      radeonColorMaterial( ctx, 0, 0 );
1805      radeonUpdateMaterial( ctx );
1806      break;
1807
1808   case GL_CULL_FACE:
1809      radeonCullFace( ctx, 0 );
1810      break;
1811
1812   case GL_DEPTH_TEST:
1813      RADEON_STATECHANGE(rmesa, ctx );
1814      if ( state ) {
1815	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_Z_ENABLE;
1816      } else {
1817	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_Z_ENABLE;
1818      }
1819      break;
1820
1821   case GL_DITHER:
1822      RADEON_STATECHANGE(rmesa, ctx );
1823      if ( state ) {
1824	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_DITHER_ENABLE;
1825	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->state.color.roundEnable;
1826      } else {
1827	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_DITHER_ENABLE;
1828	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  rmesa->state.color.roundEnable;
1829      }
1830      break;
1831
1832   case GL_FOG:
1833      RADEON_STATECHANGE(rmesa, ctx );
1834      if ( state ) {
1835	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= RADEON_FOG_ENABLE;
1836	 radeonFogfv( ctx, GL_FOG_MODE, NULL );
1837      } else {
1838	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_FOG_ENABLE;
1839	 RADEON_STATECHANGE(rmesa, tcl);
1840	 rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~RADEON_TCL_FOG_MASK;
1841      }
1842      radeonUpdateSpecular( ctx ); /* for PK_SPEC */
1843      _mesa_allow_light_in_model( ctx, !state );
1844      break;
1845
1846   case GL_LIGHT0:
1847   case GL_LIGHT1:
1848   case GL_LIGHT2:
1849   case GL_LIGHT3:
1850   case GL_LIGHT4:
1851   case GL_LIGHT5:
1852   case GL_LIGHT6:
1853   case GL_LIGHT7:
1854      RADEON_STATECHANGE(rmesa, tcl);
1855      p = cap - GL_LIGHT0;
1856      if (p&1)
1857	 flag = (RADEON_LIGHT_1_ENABLE |
1858		 RADEON_LIGHT_1_ENABLE_AMBIENT |
1859		 RADEON_LIGHT_1_ENABLE_SPECULAR);
1860      else
1861	 flag = (RADEON_LIGHT_0_ENABLE |
1862		 RADEON_LIGHT_0_ENABLE_AMBIENT |
1863		 RADEON_LIGHT_0_ENABLE_SPECULAR);
1864
1865      if (state)
1866	 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag;
1867      else
1868	 rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag;
1869
1870      /*
1871       */
1872      update_light_colors( ctx, p );
1873      break;
1874
1875   case GL_LIGHTING:
1876      RADEON_STATECHANGE(rmesa, tcl);
1877      radeonUpdateSpecular(ctx);
1878      check_twoside_fallback( ctx );
1879      break;
1880
1881   case GL_LINE_SMOOTH:
1882      RADEON_STATECHANGE( rmesa, ctx );
1883      if ( state ) {
1884	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  RADEON_ANTI_ALIAS_LINE;
1885      } else {
1886	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_LINE;
1887      }
1888      break;
1889
1890   case GL_LINE_STIPPLE:
1891      RADEON_STATECHANGE( rmesa, ctx );
1892      if ( state ) {
1893	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  RADEON_PATTERN_ENABLE;
1894      } else {
1895	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_PATTERN_ENABLE;
1896      }
1897      break;
1898
1899   case GL_COLOR_LOGIC_OP:
1900      RADEON_STATECHANGE( rmesa, ctx );
1901      if ( (ctx->Color.ColorLogicOpEnabled || (ctx->Color.BlendEnabled
1902	    && ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) ) {
1903	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_ROP_ENABLE;
1904      } else {
1905	 rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_ROP_ENABLE;
1906      }
1907      break;
1908
1909   case GL_NORMALIZE:
1910      RADEON_STATECHANGE( rmesa, tcl );
1911      if ( state ) {
1912	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |=  RADEON_NORMALIZE_NORMALS;
1913      } else {
1914	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_NORMALIZE_NORMALS;
1915      }
1916      break;
1917
1918   case GL_POLYGON_OFFSET_POINT:
1919      RADEON_STATECHANGE( rmesa, set );
1920      if ( state ) {
1921	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_POINT;
1922      } else {
1923	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_POINT;
1924      }
1925      break;
1926
1927   case GL_POLYGON_OFFSET_LINE:
1928      RADEON_STATECHANGE( rmesa, set );
1929      if ( state ) {
1930	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_LINE;
1931      } else {
1932	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_LINE;
1933      }
1934      break;
1935
1936   case GL_POLYGON_OFFSET_FILL:
1937      RADEON_STATECHANGE( rmesa, set );
1938      if ( state ) {
1939	 rmesa->hw.set.cmd[SET_SE_CNTL] |=  RADEON_ZBIAS_ENABLE_TRI;
1940      } else {
1941	 rmesa->hw.set.cmd[SET_SE_CNTL] &= ~RADEON_ZBIAS_ENABLE_TRI;
1942      }
1943      break;
1944
1945   case GL_POLYGON_SMOOTH:
1946      RADEON_STATECHANGE( rmesa, ctx );
1947      if ( state ) {
1948	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  RADEON_ANTI_ALIAS_POLY;
1949      } else {
1950	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_ANTI_ALIAS_POLY;
1951      }
1952      break;
1953
1954   case GL_POLYGON_STIPPLE:
1955      RADEON_STATECHANGE(rmesa, ctx );
1956      if ( state ) {
1957	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |=  RADEON_STIPPLE_ENABLE;
1958      } else {
1959	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~RADEON_STIPPLE_ENABLE;
1960      }
1961      break;
1962
1963   case GL_RESCALE_NORMAL_EXT: {
1964      GLboolean tmp = ctx->_NeedEyeCoords ? state : !state;
1965      RADEON_STATECHANGE( rmesa, tcl );
1966      if ( tmp ) {
1967	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |=  RADEON_RESCALE_NORMALS;
1968      } else {
1969	 rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
1970      }
1971      break;
1972   }
1973
1974   case GL_SCISSOR_TEST:
1975      RADEON_FIREVERTICES( rmesa );
1976      rmesa->state.scissor.enabled = state;
1977      radeonUpdateScissor( ctx );
1978      break;
1979
1980   case GL_STENCIL_TEST:
1981      if ( rmesa->state.stencil.hwBuffer ) {
1982	 RADEON_STATECHANGE( rmesa, ctx );
1983	 if ( state ) {
1984	    rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |=  RADEON_STENCIL_ENABLE;
1985	 } else {
1986	    rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~RADEON_STENCIL_ENABLE;
1987	 }
1988      } else {
1989	 FALLBACK( rmesa, RADEON_FALLBACK_STENCIL, state );
1990      }
1991      break;
1992
1993   case GL_TEXTURE_GEN_Q:
1994   case GL_TEXTURE_GEN_R:
1995   case GL_TEXTURE_GEN_S:
1996   case GL_TEXTURE_GEN_T:
1997      /* Picked up in radeonUpdateTextureState.
1998       */
1999      rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE;
2000      break;
2001
2002   case GL_COLOR_SUM_EXT:
2003      radeonUpdateSpecular ( ctx );
2004      break;
2005
2006   default:
2007      return;
2008   }
2009}
2010
2011
2012static void radeonLightingSpaceChange( GLcontext *ctx )
2013{
2014   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2015   GLboolean tmp;
2016   RADEON_STATECHANGE( rmesa, tcl );
2017
2018   if (RADEON_DEBUG & DEBUG_STATE)
2019      fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2020	      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
2021
2022   if (ctx->_NeedEyeCoords)
2023      tmp = ctx->Transform.RescaleNormals;
2024   else
2025      tmp = !ctx->Transform.RescaleNormals;
2026
2027   if ( tmp ) {
2028      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] |=  RADEON_RESCALE_NORMALS;
2029   } else {
2030      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL] &= ~RADEON_RESCALE_NORMALS;
2031   }
2032
2033   if (RADEON_DEBUG & DEBUG_STATE)
2034      fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords,
2035	      rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL]);
2036}
2037
2038/* =============================================================
2039 * Deferred state management - matrices, textures, other?
2040 */
2041
2042
2043void radeonUploadTexMatrix( radeonContextPtr rmesa,
2044			    int unit, GLboolean swapcols )
2045{
2046/* Here's how this works: on r100, only 3 tex coords can be submitted, so the
2047   vector looks like this probably: (s t r|q 0) (not sure if the last coord
2048   is hardwired to 0, could be 1 too). Interestingly, it actually looks like
2049   texgen generates all 4 coords, at least tests with projtex indicated that.
2050   So: if we need the q coord in the end (solely determined by the texture
2051   target, i.e. 2d / 1d / texrect targets) we swap the third and 4th row.
2052   Additionally, if we don't have texgen but 4 tex coords submitted, we swap
2053   column 3 and 4 (for the 2d / 1d / texrect targets) since the the q coord
2054   will get submitted in the "wrong", i.e. 3rd, slot.
2055   If an app submits 3 coords for 2d targets, we assume it is saving on vertex
2056   size and using the texture matrix to swap the r and q coords around (ut2k3
2057   does exactly that), so we don't need the 3rd / 4th column swap - still need
2058   the 3rd / 4th row swap of course. This will potentially break for apps which
2059   use TexCoord3x just for fun. Additionally, it will never work if an app uses
2060   an "advanced" texture matrix and relies on all 4 texcoord inputs to generate
2061   the maximum needed 3. This seems impossible to do with hw tcl on r100, and
2062   incredibly hard to detect so we can't just fallback in such a case. Assume
2063   it never happens... - rs
2064*/
2065
2066   int idx = TEXMAT_0 + unit;
2067   float *dest = ((float *)RADEON_DB_STATE( mat[idx] )) + MAT_ELT_0;
2068   int i;
2069   struct gl_texture_unit tUnit = rmesa->glCtx->Texture.Unit[unit];
2070   GLfloat *src = rmesa->tmpmat[unit].m;
2071
2072   rmesa->TexMatColSwap &= ~(1 << unit);
2073   if ((tUnit._ReallyEnabled & (TEXTURE_3D_BIT | TEXTURE_CUBE_BIT)) == 0) {
2074      if (swapcols) {
2075	 rmesa->TexMatColSwap |= 1 << unit;
2076	 /* attention some elems are swapped 2 times! */
2077	 *dest++ = src[0];
2078	 *dest++ = src[4];
2079	 *dest++ = src[12];
2080	 *dest++ = src[8];
2081	 *dest++ = src[1];
2082	 *dest++ = src[5];
2083	 *dest++ = src[13];
2084	 *dest++ = src[9];
2085	 *dest++ = src[2];
2086	 *dest++ = src[6];
2087	 *dest++ = src[15];
2088	 *dest++ = src[11];
2089	 /* those last 4 are probably never used */
2090	 *dest++ = src[3];
2091	 *dest++ = src[7];
2092	 *dest++ = src[14];
2093	 *dest++ = src[10];
2094      }
2095      else {
2096	 for (i = 0; i < 2; i++) {
2097	    *dest++ = src[i];
2098	    *dest++ = src[i+4];
2099	    *dest++ = src[i+8];
2100	    *dest++ = src[i+12];
2101	 }
2102	 for (i = 3; i >= 2; i--) {
2103	    *dest++ = src[i];
2104	    *dest++ = src[i+4];
2105	    *dest++ = src[i+8];
2106	    *dest++ = src[i+12];
2107	 }
2108      }
2109   }
2110   else {
2111      for (i = 0 ; i < 4 ; i++) {
2112	 *dest++ = src[i];
2113	 *dest++ = src[i+4];
2114	 *dest++ = src[i+8];
2115	 *dest++ = src[i+12];
2116      }
2117   }
2118
2119   RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2120}
2121
2122
2123static void upload_matrix( radeonContextPtr rmesa, GLfloat *src, int idx )
2124{
2125   float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
2126   int i;
2127
2128
2129   for (i = 0 ; i < 4 ; i++) {
2130      *dest++ = src[i];
2131      *dest++ = src[i+4];
2132      *dest++ = src[i+8];
2133      *dest++ = src[i+12];
2134   }
2135
2136   RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2137}
2138
2139static void upload_matrix_t( radeonContextPtr rmesa, GLfloat *src, int idx )
2140{
2141   float *dest = ((float *)RADEON_DB_STATE( mat[idx] ))+MAT_ELT_0;
2142   memcpy(dest, src, 16*sizeof(float));
2143   RADEON_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] );
2144}
2145
2146
2147static void update_texturematrix( GLcontext *ctx )
2148{
2149   radeonContextPtr rmesa = RADEON_CONTEXT( ctx );
2150   GLuint tpc = rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL];
2151   GLuint vs = rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL];
2152   int unit;
2153   GLuint texMatEnabled = 0;
2154   rmesa->NeedTexMatrix = 0;
2155   rmesa->TexMatColSwap = 0;
2156
2157   for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) {
2158      if (ctx->Texture.Unit[unit]._ReallyEnabled) {
2159	 GLboolean needMatrix = GL_FALSE;
2160	 if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) {
2161	    needMatrix = GL_TRUE;
2162	    texMatEnabled |= (RADEON_TEXGEN_TEXMAT_0_ENABLE |
2163			      RADEON_TEXMAT_0_ENABLE) << unit;
2164
2165	    if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
2166	       /* Need to preconcatenate any active texgen
2167	        * obj/eyeplane matrices:
2168	        */
2169	       _math_matrix_mul_matrix( &rmesa->tmpmat[unit],
2170				     ctx->TextureMatrixStack[unit].Top,
2171				     &rmesa->TexGenMatrix[unit] );
2172	    }
2173	    else {
2174	       _math_matrix_copy( &rmesa->tmpmat[unit],
2175		  ctx->TextureMatrixStack[unit].Top );
2176	    }
2177	 }
2178	 else if (rmesa->TexGenEnabled & (RADEON_TEXMAT_0_ENABLE << unit)) {
2179	    _math_matrix_copy( &rmesa->tmpmat[unit], &rmesa->TexGenMatrix[unit] );
2180	    needMatrix = GL_TRUE;
2181	 }
2182	 if (needMatrix) {
2183	    rmesa->NeedTexMatrix |= 1 << unit;
2184	    radeonUploadTexMatrix( rmesa, unit,
2185			!ctx->Texture.Unit[unit].TexGenEnabled );
2186	 }
2187      }
2188   }
2189
2190   tpc = (texMatEnabled | rmesa->TexGenEnabled);
2191
2192   /* TCL_TEX_COMPUTED_x is TCL_TEX_INPUT_x | 0x8 */
2193   vs &= ~((RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_0_OUTPUT_SHIFT) |
2194	   (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_1_OUTPUT_SHIFT) |
2195	   (RADEON_TCL_TEX_COMPUTED_TEX_0 << RADEON_TCL_TEX_2_OUTPUT_SHIFT));
2196
2197   vs |= (((tpc & RADEON_TEXGEN_TEXMAT_0_ENABLE) <<
2198	 (RADEON_TCL_TEX_0_OUTPUT_SHIFT + 3)) |
2199      ((tpc & RADEON_TEXGEN_TEXMAT_1_ENABLE) <<
2200	 (RADEON_TCL_TEX_1_OUTPUT_SHIFT + 2)) |
2201      ((tpc & RADEON_TEXGEN_TEXMAT_2_ENABLE) <<
2202	 (RADEON_TCL_TEX_2_OUTPUT_SHIFT + 1)));
2203
2204   if (tpc != rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] ||
2205       vs != rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL]) {
2206
2207      RADEON_STATECHANGE(rmesa, tcl);
2208      rmesa->hw.tcl.cmd[TCL_TEXTURE_PROC_CTL] = tpc;
2209      rmesa->hw.tcl.cmd[TCL_OUTPUT_VTXSEL] = vs;
2210   }
2211}
2212
2213
2214/**
2215 * Tell the card where to render (offset, pitch).
2216 * Effected by glDrawBuffer, etc
2217 */
2218void
2219radeonUpdateDrawBuffer(GLcontext *ctx)
2220{
2221   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2222   struct gl_framebuffer *fb = ctx->DrawBuffer;
2223   driRenderbuffer *drb;
2224
2225   if (fb->_ColorDrawBufferIndexes[0] == BUFFER_FRONT_LEFT) {
2226      /* draw to front */
2227      drb = (driRenderbuffer *) fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer;
2228   }
2229   else if (fb->_ColorDrawBufferIndexes[0] == BUFFER_BACK_LEFT) {
2230      /* draw to back */
2231      drb = (driRenderbuffer *) fb->Attachment[BUFFER_BACK_LEFT].Renderbuffer;
2232   }
2233   else {
2234      /* drawing to multiple buffers, or none */
2235      return;
2236   }
2237
2238   assert(drb);
2239   assert(drb->flippedPitch);
2240
2241   RADEON_STATECHANGE( rmesa, ctx );
2242
2243   /* Note: we used the (possibly) page-flipped values */
2244   rmesa->hw.ctx.cmd[CTX_RB3D_COLOROFFSET]
2245     = ((drb->flippedOffset + rmesa->radeonScreen->fbLocation)
2246	& RADEON_COLOROFFSET_MASK);
2247   rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] = drb->flippedPitch;
2248   if (rmesa->sarea->tiling_enabled) {
2249      rmesa->hw.ctx.cmd[CTX_RB3D_COLORPITCH] |= RADEON_COLOR_TILE_ENABLE;
2250   }
2251}
2252
2253
2254void radeonValidateState( GLcontext *ctx )
2255{
2256   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2257   GLuint new_state = rmesa->NewGLState;
2258
2259   if (new_state & (_NEW_BUFFERS | _NEW_COLOR | _NEW_PIXEL)) {
2260     radeonUpdateDrawBuffer(ctx);
2261   }
2262
2263   if (new_state & _NEW_TEXTURE) {
2264      radeonUpdateTextureState( ctx );
2265      new_state |= rmesa->NewGLState; /* may add TEXTURE_MATRIX */
2266   }
2267
2268   /* Need an event driven matrix update?
2269    */
2270   if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION))
2271      upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, MODEL_PROJ );
2272
2273   /* Need these for lighting (shouldn't upload otherwise)
2274    */
2275   if (new_state & (_NEW_MODELVIEW)) {
2276      upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, MODEL );
2277      upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, MODEL_IT );
2278   }
2279
2280   /* Does this need to be triggered on eg. modelview for
2281    * texgen-derived objplane/eyeplane matrices?
2282    */
2283   if (new_state & _NEW_TEXTURE_MATRIX) {
2284      update_texturematrix( ctx );
2285   }
2286
2287   if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) {
2288      update_light( ctx );
2289   }
2290
2291   /* emit all active clip planes if projection matrix changes.
2292    */
2293   if (new_state & (_NEW_PROJECTION)) {
2294      if (ctx->Transform.ClipPlanesEnabled)
2295	 radeonUpdateClipPlanes( ctx );
2296   }
2297
2298
2299   rmesa->NewGLState = 0;
2300}
2301
2302
2303static void radeonInvalidateState( GLcontext *ctx, GLuint new_state )
2304{
2305   _swrast_InvalidateState( ctx, new_state );
2306   _swsetup_InvalidateState( ctx, new_state );
2307   _vbo_InvalidateState( ctx, new_state );
2308   _tnl_InvalidateState( ctx, new_state );
2309   _ae_invalidate_state( ctx, new_state );
2310   RADEON_CONTEXT(ctx)->NewGLState |= new_state;
2311}
2312
2313
2314/* A hack.  Need a faster way to find this out.
2315 */
2316static GLboolean check_material( GLcontext *ctx )
2317{
2318   TNLcontext *tnl = TNL_CONTEXT(ctx);
2319   GLint i;
2320
2321   for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT;
2322	i < _TNL_ATTRIB_MAT_BACK_INDEXES;
2323	i++)
2324      if (tnl->vb.AttribPtr[i] &&
2325	  tnl->vb.AttribPtr[i]->stride)
2326	 return GL_TRUE;
2327
2328   return GL_FALSE;
2329}
2330
2331
2332static void radeonWrapRunPipeline( GLcontext *ctx )
2333{
2334   radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
2335   GLboolean has_material;
2336
2337   if (0)
2338      fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->NewGLState);
2339
2340   /* Validate state:
2341    */
2342   if (rmesa->NewGLState)
2343      radeonValidateState( ctx );
2344
2345   has_material = (ctx->Light.Enabled && check_material( ctx ));
2346
2347   if (has_material) {
2348      TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_TRUE );
2349   }
2350
2351   /* Run the pipeline.
2352    */
2353   _tnl_run_pipeline( ctx );
2354
2355   if (has_material) {
2356      TCL_FALLBACK( ctx, RADEON_TCL_FALLBACK_MATERIAL, GL_FALSE );
2357   }
2358}
2359
2360
2361/* Initialize the driver's state functions.
2362 * Many of the ctx->Driver functions might have been initialized to
2363 * software defaults in the earlier _mesa_init_driver_functions() call.
2364 */
2365void radeonInitStateFuncs( GLcontext *ctx )
2366{
2367   ctx->Driver.UpdateState		= radeonInvalidateState;
2368   ctx->Driver.LightingSpaceChange      = radeonLightingSpaceChange;
2369
2370   ctx->Driver.DrawBuffer		= radeonDrawBuffer;
2371   ctx->Driver.ReadBuffer		= radeonReadBuffer;
2372
2373   ctx->Driver.AlphaFunc		= radeonAlphaFunc;
2374   ctx->Driver.BlendEquationSeparate	= radeonBlendEquationSeparate;
2375   ctx->Driver.BlendFuncSeparate	= radeonBlendFuncSeparate;
2376   ctx->Driver.ClearColor		= radeonClearColor;
2377   ctx->Driver.ClearDepth		= radeonClearDepth;
2378   ctx->Driver.ClearIndex		= NULL;
2379   ctx->Driver.ClearStencil		= radeonClearStencil;
2380   ctx->Driver.ClipPlane		= radeonClipPlane;
2381   ctx->Driver.ColorMask		= radeonColorMask;
2382   ctx->Driver.CullFace			= radeonCullFace;
2383   ctx->Driver.DepthFunc		= radeonDepthFunc;
2384   ctx->Driver.DepthMask		= radeonDepthMask;
2385   ctx->Driver.DepthRange		= radeonDepthRange;
2386   ctx->Driver.Enable			= radeonEnable;
2387   ctx->Driver.Fogfv			= radeonFogfv;
2388   ctx->Driver.FrontFace		= radeonFrontFace;
2389   ctx->Driver.Hint			= NULL;
2390   ctx->Driver.IndexMask		= NULL;
2391   ctx->Driver.LightModelfv		= radeonLightModelfv;
2392   ctx->Driver.Lightfv			= radeonLightfv;
2393   ctx->Driver.LineStipple              = radeonLineStipple;
2394   ctx->Driver.LineWidth                = radeonLineWidth;
2395   ctx->Driver.LogicOpcode		= radeonLogicOpCode;
2396   ctx->Driver.PolygonMode		= radeonPolygonMode;
2397   ctx->Driver.PolygonOffset		= radeonPolygonOffset;
2398   ctx->Driver.PolygonStipple		= radeonPolygonStipple;
2399   ctx->Driver.RenderMode		= radeonRenderMode;
2400   ctx->Driver.Scissor			= radeonScissor;
2401   ctx->Driver.ShadeModel		= radeonShadeModel;
2402   ctx->Driver.StencilFuncSeparate	= radeonStencilFuncSeparate;
2403   ctx->Driver.StencilMaskSeparate	= radeonStencilMaskSeparate;
2404   ctx->Driver.StencilOpSeparate	= radeonStencilOpSeparate;
2405   ctx->Driver.Viewport			= radeonViewport;
2406
2407   TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = radeonUpdateMaterial;
2408   TNL_CONTEXT(ctx)->Driver.RunPipeline = radeonWrapRunPipeline;
2409}
2410