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