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