1 /* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_texstate.c,v 1.1 2002/02/22 21:44:58 dawes Exp $ */
2 /**************************************************************************
4 Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
8 Permission is hereby granted, free of charge, to any person obtaining a
9 copy of this software and associated documentation files (the "Software"),
10 to deal in the Software without restriction, including without limitation
11 on the rights to use, copy, modify, merge, publish, distribute, sub
12 license, and/or sell copies of the Software, and to permit persons to whom
13 the Software is furnished to do so, subject to the following conditions:
15 The above copyright notice and this permission notice (including the next
16 paragraph) shall be included in all copies or substantial portions of the
19 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
22 ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
24 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
25 USE OR OTHER DEALINGS IN THE SOFTWARE.
27 **************************************************************************/
31 * Gareth Hughes <gareth@valinux.com>
32 * Kevin E. Martin <martin@valinux.com>
33 * Brian Paul <brianp@valinux.com>
40 #include "texformat.h"
42 #include "r128_context.h"
43 #include "r128_state.h"
44 #include "r128_ioctl.h"
46 #include "r128_tris.h"
50 static void r128SetTexImages( r128ContextPtr rmesa
,
51 const struct gl_texture_object
*tObj
)
53 r128TexObjPtr t
= (r128TexObjPtr
) tObj
->DriverData
;
54 struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
55 int log2Pitch
, log2Height
, log2Size
, log2MinSize
;
58 GLint firstLevel
, lastLevel
;
63 if ( R128_DEBUG
& DEBUG_VERBOSE_API
)
64 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *) tObj
);
66 switch (baseImage
->TexFormat
->MesaFormat
) {
67 case MESA_FORMAT_ARGB8888
:
68 t
->textureFormat
= R128_DATATYPE_ARGB8888
;
70 case MESA_FORMAT_ARGB4444
:
71 t
->textureFormat
= R128_DATATYPE_ARGB4444
;
73 case MESA_FORMAT_RGB565
:
74 t
->textureFormat
= R128_DATATYPE_RGB565
;
76 case MESA_FORMAT_RGB332
:
77 t
->textureFormat
= R128_DATATYPE_RGB8
;
80 t
->textureFormat
= R128_DATATYPE_CI8
;
82 case MESA_FORMAT_YCBCR
:
83 t
->textureFormat
= R128_DATATYPE_YVYU422
;
85 case MESA_FORMAT_YCBCR_REV
:
86 t
->textureFormat
= R128_DATATYPE_VYUY422
;
89 _mesa_problem(rmesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
92 /* Compute which mipmap levels we really want to send to the hardware.
95 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
96 firstLevel
= t
->base
.firstLevel
;
97 lastLevel
= t
->base
.lastLevel
;
99 log2Pitch
= tObj
->Image
[0][firstLevel
]->WidthLog2
;
100 log2Height
= tObj
->Image
[0][firstLevel
]->HeightLog2
;
101 log2Size
= MAX2(log2Pitch
, log2Height
);
102 log2MinSize
= log2Size
;
104 t
->base
.dirty_images
[0] = 0;
106 for ( i
= firstLevel
; i
<= lastLevel
; i
++ ) {
107 const struct gl_texture_image
*texImage
;
109 texImage
= tObj
->Image
[0][i
];
110 if ( !texImage
|| !texImage
->Data
) {
115 log2MinSize
= texImage
->MaxLog2
;
117 t
->image
[i
- firstLevel
].offset
= totalSize
;
118 t
->image
[i
- firstLevel
].width
= tObj
->Image
[0][i
]->Width
;
119 t
->image
[i
- firstLevel
].height
= tObj
->Image
[0][i
]->Height
;
121 t
->base
.dirty_images
[0] |= (1 << i
);
123 totalSize
+= (tObj
->Image
[0][i
]->Height
*
124 tObj
->Image
[0][i
]->Width
*
125 tObj
->Image
[0][i
]->TexFormat
->TexelBytes
);
127 /* Offsets must be 32-byte aligned for host data blits and tiling */
128 totalSize
= (totalSize
+ 31) & ~31;
131 t
->base
.totalSize
= totalSize
;
132 t
->base
.firstLevel
= firstLevel
;
133 t
->base
.lastLevel
= lastLevel
;
135 /* Set the texture format */
136 t
->setup
.tex_cntl
&= ~(0xf << 16);
137 t
->setup
.tex_cntl
|= t
->textureFormat
;
139 t
->setup
.tex_combine_cntl
= 0x00000000; /* XXX is this right? */
141 t
->setup
.tex_size_pitch
= ((log2Pitch
<< R128_TEX_PITCH_SHIFT
) |
142 (log2Size
<< R128_TEX_SIZE_SHIFT
) |
143 (log2Height
<< R128_TEX_HEIGHT_SHIFT
) |
144 (log2MinSize
<< R128_TEX_MIN_SIZE_SHIFT
));
146 for ( i
= 0 ; i
< R128_MAX_TEXTURE_LEVELS
; i
++ ) {
147 t
->setup
.tex_offset
[i
] = 0x00000000;
150 if (firstLevel
== lastLevel
)
151 t
->setup
.tex_cntl
|= R128_MIP_MAP_DISABLE
;
153 t
->setup
.tex_cntl
&= ~R128_MIP_MAP_DISABLE
;
155 /* FYI: r128UploadTexImages( rmesa, t ); used to be called here */
159 /* ================================================================
160 * Texture combine functions
163 #define COLOR_COMB_DISABLE (R128_COMB_DIS | \
164 R128_COLOR_FACTOR_TEX)
165 #define COLOR_COMB_COPY_INPUT (R128_COMB_COPY_INP | \
166 R128_COLOR_FACTOR_TEX)
167 #define COLOR_COMB_MODULATE (R128_COMB_MODULATE | \
168 R128_COLOR_FACTOR_TEX)
169 #define COLOR_COMB_MODULATE_NTEX (R128_COMB_MODULATE | \
170 R128_COLOR_FACTOR_NTEX)
171 #define COLOR_COMB_ADD (R128_COMB_ADD | \
172 R128_COLOR_FACTOR_TEX)
173 #define COLOR_COMB_BLEND_TEX (R128_COMB_BLEND_TEXTURE | \
174 R128_COLOR_FACTOR_TEX)
175 /* Rage 128 Pro/M3 only! */
176 #define COLOR_COMB_BLEND_COLOR (R128_COMB_MODULATE2X | \
177 R128_COMB_FCN_MSB | \
178 R128_COLOR_FACTOR_CONST_COLOR)
180 #define ALPHA_COMB_DISABLE (R128_COMB_ALPHA_DIS | \
181 R128_ALPHA_FACTOR_TEX_ALPHA)
182 #define ALPHA_COMB_COPY_INPUT (R128_COMB_ALPHA_COPY_INP | \
183 R128_ALPHA_FACTOR_TEX_ALPHA)
184 #define ALPHA_COMB_MODULATE (R128_COMB_ALPHA_MODULATE | \
185 R128_ALPHA_FACTOR_TEX_ALPHA)
186 #define ALPHA_COMB_MODULATE_NTEX (R128_COMB_ALPHA_MODULATE | \
187 R128_ALPHA_FACTOR_NTEX_ALPHA)
188 #define ALPHA_COMB_ADD (R128_COMB_ALPHA_ADD | \
189 R128_ALPHA_FACTOR_TEX_ALPHA)
191 #define INPUT_INTERP (R128_INPUT_FACTOR_INT_COLOR | \
192 R128_INP_FACTOR_A_INT_ALPHA)
193 #define INPUT_PREVIOUS (R128_INPUT_FACTOR_PREV_COLOR | \
194 R128_INP_FACTOR_A_PREV_ALPHA)
196 static GLboolean
r128UpdateTextureEnv( GLcontext
*ctx
, int unit
)
198 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
199 GLint source
= rmesa
->tmu_source
[unit
];
200 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
201 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
202 const GLenum format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
205 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
206 fprintf( stderr
, "%s( %p, %d )\n",
207 __FUNCTION__
, (void *) ctx
, (void *) unit
);
211 combine
= INPUT_INTERP
;
213 combine
= INPUT_PREVIOUS
;
216 /* Set the texture environment state */
217 switch ( texUnit
->EnvMode
) {
221 case GL_LUMINANCE_ALPHA
:
223 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
224 ALPHA_COMB_DISABLE
); /* A = At */
228 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
229 ALPHA_COMB_COPY_INPUT
); /* A = Af */
232 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
233 ALPHA_COMB_DISABLE
); /* A = At */
244 case GL_LUMINANCE_ALPHA
:
246 combine
|= (COLOR_COMB_MODULATE
| /* C = CfCt */
247 ALPHA_COMB_MODULATE
); /* A = AfAt */
251 combine
|= (COLOR_COMB_MODULATE
| /* C = CfCt */
252 ALPHA_COMB_COPY_INPUT
); /* A = Af */
255 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
256 ALPHA_COMB_MODULATE
); /* A = AfAt */
267 combine
|= (COLOR_COMB_BLEND_TEX
| /* C = Cf(1-At)+CtAt */
268 ALPHA_COMB_COPY_INPUT
); /* A = Af */
271 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
272 ALPHA_COMB_COPY_INPUT
); /* A = Af */
276 case GL_LUMINANCE_ALPHA
:
278 /* Undefined behaviour - just copy the incoming fragment */
279 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = undefined */
280 ALPHA_COMB_COPY_INPUT
); /* A = undefined */
289 /* Rage 128 Pro and M3 can handle GL_BLEND texturing.
291 if ( !R128_IS_PLAIN( rmesa
) ) {
292 /* XXX this hasn't been fully tested, I don't have a Pro card. -BP */
295 case GL_LUMINANCE_ALPHA
:
296 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-Ct)+CcCt */
297 ALPHA_COMB_MODULATE
); /* A = AfAt */
302 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-Ct)+CcCt */
303 ALPHA_COMB_COPY_INPUT
); /* A = Af */
307 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
308 ALPHA_COMB_MODULATE
); /* A = AfAt */
312 /* GH: We could be smarter about this... */
313 switch ( rmesa
->env_color
& 0xff000000 ) {
315 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-It)+CcIt */
316 ALPHA_COMB_MODULATE_NTEX
); /* A = Af(1-It) */
318 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
319 ALPHA_COMB_MODULATE
); /* A = fallback */
331 /* Rage 128 has to fake some cases of GL_BLEND, otherwise fallback
332 * to software rendering.
334 if ( rmesa
->blend_flags
) {
339 case GL_LUMINANCE_ALPHA
:
340 switch ( rmesa
->env_color
& 0x00ffffff ) {
342 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
343 ALPHA_COMB_MODULATE
); /* A = AfAt */
346 /* This isn't right - BP */
349 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
350 ALPHA_COMB_MODULATE
); /* A = AfAt */
352 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
353 ALPHA_COMB_COPY_INPUT
); /* A = Af */
358 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
359 ALPHA_COMB_MODULATE
); /* A = fallback */
365 switch ( rmesa
->env_color
& 0x00ffffff ) {
367 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
368 ALPHA_COMB_COPY_INPUT
); /* A = Af */
371 /* This isn't right - BP */
374 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
375 ALPHA_COMB_COPY_INPUT
); /* A = Af */
377 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
378 ALPHA_COMB_COPY_INPUT
); /* A = Af */
383 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
384 ALPHA_COMB_COPY_INPUT
); /* A = fallback */
390 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
391 ALPHA_COMB_MODULATE
); /* A = AfAt */
393 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
394 ALPHA_COMB_COPY_INPUT
); /* A = Af */
398 switch ( rmesa
->env_color
& 0x00ffffff ) {
400 combine
|= COLOR_COMB_MODULATE_NTEX
; /* C = Cf(1-It) */
403 /* This isn't right - BP */
406 combine
|= COLOR_COMB_MODULATE_NTEX
; /* C = Cf(1-It) */
408 combine
|= COLOR_COMB_ADD
; /* C = Cf+It */
413 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
414 ALPHA_COMB_MODULATE
); /* A = fallback */
417 switch ( rmesa
->env_color
& 0xff000000 ) {
419 combine
|= ALPHA_COMB_MODULATE_NTEX
; /* A = Af(1-It) */
422 /* This isn't right - BP */
425 combine
|= ALPHA_COMB_MODULATE_NTEX
; /* A = Af(1-It) */
427 combine
|= ALPHA_COMB_ADD
; /* A = Af+It */
432 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
433 ALPHA_COMB_MODULATE
); /* A = fallback */
446 case GL_LUMINANCE_ALPHA
:
447 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
448 ALPHA_COMB_MODULATE
); /* A = AfAt */
452 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
453 ALPHA_COMB_COPY_INPUT
); /* A = Af */
456 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
457 ALPHA_COMB_MODULATE
); /* A = AfAt */
460 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
461 ALPHA_COMB_ADD
); /* A = Af+At */
473 if ( rmesa
->tex_combine
[unit
] != combine
) {
474 rmesa
->tex_combine
[unit
] = combine
;
475 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
480 static void disable_tex( GLcontext
*ctx
, int unit
)
482 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
484 FLUSH_BATCH( rmesa
);
486 if ( rmesa
->CurrentTexObj
[unit
] ) {
487 rmesa
->CurrentTexObj
[unit
]->base
.bound
&= ~(1 << unit
);
488 rmesa
->CurrentTexObj
[unit
] = NULL
;
491 rmesa
->setup
.tex_cntl_c
&= ~(R128_TEXMAP_ENABLE
<< unit
);
492 rmesa
->setup
.tex_size_pitch_c
&= ~(R128_TEX_SIZE_PITCH_MASK
<<
493 (R128_SEC_TEX_SIZE_PITCH_SHIFT
* unit
));
494 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
496 /* If either texture unit is disabled, then multitexturing is not
500 rmesa
->blend_flags
&= ~R128_BLEND_MULTITEX
;
503 static GLboolean
enable_tex_2d( GLcontext
*ctx
, int unit
)
505 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
506 const int source
= rmesa
->tmu_source
[unit
];
507 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
508 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
509 r128TexObjPtr t
= (r128TexObjPtr
) tObj
->DriverData
;
511 /* Need to load the 2d images associated with this unit.
513 if ( t
->base
.dirty_images
[0] ) {
514 /* FIXME: For Radeon, RADEON_FIREVERTICES is called here. Should
515 * FIXME: something similar be done for R128?
517 /* FLUSH_BATCH( rmesa ); */
519 r128SetTexImages( rmesa
, tObj
);
520 r128UploadTexImages( rmesa
, t
);
521 if ( !t
->base
.memBlock
)
528 static GLboolean
update_tex_common( GLcontext
*ctx
, int unit
)
530 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
531 const int source
= rmesa
->tmu_source
[unit
];
532 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
533 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
534 r128TexObjPtr t
= (r128TexObjPtr
) tObj
->DriverData
;
537 /* Fallback if there's a texture border */
538 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 ) {
543 /* Update state if this is a different texture object to last
546 if ( rmesa
->CurrentTexObj
[unit
] != t
) {
547 if ( rmesa
->CurrentTexObj
[unit
] != NULL
) {
548 /* The old texture is no longer bound to this texture unit.
552 rmesa
->CurrentTexObj
[unit
]->base
.bound
&=
556 rmesa
->CurrentTexObj
[unit
] = t
;
557 t
->base
.bound
|= (1UL << unit
);
558 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
560 driUpdateTextureLRU( (driTextureObject
*) t
); /* XXX: should be locked! */
563 /* FIXME: We need to update the texture unit if any texture parameters have
564 * changed, but this texture was already bound. This could be changed to
565 * work like the Radeon driver where the texture object has it's own
568 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
571 rmesa
->setup
.tex_size_pitch_c
&= ~(R128_TEX_SIZE_PITCH_MASK
<<
572 (R128_SEC_TEX_SIZE_PITCH_SHIFT
* unit
));
575 rmesa
->setup
.tex_cntl_c
|= R128_TEXMAP_ENABLE
;
576 rmesa
->setup
.tex_size_pitch_c
|= t
->setup
.tex_size_pitch
<< 0;
577 rmesa
->setup
.scale_3d_cntl
&= ~R128_TEX_CACHE_SPLIT
;
578 t
->setup
.tex_cntl
&= ~R128_SEC_SELECT_SEC_ST
;
581 rmesa
->setup
.tex_cntl_c
|= R128_SEC_TEXMAP_ENABLE
;
582 rmesa
->setup
.tex_size_pitch_c
|= t
->setup
.tex_size_pitch
<< 16;
583 rmesa
->setup
.scale_3d_cntl
|= R128_TEX_CACHE_SPLIT
;
584 t
->setup
.tex_cntl
|= R128_SEC_SELECT_SEC_ST
;
586 /* If the second TMU is enabled, then multitexturing is happening.
588 if ( R128_IS_PLAIN( rmesa
) )
589 rmesa
->blend_flags
|= R128_BLEND_MULTITEX
;
592 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
595 /* FIXME: The Radeon has some cached state so that it can avoid calling
596 * FIXME: UpdateTextureEnv in some cases. Is that possible here?
598 return r128UpdateTextureEnv( ctx
, unit
);
601 static GLboolean
updateTextureUnit( GLcontext
*ctx
, int unit
)
603 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
604 const int source
= rmesa
->tmu_source
[unit
];
605 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
608 if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
609 return (enable_tex_2d( ctx
, unit
) &&
610 update_tex_common( ctx
, unit
));
612 else if ( texUnit
->_ReallyEnabled
) {
616 disable_tex( ctx
, unit
);
622 void r128UpdateTextureState( GLcontext
*ctx
)
624 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
628 /* This works around a quirk with the R128 hardware. If only OpenGL
629 * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used. The
630 * hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
633 rmesa
->tmu_source
[0] = 0;
634 rmesa
->tmu_source
[1] = 1;
636 if ((ctx
->Texture
._EnabledUnits
& 0x03) == 0x02) {
637 /* only texture 1 enabled */
638 rmesa
->tmu_source
[0] = 1;
639 rmesa
->tmu_source
[1] = 0;
642 ok
= (updateTextureUnit( ctx
, 0 ) &&
643 updateTextureUnit( ctx
, 1 ));
645 FALLBACK( rmesa
, R128_FALLBACK_TEXTURE
, !ok
);