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