1 /**************************************************************************
3 Copyright 2001 2d3d Inc., Delray Beach, FL
7 Permission is hereby granted, free of charge, to any person obtaining a
8 copy of this software and associated documentation files (the "Software"),
9 to deal in the Software without restriction, including without limitation
10 on the rights to use, copy, modify, merge, publish, distribute, sub
11 license, and/or sell copies of the Software, and to permit persons to whom
12 the Software is furnished to do so, subject to the following conditions:
14 The above copyright notice and this permission notice (including the next
15 paragraph) shall be included in all copies or substantial portions of the
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
22 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
23 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
24 USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
28 /* $XFree86: xc/lib/GL/mesa/src/drv/i830/i830_texstate.c,v 1.3 2002/12/10 01:26:53 dawes Exp $ */
31 * \file i830_texstate.c
33 * Heavily based on the I810 driver, which was written by Keith Whitwell.
35 * \author Jeff Hartmann <jhartmann@2d3d.com>
36 * \author Keith Whitwell <keithw@tungstengraphics.com>
42 #include "simple_list.h"
44 #include "texformat.h"
49 #include "i830_screen.h"
52 #include "i830_context.h"
54 #include "i830_state.h"
55 #include "i830_ioctl.h"
57 #define I830_TEX_UNIT_ENABLED(unit) (1<<unit)
59 static void i830SetTexImages( i830ContextPtr imesa
,
60 struct gl_texture_object
*tObj
)
62 GLuint total_height
, pitch
, i
, textureFormat
;
63 i830TextureObjectPtr t
= (i830TextureObjectPtr
) tObj
->DriverData
;
64 const struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
67 switch( baseImage
->TexFormat
->MesaFormat
) {
70 textureFormat
= MAPSURF_8BIT
| MT_8BIT_L8
;
75 textureFormat
= MAPSURF_8BIT
| MT_8BIT_I8
;
78 case MESA_FORMAT_AL88
:
80 textureFormat
= MAPSURF_16BIT
| MT_16BIT_AY88
;
83 case MESA_FORMAT_RGB565
:
85 textureFormat
= MAPSURF_16BIT
| MT_16BIT_RGB565
;
88 case MESA_FORMAT_ARGB1555
:
90 textureFormat
= MAPSURF_16BIT
| MT_16BIT_ARGB1555
;
93 case MESA_FORMAT_ARGB4444
:
95 textureFormat
= MAPSURF_16BIT
| MT_16BIT_ARGB4444
;
98 case MESA_FORMAT_ARGB8888
:
100 textureFormat
= MAPSURF_32BIT
| MT_32BIT_ARGB8888
;
103 case MESA_FORMAT_YCBCR_REV
:
105 textureFormat
= (MAPSURF_422
| MT_422_YCRCB_NORMAL
|
106 TM0S1_COLORSPACE_CONVERSION
);
109 case MESA_FORMAT_YCBCR
:
111 textureFormat
= (MAPSURF_422
| MT_422_YCRCB_SWAPY
| /* ??? */
112 TM0S1_COLORSPACE_CONVERSION
);
115 case MESA_FORMAT_RGB_FXT1
:
116 case MESA_FORMAT_RGBA_FXT1
:
118 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_FXT1
);
120 case MESA_FORMAT_RGBA_DXT1
:
121 case MESA_FORMAT_RGB_DXT1
:
123 * DXTn pitches are Width/4 * blocksize in bytes
124 * for DXT1: blocksize=8 so Width/4*8 = Width * 2
125 * for DXT3/5: blocksize=16 so Width/4*16 = Width * 4
128 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_DXT1
);
130 case MESA_FORMAT_RGBA_DXT3
:
132 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_DXT2_3
);
134 case MESA_FORMAT_RGBA_DXT5
:
136 textureFormat
= (MAPSURF_COMPRESSED
| MT_COMPRESS_DXT4_5
);
139 fprintf(stderr
, "%s: bad image format\n", __FUNCTION__
);
144 /* Compute which mipmap levels we really want to send to the hardware.
147 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
150 /* Figure out the amount of memory required to hold all the mipmap
151 * levels. Choose the smallest pitch to accomodate the largest
154 numLevels
= t
->base
.lastLevel
- t
->base
.firstLevel
+ 1;
156 /* Pitch would be subject to additional rules if texture memory were
157 * tiled. Currently it isn't.
161 while (pitch
< tObj
->Image
[0][t
->base
.firstLevel
]->Width
* t
->texelBytes
)
165 pitch
= tObj
->Image
[0][t
->base
.firstLevel
]->Width
* t
->texelBytes
;
166 pitch
= (pitch
+ 3) & ~3;
170 /* All images must be loaded at this pitch. Count the number of
173 for ( total_height
= i
= 0 ; i
< numLevels
; i
++ ) {
174 t
->image
[0][i
].image
= tObj
->Image
[0][t
->base
.firstLevel
+ i
];
175 if (!t
->image
[0][i
].image
)
178 t
->image
[0][i
].offset
= total_height
* pitch
;
179 if (t
->image
[0][i
].image
->IsCompressed
)
181 if (t
->image
[0][i
].image
->Height
> 4)
182 total_height
+= t
->image
[0][i
].image
->Height
/4;
187 total_height
+= t
->image
[0][i
].image
->Height
;
188 t
->image
[0][i
].internalFormat
= baseImage
->Format
;
192 t
->base
.totalSize
= total_height
*pitch
;
193 t
->Setup
[I830_TEXREG_TM0S1
] =
194 (((tObj
->Image
[0][t
->base
.firstLevel
]->Height
- 1) << TM0S1_HEIGHT_SHIFT
) |
195 ((tObj
->Image
[0][t
->base
.firstLevel
]->Width
- 1) << TM0S1_WIDTH_SHIFT
) |
197 t
->Setup
[I830_TEXREG_TM0S2
] =
198 ((((pitch
/ 4) - 1) << TM0S2_PITCH_SHIFT
));
199 t
->Setup
[I830_TEXREG_TM0S3
] &= ~TM0S3_MAX_MIP_MASK
;
200 t
->Setup
[I830_TEXREG_TM0S3
] &= ~TM0S3_MIN_MIP_MASK
;
201 t
->Setup
[I830_TEXREG_TM0S3
] |= ((numLevels
- 1)*4) << TM0S3_MIN_MIP_SHIFT
;
202 t
->dirty
= I830_UPLOAD_TEX0
| I830_UPLOAD_TEX1
203 | I830_UPLOAD_TEX2
| I830_UPLOAD_TEX3
;
205 LOCK_HARDWARE( imesa
);
206 i830UploadTexImagesLocked( imesa
, t
);
207 UNLOCK_HARDWARE( imesa
);
210 /* ================================================================
211 * Texture combine functions
216 * Calculate the hardware instuctions to setup the current texture enviromnemt
217 * settings. Since \c gl_texture_unit::_CurrentCombine is used, both
218 * "classic" texture enviroments and GL_ARB_texture_env_combine type texture
219 * environments are treated identically.
222 * This function should return \c GLboolean. When \c GL_FALSE is returned,
223 * it means that an environment is selected that the hardware cannot do. This
224 * is the way the Radeon and R200 drivers work.
227 * Looking at i830_3d_regs.h, it seems the i830 can do part of
228 * GL_ATI_texture_env_combine3. It can handle using \c GL_ONE and
229 * \c GL_ZERO as combine inputs (which the code already supports). It can
230 * also handle the \c GL_MODULATE_ADD_ATI mode. Is it worth investigating
231 * partial support for the extension?
234 * Some thought needs to be put into the way combiners work. The driver
235 * treats the hardware as if there's a specific combine unit tied to each
236 * texture unit. That's why there's the special case for a disabled texture
237 * unit. That's not the way the hardware works. In reality, there are 4
238 * texture units and four general instruction slots. Each instruction slot
239 * can use any texture as an input. There's no need for this wierd "no-op"
240 * stuff. If texture units 0 and 3 are enabled, the instructions to combine
241 * them should be in slots 0 and 1, not 0 and 3 with two no-ops inbetween.
244 static void i830UpdateTexEnv( GLcontext
*ctx
, GLuint unit
)
246 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
247 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
248 const GLuint numColorArgs
= texUnit
->_CurrentCombine
->_NumArgsRGB
;
249 const GLuint numAlphaArgs
= texUnit
->_CurrentCombine
->_NumArgsA
;
251 GLboolean need_constant_color
= GL_FALSE
;
256 GLuint rgb_shift
= texUnit
->Combine
.ScaleShiftRGB
;
257 GLuint alpha_shift
= texUnit
->Combine
.ScaleShiftA
;
260 static const GLuint tex_blend_rgb
[3] = {
261 TEXPIPE_COLOR
| TEXBLEND_ARG1
| TEXBLENDARG_MODIFY_PARMS
,
262 TEXPIPE_COLOR
| TEXBLEND_ARG2
| TEXBLENDARG_MODIFY_PARMS
,
263 TEXPIPE_COLOR
| TEXBLEND_ARG0
| TEXBLENDARG_MODIFY_PARMS
,
265 static const GLuint tex_blend_a
[3] = {
266 TEXPIPE_ALPHA
| TEXBLEND_ARG1
| TEXBLENDARG_MODIFY_PARMS
,
267 TEXPIPE_ALPHA
| TEXBLEND_ARG2
| TEXBLENDARG_MODIFY_PARMS
,
268 TEXPIPE_ALPHA
| TEXBLEND_ARG0
| TEXBLENDARG_MODIFY_PARMS
,
270 static const GLuint op_rgb
[4] = {
273 TEXBLENDARG_REPLICATE_ALPHA
,
274 TEXBLENDARG_REPLICATE_ALPHA
| TEXBLENDARG_INV_ARG
,
279 imesa
->TexBlendWordsUsed
[unit
] = 0;
281 if(I830_DEBUG
&DEBUG_TEXTURE
)
282 fprintf(stderr
, "[%s:%u] env. mode = %s\n", __FUNCTION__
, __LINE__
,
283 _mesa_lookup_enum_by_nr(texUnit
->EnvMode
));
286 if ( !texUnit
->_ReallyEnabled
) {
287 imesa
->TexBlend
[unit
][0] = (STATE3D_MAP_BLEND_OP_CMD(unit
) |
289 ENABLE_TEXOUTPUT_WRT_SEL
|
290 TEXOP_OUTPUT_CURRENT
|
291 DISABLE_TEX_CNTRL_STAGE
|
295 imesa
->TexBlend
[unit
][1] = (STATE3D_MAP_BLEND_OP_CMD(unit
) |
297 ENABLE_TEXOUTPUT_WRT_SEL
|
298 TEXOP_OUTPUT_CURRENT
|
302 imesa
->TexBlend
[unit
][2] = (STATE3D_MAP_BLEND_ARG_CMD(unit
) |
305 TEXBLENDARG_MODIFY_PARMS
|
306 TEXBLENDARG_CURRENT
);
307 imesa
->TexBlend
[unit
][3] = (STATE3D_MAP_BLEND_ARG_CMD(unit
) |
310 TEXBLENDARG_MODIFY_PARMS
|
311 TEXBLENDARG_CURRENT
);
312 imesa
->TexBlendWordsUsed
[unit
] = 4;
315 switch(texUnit
->_CurrentCombine
->ModeRGB
) {
317 blendop
= TEXBLENDOP_ARG1
;
320 blendop
= TEXBLENDOP_MODULATE
;
323 blendop
= TEXBLENDOP_ADD
;
326 blendop
= TEXBLENDOP_ADDSIGNED
;
329 blendop
= TEXBLENDOP_BLEND
;
332 blendop
= TEXBLENDOP_SUBTRACT
;
334 case GL_DOT3_RGB_EXT
:
335 case GL_DOT3_RGBA_EXT
:
336 /* The EXT version of the DOT3 extension does not support the
337 * scale factor, but the ARB version (and the version in OpenGL
346 blendop
= TEXBLENDOP_DOT3
;
352 blendop
|= (rgb_shift
<< TEXOP_SCALE_SHIFT
);
354 switch(texUnit
->_CurrentCombine
->ModeA
) {
356 ablendop
= TEXBLENDOP_ARG1
;
359 ablendop
= TEXBLENDOP_MODULATE
;
362 ablendop
= TEXBLENDOP_ADD
;
365 ablendop
= TEXBLENDOP_ADDSIGNED
;
368 ablendop
= TEXBLENDOP_BLEND
;
371 ablendop
= TEXBLENDOP_SUBTRACT
;
377 if ( (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA_EXT
)
378 || (texUnit
->_CurrentCombine
->ModeRGB
== GL_DOT3_RGBA
) ) {
379 ablendop
= TEXBLENDOP_DOT3
;
382 ablendop
|= (alpha_shift
<< TEXOP_SCALE_SHIFT
);
384 /* Handle RGB args */
385 for( i
= 0 ; i
< numColorArgs
; i
++ ) {
386 const int op
= texUnit
->_CurrentCombine
->OperandRGB
[i
] - GL_SRC_COLOR
;
388 assert( (op
>= 0) && (op
<= 3) );
389 switch(texUnit
->_CurrentCombine
->SourceRGB
[i
]) {
391 args_RGB
[i
] = TEXBLENDARG_TEXEL0
+ unit
;
397 args_RGB
[i
] = TEXBLENDARG_TEXEL0
398 + (texUnit
->_CurrentCombine
->SourceRGB
[i
] & 0x03);
401 args_RGB
[i
] = TEXBLENDARG_FACTOR_N
;
402 need_constant_color
= GL_TRUE
;
404 case GL_PRIMARY_COLOR
:
405 args_RGB
[i
] = TEXBLENDARG_DIFFUSE
;
408 args_RGB
[i
] = TEXBLENDARG_CURRENT
;
411 args_RGB
[i
] = TEXBLENDARG_ONE
;
414 args_RGB
[i
] = TEXBLENDARG_ONE
| TEXBLENDARG_INV_ARG
;
420 /* Xor is used so that GL_ONE_MINUS_SRC_COLOR with GL_ZERO
423 args_RGB
[i
] ^= op_rgb
[op
];
427 for( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
428 const int op
= texUnit
->_CurrentCombine
->OperandA
[i
] - GL_SRC_ALPHA
;
430 assert( (op
>= 0) && (op
<= 1) );
431 switch(texUnit
->_CurrentCombine
->SourceA
[i
]) {
433 args_A
[i
] = TEXBLENDARG_TEXEL0
+ unit
;
439 args_A
[i
] = TEXBLENDARG_TEXEL0
440 + (texUnit
->_CurrentCombine
->SourceA
[i
] & 0x03);
443 args_A
[i
] = TEXBLENDARG_FACTOR_N
;
444 need_constant_color
= GL_TRUE
;
446 case GL_PRIMARY_COLOR
:
447 args_A
[i
] = TEXBLENDARG_DIFFUSE
;
450 args_A
[i
] = TEXBLENDARG_CURRENT
;
453 args_A
[i
] = TEXBLENDARG_ONE
;
456 args_A
[i
] = TEXBLENDARG_ONE
| TEXBLENDARG_INV_ARG
;
462 /* We cheat. :) The register values for this are the same as for
463 * RGB. Xor is used so that GL_ONE_MINUS_SRC_ALPHA with GL_ZERO
466 args_A
[i
] ^= op_rgb
[op
];
469 /* Native Arg1 == Arg0 in GL_EXT_texture_env_combine spec */
470 /* Native Arg2 == Arg1 in GL_EXT_texture_env_combine spec */
471 /* Native Arg0 == Arg2 in GL_EXT_texture_env_combine spec */
473 /* Build color pipeline */
476 imesa
->TexBlend
[unit
][used
++] = (STATE3D_MAP_BLEND_OP_CMD(unit
) |
478 ENABLE_TEXOUTPUT_WRT_SEL
|
479 TEXOP_OUTPUT_CURRENT
|
480 DISABLE_TEX_CNTRL_STAGE
|
484 imesa
->TexBlend
[unit
][used
++] = (STATE3D_MAP_BLEND_OP_CMD(unit
) |
486 ENABLE_TEXOUTPUT_WRT_SEL
|
487 TEXOP_OUTPUT_CURRENT
|
491 for ( i
= 0 ; i
< numColorArgs
; i
++ ) {
492 imesa
->TexBlend
[unit
][used
++] = (STATE3D_MAP_BLEND_ARG_CMD(unit
) |
497 for ( i
= 0 ; i
< numAlphaArgs
; i
++ ) {
498 imesa
->TexBlend
[unit
][used
++] = (STATE3D_MAP_BLEND_ARG_CMD(unit
) |
504 if ( need_constant_color
) {
506 const GLfloat
* const fc
= texUnit
->EnvColor
;
508 FLOAT_COLOR_TO_UBYTE_COLOR(r
, fc
[RCOMP
]);
509 FLOAT_COLOR_TO_UBYTE_COLOR(g
, fc
[GCOMP
]);
510 FLOAT_COLOR_TO_UBYTE_COLOR(b
, fc
[BCOMP
]);
511 FLOAT_COLOR_TO_UBYTE_COLOR(a
, fc
[ACOMP
]);
513 imesa
->TexBlend
[unit
][used
++] = STATE3D_COLOR_FACTOR_CMD(unit
);
514 imesa
->TexBlend
[unit
][used
++] = ((a
<< 24) | (r
<< 16) | (g
<< 8) | b
);
517 imesa
->TexBlendWordsUsed
[unit
] = used
;
520 I830_STATECHANGE( imesa
, I830_UPLOAD_TEXBLEND_N(unit
) );
524 /* This is bogus -- can't load the same texture object on two units.
526 static void i830TexSetUnit( i830TextureObjectPtr t
, GLuint unit
)
528 if(I830_DEBUG
&DEBUG_TEXTURE
)
529 fprintf(stderr
, "%s unit(%d)\n", __FUNCTION__
, unit
);
531 t
->Setup
[I830_TEXREG_TM0LI
] = (STATE3D_LOAD_STATE_IMMEDIATE_2
|
532 (LOAD_TEXTURE_MAP0
<< unit
) | 4);
534 I830_SET_FIELD(t
->Setup
[I830_TEXREG_MCS
], MAP_UNIT_MASK
, MAP_UNIT(unit
));
536 t
->current_unit
= unit
;
537 t
->base
.bound
|= (1U << unit
);
540 #define TEXCOORDTYPE_MASK (~((1<<13)|(1<<12)|(1<<11)))
543 static GLboolean
enable_tex_common( GLcontext
*ctx
, GLuint unit
)
545 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
546 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
547 struct gl_texture_object
*tObj
= texUnit
->_Current
;
548 i830TextureObjectPtr t
= (i830TextureObjectPtr
)tObj
->DriverData
;
550 /* Fallback if there's a texture border */
551 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 ) {
555 /* Upload teximages (not pipelined)
557 if (t
->base
.dirty_images
[0]) {
558 i830SetTexImages( imesa
, tObj
);
559 if (!t
->base
.memBlock
) {
564 /* Update state if this is a different texture object to last
567 if (imesa
->CurrentTexObj
[unit
] != t
) {
569 if ( imesa
->CurrentTexObj
[unit
] != NULL
) {
570 /* The old texture is no longer bound to this texture unit.
574 imesa
->CurrentTexObj
[unit
]->base
.bound
&= ~(1U << unit
);
577 I830_STATECHANGE( imesa
, I830_UPLOAD_TEX_N(unit
) );
578 imesa
->CurrentTexObj
[unit
] = t
;
579 i830TexSetUnit(t
, unit
);
582 /* Update texture environment if texture object image format or
583 * texture environment state has changed.
585 * KW: doesn't work -- change from tex0 only to tex0+tex1 gets
586 * missed (need to update last stage flag?). Call
587 * i830UpdateTexEnv always.
589 if (tObj
->Image
[0][tObj
->BaseLevel
]->Format
!=
590 imesa
->TexEnvImageFmt
[unit
]) {
591 imesa
->TexEnvImageFmt
[unit
] = tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
593 i830UpdateTexEnv( ctx
, unit
);
594 imesa
->TexEnabledMask
|= I830_TEX_UNIT_ENABLED(unit
);
599 static GLboolean
enable_tex_rect( GLcontext
*ctx
, GLuint unit
)
601 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
602 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
603 struct gl_texture_object
*tObj
= texUnit
->_Current
;
604 i830TextureObjectPtr t
= (i830TextureObjectPtr
)tObj
->DriverData
;
605 GLuint mcs
= t
->Setup
[I830_TEXREG_MCS
];
607 mcs
&= ~TEXCOORDS_ARE_NORMAL
;
608 mcs
|= TEXCOORDS_ARE_IN_TEXELUNITS
;
610 if (mcs
!= t
->Setup
[I830_TEXREG_MCS
]) {
611 I830_STATECHANGE( imesa
, I830_UPLOAD_TEX_N(unit
) );
612 t
->Setup
[I830_TEXREG_MCS
] = mcs
;
619 static GLboolean
enable_tex_2d( GLcontext
*ctx
, GLuint unit
)
621 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
622 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
623 struct gl_texture_object
*tObj
= texUnit
->_Current
;
624 i830TextureObjectPtr t
= (i830TextureObjectPtr
)tObj
->DriverData
;
625 GLuint mcs
= t
->Setup
[I830_TEXREG_MCS
];
627 mcs
&= ~TEXCOORDS_ARE_IN_TEXELUNITS
;
628 mcs
|= TEXCOORDS_ARE_NORMAL
;
630 if (mcs
!= t
->Setup
[I830_TEXREG_MCS
]) {
631 I830_STATECHANGE( imesa
, I830_UPLOAD_TEX_N(unit
) );
632 t
->Setup
[I830_TEXREG_MCS
] = mcs
;
639 static GLboolean
disable_tex( GLcontext
*ctx
, int unit
)
641 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
643 /* This is happening too often. I need to conditionally send diffuse
644 * state to the card. Perhaps a diffuse dirty flag of some kind.
645 * Will need to change this logic if more than 2 texture units are
646 * used. We need to only do this up to the last unit enabled, or unit
647 * one if nothing is enabled.
650 if ( imesa
->CurrentTexObj
[unit
] != NULL
) {
651 /* The old texture is no longer bound to this texture unit.
655 imesa
->CurrentTexObj
[unit
]->base
.bound
&= ~(1U << unit
);
656 imesa
->CurrentTexObj
[unit
] = NULL
;
659 imesa
->TexEnvImageFmt
[unit
] = 0;
660 imesa
->dirty
&= ~(I830_UPLOAD_TEX_N(unit
));
662 i830UpdateTexEnv( ctx
, unit
);
667 static GLboolean
i830UpdateTexUnit( GLcontext
*ctx
, GLuint unit
)
669 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
670 struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
672 imesa
->TexEnabledMask
&= ~(I830_TEX_UNIT_ENABLED(unit
));
674 if (texUnit
->_ReallyEnabled
== TEXTURE_2D_BIT
) {
675 return (enable_tex_common( ctx
, unit
) &&
676 enable_tex_2d( ctx
, unit
));
678 else if (texUnit
->_ReallyEnabled
== TEXTURE_RECT_BIT
) {
679 return (enable_tex_common( ctx
, unit
) &&
680 enable_tex_rect( ctx
, unit
));
682 else if (texUnit
->_ReallyEnabled
) {
686 return disable_tex( ctx
, unit
);
692 void i830UpdateTextureState( GLcontext
*ctx
)
694 i830ContextPtr imesa
= I830_CONTEXT(ctx
);
699 for ( i
= 0 ; i
< ctx
->Const
.MaxTextureUnits
; i
++ ) {
700 if ( (ctx
->Texture
.Unit
[i
]._ReallyEnabled
== TEXTURE_2D_BIT
)
701 || (ctx
->Texture
.Unit
[i
]._ReallyEnabled
== TEXTURE_RECT_BIT
) ) {
707 for ( i
= 0 ; i
<= last_stage
; i
++ ) {
708 ok
= ok
&& i830UpdateTexUnit( ctx
, i
);
711 FALLBACK( imesa
, I830_FALLBACK_TEXTURE
, !ok
);
714 /* Make sure last stage is set correctly */
715 imesa
->TexBlend
[last_stage
][0] |= TEXOP_LAST_STAGE
;