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