r200_texstate.c revision 97aa3d553f73d955a5c3eced33384348158307a7
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   R200_STATECHANGE( rmesa, ctx );
1088   rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~(R200_TEX_0_ENABLE << unit);
1089   if (rmesa->radeon.TclFallback & (R200_TCL_FALLBACK_TEXGEN_0<<unit)) {
1090      TCL_FALLBACK( rmesa->radeon.glCtx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
1091   }
1092
1093   /* Actually want to keep all units less than max active texture
1094    * enabled, right?  Fix this for >2 texunits.
1095    */
1096
1097   {
1098      GLuint tmp = rmesa->TexGenEnabled;
1099
1100      rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
1101      rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
1102      rmesa->TexGenNeedNormals[unit] = GL_FALSE;
1103      rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
1104
1105      if (tmp != rmesa->TexGenEnabled) {
1106	 rmesa->recheck_texgen[unit] = GL_TRUE;
1107	 rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
1108      }
1109   }
1110}
1111static void import_tex_obj_state( r200ContextPtr rmesa,
1112				  int unit,
1113				  radeonTexObjPtr texobj )
1114{
1115/* do not use RADEON_DB_STATE to avoid stale texture caches */
1116   GLuint *cmd = &rmesa->hw.tex[unit].cmd[TEX_CMD_0];
1117
1118   R200_STATECHANGE( rmesa, tex[unit] );
1119
1120   cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
1121   cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
1122   cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1123   cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
1124   cmd[TEX_PP_TXFORMAT_X] &= ~TEXOBJ_TXFORMAT_X_MASK;
1125   cmd[TEX_PP_TXFORMAT_X] |= texobj->pp_txformat_x & TEXOBJ_TXFORMAT_X_MASK;
1126   cmd[TEX_PP_TXSIZE] = texobj->pp_txsize; /* NPOT only! */
1127   cmd[TEX_PP_TXPITCH] = texobj->pp_txpitch; /* NPOT only! */
1128   cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
1129
1130   if (texobj->base.Target == GL_TEXTURE_CUBE_MAP) {
1131      GLuint *cube_cmd = &rmesa->hw.cube[unit].cmd[CUBE_CMD_0];
1132
1133      R200_STATECHANGE( rmesa, cube[unit] );
1134      cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
1135      if (rmesa->radeon.radeonScreen->drmSupportsFragShader) {
1136	 /* that value is submitted twice. could change cube atom
1137	    to not include that command when new drm is used */
1138	 cmd[TEX_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
1139      }
1140   }
1141
1142}
1143
1144static void set_texgen_matrix( r200ContextPtr rmesa,
1145			       GLuint unit,
1146			       const GLfloat *s_plane,
1147			       const GLfloat *t_plane,
1148			       const GLfloat *r_plane,
1149			       const GLfloat *q_plane )
1150{
1151   GLfloat m[16];
1152
1153   m[0]  = s_plane[0];
1154   m[4]  = s_plane[1];
1155   m[8]  = s_plane[2];
1156   m[12] = s_plane[3];
1157
1158   m[1]  = t_plane[0];
1159   m[5]  = t_plane[1];
1160   m[9]  = t_plane[2];
1161   m[13] = t_plane[3];
1162
1163   m[2]  = r_plane[0];
1164   m[6]  = r_plane[1];
1165   m[10] = r_plane[2];
1166   m[14] = r_plane[3];
1167
1168   m[3]  = q_plane[0];
1169   m[7]  = q_plane[1];
1170   m[11] = q_plane[2];
1171   m[15] = q_plane[3];
1172
1173   _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m);
1174   _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) );
1175   rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;
1176}
1177
1178
1179static GLuint r200_need_dis_texgen(const GLbitfield texGenEnabled,
1180				   const GLfloat *planeS,
1181				   const GLfloat *planeT,
1182				   const GLfloat *planeR,
1183				   const GLfloat *planeQ)
1184{
1185   GLuint needtgenable = 0;
1186
1187   if (!(texGenEnabled & S_BIT)) {
1188      if (((texGenEnabled & T_BIT) && planeT[0] != 0.0) ||
1189	 ((texGenEnabled & R_BIT) && planeR[0] != 0.0) ||
1190	 ((texGenEnabled & Q_BIT) && planeQ[0] != 0.0)) {
1191	 needtgenable |= S_BIT;
1192      }
1193   }
1194   if (!(texGenEnabled & T_BIT)) {
1195      if (((texGenEnabled & S_BIT) && planeS[1] != 0.0) ||
1196	 ((texGenEnabled & R_BIT) && planeR[1] != 0.0) ||
1197	 ((texGenEnabled & Q_BIT) && planeQ[1] != 0.0)) {
1198	 needtgenable |= T_BIT;
1199     }
1200   }
1201   if (!(texGenEnabled & R_BIT)) {
1202      if (((texGenEnabled & S_BIT) && planeS[2] != 0.0) ||
1203	 ((texGenEnabled & T_BIT) && planeT[2] != 0.0) ||
1204	 ((texGenEnabled & Q_BIT) && planeQ[2] != 0.0)) {
1205	 needtgenable |= R_BIT;
1206      }
1207   }
1208   if (!(texGenEnabled & Q_BIT)) {
1209      if (((texGenEnabled & S_BIT) && planeS[3] != 0.0) ||
1210	 ((texGenEnabled & T_BIT) && planeT[3] != 0.0) ||
1211	 ((texGenEnabled & R_BIT) && planeR[3] != 0.0)) {
1212	 needtgenable |= Q_BIT;
1213      }
1214   }
1215
1216   return needtgenable;
1217}
1218
1219
1220/*
1221 * Returns GL_FALSE if fallback required.
1222 */
1223static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit )
1224{
1225   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1226   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1227   GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4;
1228   GLuint tgi, tgcm;
1229   GLuint mode = 0;
1230   GLboolean mixed_fallback = GL_FALSE;
1231   static const GLfloat I[16] = {
1232      1,  0,  0,  0,
1233      0,  1,  0,  0,
1234      0,  0,  1,  0,
1235      0,  0,  0,  1 };
1236   static const GLfloat reflect[16] = {
1237      -1,  0,  0,  0,
1238       0, -1,  0,  0,
1239       0,  0,  -1, 0,
1240       0,  0,  0,  1 };
1241
1242   rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
1243   rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
1244   rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
1245   rmesa->TexGenNeedNormals[unit] = GL_FALSE;
1246   tgi = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] & ~(R200_TEXGEN_INPUT_MASK <<
1247						   inputshift);
1248   tgcm = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] & ~(R200_TEXGEN_COMP_MASK <<
1249						    (unit * 4));
1250
1251   if (0)
1252      fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit);
1253
1254   if (texUnit->TexGenEnabled & S_BIT) {
1255      mode = texUnit->GenS.Mode;
1256   } else {
1257      tgcm |= R200_TEXGEN_COMP_S << (unit * 4);
1258   }
1259
1260   if (texUnit->TexGenEnabled & T_BIT) {
1261      if (texUnit->GenT.Mode != mode)
1262	 mixed_fallback = GL_TRUE;
1263   } else {
1264      tgcm |= R200_TEXGEN_COMP_T << (unit * 4);
1265   }
1266   if (texUnit->TexGenEnabled & R_BIT) {
1267      if (texUnit->GenR.Mode != mode)
1268	 mixed_fallback = GL_TRUE;
1269   } else {
1270      tgcm |= R200_TEXGEN_COMP_R << (unit * 4);
1271   }
1272
1273   if (texUnit->TexGenEnabled & Q_BIT) {
1274      if (texUnit->GenQ.Mode != mode)
1275	 mixed_fallback = GL_TRUE;
1276   } else {
1277      tgcm |= R200_TEXGEN_COMP_Q << (unit * 4);
1278   }
1279
1280   if (mixed_fallback) {
1281      if (R200_DEBUG & RADEON_FALLBACKS)
1282	 fprintf(stderr, "fallback mixed texgen, 0x%x (0x%x 0x%x 0x%x 0x%x)\n",
1283		 texUnit->TexGenEnabled, texUnit->GenS.Mode, texUnit->GenT.Mode,
1284		 texUnit->GenR.Mode, texUnit->GenQ.Mode);
1285      return GL_FALSE;
1286   }
1287
1288/* we CANNOT do mixed mode if the texgen mode requires a plane where the input
1289   is not enabled for texgen, since the planes are concatenated into texmat,
1290   and thus the input will come from texcoord rather than tex gen equation!
1291   Either fallback or just hope that those texcoords aren't really needed...
1292   Assuming the former will cause lots of unnecessary fallbacks, the latter will
1293   generate bogus results sometimes - it's pretty much impossible to really know
1294   when a fallback is needed, depends on texmat and what sort of texture is bound
1295   etc, - for now fallback if we're missing either S or T bits, there's a high
1296   probability we need the texcoords in that case.
1297   That's a lot of work for some obscure texgen mixed mode fixup - why oh why
1298   doesn't the chip just directly accept the plane parameters :-(. */
1299   switch (mode) {
1300   case GL_OBJECT_LINEAR: {
1301      GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled,
1302                                                  texUnit->GenS.ObjectPlane,
1303                                                  texUnit->GenT.ObjectPlane,
1304                                                  texUnit->GenR.ObjectPlane,
1305                                                  texUnit->GenQ.ObjectPlane );
1306      if (needtgenable & (S_BIT | T_BIT)) {
1307	 if (R200_DEBUG & RADEON_FALLBACKS)
1308	 fprintf(stderr, "fallback mixed texgen / obj plane, 0x%x\n",
1309		 texUnit->TexGenEnabled);
1310	 return GL_FALSE;
1311      }
1312      if (needtgenable & (R_BIT)) {
1313	 tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4));
1314      }
1315      if (needtgenable & (Q_BIT)) {
1316	 tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4));
1317      }
1318
1319      tgi |= R200_TEXGEN_INPUT_OBJ << inputshift;
1320      set_texgen_matrix( rmesa, unit,
1321	 (texUnit->TexGenEnabled & S_BIT) ? texUnit->GenS.ObjectPlane : I,
1322	 (texUnit->TexGenEnabled & T_BIT) ? texUnit->GenT.ObjectPlane : I + 4,
1323	 (texUnit->TexGenEnabled & R_BIT) ? texUnit->GenR.ObjectPlane : I + 8,
1324	 (texUnit->TexGenEnabled & Q_BIT) ? texUnit->GenQ.ObjectPlane : I + 12);
1325      }
1326      break;
1327
1328   case GL_EYE_LINEAR: {
1329      GLuint needtgenable = r200_need_dis_texgen( texUnit->TexGenEnabled,
1330                                                  texUnit->GenS.EyePlane,
1331                                                  texUnit->GenT.EyePlane,
1332                                                  texUnit->GenR.EyePlane,
1333                                                  texUnit->GenQ.EyePlane );
1334      if (needtgenable & (S_BIT | T_BIT)) {
1335	 if (R200_DEBUG & RADEON_FALLBACKS)
1336	 fprintf(stderr, "fallback mixed texgen / eye plane, 0x%x\n",
1337		 texUnit->TexGenEnabled);
1338	 return GL_FALSE;
1339      }
1340      if (needtgenable & (R_BIT)) {
1341	 tgcm &= ~(R200_TEXGEN_COMP_R << (unit * 4));
1342      }
1343      if (needtgenable & (Q_BIT)) {
1344	 tgcm &= ~(R200_TEXGEN_COMP_Q << (unit * 4));
1345      }
1346      tgi |= R200_TEXGEN_INPUT_EYE << inputshift;
1347      set_texgen_matrix( rmesa, unit,
1348	 (texUnit->TexGenEnabled & S_BIT) ? texUnit->GenS.EyePlane : I,
1349	 (texUnit->TexGenEnabled & T_BIT) ? texUnit->GenT.EyePlane : I + 4,
1350	 (texUnit->TexGenEnabled & R_BIT) ? texUnit->GenR.EyePlane : I + 8,
1351	 (texUnit->TexGenEnabled & Q_BIT) ? texUnit->GenQ.EyePlane : I + 12);
1352      }
1353      break;
1354
1355   case GL_REFLECTION_MAP_NV:
1356      rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1357      tgi |= R200_TEXGEN_INPUT_EYE_REFLECT << inputshift;
1358      /* pretty weird, must only negate when lighting is enabled? */
1359      if (ctx->Light.Enabled)
1360	 set_texgen_matrix( rmesa, unit,
1361	    (texUnit->TexGenEnabled & S_BIT) ? reflect : I,
1362	    (texUnit->TexGenEnabled & T_BIT) ? reflect + 4 : I + 4,
1363	    (texUnit->TexGenEnabled & R_BIT) ? reflect + 8 : I + 8,
1364	    I + 12);
1365      break;
1366
1367   case GL_NORMAL_MAP_NV:
1368      rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1369      tgi |= R200_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
1370      break;
1371
1372   case GL_SPHERE_MAP:
1373      rmesa->TexGenNeedNormals[unit] = GL_TRUE;
1374      tgi |= R200_TEXGEN_INPUT_SPHERE<<inputshift;
1375      break;
1376
1377   case 0:
1378      /* All texgen units were disabled, so just pass coords through. */
1379      tgi |= unit << inputshift;
1380      break;
1381
1382   default:
1383      /* Unsupported mode, fallback:
1384       */
1385      if (R200_DEBUG & RADEON_FALLBACKS)
1386	 fprintf(stderr, "fallback unsupported texgen, %d\n",
1387		 texUnit->GenS.Mode);
1388      return GL_FALSE;
1389   }
1390
1391   rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit;
1392   rmesa->TexGenCompSel |= R200_OUTPUT_TEX_0 << unit;
1393
1394   if (tgi != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] ||
1395       tgcm != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2])
1396   {
1397      R200_STATECHANGE(rmesa, tcg);
1398      rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_1] = tgi;
1399      rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_2] = tgcm;
1400   }
1401
1402   return GL_TRUE;
1403}
1404
1405void set_re_cntl_d3d( GLcontext *ctx, int unit, GLboolean use_d3d )
1406{
1407   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1408
1409   GLuint re_cntl;
1410
1411   re_cntl = rmesa->hw.set.cmd[SET_RE_CNTL] & ~(R200_VTX_STQ0_D3D << (2 * unit));
1412   if (use_d3d)
1413      re_cntl |= R200_VTX_STQ0_D3D << (2 * unit);
1414
1415   if ( re_cntl != rmesa->hw.set.cmd[SET_RE_CNTL] ) {
1416      R200_STATECHANGE( rmesa, set );
1417      rmesa->hw.set.cmd[SET_RE_CNTL] = re_cntl;
1418   }
1419}
1420
1421/**
1422 * Compute the cached hardware register values for the given texture object.
1423 *
1424 * \param rmesa Context pointer
1425 * \param t the r300 texture object
1426 */
1427static void setup_hardware_state(r200ContextPtr rmesa, radeonTexObj *t)
1428{
1429   int firstlevel = t->mt ? t->mt->firstLevel : 0;
1430   const struct gl_texture_image *firstImage = t->base.Image[0][firstlevel];
1431   GLint log2Width, log2Height, log2Depth, texelBytes;
1432
1433   if ( t->bo ) {
1434       return;
1435   }
1436
1437   log2Width  = firstImage->WidthLog2;
1438   log2Height = firstImage->HeightLog2;
1439   log2Depth  = firstImage->DepthLog2;
1440   texelBytes = firstImage->TexFormat->TexelBytes;
1441
1442
1443   if (!t->image_override) {
1444      if (VALID_FORMAT(firstImage->TexFormat->MesaFormat)) {
1445	 const struct tx_table *table = _mesa_little_endian() ? tx_table_le :
1446	    tx_table_be;
1447
1448	 t->pp_txformat &= ~(R200_TXFORMAT_FORMAT_MASK |
1449			     R200_TXFORMAT_ALPHA_IN_MAP);
1450	 t->pp_txfilter &= ~R200_YUV_TO_RGB;
1451
1452	 t->pp_txformat |= table[ firstImage->TexFormat->MesaFormat ].format;
1453	 t->pp_txfilter |= table[ firstImage->TexFormat->MesaFormat ].filter;
1454      } else {
1455	 _mesa_problem(NULL, "unexpected texture format in %s",
1456		       __FUNCTION__);
1457	 return;
1458      }
1459   }
1460
1461   t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK;
1462   t->pp_txfilter |= (t->mt->lastLevel - t->mt->firstLevel) << R200_MAX_MIP_LEVEL_SHIFT;
1463
1464   t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
1465		       R200_TXFORMAT_HEIGHT_MASK |
1466		       R200_TXFORMAT_CUBIC_MAP_ENABLE |
1467		       R200_TXFORMAT_F5_WIDTH_MASK |
1468		       R200_TXFORMAT_F5_HEIGHT_MASK);
1469   t->pp_txformat |= ((log2Width << R200_TXFORMAT_WIDTH_SHIFT) |
1470		      (log2Height << R200_TXFORMAT_HEIGHT_SHIFT));
1471
1472   t->tile_bits = 0;
1473
1474   t->pp_txformat_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK);
1475   if (t->base.Target == GL_TEXTURE_3D) {
1476      t->pp_txformat_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT);
1477      t->pp_txformat_x |= R200_TEXCOORD_VOLUME;
1478
1479   }
1480   else if (t->base.Target == GL_TEXTURE_CUBE_MAP) {
1481      ASSERT(log2Width == log2Height);
1482      t->pp_txformat |= ((log2Width << R200_TXFORMAT_F5_WIDTH_SHIFT) |
1483			 (log2Height << R200_TXFORMAT_F5_HEIGHT_SHIFT) |
1484			 /* don't think we need this bit, if it exists at all - fglrx does not set it */
1485			 (R200_TXFORMAT_CUBIC_MAP_ENABLE));
1486      t->pp_txformat_x |= R200_TEXCOORD_CUBIC_ENV;
1487      t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) |
1488                           (log2Height << R200_FACE_HEIGHT_1_SHIFT) |
1489                           (log2Width << R200_FACE_WIDTH_2_SHIFT) |
1490                           (log2Height << R200_FACE_HEIGHT_2_SHIFT) |
1491                           (log2Width << R200_FACE_WIDTH_3_SHIFT) |
1492                           (log2Height << R200_FACE_HEIGHT_3_SHIFT) |
1493                           (log2Width << R200_FACE_WIDTH_4_SHIFT) |
1494                           (log2Height << R200_FACE_HEIGHT_4_SHIFT));
1495   }
1496   else {
1497      /* If we don't in fact send enough texture coordinates, q will be 1,
1498       * making TEXCOORD_PROJ act like TEXCOORD_NONPROJ (Right?)
1499       */
1500      t->pp_txformat_x |= R200_TEXCOORD_PROJ;
1501   }
1502
1503   t->pp_txsize = (((firstImage->Width - 1) << R200_PP_TX_WIDTHMASK_SHIFT)
1504		   | ((firstImage->Height - 1) << R200_PP_TX_HEIGHTMASK_SHIFT));
1505
1506   if ( !t->image_override ) {
1507      if (firstImage->IsCompressed)
1508         t->pp_txpitch = (firstImage->Width + 63) & ~(63);
1509      else
1510         t->pp_txpitch = ((firstImage->Width * texelBytes) + 63) & ~(63);
1511      t->pp_txpitch -= 32;
1512   }
1513
1514   if (t->base.Target == GL_TEXTURE_RECTANGLE_NV) {
1515      t->pp_txformat |= R200_TXFORMAT_NON_POWER2;
1516   }
1517
1518}
1519
1520static GLboolean r200_validate_texture(GLcontext *ctx, struct gl_texture_object *texObj, int unit)
1521{
1522   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1523   radeonTexObj *t = radeon_tex_obj(texObj);
1524
1525   if (!radeon_validate_texture_miptree(ctx, texObj))
1526      return GL_FALSE;
1527
1528   r200_validate_texgen(ctx, unit);
1529   /* Configure the hardware registers (more precisely, the cached version
1530    * of the hardware registers). */
1531   setup_hardware_state(rmesa, t);
1532
1533   if (texObj->Target == GL_TEXTURE_RECTANGLE_NV ||
1534       texObj->Target == GL_TEXTURE_2D ||
1535       texObj->Target == GL_TEXTURE_1D)
1536      set_re_cntl_d3d( ctx, unit, GL_FALSE );
1537   else
1538      set_re_cntl_d3d( ctx, unit, GL_TRUE );
1539   R200_STATECHANGE( rmesa, ctx );
1540   rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_0_ENABLE << unit;
1541
1542   R200_STATECHANGE( rmesa, vtx );
1543   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
1544   rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3);
1545
1546   rmesa->recheck_texgen[unit] = GL_TRUE;
1547   import_tex_obj_state( rmesa, unit, t );
1548
1549   if (rmesa->recheck_texgen[unit]) {
1550      GLboolean fallback = !r200_validate_texgen( ctx, unit );
1551      TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
1552      rmesa->recheck_texgen[unit] = 0;
1553      rmesa->radeon.NewGLState |= _NEW_TEXTURE_MATRIX;
1554   }
1555
1556   t->validated = GL_TRUE;
1557
1558   FALLBACK( rmesa, RADEON_FALLBACK_BORDER_MODE, t->border_fallback );
1559
1560   return !t->border_fallback;
1561}
1562
1563static GLboolean r200UpdateTextureUnit(GLcontext *ctx, int unit)
1564{
1565   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1566   GLuint unitneeded = rmesa->state.texture.unit[unit].unitneeded;
1567
1568   if (!unitneeded) {
1569      /* disable the unit */
1570     disable_tex_obj_state(rmesa, unit);
1571     return GL_TRUE;
1572   }
1573
1574   if (!r200_validate_texture(ctx, ctx->Texture.Unit[unit]._Current, unit)) {
1575    _mesa_warning(ctx,
1576		  "failed to validate texture for unit %d.\n",
1577		  unit);
1578    rmesa->state.texture.unit[unit].texobj = NULL;
1579    return GL_FALSE;
1580  }
1581
1582   rmesa->state.texture.unit[unit].texobj = radeon_tex_obj(ctx->Texture.Unit[unit]._Current);
1583  return GL_TRUE;
1584}
1585
1586
1587void r200UpdateTextureState( GLcontext *ctx )
1588{
1589   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1590   GLboolean ok;
1591   GLuint dbg;
1592
1593   /* NOTE: must not manipulate rmesa->state.texture.unit[].unitneeded or
1594      rmesa->state.envneeded before a R200_STATECHANGE (or R200_NEWPRIM) since
1595      we use these to determine if we want to emit the corresponding state
1596      atoms. */
1597   R200_NEWPRIM( rmesa );
1598
1599   if (ctx->ATIFragmentShader._Enabled) {
1600      GLuint i;
1601      for (i = 0; i < R200_MAX_TEXTURE_UNITS; i++) {
1602	 rmesa->state.texture.unit[i].unitneeded = ctx->Texture.Unit[i]._ReallyEnabled;
1603      }
1604      ok = GL_TRUE;
1605   }
1606   else {
1607      ok = r200UpdateAllTexEnv( ctx );
1608   }
1609   if (ok) {
1610      ok = (r200UpdateTextureUnit( ctx, 0 ) &&
1611	 r200UpdateTextureUnit( ctx, 1 ) &&
1612	 r200UpdateTextureUnit( ctx, 2 ) &&
1613	 r200UpdateTextureUnit( ctx, 3 ) &&
1614	 r200UpdateTextureUnit( ctx, 4 ) &&
1615	 r200UpdateTextureUnit( ctx, 5 ));
1616   }
1617
1618   if (ok && ctx->ATIFragmentShader._Enabled) {
1619      r200UpdateFragmentShader(ctx);
1620   }
1621
1622   FALLBACK( rmesa, R200_FALLBACK_TEXTURE, !ok );
1623
1624   if (rmesa->radeon.TclFallback)
1625      r200ChooseVertexState( ctx );
1626
1627
1628   if (rmesa->radeon.radeonScreen->chip_family == CHIP_FAMILY_R200) {
1629
1630      /*
1631       * T0 hang workaround -------------
1632       * not needed for r200 derivatives
1633        */
1634      if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_ENABLE_MASK) == R200_TEX_0_ENABLE &&
1635	 (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) {
1636
1637	 R200_STATECHANGE(rmesa, ctx);
1638	 R200_STATECHANGE(rmesa, tex[1]);
1639	 rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE;
1640	 if (!(rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_1_ENABLE))
1641	   rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1642	 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= R200_TXFORMAT_LOOKUP_DISABLE;
1643      }
1644      else if (!ctx->ATIFragmentShader._Enabled) {
1645	 if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) &&
1646	    (rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] & R200_TXFORMAT_LOOKUP_DISABLE)) {
1647	    R200_STATECHANGE(rmesa, tex[1]);
1648	    rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~R200_TXFORMAT_LOOKUP_DISABLE;
1649         }
1650      }
1651      /* do the same workaround for the first pass of a fragment shader.
1652       * completely unknown if necessary / sufficient.
1653       */
1654      if ((rmesa->hw.cst.cmd[CST_PP_CNTL_X] & R200_PPX_TEX_ENABLE_MASK) == R200_PPX_TEX_0_ENABLE &&
1655	 (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) {
1656
1657	 R200_STATECHANGE(rmesa, cst);
1658	 R200_STATECHANGE(rmesa, tex[1]);
1659	 rmesa->hw.cst.cmd[CST_PP_CNTL_X] |= R200_PPX_TEX_1_ENABLE;
1660	 if (!(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE))
1661	    rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1662	 rmesa->hw.tex[1].cmd[TEX_PP_TXMULTI_CTL] |= R200_PASS1_TXFORMAT_LOOKUP_DISABLE;
1663      }
1664
1665      /* maybe needs to be done pairwise due to 2 parallel (physical) tex units ?
1666         looks like that's not the case, if 8500/9100 owners don't complain remove this...
1667      for ( i = 0; i < ctx->Const.MaxTextureUnits; i += 2) {
1668         if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & ((R200_TEX_0_ENABLE |
1669            R200_TEX_1_ENABLE ) << i)) == (R200_TEX_0_ENABLE << i)) &&
1670            ((rmesa->hw.tex[i].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) >
1671            R200_MIN_FILTER_LINEAR)) {
1672            R200_STATECHANGE(rmesa, ctx);
1673            R200_STATECHANGE(rmesa, tex[i+1]);
1674            rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_1_ENABLE << i);
1675            rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1676            rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1677         }
1678         else {
1679            if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE << i)) &&
1680               (rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1681               R200_STATECHANGE(rmesa, tex[i+1]);
1682               rmesa->hw.tex[i+1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1683            }
1684         }
1685      } */
1686
1687      /*
1688       * Texture cache LRU hang workaround -------------
1689       * not needed for r200 derivatives
1690       * hopefully this covers first pass of a shader as well
1691       */
1692
1693      /* While the cases below attempt to only enable the workaround in the
1694       * specific cases necessary, they were insufficient.  See bugzilla #1519,
1695       * #729, #814.  Tests with quake3 showed no impact on performance.
1696       */
1697      dbg = 0x6;
1698
1699      /*
1700      if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE )) &&
1701         ((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1702         0x04) == 0)) ||
1703         ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1704         ((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1705         0x04) == 0)) ||
1706         ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1707         ((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1708         0x04) == 0)))
1709      {
1710         dbg |= 0x02;
1711      }
1712
1713      if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_1_ENABLE )) &&
1714         ((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1715         0x04) == 0)) ||
1716         ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1717         ((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1718         0x04) == 0)) ||
1719         ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1720         ((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1721         0x04) == 0)))
1722      {
1723         dbg |= 0x04;
1724      }*/
1725
1726      if (dbg != rmesa->hw.tam.cmd[TAM_DEBUG3]) {
1727         R200_STATECHANGE( rmesa, tam );
1728         rmesa->hw.tam.cmd[TAM_DEBUG3] = dbg;
1729         if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg);
1730      }
1731   }
1732}
1733