1/*
2Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
3
4The Weather Channel (TM) funded Tungsten Graphics to develop the
5initial release of the Radeon 8500 driver under the XFree86 license.
6This notice must be preserved.
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 *   Keith Whitwell <keithw@vmware.com>
33 */
34
35#include "main/glheader.h"
36
37#include "main/context.h"
38#include "main/macros.h"
39#include "main/state.h"
40#include "main/teximage.h"
41#include "main/texobj.h"
42#include "main/enums.h"
43
44#include "radeon_common.h"
45#include "radeon_mipmap_tree.h"
46#include "r200_context.h"
47#include "r200_state.h"
48#include "r200_ioctl.h"
49#include "r200_swtcl.h"
50#include "r200_tex.h"
51#include "r200_tcl.h"
52
53#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_RGBA_DXT5) \
54                             && (tx_table_be[f].format != 0xffffffff) )
55
56/* ================================================================
57 * Texture combine functions
58 */
59
60/* GL_ARB_texture_env_combine support
61 */
62
63/* The color tables have combine functions for GL_SRC_COLOR,
64 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
65 */
66static GLuint r200_register_color[][R200_MAX_TEXTURE_UNITS] =
67{
68   {
69      R200_TXC_ARG_A_R0_COLOR,
70      R200_TXC_ARG_A_R1_COLOR,
71      R200_TXC_ARG_A_R2_COLOR,
72      R200_TXC_ARG_A_R3_COLOR,
73      R200_TXC_ARG_A_R4_COLOR,
74      R200_TXC_ARG_A_R5_COLOR
75   },
76   {
77      R200_TXC_ARG_A_R0_COLOR | R200_TXC_COMP_ARG_A,
78      R200_TXC_ARG_A_R1_COLOR | R200_TXC_COMP_ARG_A,
79      R200_TXC_ARG_A_R2_COLOR | R200_TXC_COMP_ARG_A,
80      R200_TXC_ARG_A_R3_COLOR | R200_TXC_COMP_ARG_A,
81      R200_TXC_ARG_A_R4_COLOR | R200_TXC_COMP_ARG_A,
82      R200_TXC_ARG_A_R5_COLOR | R200_TXC_COMP_ARG_A
83   },
84   {
85      R200_TXC_ARG_A_R0_ALPHA,
86      R200_TXC_ARG_A_R1_ALPHA,
87      R200_TXC_ARG_A_R2_ALPHA,
88      R200_TXC_ARG_A_R3_ALPHA,
89      R200_TXC_ARG_A_R4_ALPHA,
90      R200_TXC_ARG_A_R5_ALPHA
91   },
92   {
93      R200_TXC_ARG_A_R0_ALPHA | R200_TXC_COMP_ARG_A,
94      R200_TXC_ARG_A_R1_ALPHA | R200_TXC_COMP_ARG_A,
95      R200_TXC_ARG_A_R2_ALPHA | R200_TXC_COMP_ARG_A,
96      R200_TXC_ARG_A_R3_ALPHA | R200_TXC_COMP_ARG_A,
97      R200_TXC_ARG_A_R4_ALPHA | R200_TXC_COMP_ARG_A,
98      R200_TXC_ARG_A_R5_ALPHA | R200_TXC_COMP_ARG_A
99   },
100};
101
102static GLuint r200_tfactor_color[] =
103{
104   R200_TXC_ARG_A_TFACTOR_COLOR,
105   R200_TXC_ARG_A_TFACTOR_COLOR | R200_TXC_COMP_ARG_A,
106   R200_TXC_ARG_A_TFACTOR_ALPHA,
107   R200_TXC_ARG_A_TFACTOR_ALPHA | R200_TXC_COMP_ARG_A
108};
109
110static GLuint r200_tfactor1_color[] =
111{
112   R200_TXC_ARG_A_TFACTOR1_COLOR,
113   R200_TXC_ARG_A_TFACTOR1_COLOR | R200_TXC_COMP_ARG_A,
114   R200_TXC_ARG_A_TFACTOR1_ALPHA,
115   R200_TXC_ARG_A_TFACTOR1_ALPHA | R200_TXC_COMP_ARG_A
116};
117
118static GLuint r200_primary_color[] =
119{
120   R200_TXC_ARG_A_DIFFUSE_COLOR,
121   R200_TXC_ARG_A_DIFFUSE_COLOR | R200_TXC_COMP_ARG_A,
122   R200_TXC_ARG_A_DIFFUSE_ALPHA,
123   R200_TXC_ARG_A_DIFFUSE_ALPHA | R200_TXC_COMP_ARG_A
124};
125
126/* GL_ZERO table - indices 0-3
127 * GL_ONE  table - indices 1-4
128 */
129static GLuint r200_zero_color[] =
130{
131   R200_TXC_ARG_A_ZERO,
132   R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
133   R200_TXC_ARG_A_ZERO,
134   R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
135   R200_TXC_ARG_A_ZERO
136};
137
138/* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
139 */
140static GLuint r200_register_alpha[][R200_MAX_TEXTURE_UNITS] =
141{
142   {
143      R200_TXA_ARG_A_R0_ALPHA,
144      R200_TXA_ARG_A_R1_ALPHA,
145      R200_TXA_ARG_A_R2_ALPHA,
146      R200_TXA_ARG_A_R3_ALPHA,
147      R200_TXA_ARG_A_R4_ALPHA,
148      R200_TXA_ARG_A_R5_ALPHA
149   },
150   {
151      R200_TXA_ARG_A_R0_ALPHA | R200_TXA_COMP_ARG_A,
152      R200_TXA_ARG_A_R1_ALPHA | R200_TXA_COMP_ARG_A,
153      R200_TXA_ARG_A_R2_ALPHA | R200_TXA_COMP_ARG_A,
154      R200_TXA_ARG_A_R3_ALPHA | R200_TXA_COMP_ARG_A,
155      R200_TXA_ARG_A_R4_ALPHA | R200_TXA_COMP_ARG_A,
156      R200_TXA_ARG_A_R5_ALPHA | R200_TXA_COMP_ARG_A
157   },
158};
159
160static GLuint r200_tfactor_alpha[] =
161{
162   R200_TXA_ARG_A_TFACTOR_ALPHA,
163   R200_TXA_ARG_A_TFACTOR_ALPHA | R200_TXA_COMP_ARG_A
164};
165
166static GLuint r200_tfactor1_alpha[] =
167{
168   R200_TXA_ARG_A_TFACTOR1_ALPHA,
169   R200_TXA_ARG_A_TFACTOR1_ALPHA | R200_TXA_COMP_ARG_A
170};
171
172static GLuint r200_primary_alpha[] =
173{
174   R200_TXA_ARG_A_DIFFUSE_ALPHA,
175   R200_TXA_ARG_A_DIFFUSE_ALPHA | R200_TXA_COMP_ARG_A
176};
177
178/* GL_ZERO table - indices 0-1
179 * GL_ONE  table - indices 1-2
180 */
181static GLuint r200_zero_alpha[] =
182{
183   R200_TXA_ARG_A_ZERO,
184   R200_TXA_ARG_A_ZERO | R200_TXA_COMP_ARG_A,
185   R200_TXA_ARG_A_ZERO,
186};
187
188
189/* Extract the arg from slot A, shift it into the correct argument slot
190 * and set the corresponding complement bit.
191 */
192#define R200_COLOR_ARG( n, arg )			\
193do {							\
194   color_combine |=					\
195      ((color_arg[n] & R200_TXC_ARG_A_MASK)		\
196       << R200_TXC_ARG_##arg##_SHIFT);			\
197   color_combine |=					\
198      ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT)	\
199       << R200_TXC_COMP_ARG_##arg##_SHIFT);		\
200} while (0)
201
202#define R200_ALPHA_ARG( n, arg )			\
203do {							\
204   alpha_combine |=					\
205      ((alpha_arg[n] & R200_TXA_ARG_A_MASK)		\
206       << R200_TXA_ARG_##arg##_SHIFT);			\
207   alpha_combine |=					\
208      ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT)	\
209       << R200_TXA_COMP_ARG_##arg##_SHIFT);		\
210} while (0)
211
212
213/* ================================================================
214 * Texture unit state management
215 */
216
217static GLboolean r200UpdateTextureEnv( struct gl_context *ctx, int unit, int slot, GLuint replaceargs )
218{
219   r200ContextPtr rmesa = R200_CONTEXT(ctx);
220   const struct gl_texture_unit *rtexUnit = &ctx->Texture.Unit[unit];
221   const struct gl_fixedfunc_texture_unit *texUnit =
222      &ctx->Texture.FixedFuncUnit[unit];
223   GLuint color_combine, alpha_combine;
224   GLuint color_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] &
225      ~(R200_TXC_SCALE_MASK | R200_TXC_OUTPUT_REG_MASK | R200_TXC_TFACTOR_SEL_MASK |
226	R200_TXC_TFACTOR1_SEL_MASK);
227   GLuint alpha_scale = rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] &
228      ~(R200_TXA_DOT_ALPHA | R200_TXA_SCALE_MASK | R200_TXA_OUTPUT_REG_MASK |
229	R200_TXA_TFACTOR_SEL_MASK | R200_TXA_TFACTOR1_SEL_MASK);
230
231   if ( R200_DEBUG & RADEON_TEXTURE ) {
232      fprintf( stderr, "%s( %p, %d )\n", __func__, (void *)ctx, unit );
233   }
234
235   /* Set the texture environment state.  Isn't this nice and clean?
236    * The chip will automagically set the texture alpha to 0xff when
237    * the texture format does not include an alpha component.  This
238    * reduces the amount of special-casing we have to do, alpha-only
239    * textures being a notable exception.
240    */
241
242   color_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXC_OUTPUT_REG_SHIFT) |
243			(unit << R200_TXC_TFACTOR_SEL_SHIFT) |
244			(replaceargs << R200_TXC_TFACTOR1_SEL_SHIFT);
245   alpha_scale |= ((rmesa->state.texture.unit[unit].outputreg + 1) << R200_TXA_OUTPUT_REG_SHIFT) |
246			(unit << R200_TXA_TFACTOR_SEL_SHIFT) |
247			(replaceargs << R200_TXA_TFACTOR1_SEL_SHIFT);
248
249   if ( !rtexUnit->_Current ) {
250      assert( unit == 0);
251      color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO
252	  | R200_TXC_ARG_C_DIFFUSE_COLOR | R200_TXC_OP_MADD;
253      alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO
254	  | R200_TXA_ARG_C_DIFFUSE_ALPHA | R200_TXA_OP_MADD;
255   }
256   else {
257      GLuint color_arg[3], alpha_arg[3];
258      GLuint i;
259      const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
260      const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
261      GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB;
262      GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA;
263
264
265      const GLint replaceoprgb =
266	 ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->OperandRGB[0] - GL_SRC_COLOR;
267      const GLint replaceopa =
268	 ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->OperandA[0] - GL_SRC_ALPHA;
269
270      /* Step 1:
271       * Extract the color and alpha combine function arguments.
272       */
273      for ( i = 0 ; i < numColorArgs ; i++ ) {
274	 GLint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
275	 const GLint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i];
276	 assert(op >= 0);
277	 assert(op <= 3);
278	 switch ( srcRGBi ) {
279	 case GL_TEXTURE:
280	    color_arg[i] = r200_register_color[op][unit];
281	    break;
282	 case GL_CONSTANT:
283	    color_arg[i] = r200_tfactor_color[op];
284	    break;
285	 case GL_PRIMARY_COLOR:
286	    color_arg[i] = r200_primary_color[op];
287	    break;
288	 case GL_PREVIOUS:
289	    if (replaceargs != unit) {
290	       const GLint srcRGBreplace =
291		  ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->SourceRGB[0];
292	       if (op >= 2) {
293		  op = op ^ replaceopa;
294	       }
295	       else {
296		  op = op ^ replaceoprgb;
297	       }
298	       switch (srcRGBreplace) {
299	       case GL_TEXTURE:
300		  color_arg[i] = r200_register_color[op][replaceargs];
301		  break;
302	       case GL_CONSTANT:
303		  color_arg[i] = r200_tfactor1_color[op];
304		  break;
305	       case GL_PRIMARY_COLOR:
306		  color_arg[i] = r200_primary_color[op];
307		  break;
308	       case GL_PREVIOUS:
309		  if (slot == 0)
310		     color_arg[i] = r200_primary_color[op];
311		  else
312		     color_arg[i] = r200_register_color[op]
313			[rmesa->state.texture.unit[replaceargs - 1].outputreg];
314		  break;
315	       case GL_ZERO:
316		  color_arg[i] = r200_zero_color[op];
317		  break;
318	       case GL_ONE:
319		  color_arg[i] = r200_zero_color[op+1];
320		  break;
321	       case GL_TEXTURE0:
322	       case GL_TEXTURE1:
323	       case GL_TEXTURE2:
324	       case GL_TEXTURE3:
325	       case GL_TEXTURE4:
326	       case GL_TEXTURE5:
327		  color_arg[i] = r200_register_color[op][srcRGBreplace - GL_TEXTURE0];
328		  break;
329	       default:
330	       return GL_FALSE;
331	       }
332	    }
333	    else {
334	       if (slot == 0)
335		  color_arg[i] = r200_primary_color[op];
336	       else
337		  color_arg[i] = r200_register_color[op]
338		     [rmesa->state.texture.unit[unit - 1].outputreg];
339            }
340	    break;
341	 case GL_ZERO:
342	    color_arg[i] = r200_zero_color[op];
343	    break;
344	 case GL_ONE:
345	    color_arg[i] = r200_zero_color[op+1];
346	    break;
347	 case GL_TEXTURE0:
348	 case GL_TEXTURE1:
349	 case GL_TEXTURE2:
350	 case GL_TEXTURE3:
351	 case GL_TEXTURE4:
352	 case GL_TEXTURE5:
353	    color_arg[i] = r200_register_color[op][srcRGBi - GL_TEXTURE0];
354	    break;
355	 default:
356	    return GL_FALSE;
357	 }
358      }
359
360      for ( i = 0 ; i < numAlphaArgs ; i++ ) {
361	 GLint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
362	 const GLint srcAi = texUnit->_CurrentCombine->SourceA[i];
363	 assert(op >= 0);
364	 assert(op <= 1);
365	 switch ( srcAi ) {
366	 case GL_TEXTURE:
367	    alpha_arg[i] = r200_register_alpha[op][unit];
368	    break;
369	 case GL_CONSTANT:
370	    alpha_arg[i] = r200_tfactor_alpha[op];
371	    break;
372	 case GL_PRIMARY_COLOR:
373	    alpha_arg[i] = r200_primary_alpha[op];
374	    break;
375	 case GL_PREVIOUS:
376	    if (replaceargs != unit) {
377	       const GLint srcAreplace =
378		  ctx->Texture.FixedFuncUnit[replaceargs]._CurrentCombine->SourceA[0];
379	       op = op ^ replaceopa;
380	       switch (srcAreplace) {
381	       case GL_TEXTURE:
382		  alpha_arg[i] = r200_register_alpha[op][replaceargs];
383		  break;
384	       case GL_CONSTANT:
385		  alpha_arg[i] = r200_tfactor1_alpha[op];
386		  break;
387	       case GL_PRIMARY_COLOR:
388		  alpha_arg[i] = r200_primary_alpha[op];
389		  break;
390	       case GL_PREVIOUS:
391		  if (slot == 0)
392		     alpha_arg[i] = r200_primary_alpha[op];
393		  else
394		     alpha_arg[i] = r200_register_alpha[op]
395			[rmesa->state.texture.unit[replaceargs - 1].outputreg];
396		  break;
397	       case GL_ZERO:
398		  alpha_arg[i] = r200_zero_alpha[op];
399		  break;
400	       case GL_ONE:
401		  alpha_arg[i] = r200_zero_alpha[op+1];
402		  break;
403	       case GL_TEXTURE0:
404	       case GL_TEXTURE1:
405	       case GL_TEXTURE2:
406	       case GL_TEXTURE3:
407	       case GL_TEXTURE4:
408	       case GL_TEXTURE5:
409		  alpha_arg[i] = r200_register_alpha[op][srcAreplace - GL_TEXTURE0];
410		  break;
411	       default:
412	       return GL_FALSE;
413	       }
414	    }
415	    else {
416	       if (slot == 0)
417		  alpha_arg[i] = r200_primary_alpha[op];
418	       else
419		  alpha_arg[i] = r200_register_alpha[op]
420		    [rmesa->state.texture.unit[unit - 1].outputreg];
421            }
422	    break;
423	 case GL_ZERO:
424	    alpha_arg[i] = r200_zero_alpha[op];
425	    break;
426	 case GL_ONE:
427	    alpha_arg[i] = r200_zero_alpha[op+1];
428	    break;
429	 case GL_TEXTURE0:
430	 case GL_TEXTURE1:
431	 case GL_TEXTURE2:
432	 case GL_TEXTURE3:
433	 case GL_TEXTURE4:
434	 case GL_TEXTURE5:
435	    alpha_arg[i] = r200_register_alpha[op][srcAi - GL_TEXTURE0];
436	    break;
437	 default:
438	    return GL_FALSE;
439	 }
440      }
441
442      /* Step 2:
443       * Build up the color and alpha combine functions.
444       */
445      switch ( texUnit->_CurrentCombine->ModeRGB ) {
446      case GL_REPLACE:
447	 color_combine = (R200_TXC_ARG_A_ZERO |
448			  R200_TXC_ARG_B_ZERO |
449			  R200_TXC_OP_MADD);
450	 R200_COLOR_ARG( 0, C );
451	 break;
452      case GL_MODULATE:
453	 color_combine = (R200_TXC_ARG_C_ZERO |
454			  R200_TXC_OP_MADD);
455	 R200_COLOR_ARG( 0, A );
456	 R200_COLOR_ARG( 1, B );
457	 break;
458      case GL_ADD:
459	 color_combine = (R200_TXC_ARG_B_ZERO |
460			  R200_TXC_COMP_ARG_B |
461			  R200_TXC_OP_MADD);
462	 R200_COLOR_ARG( 0, A );
463	 R200_COLOR_ARG( 1, C );
464	 break;
465      case GL_ADD_SIGNED:
466	 color_combine = (R200_TXC_ARG_B_ZERO |
467			  R200_TXC_COMP_ARG_B |
468			  R200_TXC_BIAS_ARG_C |	/* new */
469			  R200_TXC_OP_MADD); /* was ADDSIGNED */
470	 R200_COLOR_ARG( 0, A );
471	 R200_COLOR_ARG( 1, C );
472	 break;
473      case GL_SUBTRACT:
474	 color_combine = (R200_TXC_ARG_B_ZERO |
475			  R200_TXC_COMP_ARG_B |
476			  R200_TXC_NEG_ARG_C |
477			  R200_TXC_OP_MADD);
478	 R200_COLOR_ARG( 0, A );
479	 R200_COLOR_ARG( 1, C );
480	 break;
481      case GL_INTERPOLATE:
482	 color_combine = (R200_TXC_OP_LERP);
483	 R200_COLOR_ARG( 0, B );
484	 R200_COLOR_ARG( 1, A );
485	 R200_COLOR_ARG( 2, C );
486	 break;
487
488      case GL_DOT3_RGB_EXT:
489      case GL_DOT3_RGBA_EXT:
490	 /* The EXT version of the DOT3 extension does not support the
491	  * scale factor, but the ARB version (and the version in OpenGL
492	  * 1.3) does.
493	  */
494	 RGBshift = 0;
495	 FALLTHROUGH;
496
497      case GL_DOT3_RGB:
498      case GL_DOT3_RGBA:
499	 /* DOT3 works differently on R200 than on R100.  On R100, just
500	  * setting the DOT3 mode did everything for you.  On R200, the
501	  * driver has to enable the biasing and scale in the inputs to
502	  * put them in the proper [-1,1] range.  This is what the 4x and
503	  * the -0.5 in the DOT3 spec do.  The post-scale is then set
504	  * normally.
505	  */
506
507	 color_combine = (R200_TXC_ARG_C_ZERO |
508			  R200_TXC_OP_DOT3 |
509			  R200_TXC_BIAS_ARG_A |
510			  R200_TXC_BIAS_ARG_B |
511			  R200_TXC_SCALE_ARG_A |
512			  R200_TXC_SCALE_ARG_B);
513	 R200_COLOR_ARG( 0, A );
514	 R200_COLOR_ARG( 1, B );
515	 break;
516
517      case GL_MODULATE_ADD_ATI:
518	 color_combine = (R200_TXC_OP_MADD);
519	 R200_COLOR_ARG( 0, A );
520	 R200_COLOR_ARG( 1, C );
521	 R200_COLOR_ARG( 2, B );
522	 break;
523      case GL_MODULATE_SIGNED_ADD_ATI:
524	 color_combine = (R200_TXC_BIAS_ARG_C |	/* new */
525			  R200_TXC_OP_MADD); /* was ADDSIGNED */
526	 R200_COLOR_ARG( 0, A );
527	 R200_COLOR_ARG( 1, C );
528	 R200_COLOR_ARG( 2, B );
529	 break;
530      case GL_MODULATE_SUBTRACT_ATI:
531	 color_combine = (R200_TXC_NEG_ARG_C |
532			  R200_TXC_OP_MADD);
533	 R200_COLOR_ARG( 0, A );
534	 R200_COLOR_ARG( 1, C );
535	 R200_COLOR_ARG( 2, B );
536	 break;
537      default:
538	 return GL_FALSE;
539      }
540
541      switch ( texUnit->_CurrentCombine->ModeA ) {
542      case GL_REPLACE:
543	 alpha_combine = (R200_TXA_ARG_A_ZERO |
544			  R200_TXA_ARG_B_ZERO |
545			  R200_TXA_OP_MADD);
546	 R200_ALPHA_ARG( 0, C );
547	 break;
548      case GL_MODULATE:
549	 alpha_combine = (R200_TXA_ARG_C_ZERO |
550			  R200_TXA_OP_MADD);
551	 R200_ALPHA_ARG( 0, A );
552	 R200_ALPHA_ARG( 1, B );
553	 break;
554      case GL_ADD:
555	 alpha_combine = (R200_TXA_ARG_B_ZERO |
556			  R200_TXA_COMP_ARG_B |
557			  R200_TXA_OP_MADD);
558	 R200_ALPHA_ARG( 0, A );
559	 R200_ALPHA_ARG( 1, C );
560	 break;
561      case GL_ADD_SIGNED:
562	 alpha_combine = (R200_TXA_ARG_B_ZERO |
563			  R200_TXA_COMP_ARG_B |
564			  R200_TXA_BIAS_ARG_C |	/* new */
565			  R200_TXA_OP_MADD); /* was ADDSIGNED */
566	 R200_ALPHA_ARG( 0, A );
567	 R200_ALPHA_ARG( 1, C );
568	 break;
569      case GL_SUBTRACT:
570	 alpha_combine = (R200_TXA_ARG_B_ZERO |
571			  R200_TXA_COMP_ARG_B |
572			  R200_TXA_NEG_ARG_C |
573			  R200_TXA_OP_MADD);
574	 R200_ALPHA_ARG( 0, A );
575	 R200_ALPHA_ARG( 1, C );
576	 break;
577      case GL_INTERPOLATE:
578	 alpha_combine = (R200_TXA_OP_LERP);
579	 R200_ALPHA_ARG( 0, B );
580	 R200_ALPHA_ARG( 1, A );
581	 R200_ALPHA_ARG( 2, C );
582	 break;
583
584      case GL_MODULATE_ADD_ATI:
585	 alpha_combine = (R200_TXA_OP_MADD);
586	 R200_ALPHA_ARG( 0, A );
587	 R200_ALPHA_ARG( 1, C );
588	 R200_ALPHA_ARG( 2, B );
589	 break;
590      case GL_MODULATE_SIGNED_ADD_ATI:
591	 alpha_combine = (R200_TXA_BIAS_ARG_C |	/* new */
592			  R200_TXA_OP_MADD); /* was ADDSIGNED */
593	 R200_ALPHA_ARG( 0, A );
594	 R200_ALPHA_ARG( 1, C );
595	 R200_ALPHA_ARG( 2, B );
596	 break;
597      case GL_MODULATE_SUBTRACT_ATI:
598	 alpha_combine = (R200_TXA_NEG_ARG_C |
599			  R200_TXA_OP_MADD);
600	 R200_ALPHA_ARG( 0, A );
601	 R200_ALPHA_ARG( 1, C );
602	 R200_ALPHA_ARG( 2, B );
603	 break;
604      default:
605	 return GL_FALSE;
606      }
607
608      if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT)
609	   || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ) {
610	 alpha_scale |= R200_TXA_DOT_ALPHA;
611	 Ashift = RGBshift;
612      }
613
614      /* Step 3:
615       * Apply the scale factor.
616       */
617      color_scale |= (RGBshift << R200_TXC_SCALE_SHIFT);
618      alpha_scale |= (Ashift   << R200_TXA_SCALE_SHIFT);
619
620      /* All done!
621       */
622   }
623
624   if ( rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] != color_combine ||
625	rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] != alpha_combine ||
626	rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] != color_scale ||
627	rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] != alpha_scale) {
628      R200_STATECHANGE( rmesa, pix[slot] );
629      rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND] = color_combine;
630      rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND] = alpha_combine;
631      rmesa->hw.pix[slot].cmd[PIX_PP_TXCBLEND2] = color_scale;
632      rmesa->hw.pix[slot].cmd[PIX_PP_TXABLEND2] = alpha_scale;
633   }
634
635   return GL_TRUE;
636}
637
638void r200SetTexBuffer2(__DRIcontext *pDRICtx, GLint target, GLint texture_format,
639		       __DRIdrawable *dPriv)
640{
641	struct gl_texture_object *texObj;
642	struct gl_texture_image *texImage;
643	struct radeon_renderbuffer *rb;
644	radeon_texture_image *rImage;
645	radeonContextPtr radeon;
646	struct radeon_framebuffer *rfb;
647	radeonTexObjPtr t;
648	uint32_t pitch_val;
649	mesa_format texFormat;
650
651	radeon = pDRICtx->driverPrivate;
652
653	rfb = dPriv->driverPrivate;
654	texObj = _mesa_get_current_tex_object(&radeon->glCtx, target);
655	texImage = _mesa_get_tex_image(&radeon->glCtx, texObj, target, 0);
656
657	rImage = get_radeon_texture_image(texImage);
658	t = radeon_tex_obj(texObj);
659        if (t == NULL) {
660    	    return;
661    	}
662
663	radeon_update_renderbuffers(pDRICtx, dPriv, GL_TRUE);
664	rb = rfb->color_rb[0];
665	if (rb->bo == NULL) {
666		/* Failed to BO for the buffer */
667		return;
668	}
669
670	_mesa_lock_texture(&radeon->glCtx, texObj);
671	if (t->bo) {
672		radeon_bo_unref(t->bo);
673		t->bo = NULL;
674	}
675	if (rImage->bo) {
676		radeon_bo_unref(rImage->bo);
677		rImage->bo = NULL;
678	}
679
680	radeon_miptree_unreference(&t->mt);
681	radeon_miptree_unreference(&rImage->mt);
682
683	rImage->bo = rb->bo;
684	radeon_bo_ref(rImage->bo);
685	t->bo = rb->bo;
686	radeon_bo_ref(t->bo);
687	t->tile_bits = 0;
688	t->image_override = GL_TRUE;
689	t->override_offset = 0;
690	t->pp_txpitch &= (1 << 13) -1;
691	pitch_val = rb->pitch;
692	switch (rb->cpp) {
693	case 4:
694		if (texture_format == __DRI_TEXTURE_FORMAT_RGB)
695			texFormat = MESA_FORMAT_BGR_UNORM8;
696		else
697			texFormat = MESA_FORMAT_B8G8R8A8_UNORM;
698		break;
699	case 3:
700	default:
701		texFormat = MESA_FORMAT_BGR_UNORM8;
702		break;
703	case 2:
704		texFormat = MESA_FORMAT_B5G6R5_UNORM;
705		break;
706	}
707
708        t->pp_txformat = tx_table_le[texFormat].format;
709        t->pp_txfilter |= tx_table_le[texFormat].filter;
710
711	_mesa_init_teximage_fields(&radeon->glCtx, texImage,
712				   rb->base.Base.Width, rb->base.Base.Height,
713				   1, 0,
714				   rb->cpp, texFormat);
715	rImage->base.RowStride = rb->pitch / rb->cpp;
716
717
718        t->pp_txsize = ((rb->base.Base.Width - 1) << RADEON_TEX_USIZE_SHIFT)
719		   | ((rb->base.Base.Height - 1) << RADEON_TEX_VSIZE_SHIFT);
720
721	if (target == GL_TEXTURE_RECTANGLE_NV) {
722		t->pp_txformat |= R200_TXFORMAT_NON_POWER2;
723		t->pp_txpitch = pitch_val;
724		t->pp_txpitch -= 32;
725	} else {
726		t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
727				    R200_TXFORMAT_HEIGHT_MASK |
728				    R200_TXFORMAT_CUBIC_MAP_ENABLE |
729				    R200_TXFORMAT_F5_WIDTH_MASK |
730				    R200_TXFORMAT_F5_HEIGHT_MASK);
731		t->pp_txformat |= ((texImage->WidthLog2 << R200_TXFORMAT_WIDTH_SHIFT) |
732				   (texImage->HeightLog2 << R200_TXFORMAT_HEIGHT_SHIFT));
733	}
734
735	t->validated = GL_TRUE;
736	_mesa_unlock_texture(&radeon->glCtx, texObj);
737	return;
738}
739
740
741void r200SetTexBuffer(__DRIcontext *pDRICtx, GLint target, __DRIdrawable *dPriv)
742{
743        r200SetTexBuffer2(pDRICtx, target, __DRI_TEXTURE_FORMAT_RGBA, dPriv);
744}
745
746
747#define REF_COLOR 1
748#define REF_ALPHA 2
749
750static GLboolean r200UpdateAllTexEnv( struct gl_context *ctx )
751{
752   r200ContextPtr rmesa = R200_CONTEXT(ctx);
753   GLint i, j, currslot;
754   GLint maxunitused = -1;
755   GLboolean texregfree[6] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE};
756   GLubyte stageref[7] = {0, 0, 0, 0, 0, 0, 0};
757   GLint nextunit[R200_MAX_TEXTURE_UNITS] = {0, 0, 0, 0, 0, 0};
758   GLint currentnext = -1;
759   GLboolean ok;
760
761   /* find highest used unit */
762   for ( j = 0; j < R200_MAX_TEXTURE_UNITS; j++) {
763      if (ctx->Texture.Unit[j]._Current) {
764	 maxunitused = j;
765      }
766   }
767   stageref[maxunitused + 1] = REF_COLOR | REF_ALPHA;
768
769   for ( j = maxunitused; j >= 0; j-- ) {
770      const struct gl_texture_unit *rtexUnit = &ctx->Texture.Unit[j];
771      const struct gl_fixedfunc_texture_unit *texUnit =
772         &ctx->Texture.FixedFuncUnit[j];
773
774      rmesa->state.texture.unit[j].outputreg = -1;
775
776      if (stageref[j + 1]) {
777
778	 /* use the lowest available reg. That gets us automatically reg0 for the last stage.
779	    need this even for disabled units, as it may get referenced due to the replace
780	    optimization */
781	 for ( i = 0 ; i < R200_MAX_TEXTURE_UNITS; i++ ) {
782	    if (texregfree[i]) {
783	       rmesa->state.texture.unit[j].outputreg = i;
784	       break;
785	    }
786	 }
787	 if (rmesa->state.texture.unit[j].outputreg == -1) {
788	    /* no more free regs we can use. Need a fallback :-( */
789	    return GL_FALSE;
790         }
791
792         nextunit[j] = currentnext;
793
794         if (!rtexUnit->_Current) {
795	 /* the not enabled stages are referenced "indirectly",
796            must not cut off the lower stages */
797	    stageref[j] = REF_COLOR | REF_ALPHA;
798	    continue;
799         }
800	 currentnext = j;
801
802	 const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
803	 const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
804	 const GLboolean isdot3rgba = (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA) ||
805				      (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGBA_EXT);
806
807
808	 /* check if we need the color part, special case for dot3_rgba
809	    as if only the alpha part is referenced later on it still is using the color part */
810	 if ((stageref[j + 1] & REF_COLOR) || isdot3rgba) {
811	    for ( i = 0 ; i < numColorArgs ; i++ ) {
812	       const GLuint srcRGBi = texUnit->_CurrentCombine->SourceRGB[i];
813	       const GLuint op = texUnit->_CurrentCombine->OperandRGB[i];
814	       switch ( srcRGBi ) {
815	       case GL_PREVIOUS:
816		  /* op 0/1 are referencing color, op 2/3 alpha */
817		  stageref[j] |= (op >> 1) + 1;
818	          break;
819	       case GL_TEXTURE:
820		  texregfree[j] = GL_FALSE;
821		  break;
822	       case GL_TEXTURE0:
823	       case GL_TEXTURE1:
824	       case GL_TEXTURE2:
825	       case GL_TEXTURE3:
826	       case GL_TEXTURE4:
827	       case GL_TEXTURE5:
828		  texregfree[srcRGBi - GL_TEXTURE0] = GL_FALSE;
829	          break;
830	       default: /* don't care about other sources here */
831		  break;
832	       }
833	    }
834	 }
835
836	 /* alpha args are ignored for dot3_rgba */
837	 if ((stageref[j + 1] & REF_ALPHA) && !isdot3rgba) {
838
839	    for ( i = 0 ; i < numAlphaArgs ; i++ ) {
840	       const GLuint srcAi = texUnit->_CurrentCombine->SourceA[i];
841	       switch ( srcAi ) {
842	       case GL_PREVIOUS:
843		  stageref[j] |= REF_ALPHA;
844		  break;
845	       case GL_TEXTURE:
846		  texregfree[j] = GL_FALSE;
847		  break;
848	       case GL_TEXTURE0:
849	       case GL_TEXTURE1:
850	       case GL_TEXTURE2:
851	       case GL_TEXTURE3:
852	       case GL_TEXTURE4:
853	       case GL_TEXTURE5:
854		  texregfree[srcAi - GL_TEXTURE0] = GL_FALSE;
855		  break;
856	       default: /* don't care about other sources here */
857		  break;
858	       }
859	    }
860	 }
861      }
862   }
863
864   /* don't enable texture sampling for units if the result is not used */
865   for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) {
866      if (ctx->Texture.Unit[i]._Current && !texregfree[i])
867	 rmesa->state.texture.unit[i].unitneeded = 1 << _mesa_tex_target_to_index(ctx, ctx->Texture.Unit[i]._Current->Target);
868      else rmesa->state.texture.unit[i].unitneeded = 0;
869   }
870
871   ok = GL_TRUE;
872   currslot = 0;
873   rmesa->state.envneeded = 1;
874
875   i = 0;
876   while ((i <= maxunitused) && (i >= 0)) {
877      /* only output instruction if the results are referenced */
878      if (ctx->Texture.Unit[i]._Current && stageref[i+1]) {
879         GLuint replaceunit = i;
880	 /* try to optimize GL_REPLACE away (only one level deep though) */
881	 if (	(ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ModeRGB == GL_REPLACE) &&
882		(ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ModeA == GL_REPLACE) &&
883		(ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ScaleShiftRGB == 0) &&
884		(ctx->Texture.FixedFuncUnit[i]._CurrentCombine->ScaleShiftA == 0) &&
885		(nextunit[i] > 0) ) {
886	    /* yippie! can optimize it away! */
887	    replaceunit = i;
888	    i = nextunit[i];
889	 }
890
891	 /* need env instruction slot */
892	 rmesa->state.envneeded |= 1 << currslot;
893	 ok = r200UpdateTextureEnv( ctx, i, currslot, replaceunit );
894	 if (!ok) return GL_FALSE;
895	 currslot++;
896      }
897      i = i + 1;
898   }
899
900   if (currslot == 0) {
901      /* need one stage at least */
902      rmesa->state.texture.unit[0].outputreg = 0;
903      ok = r200UpdateTextureEnv( ctx, 0, 0, 0 );
904   }
905
906   R200_STATECHANGE( rmesa, ctx );
907   rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_BLEND_ENABLE_MASK | R200_MULTI_PASS_ENABLE);
908   rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= rmesa->state.envneeded << R200_TEX_BLEND_0_ENABLE_SHIFT;
909
910   return ok;
911}
912
913#undef REF_COLOR
914#undef REF_ALPHA
915
916
917#define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK |		\
918			      R200_MIN_FILTER_MASK | 		\
919			      R200_MAG_FILTER_MASK |		\
920			      R200_MAX_ANISO_MASK |		\
921			      R200_YUV_TO_RGB |			\
922			      R200_YUV_TEMPERATURE_MASK |	\
923			      R200_CLAMP_S_MASK | 		\
924			      R200_CLAMP_T_MASK | 		\
925			      R200_BORDER_MODE_D3D )
926
927#define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK |	\
928			      R200_TXFORMAT_HEIGHT_MASK |	\
929			      R200_TXFORMAT_FORMAT_MASK |	\
930			      R200_TXFORMAT_F5_WIDTH_MASK |	\
931			      R200_TXFORMAT_F5_HEIGHT_MASK |	\
932			      R200_TXFORMAT_ALPHA_IN_MAP |	\
933			      R200_TXFORMAT_CUBIC_MAP_ENABLE |	\
934			      R200_TXFORMAT_NON_POWER2)
935
936#define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK |		\
937                                R200_TEXCOORD_MASK |		\
938                                R200_MIN_MIP_LEVEL_MASK |	\
939                                R200_CLAMP_Q_MASK | 		\
940                                R200_VOLUME_FILTER_MASK)
941
942
943static void disable_tex_obj_state( r200ContextPtr rmesa,
944				   int unit )
945{
946
947   R200_STATECHANGE( rmesa, vtx );
948   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
949
950   R200_STATECHANGE( rmesa, ctx );
951   rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_0_ENABLE << unit);
952   if (rmesa->radeon.TclFallback & (R200_TCL_FALLBACK_TEXGEN_0<<unit)) {
953      TCL_FALLBACK( &rmesa->radeon.glCtx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
954   }
955
956   /* Actually want to keep all units less than max active texture
957    * enabled, right?  Fix this for >2 texunits.
958    */
959
960   {
961      GLuint tmp = rmesa->TexGenEnabled;
962
963      rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
964      rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
965      rmesa->TexGenNeedNormals[unit] = GL_FALSE;
966      rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
967
968      if (tmp != rmesa->TexGenEnabled) {
969	 rmesa->recheck_texgen[unit] = GL_TRUE;
970	 rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
971      }
972   }
973}
974static void import_tex_obj_state( r200ContextPtr rmesa,
975				  int unit,
976				  radeonTexObjPtr texobj )
977{
978/* do not use RADEON_DB_STATE to avoid stale texture caches */
979   GLuint *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0];
980
981   R200_STATECHANGE( rmesa, tex[unit] );
982
983   cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
984   cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
985   cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
986   cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
987   cmd[TEX_PP_TXFORMAT_X] &= ~TEXOBJ_TXFORMAT_X_MASK;
988   cmd[TEX_PP_TXFORMAT_X] |= texobj->pp_txformat_x & TEXOBJ_TXFORMAT_X_MASK;
989   cmd[TEX_PP_TXSIZE] = texobj->pp_txsize; /* NPOT only! */
990   cmd[TEX_PP_TXPITCH] = texobj->pp_txpitch; /* NPOT only! */
991   cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
992
993   if (texobj->base.Target == GL_TEXTURE_CUBE_MAP) {
994      GLuint *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0];
995
996      R200_STATECHANGE( rmesa, cube[unit] );
997      cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
998      /* that value is submitted twice. could change cube atom
999         to not include that command when new drm is used */
1000      cmd[TEX_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
1001   }
1002
1003}
1004
1005static void set_texgen_matrix( r200ContextPtr rmesa,
1006			       GLuint unit,
1007			       const GLfloat *s_plane,
1008			       const GLfloat *t_plane,
1009			       const GLfloat *r_plane,
1010			       const GLfloat *q_plane )
1011{
1012   GLfloat m[16];
1013
1014   m[0]  = s_plane[0];
1015   m[4]  = s_plane[1];
1016   m[8]  = s_plane[2];
1017   m[12] = s_plane[3];
1018
1019   m[1]  = t_plane[0];
1020   m[5]  = t_plane[1];
1021   m[9]  = t_plane[2];
1022   m[13] = t_plane[3];
1023
1024   m[2]  = r_plane[0];
1025   m[6]  = r_plane[1];
1026   m[10] = r_plane[2];
1027   m[14] = r_plane[3];
1028
1029   m[3]  = q_plane[0];
1030   m[7]  = q_plane[1];
1031   m[11] = q_plane[2];
1032   m[15] = q_plane[3];
1033
1034   _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m);
1035   _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) );
1036   rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;
1037}
1038
1039
1040static GLuint r200_need_dis_texgen(const GLbitfield texGenEnabled,
1041				   const GLfloat *planeS,
1042				   const GLfloat *planeT,
1043				   const GLfloat *planeR,
1044				   const GLfloat *planeQ)
1045{
1046   GLuint needtgenable = 0;
1047
1048   if (!(texGenEnabled & S_BIT)) {
1049      if (((texGenEnabled & T_BIT) && planeT[0] != 0.0) ||
1050	 ((texGenEnabled & R_BIT) && planeR[0] != 0.0) ||
1051	 ((texGenEnabled & Q_BIT) && planeQ[0] != 0.0)) {
1052	 needtgenable |= S_BIT;
1053      }
1054   }
1055   if (!(texGenEnabled & T_BIT)) {
1056      if (((texGenEnabled & S_BIT) && planeS[1] != 0.0) ||
1057	 ((texGenEnabled & R_BIT) && planeR[1] != 0.0) ||
1058	 ((texGenEnabled & Q_BIT) && planeQ[1] != 0.0)) {
1059	 needtgenable |= T_BIT;
1060     }
1061   }
1062   if (!(texGenEnabled & R_BIT)) {
1063      if (((texGenEnabled & S_BIT) && planeS[2] != 0.0) ||
1064	 ((texGenEnabled & T_BIT) && planeT[2] != 0.0) ||
1065	 ((texGenEnabled & Q_BIT) && planeQ[2] != 0.0)) {
1066	 needtgenable |= R_BIT;
1067      }
1068   }
1069   if (!(texGenEnabled & Q_BIT)) {
1070      if (((texGenEnabled & S_BIT) && planeS[3] != 0.0) ||
1071	 ((texGenEnabled & T_BIT) && planeT[3] != 0.0) ||
1072	 ((texGenEnabled & R_BIT) && planeR[3] != 0.0)) {
1073	 needtgenable |= Q_BIT;
1074      }
1075   }
1076
1077   return needtgenable;
1078}
1079
1080
1081/*
1082 * Returns GL_FALSE if fallback required.
1083 */
1084static GLboolean r200_validate_texgen( struct gl_context *ctx, GLuint unit )
1085{
1086   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1087   const struct gl_fixedfunc_texture_unit *texUnit =
1088      &ctx->Texture.FixedFuncUnit[unit];
1089   GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4;
1090   GLuint tgi, tgcm;
1091   GLuint mode = 0;
1092   GLboolean mixed_fallback = GL_FALSE;
1093   static const GLfloat I[16] = {
1094      1,  0,  0,  0,
1095      0,  1,  0,  0,
1096      0,  0,  1,  0,
1097      0,  0,  0,  1 };
1098   static const GLfloat reflect[16] = {
1099      -1,  0,  0,  0,
1100       0, -1,  0,  0,
1101       0,  0,  -1, 0,
1102       0,  0,  0,  1 };
1103
1104   rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
1105   rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
1106   rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
1107   rmesa->TexGenNeedNormals[unit] = GL_FALSE;
1108   tgi = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] & ~(R200_TEXGEN_INPUT_MASK <<
1109						   inputshift);
1110   tgcm = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] & ~(R200_TEXGEN_COMP_MASK <<
1111						    (unit * 4));
1112
1113   if (0)
1114      fprintf(stderr, "%s unit %d\n", __func__, unit);
1115
1116   if (texUnit->TexGenEnabled & S_BIT) {
1117      mode = texUnit->GenS.Mode;
1118   } else {
1119      tgcm |= R200_TEXGEN_COMP_S << (unit * 4);
1120   }
1121
1122   if (texUnit->TexGenEnabled & T_BIT) {
1123      if (texUnit->GenT.Mode != mode)
1124	 mixed_fallback = GL_TRUE;
1125   } else {
1126      tgcm |= R200_TEXGEN_COMP_T << (unit * 4);
1127   }
1128   if (texUnit->TexGenEnabled & R_BIT) {
1129      if (texUnit->GenR.Mode != mode)
1130	 mixed_fallback = GL_TRUE;
1131   } else {
1132      tgcm |= R200_TEXGEN_COMP_R << (unit * 4);
1133   }
1134
1135   if (texUnit->TexGenEnabled & Q_BIT) {
1136      if (texUnit->GenQ.Mode != mode)
1137	 mixed_fallback = GL_TRUE;
1138   } else {
1139      tgcm |= R200_TEXGEN_COMP_Q << (unit * 4);
1140   }
1141
1142   if (mixed_fallback) {
1143      if (R200_DEBUG & RADEON_FALLBACKS)
1144	 fprintf(stderr, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
1145		 texUnit->TexGenEnabled, texUnit->GenS.Mode, texUnit->GenT.Mode,
1146		 texUnit->GenR.Mode, texUnit->GenQ.Mode);
1147      return GL_FALSE;
1148   }
1149
1150/* we CANNOT do mixed mode if the texgen mode requires a plane where the input
1151   is not enabled for texgen, since the planes are concatenated into texmat,
1152   and thus the input will come from texcoord rather than tex gen equation!
1153   Either fallback or just hope that those texcoords aren't really needed...
1154   Assuming the former will cause lots of unnecessary fallbacks, the latter will
1155   generate bogus results sometimes - it's pretty much impossible to really know
1156   when a fallback is needed, depends on texmat and what sort of texture is bound
1157   etc, - for now fallback if we're missing either S or T bits, there's a high
1158   probability we need the texcoords in that case.
1159   That's a lot of work for some obscure texgen mixed mode fixup - why oh why
1160   doesn't the chip just directly accept the plane parameters :-(. */
1161   switch (mode) {
1162   case GL_OBJECT_LINEAR: {
1163      GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled,
1164                                                  texUnit->ObjectPlane[GEN_S],
1165                                                  texUnit->ObjectPlane[GEN_T],
1166                                                  texUnit->ObjectPlane[GEN_R],
1167                                                  texUnit->ObjectPlane[GEN_Q] );
1168      if (needtgenable & (S_BIT | T_BIT)) {
1169	 if (R200_DEBUG & RADEON_FALLBACKS)
1170	 fprintf(stderr, "fallback mixed texgen / obj plane, 0x%x\n",
1171		 texUnit->TexGenEnabled);
1172	 return GL_FALSE;
1173      }
1174      if (needtgenable & (R_BIT)) {
1175	 tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4));
1176      }
1177      if (needtgenable & (Q_BIT)) {
1178	 tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4));
1179      }
1180
1181      tgi |= R200_TEXGEN_INPUT_OBJ << inputshift;
1182      set_texgen_matrix( rmesa, unit,
1183	 (texUnit->TexGenEnabled & S_BIT) ? texUnit->ObjectPlane[GEN_S] : I,
1184	 (texUnit->TexGenEnabled & T_BIT) ? texUnit->ObjectPlane[GEN_T] : I + 4,
1185	 (texUnit->TexGenEnabled & R_BIT) ? texUnit->ObjectPlane[GEN_R] : I + 8,
1186	 (texUnit->TexGenEnabled & Q_BIT) ? texUnit->ObjectPlane[GEN_Q] : I + 12);
1187      }
1188      break;
1189
1190   case GL_EYE_LINEAR: {
1191      GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled,
1192                                                  texUnit->EyePlane[GEN_S],
1193                                                  texUnit->EyePlane[GEN_T],
1194                                                  texUnit->EyePlane[GEN_R],
1195                                                  texUnit->EyePlane[GEN_Q] );
1196      if (needtgenable & (S_BIT | T_BIT)) {
1197	 if (R200_DEBUG & RADEON_FALLBACKS)
1198	 fprintf(stderr, "fallback mixed texgen / eye plane, 0x%x\n",
1199		 texUnit->TexGenEnabled);
1200	 return GL_FALSE;
1201      }
1202      if (needtgenable & (R_BIT)) {
1203	 tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4));
1204      }
1205      if (needtgenable & (Q_BIT)) {
1206	 tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4));
1207      }
1208      tgi |= R200_TEXGEN_INPUT_EYE << inputshift;
1209      set_texgen_matrix( rmesa, unit,
1210	 (texUnit->TexGenEnabled & S_BIT) ? texUnit->EyePlane[GEN_S] : I,
1211	 (texUnit->TexGenEnabled & T_BIT) ? texUnit->EyePlane[GEN_T] : I + 4,
1212	 (texUnit->TexGenEnabled & R_BIT) ? texUnit->EyePlane[GEN_R] : I + 8,
1213	 (texUnit->TexGenEnabled & Q_BIT) ? texUnit->EyePlane[GEN_Q] : I + 12);
1214      }
1215      break;
1216
1217   case GL_REFLECTION_MAP_NV:
1218      rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1219      tgi |= R200_TEXGEN_INPUT_EYE_REFLECT << inputshift;
1220      /* pretty weird, must only negate when lighting is enabled? */
1221      if (ctx->Light.Enabled)
1222	 set_texgen_matrix( rmesa, unit,
1223	    (texUnit->TexGenEnabled & S_BIT) ? reflect : I,
1224	    (texUnit->TexGenEnabled & T_BIT) ? reflect + 4 : I + 4,
1225	    (texUnit->TexGenEnabled & R_BIT) ? reflect + 8 : I + 8,
1226	    I + 12);
1227      break;
1228
1229   case GL_NORMAL_MAP_NV:
1230      rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1231      tgi |= R200_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
1232      break;
1233
1234   case GL_SPHERE_MAP:
1235      rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1236      tgi |= R200_TEXGEN_INPUT_SPHERE<<inputshift;
1237      break;
1238
1239   case 0:
1240      /* All texgen units were disabled, so just pass coords through. */
1241      tgi |= unit << inputshift;
1242      break;
1243
1244   default:
1245      /* Unsupported mode, fallback:
1246       */
1247      if (R200_DEBUG & RADEON_FALLBACKS)
1248	 fprintf(stderr, "fallback unsupported texgen, %d\n",
1249		 texUnit->GenS.Mode);
1250      return GL_FALSE;
1251   }
1252
1253   rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit;
1254   rmesa->TexGenCompSel |= R200_OUTPUT_TEX_0 << unit;
1255
1256   if (tgi != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] ||
1257       tgcm != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2])
1258   {
1259      R200_STATECHANGE(rmesa, tcg);
1260      rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = tgi;
1261      rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] = tgcm;
1262   }
1263
1264   return GL_TRUE;
1265}
1266
1267void set_re_cntl_d3d( struct gl_context *ctx, int unit, GLboolean use_d3d )
1268{
1269   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1270
1271   GLuint re_cntl;
1272
1273   re_cntl = rmesa->hw.set.cmd[SET_RE_CNTL] & ~(R200_VTX_STQ0_D3D << (2 * unit));
1274   if (use_d3d)
1275      re_cntl |= R200_VTX_STQ0_D3D << (2 * unit);
1276
1277   if ( re_cntl != rmesa->hw.set.cmd[SET_RE_CNTL] ) {
1278      R200_STATECHANGE( rmesa, set );
1279      rmesa->hw.set.cmd[SET_RE_CNTL] = re_cntl;
1280   }
1281}
1282
1283/**
1284 * Compute the cached hardware register values for the given texture object.
1285 *
1286 * \param rmesa Context pointer
1287 * \param t the r300 texture object
1288 */
1289static void setup_hardware_state(r200ContextPtr rmesa, radeonTexObj *t)
1290{
1291   const struct gl_texture_image *firstImage = t->base.Image[0][t->minLod];
1292   GLint log2Width, log2Height, log2Depth, texelBytes;
1293   uint extra_size = 0;
1294
1295   if ( t->bo ) {
1296       return;
1297   }
1298
1299   log2Width  = firstImage->WidthLog2;
1300   log2Height = firstImage->HeightLog2;
1301   log2Depth  = firstImage->DepthLog2;
1302   texelBytes = _mesa_get_format_bytes(firstImage->TexFormat);
1303
1304   radeon_print(RADEON_TEXTURE, RADEON_TRACE,
1305	"%s(%p, tex %p) log2(w %d, h %d, d %d), texelBytes %d. format %d\n",
1306	__func__, rmesa, t, log2Width, log2Height,
1307	log2Depth, texelBytes, firstImage->TexFormat);
1308
1309   if (!t->image_override) {
1310      if (VALID_FORMAT(firstImage->TexFormat)) {
1311#if UTIL_ARCH_LITTLE_ENDIAN
1312	 const struct tx_table *table = tx_table_le;
1313#else
1314	 const struct tx_table *table = tx_table_be;
1315#endif
1316
1317	 t->pp_txformat &= ~(R200_TXFORMAT_FORMAT_MASK |
1318			     R200_TXFORMAT_ALPHA_IN_MAP);
1319	 t->pp_txfilter &= ~R200_YUV_TO_RGB;
1320
1321	 t->pp_txformat |= table[ firstImage->TexFormat ].format;
1322	 t->pp_txfilter |= table[ firstImage->TexFormat ].filter;
1323
1324
1325      } else {
1326	 _mesa_problem(NULL, "unexpected texture format in %s",
1327		       __func__);
1328	 return;
1329      }
1330   }
1331
1332   t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK;
1333   t->pp_txfilter |= ((t->maxLod) << R200_MAX_MIP_LEVEL_SHIFT)
1334	   & R200_MAX_MIP_LEVEL_MASK;
1335
1336   if ( t->pp_txfilter &
1337		(R200_MIN_FILTER_NEAREST_MIP_NEAREST
1338		 | R200_MIN_FILTER_NEAREST_MIP_LINEAR
1339		 | R200_MIN_FILTER_LINEAR_MIP_NEAREST
1340		 | R200_MIN_FILTER_LINEAR_MIP_LINEAR
1341		 | R200_MIN_FILTER_ANISO_NEAREST_MIP_NEAREST
1342		 | R200_MIN_FILTER_ANISO_NEAREST_MIP_LINEAR))
1343		 extra_size = t->minLod;
1344
1345   t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
1346		       R200_TXFORMAT_HEIGHT_MASK |
1347		       R200_TXFORMAT_CUBIC_MAP_ENABLE |
1348		       R200_TXFORMAT_F5_WIDTH_MASK |
1349		       R200_TXFORMAT_F5_HEIGHT_MASK);
1350   t->pp_txformat |= (((log2Width + extra_size) << R200_TXFORMAT_WIDTH_SHIFT) |
1351		      ((log2Height + extra_size)<< R200_TXFORMAT_HEIGHT_SHIFT));
1352
1353   t->tile_bits = 0;
1354
1355   t->pp_txformat_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK
1356		   | R200_MIN_MIP_LEVEL_MASK);
1357
1358   t->pp_txformat_x |= (t->minLod << R200_MIN_MIP_LEVEL_SHIFT)
1359	   & R200_MIN_MIP_LEVEL_MASK;
1360
1361   if (t->base.Target == GL_TEXTURE_3D) {
1362      t->pp_txformat_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT);
1363      t->pp_txformat_x |= R200_TEXCOORD_VOLUME;
1364
1365   }
1366   else if (t->base.Target == GL_TEXTURE_CUBE_MAP) {
1367      assert(log2Width == log2Height);
1368      t->pp_txformat |= ((log2Width << R200_TXFORMAT_F5_WIDTH_SHIFT) |
1369			 (log2Height << R200_TXFORMAT_F5_HEIGHT_SHIFT) |
1370			 /* don't think we need this bit, if it exists at all - fglrx does not set it */
1371			 (R200_TXFORMAT_CUBIC_MAP_ENABLE));
1372      t->pp_txformat_x |= R200_TEXCOORD_CUBIC_ENV;
1373      t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) |
1374                           (log2Height << R200_FACE_HEIGHT_1_SHIFT) |
1375                           (log2Width << R200_FACE_WIDTH_2_SHIFT) |
1376                           (log2Height << R200_FACE_HEIGHT_2_SHIFT) |
1377                           (log2Width << R200_FACE_WIDTH_3_SHIFT) |
1378                           (log2Height << R200_FACE_HEIGHT_3_SHIFT) |
1379                           (log2Width << R200_FACE_WIDTH_4_SHIFT) |
1380                           (log2Height << R200_FACE_HEIGHT_4_SHIFT));
1381   }
1382   else {
1383      /* If we don't in fact send enough texture coordinates, q will be 1,
1384       * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
1385       */
1386      t->pp_txformat_x |= R200_TEXCOORD_PROJ;
1387   }
1388   /* FIXME: NPOT sizes, is it correct really? */
1389   t->pp_txsize = (((firstImage->Width - 1) << R200_PP_TX_WIDTHMASK_SHIFT)
1390		   | ((firstImage->Height - 1) << R200_PP_TX_HEIGHTMASK_SHIFT));
1391
1392   if ( !t->image_override ) {
1393      if (_mesa_is_format_compressed(firstImage->TexFormat))
1394         t->pp_txpitch = (firstImage->Width + 63) & ~(63);
1395      else
1396         t->pp_txpitch = ((firstImage->Width * texelBytes) + 63) & ~(63);
1397      t->pp_txpitch -= 32;
1398   }
1399
1400   if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) {
1401      t->pp_txformat |= R200_TXFORMAT_NON_POWER2;
1402   }
1403
1404}
1405
1406static GLboolean r200_validate_texture(struct gl_context *ctx, struct gl_texture_object *texObj, int unit)
1407{
1408   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1409   radeonTexObj *t = radeon_tex_obj(texObj);
1410
1411   if (!radeon_validate_texture_miptree(ctx, _mesa_get_samplerobj(ctx, unit), texObj))
1412      return GL_FALSE;
1413
1414   r200_validate_texgen(ctx, unit);
1415   /* Configure the hardware registers (more precisely, the cached version
1416    * of the hardware registers). */
1417   setup_hardware_state(rmesa, t);
1418
1419   if (texObj->Target == GL_TEXTURE_RECTANGLE_NV ||
1420       texObj->Target == GL_TEXTURE_2D ||
1421       texObj->Target == GL_TEXTURE_1D)
1422      set_re_cntl_d3d( ctx, unit, GL_FALSE );
1423   else
1424      set_re_cntl_d3d( ctx, unit, GL_TRUE );
1425   R200_STATECHANGE( rmesa, ctx );
1426   rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << unit;
1427
1428   R200_STATECHANGE( rmesa, vtx );
1429   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
1430   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3);
1431
1432   rmesa->recheck_texgen[unit] = GL_TRUE;
1433   r200TexUpdateParameters(ctx, unit);
1434   import_tex_obj_state( rmesa, unit, t );
1435
1436   if (rmesa->recheck_texgen[unit]) {
1437      GLboolean fallback = !r200_validate_texgen( ctx, unit );
1438      TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
1439      rmesa->recheck_texgen[unit] = 0;
1440      rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
1441   }
1442
1443   t->validated = GL_TRUE;
1444
1445   FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback );
1446
1447   return !t->border_fallback;
1448}
1449
1450static GLboolean r200UpdateTextureUnit(struct gl_context *ctx, int unit)
1451{
1452   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1453   GLuint unitneeded = rmesa->state.texture.unit[unit].unitneeded;
1454
1455   if (!unitneeded) {
1456      /* disable the unit */
1457     disable_tex_obj_state(rmesa, unit);
1458     return GL_TRUE;
1459   }
1460
1461   if (!r200_validate_texture(ctx, ctx->Texture.Unit[unit]._Current, unit)) {
1462    _mesa_warning(ctx,
1463		  "failed to validate texture for unit %d.\n",
1464		  unit);
1465    rmesa->state.texture.unit[unit].texobj = NULL;
1466    return GL_FALSE;
1467  }
1468
1469   rmesa->state.texture.unit[unit].texobj = radeon_tex_obj(ctx->Texture.Unit[unit]._Current);
1470  return GL_TRUE;
1471}
1472
1473
1474void r200UpdateTextureState( struct gl_context *ctx )
1475{
1476   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1477   GLboolean ok;
1478   GLuint dbg;
1479
1480   /* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or
1481      rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since
1482      we use these to determine if we want to emit the corresponding state
1483      atoms. */
1484   R200_NEWPRIM( rmesa );
1485
1486   if (_mesa_ati_fragment_shader_enabled(ctx)) {
1487      GLuint i;
1488      for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) {
1489         if (ctx->Texture.Unit[i]._Current)
1490            rmesa->state.texture.unit[i].unitneeded = 1 << _mesa_tex_target_to_index(ctx, ctx->Texture.Unit[i]._Current->Target);
1491         else
1492            rmesa->state.texture.unit[i].unitneeded = 0;
1493      }
1494      ok = GL_TRUE;
1495   }
1496   else {
1497      ok = r200UpdateAllTexEnv( ctx );
1498   }
1499   if (ok) {
1500      ok = (r200UpdateTextureUnit( ctx, 0 ) &&
1501	 r200UpdateTextureUnit( ctx, 1 ) &&
1502	 r200UpdateTextureUnit( ctx, 2 ) &&
1503	 r200UpdateTextureUnit( ctx, 3 ) &&
1504	 r200UpdateTextureUnit( ctx, 4 ) &&
1505	 r200UpdateTextureUnit( ctx, 5 ));
1506   }
1507
1508   if (ok && _mesa_ati_fragment_shader_enabled(ctx)) {
1509      r200UpdateFragmentShader(ctx);
1510   }
1511
1512   FALLBACK( rmesa, R200_FALLBACK_TEXTURE, !ok );
1513
1514   if (rmesa->radeon.TclFallback)
1515      r200ChooseVertexState( ctx );
1516
1517
1518   if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200) {
1519
1520      /*
1521       * T0 hang workaround -------------
1522       * not needed for r200 derivatives
1523        */
1524      if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_ENABLE_MASK) == R200_TEX_0_ENABLE &&
1525	 (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) {
1526
1527	 R200_STATECHANGE(rmesa, ctx);
1528	 R200_STATECHANGE(rmesa, tex[1]);
1529	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE;
1530	 if (!(rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_1_ENABLE))
1531	   rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1532	 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= R200_TXFORMAT_LOOKUP_DISABLE;
1533      }
1534      else if (!_mesa_ati_fragment_shader_enabled(ctx)) {
1535	 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) &&
1536	    (rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] & R200_TXFORMAT_LOOKUP_DISABLE)) {
1537	    R200_STATECHANGE(rmesa, tex[1]);
1538	    rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~R200_TXFORMAT_LOOKUP_DISABLE;
1539         }
1540      }
1541      /* do the same workaround for the first pass of a fragment shader.
1542       * completely unknown if necessary / sufficient.
1543       */
1544      if ((rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_ENABLE_MASK) == R200_PPX_TEX_0_ENABLE &&
1545	 (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) {
1546
1547	 R200_STATECHANGE(rmesa, cst);
1548	 R200_STATECHANGE(rmesa, tex[1]);
1549	 rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_1_ENABLE;
1550	 if (!(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE))
1551	    rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1552	 rmesa->hw.tex[1].cmd[TEX_PP_TXMULTI_CTL] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE;
1553      }
1554
1555      /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1556         looks like that's not the case, if 8500/9100 owners don't complain remove this...
1557      for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1558         if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1559            R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1560            ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1561            R200_MIN_FILTER_LINEAR)) {
1562            R200_STATECHANGE(rmesa, ctx);
1563            R200_STATECHANGE(rmesa, tex[i+1]);
1564            rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1565            rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1566            rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1567         }
1568         else {
1569            if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1570               (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1571               R200_STATECHANGE(rmesa, tex[i+1]);
1572               rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1573            }
1574         }
1575      } */
1576
1577      /*
1578       * Texture cache LRU hang workaround -------------
1579       * not needed for r200 derivatives
1580       * hopefully this covers first pass of a shader as well
1581       */
1582
1583      /* While the cases below attempt to only enable the workaround in the
1584       * specific cases necessary, they were insufficient.  See bugzilla #1519,
1585       * #729, #814.  Tests with quake3 showed no impact on performance.
1586       */
1587      dbg = 0x6;
1588
1589      /*
1590      if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1591         ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1592         0x04) == 0)) ||
1593         ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1594         ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1595         0x04) == 0)) ||
1596         ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1597         ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1598         0x04) == 0)))
1599      {
1600         dbg |= 0x02;
1601      }
1602
1603      if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1604         ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1605         0x04) == 0)) ||
1606         ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1607         ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1608         0x04) == 0)) ||
1609         ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1610         ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1611         0x04) == 0)))
1612      {
1613         dbg |= 0x04;
1614      }*/
1615
1616      if (dbg != rmesa->hw.tam.cmd[TAM_DEBUG3]) {
1617         R200_STATECHANGE( rmesa, tam );
1618         rmesa->hw.tam.cmd[TAM_DEBUG3] = dbg;
1619         if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg);
1620      }
1621   }
1622}
1623