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"
45 #include "r128_tris.h"
49 static void r128SetTexImages( r128ContextPtr rmesa
,
50 const struct gl_texture_object
*tObj
)
52 r128TexObjPtr t
= (r128TexObjPtr
) tObj
->DriverData
;
53 struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
54 int log2Pitch
, log2Height
, log2Size
, log2MinSize
;
57 GLint firstLevel
, lastLevel
;
62 if ( R128_DEBUG
& DEBUG_VERBOSE_API
)
63 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, (void *) tObj
);
65 switch (baseImage
->TexFormat
->MesaFormat
) {
66 case MESA_FORMAT_ARGB8888
:
67 case MESA_FORMAT_ARGB8888_REV
:
68 t
->textureFormat
= R128_DATATYPE_ARGB8888
;
70 case MESA_FORMAT_ARGB4444
:
71 case MESA_FORMAT_ARGB4444_REV
:
72 t
->textureFormat
= R128_DATATYPE_ARGB4444
;
74 case MESA_FORMAT_RGB565
:
75 case MESA_FORMAT_RGB565_REV
:
76 t
->textureFormat
= R128_DATATYPE_RGB565
;
78 case MESA_FORMAT_RGB332
:
79 t
->textureFormat
= R128_DATATYPE_RGB8
;
82 t
->textureFormat
= R128_DATATYPE_CI8
;
84 case MESA_FORMAT_YCBCR
:
85 t
->textureFormat
= R128_DATATYPE_YVYU422
;
87 case MESA_FORMAT_YCBCR_REV
:
88 t
->textureFormat
= R128_DATATYPE_VYUY422
;
91 _mesa_problem(rmesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
94 /* Compute which mipmap levels we really want to send to the hardware.
97 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
98 firstLevel
= t
->base
.firstLevel
;
99 lastLevel
= t
->base
.lastLevel
;
101 log2Pitch
= tObj
->Image
[0][firstLevel
]->WidthLog2
;
102 log2Height
= tObj
->Image
[0][firstLevel
]->HeightLog2
;
103 log2Size
= MAX2(log2Pitch
, log2Height
);
104 log2MinSize
= log2Size
;
106 t
->base
.dirty_images
[0] = 0;
108 for ( i
= firstLevel
; i
<= lastLevel
; i
++ ) {
109 const struct gl_texture_image
*texImage
;
111 texImage
= tObj
->Image
[0][i
];
112 if ( !texImage
|| !texImage
->Data
) {
117 log2MinSize
= texImage
->MaxLog2
;
119 t
->image
[i
- firstLevel
].offset
= totalSize
;
120 t
->image
[i
- firstLevel
].width
= tObj
->Image
[0][i
]->Width
;
121 t
->image
[i
- firstLevel
].height
= tObj
->Image
[0][i
]->Height
;
123 t
->base
.dirty_images
[0] |= (1 << i
);
125 totalSize
+= (tObj
->Image
[0][i
]->Height
*
126 tObj
->Image
[0][i
]->Width
*
127 tObj
->Image
[0][i
]->TexFormat
->TexelBytes
);
129 /* Offsets must be 32-byte aligned for host data blits and tiling */
130 totalSize
= (totalSize
+ 31) & ~31;
133 t
->base
.totalSize
= totalSize
;
134 t
->base
.firstLevel
= firstLevel
;
135 t
->base
.lastLevel
= lastLevel
;
137 /* Set the texture format */
138 t
->setup
.tex_cntl
&= ~(0xf << 16);
139 t
->setup
.tex_cntl
|= t
->textureFormat
;
141 t
->setup
.tex_combine_cntl
= 0x00000000; /* XXX is this right? */
143 t
->setup
.tex_size_pitch
= ((log2Pitch
<< R128_TEX_PITCH_SHIFT
) |
144 (log2Size
<< R128_TEX_SIZE_SHIFT
) |
145 (log2Height
<< R128_TEX_HEIGHT_SHIFT
) |
146 (log2MinSize
<< R128_TEX_MIN_SIZE_SHIFT
));
148 for ( i
= 0 ; i
< R128_MAX_TEXTURE_LEVELS
; i
++ ) {
149 t
->setup
.tex_offset
[i
] = 0x00000000;
152 if (firstLevel
== lastLevel
)
153 t
->setup
.tex_cntl
|= R128_MIP_MAP_DISABLE
;
155 t
->setup
.tex_cntl
&= ~R128_MIP_MAP_DISABLE
;
157 /* FYI: r128UploadTexImages( rmesa, t ); used to be called here */
161 /* ================================================================
162 * Texture combine functions
165 #define COLOR_COMB_DISABLE (R128_COMB_DIS | \
166 R128_COLOR_FACTOR_TEX)
167 #define COLOR_COMB_COPY_INPUT (R128_COMB_COPY_INP | \
168 R128_COLOR_FACTOR_TEX)
169 #define COLOR_COMB_MODULATE (R128_COMB_MODULATE | \
170 R128_COLOR_FACTOR_TEX)
171 #define COLOR_COMB_MODULATE_NTEX (R128_COMB_MODULATE | \
172 R128_COLOR_FACTOR_NTEX)
173 #define COLOR_COMB_ADD (R128_COMB_ADD | \
174 R128_COLOR_FACTOR_TEX)
175 #define COLOR_COMB_BLEND_TEX (R128_COMB_BLEND_TEXTURE | \
176 R128_COLOR_FACTOR_TEX)
177 /* Rage 128 Pro/M3 only! */
178 #define COLOR_COMB_BLEND_COLOR (R128_COMB_MODULATE2X | \
179 R128_COMB_FCN_MSB | \
180 R128_COLOR_FACTOR_CONST_COLOR)
182 #define ALPHA_COMB_DISABLE (R128_COMB_ALPHA_DIS | \
183 R128_ALPHA_FACTOR_TEX_ALPHA)
184 #define ALPHA_COMB_COPY_INPUT (R128_COMB_ALPHA_COPY_INP | \
185 R128_ALPHA_FACTOR_TEX_ALPHA)
186 #define ALPHA_COMB_MODULATE (R128_COMB_ALPHA_MODULATE | \
187 R128_ALPHA_FACTOR_TEX_ALPHA)
188 #define ALPHA_COMB_MODULATE_NTEX (R128_COMB_ALPHA_MODULATE | \
189 R128_ALPHA_FACTOR_NTEX_ALPHA)
190 #define ALPHA_COMB_ADD (R128_COMB_ALPHA_ADD | \
191 R128_ALPHA_FACTOR_TEX_ALPHA)
193 #define INPUT_INTERP (R128_INPUT_FACTOR_INT_COLOR | \
194 R128_INP_FACTOR_A_INT_ALPHA)
195 #define INPUT_PREVIOUS (R128_INPUT_FACTOR_PREV_COLOR | \
196 R128_INP_FACTOR_A_PREV_ALPHA)
198 static GLboolean
r128UpdateTextureEnv( GLcontext
*ctx
, int unit
)
200 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
201 GLint source
= rmesa
->tmu_source
[unit
];
202 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
203 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
204 const GLenum format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
207 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
208 fprintf( stderr
, "%s( %p, %d )\n",
209 __FUNCTION__
, (void *) ctx
, unit
);
213 combine
= INPUT_INTERP
;
215 combine
= INPUT_PREVIOUS
;
218 /* Set the texture environment state */
219 switch ( texUnit
->EnvMode
) {
223 case GL_LUMINANCE_ALPHA
:
225 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
226 ALPHA_COMB_DISABLE
); /* A = At */
230 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
231 ALPHA_COMB_COPY_INPUT
); /* A = Af */
234 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
235 ALPHA_COMB_DISABLE
); /* A = At */
246 case GL_LUMINANCE_ALPHA
:
248 combine
|= (COLOR_COMB_MODULATE
| /* C = CfCt */
249 ALPHA_COMB_MODULATE
); /* A = AfAt */
253 combine
|= (COLOR_COMB_MODULATE
| /* C = CfCt */
254 ALPHA_COMB_COPY_INPUT
); /* A = Af */
257 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
258 ALPHA_COMB_MODULATE
); /* A = AfAt */
269 combine
|= (COLOR_COMB_BLEND_TEX
| /* C = Cf(1-At)+CtAt */
270 ALPHA_COMB_COPY_INPUT
); /* A = Af */
273 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
274 ALPHA_COMB_COPY_INPUT
); /* A = Af */
278 case GL_LUMINANCE_ALPHA
:
280 /* Undefined behaviour - just copy the incoming fragment */
281 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = undefined */
282 ALPHA_COMB_COPY_INPUT
); /* A = undefined */
291 /* Rage 128 Pro and M3 can handle GL_BLEND texturing.
293 if ( !R128_IS_PLAIN( rmesa
) ) {
294 /* XXX this hasn't been fully tested, I don't have a Pro card. -BP */
297 case GL_LUMINANCE_ALPHA
:
298 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-Ct)+CcCt */
299 ALPHA_COMB_MODULATE
); /* A = AfAt */
304 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-Ct)+CcCt */
305 ALPHA_COMB_COPY_INPUT
); /* A = Af */
309 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
310 ALPHA_COMB_MODULATE
); /* A = AfAt */
314 /* GH: We could be smarter about this... */
315 switch ( rmesa
->env_color
& 0xff000000 ) {
317 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-It)+CcIt */
318 ALPHA_COMB_MODULATE_NTEX
); /* A = Af(1-It) */
320 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
321 ALPHA_COMB_MODULATE
); /* A = fallback */
333 /* Rage 128 has to fake some cases of GL_BLEND, otherwise fallback
334 * to software rendering.
336 if ( rmesa
->blend_flags
) {
341 case GL_LUMINANCE_ALPHA
:
342 switch ( rmesa
->env_color
& 0x00ffffff ) {
344 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
345 ALPHA_COMB_MODULATE
); /* A = AfAt */
348 /* This isn't right - BP */
351 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
352 ALPHA_COMB_MODULATE
); /* A = AfAt */
354 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
355 ALPHA_COMB_COPY_INPUT
); /* A = Af */
360 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
361 ALPHA_COMB_MODULATE
); /* A = fallback */
367 switch ( rmesa
->env_color
& 0x00ffffff ) {
369 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
370 ALPHA_COMB_COPY_INPUT
); /* A = Af */
373 /* This isn't right - BP */
376 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
377 ALPHA_COMB_COPY_INPUT
); /* A = Af */
379 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
380 ALPHA_COMB_COPY_INPUT
); /* A = Af */
385 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
386 ALPHA_COMB_COPY_INPUT
); /* A = fallback */
392 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
393 ALPHA_COMB_MODULATE
); /* A = AfAt */
395 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
396 ALPHA_COMB_COPY_INPUT
); /* A = Af */
400 switch ( rmesa
->env_color
& 0x00ffffff ) {
402 combine
|= COLOR_COMB_MODULATE_NTEX
; /* C = Cf(1-It) */
405 /* This isn't right - BP */
408 combine
|= COLOR_COMB_MODULATE_NTEX
; /* C = Cf(1-It) */
410 combine
|= COLOR_COMB_ADD
; /* C = Cf+It */
415 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
416 ALPHA_COMB_MODULATE
); /* A = fallback */
419 switch ( rmesa
->env_color
& 0xff000000 ) {
421 combine
|= ALPHA_COMB_MODULATE_NTEX
; /* A = Af(1-It) */
424 /* This isn't right - BP */
427 combine
|= ALPHA_COMB_MODULATE_NTEX
; /* A = Af(1-It) */
429 combine
|= ALPHA_COMB_ADD
; /* A = Af+It */
434 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
435 ALPHA_COMB_MODULATE
); /* A = fallback */
448 case GL_LUMINANCE_ALPHA
:
449 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
450 ALPHA_COMB_MODULATE
); /* A = AfAt */
454 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
455 ALPHA_COMB_COPY_INPUT
); /* A = Af */
458 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
459 ALPHA_COMB_MODULATE
); /* A = AfAt */
462 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
463 ALPHA_COMB_ADD
); /* A = Af+At */
475 if ( rmesa
->tex_combine
[unit
] != combine
) {
476 rmesa
->tex_combine
[unit
] = combine
;
477 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
482 static void disable_tex( GLcontext
*ctx
, int unit
)
484 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
486 FLUSH_BATCH( rmesa
);
488 if ( rmesa
->CurrentTexObj
[unit
] ) {
489 rmesa
->CurrentTexObj
[unit
]->base
.bound
&= ~(1 << unit
);
490 rmesa
->CurrentTexObj
[unit
] = NULL
;
493 rmesa
->setup
.tex_cntl_c
&= ~(R128_TEXMAP_ENABLE
<< unit
);
494 rmesa
->setup
.tex_size_pitch_c
&= ~(R128_TEX_SIZE_PITCH_MASK
<<
495 (R128_SEC_TEX_SIZE_PITCH_SHIFT
* unit
));
496 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
498 /* If either texture unit is disabled, then multitexturing is not
502 rmesa
->blend_flags
&= ~R128_BLEND_MULTITEX
;
505 static GLboolean
enable_tex_2d( GLcontext
*ctx
, int unit
)
507 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
508 const int source
= rmesa
->tmu_source
[unit
];
509 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
510 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
511 r128TexObjPtr t
= (r128TexObjPtr
) tObj
->DriverData
;
513 /* Need to load the 2d images associated with this unit.
515 if ( t
->base
.dirty_images
[0] ) {
516 /* FIXME: For Radeon, RADEON_FIREVERTICES is called here. Should
517 * FIXME: something similar be done for R128?
519 /* FLUSH_BATCH( rmesa ); */
521 r128SetTexImages( rmesa
, tObj
);
522 r128UploadTexImages( rmesa
, t
);
523 if ( !t
->base
.memBlock
)
530 static GLboolean
update_tex_common( GLcontext
*ctx
, int unit
)
532 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
533 const int source
= rmesa
->tmu_source
[unit
];
534 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
535 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
536 r128TexObjPtr t
= (r128TexObjPtr
) tObj
->DriverData
;
539 /* Fallback if there's a texture border */
540 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 ) {
545 /* Update state if this is a different texture object to last
548 if ( rmesa
->CurrentTexObj
[unit
] != t
) {
549 if ( rmesa
->CurrentTexObj
[unit
] != NULL
) {
550 /* The old texture is no longer bound to this texture unit.
554 rmesa
->CurrentTexObj
[unit
]->base
.bound
&=
558 rmesa
->CurrentTexObj
[unit
] = t
;
559 t
->base
.bound
|= (1UL << unit
);
560 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
562 driUpdateTextureLRU( (driTextureObject
*) t
); /* XXX: should be locked! */
565 /* FIXME: We need to update the texture unit if any texture parameters have
566 * changed, but this texture was already bound. This could be changed to
567 * work like the Radeon driver where the texture object has it's own
570 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
573 rmesa
->setup
.tex_size_pitch_c
&= ~(R128_TEX_SIZE_PITCH_MASK
<<
574 (R128_SEC_TEX_SIZE_PITCH_SHIFT
* unit
));
577 rmesa
->setup
.tex_cntl_c
|= R128_TEXMAP_ENABLE
;
578 rmesa
->setup
.tex_size_pitch_c
|= t
->setup
.tex_size_pitch
<< 0;
579 rmesa
->setup
.scale_3d_cntl
&= ~R128_TEX_CACHE_SPLIT
;
580 t
->setup
.tex_cntl
&= ~R128_SEC_SELECT_SEC_ST
;
583 rmesa
->setup
.tex_cntl_c
|= R128_SEC_TEXMAP_ENABLE
;
584 rmesa
->setup
.tex_size_pitch_c
|= t
->setup
.tex_size_pitch
<< 16;
585 rmesa
->setup
.scale_3d_cntl
|= R128_TEX_CACHE_SPLIT
;
586 t
->setup
.tex_cntl
|= R128_SEC_SELECT_SEC_ST
;
588 /* If the second TMU is enabled, then multitexturing is happening.
590 if ( R128_IS_PLAIN( rmesa
) )
591 rmesa
->blend_flags
|= R128_BLEND_MULTITEX
;
594 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
597 /* FIXME: The Radeon has some cached state so that it can avoid calling
598 * FIXME: UpdateTextureEnv in some cases. Is that possible here?
600 return r128UpdateTextureEnv( ctx
, unit
);
603 static GLboolean
updateTextureUnit( GLcontext
*ctx
, int unit
)
605 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
606 const int source
= rmesa
->tmu_source
[unit
];
607 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
610 if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
611 return (enable_tex_2d( ctx
, unit
) &&
612 update_tex_common( ctx
, unit
));
614 else if ( texUnit
->_ReallyEnabled
) {
618 disable_tex( ctx
, unit
);
624 void r128UpdateTextureState( GLcontext
*ctx
)
626 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
630 /* This works around a quirk with the R128 hardware. If only OpenGL
631 * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used. The
632 * hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
635 rmesa
->tmu_source
[0] = 0;
636 rmesa
->tmu_source
[1] = 1;
638 if ((ctx
->Texture
._EnabledUnits
& 0x03) == 0x02) {
639 /* only texture 1 enabled */
640 rmesa
->tmu_source
[0] = 1;
641 rmesa
->tmu_source
[1] = 0;
644 ok
= (updateTextureUnit( ctx
, 0 ) &&
645 updateTextureUnit( ctx
, 1 ));
647 FALLBACK( rmesa
, R128_FALLBACK_TEXTURE
, !ok
);