r200_texstate.c revision 95a0bd6762737bb25bdf5c4147da9d1372f6aac3
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_AL88      R200_TXFORMAT_AI88
52#define R200_TXFORMAT_YCBCR     R200_TXFORMAT_YVYU422
53#define R200_TXFORMAT_YCBCR_REV R200_TXFORMAT_VYUY422
54
55#define _COLOR(f) \
56    [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, 0 }
57#define _ALPHA(f) \
58    [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f | R200_TXFORMAT_ALPHA_IN_MAP, 0 }
59#define _YUV(f) \
60    [ MESA_FORMAT_ ## f ] = { R200_TXFORMAT_ ## f, R200_YUV_TO_RGB }
61#define _INVALID(f) \
62    [ MESA_FORMAT_ ## f ] = { 0xffffffff, 0 }
63#define VALID_FORMAT(f) ( ((f) <= MESA_FORMAT_YCBCR_REV) \
64			     && (tx_table[f].format != 0xffffffff) )
65
66static const struct {
67   GLuint format, filter;
68}
69tx_table[] =
70{
71   _ALPHA(RGBA8888),
72   _ALPHA(ARGB8888),
73   _INVALID(RGB888),
74   _COLOR(RGB565),
75   _ALPHA(ARGB4444),
76   _ALPHA(ARGB1555),
77   _ALPHA(AL88),
78   _INVALID(A8),
79   _INVALID(L8),
80   _COLOR(I8),
81   _INVALID(CI8),
82   _YUV(YCBCR),
83   _YUV(YCBCR_REV),
84};
85
86#undef _COLOR
87#undef _ALPHA
88#undef _INVALID
89
90/**
91 * This function computes the number of bytes of storage needed for
92 * the given texture object (all mipmap levels, all cube faces).
93 * The \c image[face][level].x/y/width/height parameters for upload/blitting
94 * are computed here.  \c pp_txfilter, \c pp_txformat, etc. will be set here
95 * too.
96 *
97 * \param rmesa Context pointer
98 * \param tObj GL texture object whose images are to be posted to
99 *                 hardware state.
100 */
101static void r200SetTexImages( r200ContextPtr rmesa,
102			      struct gl_texture_object *tObj )
103{
104   r200TexObjPtr t = (r200TexObjPtr)tObj->DriverData;
105   const struct gl_texture_image *baseImage = tObj->Image[0][tObj->BaseLevel];
106   GLint curOffset;
107   GLint i;
108   GLint numLevels;
109   GLint log2Width, log2Height, log2Depth;
110
111   /* Set the hardware texture format
112    */
113
114   t->pp_txformat &= ~(R200_TXFORMAT_FORMAT_MASK |
115		       R200_TXFORMAT_ALPHA_IN_MAP);
116   t->pp_txfilter &= ~R200_YUV_TO_RGB;
117
118   if ( VALID_FORMAT( baseImage->TexFormat->MesaFormat ) ) {
119      t->pp_txformat |= tx_table[ baseImage->TexFormat->MesaFormat ].format;
120      t->pp_txfilter |= tx_table[ baseImage->TexFormat->MesaFormat ].filter;
121   }
122   else {
123      _mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
124      return;
125   }
126
127
128   /* Compute which mipmap levels we really want to send to the hardware.
129    */
130
131   driCalculateTextureFirstLastLevel( (driTextureObject *) t );
132   log2Width  = tObj->Image[0][t->base.firstLevel]->WidthLog2;
133   log2Height = tObj->Image[0][t->base.firstLevel]->HeightLog2;
134   log2Depth  = tObj->Image[0][t->base.firstLevel]->DepthLog2;
135
136   numLevels = t->base.lastLevel - t->base.firstLevel + 1;
137
138   assert(numLevels <= RADEON_MAX_TEXTURE_LEVELS);
139
140   /* Calculate mipmap offsets and dimensions for blitting (uploading)
141    * The idea is that we lay out the mipmap levels within a block of
142    * memory organized as a rectangle of width BLIT_WIDTH_BYTES.
143    */
144   curOffset = 0;
145
146   for (i = 0; i < numLevels; i++) {
147      const struct gl_texture_image *texImage;
148      GLuint size;
149
150      texImage = tObj->Image[0][i + t->base.firstLevel];
151      if ( !texImage )
152	 break;
153
154      /* find image size in bytes */
155      if (texImage->IsCompressed) {
156         size = texImage->CompressedSize;
157      }
158      else if (tObj->Target == GL_TEXTURE_RECTANGLE_NV) {
159         size = ((texImage->Width * texImage->TexFormat->TexelBytes + 63)
160                 & ~63) * texImage->Height;
161      }
162      else {
163         int w = texImage->Width * texImage->TexFormat->TexelBytes;
164         if (w < 32)
165            w = 32;
166         size = w * texImage->Height * texImage->Depth;
167      }
168      assert(size > 0);
169
170
171      /* Align to 32-byte offset.  It is faster to do this unconditionally
172       * (no branch penalty).
173       */
174
175      curOffset = (curOffset + 0x1f) & ~0x1f;
176
177      t->image[0][i].x = curOffset % BLIT_WIDTH_BYTES;
178      t->image[0][i].y = curOffset / BLIT_WIDTH_BYTES;
179      t->image[0][i].width  = MIN2(size, BLIT_WIDTH_BYTES);
180      t->image[0][i].height = size / t->image[0][i].width;
181
182#if 0
183      /* for debugging only and only  applicable to non-rectangle targets */
184      assert(size % t->image[0][i].width == 0);
185      assert(t->image[0][i].x == 0
186             || (size < BLIT_WIDTH_BYTES && t->image[0][i].height == 1));
187#endif
188
189      if (0)
190         fprintf(stderr,
191                 "level %d: %dx%d x=%d y=%d w=%d h=%d size=%d at %d\n",
192                 i, texImage->Width, texImage->Height,
193                 t->image[0][i].x, t->image[0][i].y,
194                 t->image[0][i].width, t->image[0][i].height, size, curOffset);
195
196      curOffset += size;
197
198   }
199
200   /* Align the total size of texture memory block.
201    */
202   t->base.totalSize = (curOffset + RADEON_OFFSET_MASK) & ~RADEON_OFFSET_MASK;
203
204   /* Setup remaining cube face blits, if needed */
205   if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
206      /* Round totalSize up to multiple of BLIT_WIDTH_BYTES */
207      const GLuint faceSize = (t->base.totalSize + BLIT_WIDTH_BYTES - 1)
208                              & ~(BLIT_WIDTH_BYTES-1);
209      const GLuint lines = faceSize / BLIT_WIDTH_BYTES;
210      GLuint face;
211      /* reuse face 0 x/y/width/height - just adjust y */
212      for (face = 1; face < 6; face++) {
213         for (i = 0; i < numLevels; i++) {
214            t->image[face][i].x =  t->image[0][i].x;
215            t->image[face][i].y =  t->image[0][i].y + face * lines;
216            t->image[face][i].width  = t->image[0][i].width;
217            t->image[face][i].height = t->image[0][i].height;
218         }
219      }
220      t->base.totalSize = 6 * faceSize; /* total texmem needed */
221   }
222
223
224   /* Hardware state:
225    */
226   t->pp_txfilter &= ~R200_MAX_MIP_LEVEL_MASK;
227   t->pp_txfilter |= (numLevels - 1) << R200_MAX_MIP_LEVEL_SHIFT;
228
229   t->pp_txformat &= ~(R200_TXFORMAT_WIDTH_MASK |
230		       R200_TXFORMAT_HEIGHT_MASK |
231                       R200_TXFORMAT_CUBIC_MAP_ENABLE |
232                       R200_TXFORMAT_F5_WIDTH_MASK |
233                       R200_TXFORMAT_F5_HEIGHT_MASK);
234   t->pp_txformat |= ((log2Width << R200_TXFORMAT_WIDTH_SHIFT) |
235		      (log2Height << R200_TXFORMAT_HEIGHT_SHIFT));
236
237   t->pp_txformat_x &= ~(R200_DEPTH_LOG2_MASK | R200_TEXCOORD_MASK);
238   if (tObj->Target == GL_TEXTURE_3D) {
239      t->pp_txformat_x |= (log2Depth << R200_DEPTH_LOG2_SHIFT);
240      t->pp_txformat_x |= R200_TEXCOORD_VOLUME;
241   }
242   else if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
243      ASSERT(log2Width == log2height);
244      t->pp_txformat |= ((log2Width << R200_TXFORMAT_F5_WIDTH_SHIFT) |
245                         (log2Height << R200_TXFORMAT_F5_HEIGHT_SHIFT) |
246                         (R200_TXFORMAT_CUBIC_MAP_ENABLE));
247      t->pp_txformat_x |= R200_TEXCOORD_CUBIC_ENV;
248      t->pp_cubic_faces = ((log2Width << R200_FACE_WIDTH_1_SHIFT) |
249                           (log2Height << R200_FACE_HEIGHT_1_SHIFT) |
250                           (log2Width << R200_FACE_WIDTH_2_SHIFT) |
251                           (log2Height << R200_FACE_HEIGHT_2_SHIFT) |
252                           (log2Width << R200_FACE_WIDTH_3_SHIFT) |
253                           (log2Height << R200_FACE_HEIGHT_3_SHIFT) |
254                           (log2Width << R200_FACE_WIDTH_4_SHIFT) |
255                           (log2Height << R200_FACE_HEIGHT_4_SHIFT));
256   }
257
258   t->pp_txsize = (((tObj->Image[0][t->base.firstLevel]->Width - 1) << 0) |
259                   ((tObj->Image[0][t->base.firstLevel]->Height - 1) << 16));
260
261   /* Only need to round to nearest 32 for textures, but the blitter
262    * requires 64-byte aligned pitches, and we may/may not need the
263    * blitter.   NPOT only!
264    */
265   if (baseImage->IsCompressed)
266      t->pp_txpitch = (tObj->Image[0][t->base.firstLevel]->Width + 63) & ~(63);
267   else
268      t->pp_txpitch = ((tObj->Image[0][t->base.firstLevel]->Width * baseImage->TexFormat->TexelBytes) + 63) & ~(63);
269   t->pp_txpitch -= 32;
270
271   t->dirty_state = TEX_ALL;
272
273   /* FYI: r200UploadTexImages( rmesa, t ) used to be called here */
274}
275
276
277
278/* ================================================================
279 * Texture combine functions
280 */
281
282/* GL_ARB_texture_env_combine support
283 */
284
285/* The color tables have combine functions for GL_SRC_COLOR,
286 * GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
287 */
288static GLuint r200_register_color[][R200_MAX_TEXTURE_UNITS] =
289{
290   {
291      R200_TXC_ARG_A_R0_COLOR,
292      R200_TXC_ARG_A_R1_COLOR,
293      R200_TXC_ARG_A_R2_COLOR
294   },
295   {
296      R200_TXC_ARG_A_R0_COLOR | R200_TXC_COMP_ARG_A,
297      R200_TXC_ARG_A_R1_COLOR | R200_TXC_COMP_ARG_A,
298      R200_TXC_ARG_A_R2_COLOR | R200_TXC_COMP_ARG_A
299   },
300   {
301      R200_TXC_ARG_A_R0_ALPHA,
302      R200_TXC_ARG_A_R1_ALPHA,
303      R200_TXC_ARG_A_R2_ALPHA
304   },
305   {
306      R200_TXC_ARG_A_R0_ALPHA | R200_TXC_COMP_ARG_A,
307      R200_TXC_ARG_A_R1_ALPHA | R200_TXC_COMP_ARG_A,
308      R200_TXC_ARG_A_R2_ALPHA | R200_TXC_COMP_ARG_A
309   },
310};
311
312static GLuint r200_tfactor_color[] =
313{
314   R200_TXC_ARG_A_TFACTOR_COLOR,
315   R200_TXC_ARG_A_TFACTOR_COLOR | R200_TXC_COMP_ARG_A,
316   R200_TXC_ARG_A_TFACTOR_ALPHA,
317   R200_TXC_ARG_A_TFACTOR_ALPHA | R200_TXC_COMP_ARG_A
318};
319
320static GLuint r200_primary_color[] =
321{
322   R200_TXC_ARG_A_DIFFUSE_COLOR,
323   R200_TXC_ARG_A_DIFFUSE_COLOR | R200_TXC_COMP_ARG_A,
324   R200_TXC_ARG_A_DIFFUSE_ALPHA,
325   R200_TXC_ARG_A_DIFFUSE_ALPHA | R200_TXC_COMP_ARG_A
326};
327
328/* GL_ZERO table - indices 0-3
329 * GL_ONE  table - indices 1-4
330 */
331static GLuint r200_zero_color[] =
332{
333   R200_TXC_ARG_A_ZERO,
334   R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
335   R200_TXC_ARG_A_ZERO,
336   R200_TXC_ARG_A_ZERO | R200_TXC_COMP_ARG_A,
337   R200_TXC_ARG_A_ZERO
338};
339
340/* The alpha tables only have GL_SRC_ALPHA and GL_ONE_MINUS_SRC_ALPHA.
341 */
342static GLuint r200_register_alpha[][R200_MAX_TEXTURE_UNITS] =
343{
344   {
345      R200_TXA_ARG_A_R0_ALPHA,
346      R200_TXA_ARG_A_R1_ALPHA,
347      R200_TXA_ARG_A_R2_ALPHA
348   },
349   {
350      R200_TXA_ARG_A_R0_ALPHA | R200_TXA_COMP_ARG_A,
351      R200_TXA_ARG_A_R1_ALPHA | R200_TXA_COMP_ARG_A,
352      R200_TXA_ARG_A_R2_ALPHA | R200_TXA_COMP_ARG_A
353   },
354};
355
356static GLuint r200_tfactor_alpha[] =
357{
358   R200_TXA_ARG_A_TFACTOR_ALPHA,
359   R200_TXA_ARG_A_TFACTOR_ALPHA | R200_TXA_COMP_ARG_A
360};
361
362static GLuint r200_primary_alpha[] =
363{
364   R200_TXA_ARG_A_DIFFUSE_ALPHA,
365   R200_TXA_ARG_A_DIFFUSE_ALPHA | R200_TXA_COMP_ARG_A
366};
367
368/* GL_ZERO table - indices 0-1
369 * GL_ONE  table - indices 1-2
370 */
371static GLuint r200_zero_alpha[] =
372{
373   R200_TXA_ARG_A_ZERO,
374   R200_TXA_ARG_A_ZERO | R200_TXA_COMP_ARG_A,
375   R200_TXA_ARG_A_ZERO,
376};
377
378
379/* Extract the arg from slot A, shift it into the correct argument slot
380 * and set the corresponding complement bit.
381 */
382#define R200_COLOR_ARG( n, arg )			\
383do {							\
384   color_combine |=					\
385      ((color_arg[n] & R200_TXC_ARG_A_MASK)		\
386       << R200_TXC_ARG_##arg##_SHIFT);			\
387   color_combine |=					\
388      ((color_arg[n] >> R200_TXC_COMP_ARG_A_SHIFT)	\
389       << R200_TXC_COMP_ARG_##arg##_SHIFT);		\
390} while (0)
391
392#define R200_ALPHA_ARG( n, arg )			\
393do {							\
394   alpha_combine |=					\
395      ((alpha_arg[n] & R200_TXA_ARG_A_MASK)		\
396       << R200_TXA_ARG_##arg##_SHIFT);			\
397   alpha_combine |=					\
398      ((alpha_arg[n] >> R200_TXA_COMP_ARG_A_SHIFT)	\
399       << R200_TXA_COMP_ARG_##arg##_SHIFT);		\
400} while (0)
401
402
403/* ================================================================
404 * Texture unit state management
405 */
406
407static GLboolean r200UpdateTextureEnv( GLcontext *ctx, int unit )
408{
409   r200ContextPtr rmesa = R200_CONTEXT(ctx);
410   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
411   GLuint color_combine, alpha_combine;
412   GLuint color_scale = rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2];
413   GLuint alpha_scale = rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2];
414
415   /* texUnit->_Current can be NULL if and only if the texture unit is
416    * not actually enabled.
417    */
418   assert( (texUnit->_ReallyEnabled == 0)
419	   || (texUnit->_Current != NULL) );
420
421   if ( R200_DEBUG & DEBUG_TEXTURE ) {
422      fprintf( stderr, "%s( %p, %d )\n", __FUNCTION__, (void *)ctx, unit );
423   }
424
425   /* Set the texture environment state.  Isn't this nice and clean?
426    * The chip will automagically set the texture alpha to 0xff when
427    * the texture format does not include an alpha component.  This
428    * reduces the amount of special-casing we have to do, alpha-only
429    * textures being a notable exception.
430    */
431   if ( !texUnit->_ReallyEnabled ) {
432      /* Don't cache these results.
433       */
434      rmesa->state.texture.unit[unit].format = 0;
435      rmesa->state.texture.unit[unit].envMode = 0;
436      if ( unit == 0 ) {
437	 color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO
438	     | R200_TXC_ARG_C_DIFFUSE_COLOR | R200_TXC_OP_MADD;
439	 alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO
440	     | R200_TXA_ARG_C_DIFFUSE_ALPHA | R200_TXA_OP_MADD;
441      }
442      else {
443	 color_combine = R200_TXC_ARG_A_ZERO | R200_TXC_ARG_B_ZERO
444	     | R200_TXC_ARG_C_R0_COLOR | R200_TXC_OP_MADD;
445	 alpha_combine = R200_TXA_ARG_A_ZERO | R200_TXA_ARG_B_ZERO
446	     | R200_TXA_ARG_C_R0_ALPHA | R200_TXA_OP_MADD;
447      }
448   }
449   else {
450      GLuint color_arg[3], alpha_arg[3];
451      GLuint i;
452      const GLuint numColorArgs = texUnit->_CurrentCombine->_NumArgsRGB;
453      const GLuint numAlphaArgs = texUnit->_CurrentCombine->_NumArgsA;
454      GLuint RGBshift = texUnit->_CurrentCombine->ScaleShiftRGB;
455      GLuint Ashift = texUnit->_CurrentCombine->ScaleShiftA;
456
457      /* Don't cache these results.
458       */
459      rmesa->state.texture.unit[unit].format = 0;
460      rmesa->state.texture.unit[unit].envMode = 0;
461
462
463      /* Step 1:
464       * Extract the color and alpha combine function arguments.
465       */
466      for ( i = 0 ; i < numColorArgs ; i++ ) {
467	 const GLuint op = texUnit->_CurrentCombine->OperandRGB[i] - GL_SRC_COLOR;
468	 assert(op >= 0);
469	 assert(op <= 3);
470	 switch ( texUnit->_CurrentCombine->SourceRGB[i] ) {
471	 case GL_TEXTURE:
472	    color_arg[i] = r200_register_color[op][unit];
473	    break;
474	 case GL_CONSTANT:
475	    color_arg[i] = r200_tfactor_color[op];
476	    break;
477	 case GL_PRIMARY_COLOR:
478	    color_arg[i] = r200_primary_color[op];
479	    break;
480	 case GL_PREVIOUS:
481	    if (unit == 0)
482		color_arg[i] = r200_primary_color[op];
483	    else
484		color_arg[i] = r200_register_color[op][0];
485	    break;
486	 case GL_ZERO:
487	    color_arg[i] = r200_zero_color[op];
488	    break;
489	 case GL_ONE:
490	    color_arg[i] = r200_zero_color[op+1];
491	    break;
492	 default:
493	    return GL_FALSE;
494	 }
495      }
496
497      for ( i = 0 ; i < numAlphaArgs ; i++ ) {
498	 const GLuint op = texUnit->_CurrentCombine->OperandA[i] - GL_SRC_ALPHA;
499	 assert(op >= 0);
500	 assert(op <= 1);
501	 switch ( texUnit->_CurrentCombine->SourceA[i] ) {
502	 case GL_TEXTURE:
503	    alpha_arg[i] = r200_register_alpha[op][unit];
504	    break;
505	 case GL_CONSTANT:
506	    alpha_arg[i] = r200_tfactor_alpha[op];
507	    break;
508	 case GL_PRIMARY_COLOR:
509	    alpha_arg[i] = r200_primary_alpha[op];
510	    break;
511	 case GL_PREVIOUS:
512	    if (unit == 0)
513		alpha_arg[i] = r200_primary_alpha[op];
514	    else
515		alpha_arg[i] = r200_register_alpha[op][0];
516	    break;
517	 case GL_ZERO:
518	    alpha_arg[i] = r200_zero_alpha[op];
519	    break;
520	 case GL_ONE:
521	    alpha_arg[i] = r200_zero_alpha[op+1];
522	    break;
523	 default:
524	    return GL_FALSE;
525	 }
526      }
527
528      /* Step 2:
529       * Build up the color and alpha combine functions.
530       */
531      switch ( texUnit->_CurrentCombine->ModeRGB ) {
532      case GL_REPLACE:
533	 color_combine = (R200_TXC_ARG_A_ZERO |
534			  R200_TXC_ARG_B_ZERO |
535			  R200_TXC_OP_MADD);
536	 R200_COLOR_ARG( 0, C );
537	 break;
538      case GL_MODULATE:
539	 color_combine = (R200_TXC_ARG_C_ZERO |
540			  R200_TXC_OP_MADD);
541	 R200_COLOR_ARG( 0, A );
542	 R200_COLOR_ARG( 1, B );
543	 break;
544      case GL_ADD:
545	 color_combine = (R200_TXC_ARG_B_ZERO |
546			  R200_TXC_COMP_ARG_B |
547			  R200_TXC_OP_MADD);
548	 R200_COLOR_ARG( 0, A );
549	 R200_COLOR_ARG( 1, C );
550	 break;
551      case GL_ADD_SIGNED:
552	 color_combine = (R200_TXC_ARG_B_ZERO |
553			  R200_TXC_COMP_ARG_B |
554			  R200_TXC_BIAS_ARG_C |	/* new */
555			  R200_TXC_OP_MADD); /* was ADDSIGNED */
556	 R200_COLOR_ARG( 0, A );
557	 R200_COLOR_ARG( 1, C );
558	 break;
559      case GL_SUBTRACT:
560	 color_combine = (R200_TXC_ARG_B_ZERO |
561			  R200_TXC_COMP_ARG_B |
562			  R200_TXC_NEG_ARG_C |
563			  R200_TXC_OP_MADD);
564	 R200_COLOR_ARG( 0, A );
565	 R200_COLOR_ARG( 1, C );
566	 break;
567      case GL_INTERPOLATE:
568	 color_combine = (R200_TXC_OP_LERP);
569	 R200_COLOR_ARG( 0, B );
570	 R200_COLOR_ARG( 1, A );
571	 R200_COLOR_ARG( 2, C );
572	 break;
573
574      case GL_DOT3_RGB_EXT:
575      case GL_DOT3_RGBA_EXT:
576	 /* The EXT version of the DOT3 extension does not support the
577	  * scale factor, but the ARB version (and the version in OpenGL
578	  * 1.3) does.
579	  */
580	 RGBshift = 0;
581	 Ashift = 0;
582	 /* FALLTHROUGH */
583
584      case GL_DOT3_RGB:
585      case GL_DOT3_RGBA:
586	 /* DOT3 works differently on R200 than on R100.  On R100, just
587	  * setting the DOT3 mode did everything for you.  On R200, the
588	  * driver has to enable the biasing and scale in the inputs to
589	  * put them in the proper [-1,1] range.  This is what the 4x and
590	  * the -0.5 in the DOT3 spec do.  The post-scale is then set
591	  * normally.
592	  */
593
594	 RGBshift++;
595	 Ashift = RGBshift;
596
597	 color_combine = (R200_TXC_ARG_C_ZERO |
598			  R200_TXC_OP_DOT3 |
599			  R200_TXC_BIAS_ARG_A |
600			  R200_TXC_BIAS_ARG_B |
601			  R200_TXC_SCALE_ARG_A |
602			  R200_TXC_SCALE_ARG_B);
603	 R200_COLOR_ARG( 0, A );
604	 R200_COLOR_ARG( 1, B );
605	 break;
606
607      case GL_MODULATE_ADD_ATI:
608	 color_combine = (R200_TXC_OP_MADD);
609	 R200_COLOR_ARG( 0, A );
610	 R200_COLOR_ARG( 1, C );
611	 R200_COLOR_ARG( 2, B );
612	 break;
613      case GL_MODULATE_SIGNED_ADD_ATI:
614	 color_combine = (R200_TXC_BIAS_ARG_C |	/* new */
615			  R200_TXC_OP_MADD); /* was ADDSIGNED */
616	 R200_COLOR_ARG( 0, A );
617	 R200_COLOR_ARG( 1, C );
618	 R200_COLOR_ARG( 2, B );
619	 break;
620      case GL_MODULATE_SUBTRACT_ATI:
621	 color_combine = (R200_TXC_NEG_ARG_C |
622			  R200_TXC_OP_MADD);
623	 R200_COLOR_ARG( 0, A );
624	 R200_COLOR_ARG( 1, C );
625	 R200_COLOR_ARG( 2, B );
626	 break;
627      default:
628	 return GL_FALSE;
629      }
630
631      switch ( texUnit->_CurrentCombine->ModeA ) {
632      case GL_REPLACE:
633	 alpha_combine = (R200_TXA_ARG_A_ZERO |
634			  R200_TXA_ARG_B_ZERO |
635			  R200_TXA_OP_MADD);
636	 R200_ALPHA_ARG( 0, C );
637	 break;
638      case GL_MODULATE:
639	 alpha_combine = (R200_TXA_ARG_C_ZERO |
640			  R200_TXA_OP_MADD);
641	 R200_ALPHA_ARG( 0, A );
642	 R200_ALPHA_ARG( 1, B );
643	 break;
644      case GL_ADD:
645	 alpha_combine = (R200_TXA_ARG_B_ZERO |
646			  R200_TXA_COMP_ARG_B |
647			  R200_TXA_OP_MADD);
648	 R200_ALPHA_ARG( 0, A );
649	 R200_ALPHA_ARG( 1, C );
650	 break;
651      case GL_ADD_SIGNED:
652	 alpha_combine = (R200_TXA_ARG_B_ZERO |
653			  R200_TXA_COMP_ARG_B |
654			  R200_TXA_BIAS_ARG_C |	/* new */
655			  R200_TXA_OP_MADD); /* was ADDSIGNED */
656	 R200_ALPHA_ARG( 0, A );
657	 R200_ALPHA_ARG( 1, C );
658	 break;
659      case GL_SUBTRACT:
660	 alpha_combine = (R200_TXA_ARG_B_ZERO |
661			  R200_TXA_COMP_ARG_B |
662			  R200_TXA_NEG_ARG_C |
663			  R200_TXA_OP_MADD);
664	 R200_ALPHA_ARG( 0, A );
665	 R200_ALPHA_ARG( 1, C );
666	 break;
667      case GL_INTERPOLATE:
668	 alpha_combine = (R200_TXA_OP_LERP);
669	 R200_ALPHA_ARG( 0, B );
670	 R200_ALPHA_ARG( 1, A );
671	 R200_ALPHA_ARG( 2, C );
672	 break;
673
674      case GL_MODULATE_ADD_ATI:
675	 alpha_combine = (R200_TXA_OP_MADD);
676	 R200_ALPHA_ARG( 0, A );
677	 R200_ALPHA_ARG( 1, C );
678	 R200_ALPHA_ARG( 2, B );
679	 break;
680      case GL_MODULATE_SIGNED_ADD_ATI:
681	 alpha_combine = (R200_TXA_BIAS_ARG_C |	/* new */
682			  R200_TXA_OP_MADD); /* was ADDSIGNED */
683	 R200_ALPHA_ARG( 0, A );
684	 R200_ALPHA_ARG( 1, C );
685	 R200_ALPHA_ARG( 2, B );
686	 break;
687      case GL_MODULATE_SUBTRACT_ATI:
688	 alpha_combine = (R200_TXA_NEG_ARG_C |
689			  R200_TXA_OP_MADD);
690	 R200_ALPHA_ARG( 0, A );
691	 R200_ALPHA_ARG( 1, C );
692	 R200_ALPHA_ARG( 2, B );
693	 break;
694      default:
695	 return GL_FALSE;
696      }
697
698      if ( (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGB_EXT)
699	   || (texUnit->_CurrentCombine->ModeRGB == GL_DOT3_RGB) ) {
700	 alpha_scale |= R200_TXA_DOT_ALPHA;
701      }
702
703      /* Step 3:
704       * Apply the scale factor.
705       */
706      color_scale &= ~R200_TXC_SCALE_MASK;
707      alpha_scale &= ~R200_TXA_SCALE_MASK;
708      color_scale |= (RGBshift << R200_TXC_SCALE_SHIFT);
709      alpha_scale |= (Ashift   << R200_TXA_SCALE_SHIFT);
710
711      /* All done!
712       */
713   }
714
715   if ( rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND] != color_combine ||
716	rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND] != alpha_combine ||
717	rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2] != color_scale ||
718	rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2] != alpha_scale) {
719      R200_STATECHANGE( rmesa, pix[unit] );
720      rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND] = color_combine;
721      rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND] = alpha_combine;
722      rmesa->hw.pix[unit].cmd[PIX_PP_TXCBLEND2] = color_scale;
723      rmesa->hw.pix[unit].cmd[PIX_PP_TXABLEND2] = alpha_scale;
724   }
725
726   return GL_TRUE;
727}
728
729#define TEXOBJ_TXFILTER_MASK (R200_MAX_MIP_LEVEL_MASK |		\
730			      R200_MIN_FILTER_MASK | 		\
731			      R200_MAG_FILTER_MASK |		\
732			      R200_MAX_ANISO_MASK |		\
733			      R200_YUV_TO_RGB |			\
734			      R200_YUV_TEMPERATURE_MASK |	\
735			      R200_CLAMP_S_MASK | 		\
736			      R200_CLAMP_T_MASK | 		\
737			      R200_BORDER_MODE_D3D )
738
739#define TEXOBJ_TXFORMAT_MASK (R200_TXFORMAT_WIDTH_MASK |	\
740			      R200_TXFORMAT_HEIGHT_MASK |	\
741			      R200_TXFORMAT_FORMAT_MASK |	\
742                              R200_TXFORMAT_F5_WIDTH_MASK |	\
743                              R200_TXFORMAT_F5_HEIGHT_MASK |	\
744			      R200_TXFORMAT_ALPHA_IN_MAP |	\
745			      R200_TXFORMAT_CUBIC_MAP_ENABLE |	\
746                              R200_TXFORMAT_NON_POWER2)
747
748#define TEXOBJ_TXFORMAT_X_MASK (R200_DEPTH_LOG2_MASK |		\
749                                R200_TEXCOORD_MASK |		\
750                                R200_CLAMP_Q_MASK | 		\
751                                R200_VOLUME_FILTER_MASK)
752
753
754static void import_tex_obj_state( r200ContextPtr rmesa,
755				  int unit,
756				  r200TexObjPtr texobj )
757{
758   GLuint *cmd = R200_DB_STATE( tex[unit] );
759
760   cmd[TEX_PP_TXFILTER] &= ~TEXOBJ_TXFILTER_MASK;
761   cmd[TEX_PP_TXFILTER] |= texobj->pp_txfilter & TEXOBJ_TXFILTER_MASK;
762   cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
763   cmd[TEX_PP_TXFORMAT] |= texobj->pp_txformat & TEXOBJ_TXFORMAT_MASK;
764   cmd[TEX_PP_TXFORMAT_X] &= ~TEXOBJ_TXFORMAT_X_MASK;
765   cmd[TEX_PP_TXFORMAT_X] |= texobj->pp_txformat_x & TEXOBJ_TXFORMAT_X_MASK;
766   cmd[TEX_PP_TXSIZE] = texobj->pp_txsize; /* NPOT only! */
767   cmd[TEX_PP_TXPITCH] = texobj->pp_txpitch; /* NPOT only! */
768   cmd[TEX_PP_TXOFFSET] = texobj->pp_txoffset;
769   cmd[TEX_PP_BORDER_COLOR] = texobj->pp_border_color;
770   R200_DB_STATECHANGE( rmesa, &rmesa->hw.tex[unit] );
771
772   if (texobj->base.tObj->Target == GL_TEXTURE_CUBE_MAP) {
773      GLuint *cube_cmd = R200_DB_STATE( cube[unit] );
774      GLuint bytesPerFace = texobj->base.totalSize / 6;
775      ASSERT(texobj->totalSize % 6 == 0);
776      cube_cmd[CUBE_PP_CUBIC_FACES] = texobj->pp_cubic_faces;
777      cube_cmd[CUBE_PP_CUBIC_OFFSET_F1] = texobj->pp_txoffset + 1 * bytesPerFace;
778      cube_cmd[CUBE_PP_CUBIC_OFFSET_F2] = texobj->pp_txoffset + 2 * bytesPerFace;
779      cube_cmd[CUBE_PP_CUBIC_OFFSET_F3] = texobj->pp_txoffset + 3 * bytesPerFace;
780      cube_cmd[CUBE_PP_CUBIC_OFFSET_F4] = texobj->pp_txoffset + 4 * bytesPerFace;
781      cube_cmd[CUBE_PP_CUBIC_OFFSET_F5] = texobj->pp_txoffset + 5 * bytesPerFace;
782      R200_DB_STATECHANGE( rmesa, &rmesa->hw.cube[unit] );
783   }
784
785   texobj->dirty_state &= ~(1<<unit);
786}
787
788
789
790
791static void set_texgen_matrix( r200ContextPtr rmesa,
792			       GLuint unit,
793			       const GLfloat *s_plane,
794			       const GLfloat *t_plane,
795			       const GLfloat *r_plane )
796{
797   static const GLfloat scale_identity[4] = { 1,1,1,1 };
798
799   if (!TEST_EQ_4V( s_plane, scale_identity) ||
800       !TEST_EQ_4V( t_plane, scale_identity) ||
801       !TEST_EQ_4V( r_plane, scale_identity)) {
802      rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;
803      rmesa->TexGenMatrix[unit].m[0]  = s_plane[0];
804      rmesa->TexGenMatrix[unit].m[4]  = s_plane[1];
805      rmesa->TexGenMatrix[unit].m[8]  = s_plane[2];
806      rmesa->TexGenMatrix[unit].m[12] = s_plane[3];
807
808      rmesa->TexGenMatrix[unit].m[1]  = t_plane[0];
809      rmesa->TexGenMatrix[unit].m[5]  = t_plane[1];
810      rmesa->TexGenMatrix[unit].m[9]  = t_plane[2];
811      rmesa->TexGenMatrix[unit].m[13] = t_plane[3];
812
813      /* NOTE: r_plane goes in the 4th row, not 3rd! */
814      rmesa->TexGenMatrix[unit].m[3]  = r_plane[0];
815      rmesa->TexGenMatrix[unit].m[7]  = r_plane[1];
816      rmesa->TexGenMatrix[unit].m[11] = r_plane[2];
817      rmesa->TexGenMatrix[unit].m[15] = r_plane[3];
818
819      rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
820   }
821}
822
823/* Need this special matrix to get correct reflection map coords */
824static void
825set_texgen_reflection_matrix( r200ContextPtr rmesa, GLuint unit )
826{
827   static const GLfloat m[16] = {
828      -1,  0,  0,  0,
829       0, -1,  0,  0,
830       0,  0,  0, -1,
831       0,  0, -1,  0 };
832   _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m);
833   _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) );
834   rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;
835}
836
837/* Need this special matrix to get correct normal map coords */
838static void
839set_texgen_normal_map_matrix( r200ContextPtr rmesa, GLuint unit )
840{
841   static const GLfloat m[16] = {
842      1, 0, 0, 0,
843      0, 1, 0, 0,
844      0, 0, 0, 1,
845      0, 0, 1, 0 };
846   _math_matrix_loadf( &(rmesa->TexGenMatrix[unit]), m);
847   _math_matrix_analyse( &(rmesa->TexGenMatrix[unit]) );
848   rmesa->TexGenEnabled |= R200_TEXMAT_0_ENABLE<<unit;
849}
850
851
852/* Ignoring the Q texcoord for now.
853 *
854 * Returns GL_FALSE if fallback required.
855 */
856static GLboolean r200_validate_texgen( GLcontext *ctx, GLuint unit )
857{
858   r200ContextPtr rmesa = R200_CONTEXT(ctx);
859   const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
860   GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4;
861   GLuint tmp = rmesa->TexGenEnabled;
862
863   rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
864   rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
865   rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
866   rmesa->TexGenInputs &= ~(R200_TEXGEN_INPUT_MASK<<inputshift);
867   rmesa->TexGenNeedNormals[unit] = 0;
868
869   if (0)
870      fprintf(stderr, "%s unit %d\n", __FUNCTION__, unit);
871
872   if ((texUnit->TexGenEnabled & (S_BIT|T_BIT|R_BIT)) == 0) {
873      /* Disabled, no fallback:
874       */
875      rmesa->TexGenInputs |=
876	 (R200_TEXGEN_INPUT_TEXCOORD_0+unit) << inputshift;
877      return GL_TRUE;
878   }
879   else if (texUnit->TexGenEnabled & Q_BIT) {
880      /* Very easy to do this, in fact would remove a fallback case
881       * elsewhere, but I haven't done it yet...  Fallback:
882       */
883      /*fprintf(stderr, "fallback Q_BIT\n");*/
884      return GL_FALSE;
885   }
886   else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) &&
887	    texUnit->GenModeS == texUnit->GenModeT) {
888      /* OK */
889      rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit;
890      /* continue */
891   }
892   else if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT) &&
893	    texUnit->GenModeS == texUnit->GenModeT &&
894            texUnit->GenModeT == texUnit->GenModeR) {
895      /* OK */
896      rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit;
897      /* continue */
898   }
899   else {
900      /* Mixed modes, fallback:
901       */
902      /* fprintf(stderr, "fallback mixed texgen\n"); */
903      return GL_FALSE;
904   }
905
906   rmesa->TexGenEnabled |= R200_TEXGEN_TEXMAT_0_ENABLE << unit;
907
908   switch (texUnit->GenModeS) {
909   case GL_OBJECT_LINEAR:
910      rmesa->TexGenInputs |= R200_TEXGEN_INPUT_OBJ << inputshift;
911      set_texgen_matrix( rmesa, unit,
912			 texUnit->ObjectPlaneS,
913			 texUnit->ObjectPlaneT,
914                         texUnit->ObjectPlaneR);
915      break;
916
917   case GL_EYE_LINEAR:
918      rmesa->TexGenInputs |= R200_TEXGEN_INPUT_EYE << inputshift;
919      set_texgen_matrix( rmesa, unit,
920			 texUnit->EyePlaneS,
921			 texUnit->EyePlaneT,
922			 texUnit->EyePlaneR);
923      break;
924
925   case GL_REFLECTION_MAP_NV:
926      rmesa->TexGenNeedNormals[unit] = GL_TRUE;
927      rmesa->TexGenInputs |= R200_TEXGEN_INPUT_EYE_REFLECT<<inputshift;
928      set_texgen_reflection_matrix(rmesa, unit);
929      break;
930
931   case GL_NORMAL_MAP_NV:
932      rmesa->TexGenNeedNormals[unit] = GL_TRUE;
933      rmesa->TexGenInputs |= R200_TEXGEN_INPUT_EYE_NORMAL<<inputshift;
934      set_texgen_normal_map_matrix(rmesa, unit);
935      break;
936
937   case GL_SPHERE_MAP:
938      rmesa->TexGenNeedNormals[unit] = GL_TRUE;
939      rmesa->TexGenInputs |= R200_TEXGEN_INPUT_SPHERE<<inputshift;
940      break;
941
942   default:
943      /* Unsupported mode, fallback:
944       */
945      /*  fprintf(stderr, "fallback unsupported texgen\n"); */
946      return GL_FALSE;
947   }
948
949   rmesa->TexGenCompSel |= R200_OUTPUT_TEX_0 << unit;
950
951   if (tmp != rmesa->TexGenEnabled) {
952      rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
953   }
954
955   return GL_TRUE;
956}
957
958
959static void disable_tex( GLcontext *ctx, int unit )
960{
961   r200ContextPtr rmesa = R200_CONTEXT(ctx);
962
963   if (rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE<<unit)) {
964      /* Texture unit disabled */
965      if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
966	 /* The old texture is no longer bound to this texture unit.
967	  * Mark it as such.
968	  */
969
970	 rmesa->state.texture.unit[unit].texobj->base.bound &= ~(1UL << unit);
971	 rmesa->state.texture.unit[unit].texobj = NULL;
972      }
973
974      R200_STATECHANGE( rmesa, ctx );
975      rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~((R200_TEX_0_ENABLE |
976					   R200_TEX_BLEND_0_ENABLE) << unit);
977      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_BLEND_0_ENABLE;
978
979      R200_STATECHANGE( rmesa, tcl );
980      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] &= ~(7 << (unit * 3));
981
982      if (rmesa->TclFallback & (R200_TCL_FALLBACK_TEXGEN_0<<unit)) {
983	 TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), GL_FALSE);
984      }
985
986      /* Actually want to keep all units less than max active texture
987       * enabled, right?  Fix this for >2 texunits.
988       */
989      /* FIXME: What should happen here if r200UpdateTextureEnv fails? */
990      if (unit == 0)
991	 r200UpdateTextureEnv( ctx, unit );
992
993
994      {
995	 GLuint inputshift = R200_TEXGEN_0_INPUT_SHIFT + unit*4;
996	 GLuint tmp = rmesa->TexGenEnabled;
997
998	 rmesa->TexGenEnabled &= ~(R200_TEXGEN_TEXMAT_0_ENABLE<<unit);
999	 rmesa->TexGenEnabled &= ~(R200_TEXMAT_0_ENABLE<<unit);
1000	 rmesa->TexGenEnabled &= ~(R200_TEXGEN_INPUT_MASK<<inputshift);
1001	 rmesa->TexGenNeedNormals[unit] = 0;
1002	 rmesa->TexGenCompSel &= ~(R200_OUTPUT_TEX_0 << unit);
1003	 rmesa->TexGenInputs &= ~(R200_TEXGEN_INPUT_MASK<<inputshift);
1004
1005	 if (tmp != rmesa->TexGenEnabled) {
1006	    rmesa->recheck_texgen[unit] = GL_TRUE;
1007	    rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1008	 }
1009      }
1010   }
1011}
1012
1013static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
1014{
1015   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1016   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1017   struct gl_texture_object *tObj = texUnit->_Current;
1018   r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1019
1020   /* Need to load the 2d images associated with this unit.
1021    */
1022   if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1023      t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1024      t->base.dirty_images[0] = ~0;
1025   }
1026
1027   ASSERT(tObj->Target == GL_TEXTURE_2D || tObj->Target == GL_TEXTURE_1D);
1028
1029   if ( t->base.dirty_images[0] ) {
1030      R200_FIREVERTICES( rmesa );
1031      r200SetTexImages( rmesa, tObj );
1032      r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1033      if ( !t->base.memBlock )
1034	 return GL_FALSE;
1035   }
1036
1037   return GL_TRUE;
1038}
1039
1040#if ENABLE_HW_3D_TEXTURE
1041static GLboolean enable_tex_3d( GLcontext *ctx, int unit )
1042{
1043   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1044   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1045   struct gl_texture_object *tObj = texUnit->_Current;
1046   r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1047
1048   /* Need to load the 3d images associated with this unit.
1049    */
1050   if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1051      t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1052      t->base.dirty_images[0] = ~0;
1053   }
1054
1055   ASSERT(tObj->Target == GL_TEXTURE_3D);
1056
1057   /* R100 & R200 do not support mipmaps for 3D textures.
1058    */
1059   if ( (tObj->MinFilter != GL_NEAREST) && (tObj->MinFilter != GL_LINEAR) ) {
1060      return GL_FALSE;
1061   }
1062
1063   if ( t->base.dirty_images[0] ) {
1064      R200_FIREVERTICES( rmesa );
1065      r200SetTexImages( rmesa, tObj );
1066      r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1067      if ( !t->base.memBlock )
1068	 return GL_FALSE;
1069   }
1070
1071   return GL_TRUE;
1072}
1073#endif
1074
1075static GLboolean enable_tex_cube( GLcontext *ctx, int unit )
1076{
1077   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1078   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1079   struct gl_texture_object *tObj = texUnit->_Current;
1080   r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1081   GLuint face;
1082
1083   /* Need to load the 2d images associated with this unit.
1084    */
1085   if (t->pp_txformat & R200_TXFORMAT_NON_POWER2) {
1086      t->pp_txformat &= ~R200_TXFORMAT_NON_POWER2;
1087      for (face = 0; face < 6; face++)
1088         t->base.dirty_images[face] = ~0;
1089   }
1090
1091   ASSERT(tObj->Target == GL_TEXTURE_CUBE_MAP);
1092
1093   if ( t->base.dirty_images[0] || t->base.dirty_images[1] ||
1094        t->base.dirty_images[2] || t->base.dirty_images[3] ||
1095        t->base.dirty_images[4] || t->base.dirty_images[5] ) {
1096      /* flush */
1097      R200_FIREVERTICES( rmesa );
1098      /* layout memory space, once for all faces */
1099      r200SetTexImages( rmesa, tObj );
1100   }
1101
1102   /* upload (per face) */
1103   for (face = 0; face < 6; face++) {
1104      if (t->base.dirty_images[face]) {
1105         r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, face );
1106      }
1107   }
1108
1109   if ( !t->base.memBlock ) {
1110      /* texmem alloc failed, use s/w fallback */
1111      return GL_FALSE;
1112   }
1113
1114   return GL_TRUE;
1115}
1116
1117static GLboolean enable_tex_rect( GLcontext *ctx, int unit )
1118{
1119   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1120   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1121   struct gl_texture_object *tObj = texUnit->_Current;
1122   r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1123
1124   if (!(t->pp_txformat & R200_TXFORMAT_NON_POWER2)) {
1125      t->pp_txformat |= R200_TXFORMAT_NON_POWER2;
1126      t->base.dirty_images[0] = ~0;
1127   }
1128
1129   ASSERT(tObj->Target == GL_TEXTURE_RECTANGLE_NV);
1130
1131   if ( t->base.dirty_images[0] ) {
1132      R200_FIREVERTICES( rmesa );
1133      r200SetTexImages( rmesa, tObj );
1134      r200UploadTexImages( rmesa, (r200TexObjPtr) tObj->DriverData, 0 );
1135      if ( !t->base.memBlock && !rmesa->prefer_gart_client_texturing )
1136	 return GL_FALSE;
1137   }
1138
1139   return GL_TRUE;
1140}
1141
1142
1143static GLboolean update_tex_common( GLcontext *ctx, int unit )
1144{
1145   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1146   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1147   struct gl_texture_object *tObj = texUnit->_Current;
1148   r200TexObjPtr t = (r200TexObjPtr) tObj->DriverData;
1149   GLenum format;
1150
1151   /* Fallback if there's a texture border */
1152   if ( tObj->Image[0][tObj->BaseLevel]->Border > 0 )
1153       return GL_FALSE;
1154
1155   /* Update state if this is a different texture object to last
1156    * time.
1157    */
1158   if ( rmesa->state.texture.unit[unit].texobj != t ) {
1159      if ( rmesa->state.texture.unit[unit].texobj != NULL ) {
1160	 /* The old texture is no longer bound to this texture unit.
1161	  * Mark it as such.
1162	  */
1163
1164	 rmesa->state.texture.unit[unit].texobj->base.bound &=
1165	     ~(1UL << unit);
1166      }
1167
1168      rmesa->state.texture.unit[unit].texobj = t;
1169      t->base.bound |= (1UL << unit);
1170      t->dirty_state |= 1<<unit;
1171      driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
1172   }
1173
1174
1175   /* Newly enabled?
1176    */
1177   if ( 1|| !(rmesa->hw.ctx.cmd[CTX_PP_CNTL] & (R200_TEX_0_ENABLE<<unit))) {
1178      R200_STATECHANGE( rmesa, ctx );
1179      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= (R200_TEX_0_ENABLE |
1180					 R200_TEX_BLEND_0_ENABLE) << unit;
1181
1182      R200_STATECHANGE( rmesa, vtx );
1183      rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_1] |= 4 << (unit * 3);
1184
1185      rmesa->recheck_texgen[unit] = GL_TRUE;
1186   }
1187
1188   if (t->dirty_state & (1<<unit)) {
1189      import_tex_obj_state( rmesa, unit, t );
1190   }
1191
1192   if (rmesa->recheck_texgen[unit]) {
1193      GLboolean fallback = !r200_validate_texgen( ctx, unit );
1194      TCL_FALLBACK( ctx, (R200_TCL_FALLBACK_TEXGEN_0<<unit), fallback);
1195      rmesa->recheck_texgen[unit] = 0;
1196      rmesa->NewGLState |= _NEW_TEXTURE_MATRIX;
1197   }
1198
1199   format = tObj->Image[0][tObj->BaseLevel]->Format;
1200   if ( rmesa->state.texture.unit[unit].format != format ||
1201	rmesa->state.texture.unit[unit].envMode != texUnit->EnvMode ) {
1202      rmesa->state.texture.unit[unit].format = format;
1203      rmesa->state.texture.unit[unit].envMode = texUnit->EnvMode;
1204      if ( ! r200UpdateTextureEnv( ctx, unit ) ) {
1205	 return GL_FALSE;
1206      }
1207   }
1208
1209   FALLBACK( rmesa, R200_FALLBACK_BORDER_MODE, t->border_fallback );
1210   return !t->border_fallback;
1211}
1212
1213
1214
1215static GLboolean r200UpdateTextureUnit( GLcontext *ctx, int unit )
1216{
1217   struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
1218
1219   if ( texUnit->_ReallyEnabled & (TEXTURE_RECT_BIT) ) {
1220      return (enable_tex_rect( ctx, unit ) &&
1221	      update_tex_common( ctx, unit ));
1222   }
1223   else if ( texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT) ) {
1224      return (enable_tex_2d( ctx, unit ) &&
1225	      update_tex_common( ctx, unit ));
1226   }
1227#if ENABLE_HW_3D_TEXTURE
1228   else if ( texUnit->_ReallyEnabled & (TEXTURE_3D_BIT) ) {
1229      return (enable_tex_3d( ctx, unit ) &&
1230	      update_tex_common( ctx, unit ));
1231   }
1232#endif
1233   else if ( texUnit->_ReallyEnabled & (TEXTURE_CUBE_BIT) ) {
1234      return (enable_tex_cube( ctx, unit ) &&
1235	      update_tex_common( ctx, unit ));
1236   }
1237   else if ( texUnit->_ReallyEnabled ) {
1238      return GL_FALSE;
1239   }
1240   else {
1241      disable_tex( ctx, unit );
1242      return GL_TRUE;
1243   }
1244}
1245
1246
1247void r200UpdateTextureState( GLcontext *ctx )
1248{
1249   r200ContextPtr rmesa = R200_CONTEXT(ctx);
1250   GLboolean ok;
1251   GLuint dbg;
1252
1253   ok = (r200UpdateTextureUnit( ctx, 0 ) &&
1254	 r200UpdateTextureUnit( ctx, 1 ));
1255
1256   FALLBACK( rmesa, R200_FALLBACK_TEXTURE, !ok );
1257
1258   if (rmesa->TclFallback)
1259      r200ChooseVertexState( ctx );
1260
1261   /*
1262    * T0 hang workaround -------------
1263    */
1264#if 1
1265   if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_ENABLE_MASK) == R200_TEX_0_ENABLE &&
1266       (rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK) > R200_MIN_FILTER_LINEAR) {
1267
1268      R200_STATECHANGE(rmesa, ctx);
1269      R200_STATECHANGE(rmesa, tex[1]);
1270      rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_TEX_1_ENABLE;
1271      rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~TEXOBJ_TXFORMAT_MASK;
1272      rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] |= 0x08000000;
1273   }
1274   else {
1275      if ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) &&
1276	  (rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] & 0x08000000)) {
1277	 R200_STATECHANGE(rmesa, tex[1]);
1278	 rmesa->hw.tex[1].cmd[TEX_PP_TXFORMAT] &= ~0x08000000;
1279      }
1280   }
1281#endif
1282
1283#if 1
1284   /*
1285    * Texture cache LRU hang workaround -------------
1286    */
1287   dbg = 0x0;
1288   if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_0_ENABLE) &&
1289	((((rmesa->hw.tex[0].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1290	  0x04) == 0)))
1291   {
1292      dbg |= 0x02;
1293   }
1294
1295   if (((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_1_ENABLE) &&
1296	((((rmesa->hw.tex[1].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) &
1297	  0x04) == 0)))
1298   {
1299      dbg |= 0x04;
1300   }
1301
1302   if (dbg != rmesa->hw.tam.cmd[TAM_DEBUG3]) {
1303      R200_STATECHANGE( rmesa, tam );
1304      rmesa->hw.tam.cmd[TAM_DEBUG3] = dbg;
1305      if (0) printf("TEXCACHE LRU HANG WORKAROUND %x\n", dbg);
1306   }
1307#endif
1308}
1309
1310/*
1311  also tests for higher texunits:
1312
1313       ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_2_ENABLE) &&
1314	((((rmesa->hw.tex[2].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) == 0)) ||
1315       ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_4_ENABLE) &&
1316	((((rmesa->hw.tex[4].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) == 0)))
1317
1318       ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_3_ENABLE) &&
1319	((((rmesa->hw.tex[3].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) == 0)) ||
1320       ((rmesa->hw.ctx.cmd[CTX_PP_CNTL] & R200_TEX_5_ENABLE) &&
1321	((((rmesa->hw.tex[5].cmd[TEX_PP_TXFILTER] & R200_MIN_FILTER_MASK)) & 0x04) == 0)))
1322
1323*/
1324