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 case MESA_FORMAT_ARGB8888_REV
:
69 t
->textureFormat
= R128_DATATYPE_ARGB8888
;
71 case MESA_FORMAT_ARGB4444
:
72 case MESA_FORMAT_ARGB4444_REV
:
73 t
->textureFormat
= R128_DATATYPE_ARGB4444
;
75 case MESA_FORMAT_RGB565
:
76 case MESA_FORMAT_RGB565_REV
:
77 t
->textureFormat
= R128_DATATYPE_RGB565
;
79 case MESA_FORMAT_RGB332
:
80 t
->textureFormat
= R128_DATATYPE_RGB8
;
83 t
->textureFormat
= R128_DATATYPE_CI8
;
85 case MESA_FORMAT_YCBCR
:
86 t
->textureFormat
= R128_DATATYPE_YVYU422
;
88 case MESA_FORMAT_YCBCR_REV
:
89 t
->textureFormat
= R128_DATATYPE_VYUY422
;
92 _mesa_problem(rmesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
95 /* Compute which mipmap levels we really want to send to the hardware.
98 driCalculateTextureFirstLastLevel( (driTextureObject
*) t
);
99 firstLevel
= t
->base
.firstLevel
;
100 lastLevel
= t
->base
.lastLevel
;
102 log2Pitch
= tObj
->Image
[0][firstLevel
]->WidthLog2
;
103 log2Height
= tObj
->Image
[0][firstLevel
]->HeightLog2
;
104 log2Size
= MAX2(log2Pitch
, log2Height
);
105 log2MinSize
= log2Size
;
107 t
->base
.dirty_images
[0] = 0;
109 for ( i
= firstLevel
; i
<= lastLevel
; i
++ ) {
110 const struct gl_texture_image
*texImage
;
112 texImage
= tObj
->Image
[0][i
];
113 if ( !texImage
|| !texImage
->Data
) {
118 log2MinSize
= texImage
->MaxLog2
;
120 t
->image
[i
- firstLevel
].offset
= totalSize
;
121 t
->image
[i
- firstLevel
].width
= tObj
->Image
[0][i
]->Width
;
122 t
->image
[i
- firstLevel
].height
= tObj
->Image
[0][i
]->Height
;
124 t
->base
.dirty_images
[0] |= (1 << i
);
126 totalSize
+= (tObj
->Image
[0][i
]->Height
*
127 tObj
->Image
[0][i
]->Width
*
128 tObj
->Image
[0][i
]->TexFormat
->TexelBytes
);
130 /* Offsets must be 32-byte aligned for host data blits and tiling */
131 totalSize
= (totalSize
+ 31) & ~31;
134 t
->base
.totalSize
= totalSize
;
135 t
->base
.firstLevel
= firstLevel
;
136 t
->base
.lastLevel
= lastLevel
;
138 /* Set the texture format */
139 t
->setup
.tex_cntl
&= ~(0xf << 16);
140 t
->setup
.tex_cntl
|= t
->textureFormat
;
142 t
->setup
.tex_combine_cntl
= 0x00000000; /* XXX is this right? */
144 t
->setup
.tex_size_pitch
= ((log2Pitch
<< R128_TEX_PITCH_SHIFT
) |
145 (log2Size
<< R128_TEX_SIZE_SHIFT
) |
146 (log2Height
<< R128_TEX_HEIGHT_SHIFT
) |
147 (log2MinSize
<< R128_TEX_MIN_SIZE_SHIFT
));
149 for ( i
= 0 ; i
< R128_MAX_TEXTURE_LEVELS
; i
++ ) {
150 t
->setup
.tex_offset
[i
] = 0x00000000;
153 if (firstLevel
== lastLevel
)
154 t
->setup
.tex_cntl
|= R128_MIP_MAP_DISABLE
;
156 t
->setup
.tex_cntl
&= ~R128_MIP_MAP_DISABLE
;
158 /* FYI: r128UploadTexImages( rmesa, t ); used to be called here */
162 /* ================================================================
163 * Texture combine functions
166 #define COLOR_COMB_DISABLE (R128_COMB_DIS | \
167 R128_COLOR_FACTOR_TEX)
168 #define COLOR_COMB_COPY_INPUT (R128_COMB_COPY_INP | \
169 R128_COLOR_FACTOR_TEX)
170 #define COLOR_COMB_MODULATE (R128_COMB_MODULATE | \
171 R128_COLOR_FACTOR_TEX)
172 #define COLOR_COMB_MODULATE_NTEX (R128_COMB_MODULATE | \
173 R128_COLOR_FACTOR_NTEX)
174 #define COLOR_COMB_ADD (R128_COMB_ADD | \
175 R128_COLOR_FACTOR_TEX)
176 #define COLOR_COMB_BLEND_TEX (R128_COMB_BLEND_TEXTURE | \
177 R128_COLOR_FACTOR_TEX)
178 /* Rage 128 Pro/M3 only! */
179 #define COLOR_COMB_BLEND_COLOR (R128_COMB_MODULATE2X | \
180 R128_COMB_FCN_MSB | \
181 R128_COLOR_FACTOR_CONST_COLOR)
183 #define ALPHA_COMB_DISABLE (R128_COMB_ALPHA_DIS | \
184 R128_ALPHA_FACTOR_TEX_ALPHA)
185 #define ALPHA_COMB_COPY_INPUT (R128_COMB_ALPHA_COPY_INP | \
186 R128_ALPHA_FACTOR_TEX_ALPHA)
187 #define ALPHA_COMB_MODULATE (R128_COMB_ALPHA_MODULATE | \
188 R128_ALPHA_FACTOR_TEX_ALPHA)
189 #define ALPHA_COMB_MODULATE_NTEX (R128_COMB_ALPHA_MODULATE | \
190 R128_ALPHA_FACTOR_NTEX_ALPHA)
191 #define ALPHA_COMB_ADD (R128_COMB_ALPHA_ADD | \
192 R128_ALPHA_FACTOR_TEX_ALPHA)
194 #define INPUT_INTERP (R128_INPUT_FACTOR_INT_COLOR | \
195 R128_INP_FACTOR_A_INT_ALPHA)
196 #define INPUT_PREVIOUS (R128_INPUT_FACTOR_PREV_COLOR | \
197 R128_INP_FACTOR_A_PREV_ALPHA)
199 static GLboolean
r128UpdateTextureEnv( GLcontext
*ctx
, int unit
)
201 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
202 GLint source
= rmesa
->tmu_source
[unit
];
203 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
204 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
205 const GLenum format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
208 if ( R128_DEBUG
& DEBUG_VERBOSE_API
) {
209 fprintf( stderr
, "%s( %p, %d )\n",
210 __FUNCTION__
, (void *) ctx
, unit
);
214 combine
= INPUT_INTERP
;
216 combine
= INPUT_PREVIOUS
;
219 /* Set the texture environment state */
220 switch ( texUnit
->EnvMode
) {
224 case GL_LUMINANCE_ALPHA
:
226 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
227 ALPHA_COMB_DISABLE
); /* A = At */
231 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
232 ALPHA_COMB_COPY_INPUT
); /* A = Af */
235 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
236 ALPHA_COMB_DISABLE
); /* A = At */
247 case GL_LUMINANCE_ALPHA
:
249 combine
|= (COLOR_COMB_MODULATE
| /* C = CfCt */
250 ALPHA_COMB_MODULATE
); /* A = AfAt */
254 combine
|= (COLOR_COMB_MODULATE
| /* C = CfCt */
255 ALPHA_COMB_COPY_INPUT
); /* A = Af */
258 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
259 ALPHA_COMB_MODULATE
); /* A = AfAt */
270 combine
|= (COLOR_COMB_BLEND_TEX
| /* C = Cf(1-At)+CtAt */
271 ALPHA_COMB_COPY_INPUT
); /* A = Af */
274 combine
|= (COLOR_COMB_DISABLE
| /* C = Ct */
275 ALPHA_COMB_COPY_INPUT
); /* A = Af */
279 case GL_LUMINANCE_ALPHA
:
281 /* Undefined behaviour - just copy the incoming fragment */
282 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = undefined */
283 ALPHA_COMB_COPY_INPUT
); /* A = undefined */
292 /* Rage 128 Pro and M3 can handle GL_BLEND texturing.
294 if ( !R128_IS_PLAIN( rmesa
) ) {
295 /* XXX this hasn't been fully tested, I don't have a Pro card. -BP */
298 case GL_LUMINANCE_ALPHA
:
299 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-Ct)+CcCt */
300 ALPHA_COMB_MODULATE
); /* A = AfAt */
305 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-Ct)+CcCt */
306 ALPHA_COMB_COPY_INPUT
); /* A = Af */
310 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
311 ALPHA_COMB_MODULATE
); /* A = AfAt */
315 /* GH: We could be smarter about this... */
316 switch ( rmesa
->env_color
& 0xff000000 ) {
318 combine
|= (COLOR_COMB_BLEND_COLOR
| /* C = Cf(1-It)+CcIt */
319 ALPHA_COMB_MODULATE_NTEX
); /* A = Af(1-It) */
321 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
322 ALPHA_COMB_MODULATE
); /* A = fallback */
334 /* Rage 128 has to fake some cases of GL_BLEND, otherwise fallback
335 * to software rendering.
337 if ( rmesa
->blend_flags
) {
342 case GL_LUMINANCE_ALPHA
:
343 switch ( rmesa
->env_color
& 0x00ffffff ) {
345 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
346 ALPHA_COMB_MODULATE
); /* A = AfAt */
349 /* This isn't right - BP */
352 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
353 ALPHA_COMB_MODULATE
); /* A = AfAt */
355 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
356 ALPHA_COMB_COPY_INPUT
); /* A = Af */
361 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
362 ALPHA_COMB_MODULATE
); /* A = fallback */
368 switch ( rmesa
->env_color
& 0x00ffffff ) {
370 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
371 ALPHA_COMB_COPY_INPUT
); /* A = Af */
374 /* This isn't right - BP */
377 combine
|= (COLOR_COMB_MODULATE_NTEX
| /* C = Cf(1-Ct) */
378 ALPHA_COMB_COPY_INPUT
); /* A = Af */
380 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
381 ALPHA_COMB_COPY_INPUT
); /* A = Af */
386 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
387 ALPHA_COMB_COPY_INPUT
); /* A = fallback */
393 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
394 ALPHA_COMB_MODULATE
); /* A = AfAt */
396 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
397 ALPHA_COMB_COPY_INPUT
); /* A = Af */
401 switch ( rmesa
->env_color
& 0x00ffffff ) {
403 combine
|= COLOR_COMB_MODULATE_NTEX
; /* C = Cf(1-It) */
406 /* This isn't right - BP */
409 combine
|= COLOR_COMB_MODULATE_NTEX
; /* C = Cf(1-It) */
411 combine
|= COLOR_COMB_ADD
; /* C = Cf+It */
416 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
417 ALPHA_COMB_MODULATE
); /* A = fallback */
420 switch ( rmesa
->env_color
& 0xff000000 ) {
422 combine
|= ALPHA_COMB_MODULATE_NTEX
; /* A = Af(1-It) */
425 /* This isn't right - BP */
428 combine
|= ALPHA_COMB_MODULATE_NTEX
; /* A = Af(1-It) */
430 combine
|= ALPHA_COMB_ADD
; /* A = Af+It */
435 combine
|= (COLOR_COMB_MODULATE
| /* C = fallback */
436 ALPHA_COMB_MODULATE
); /* A = fallback */
449 case GL_LUMINANCE_ALPHA
:
450 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
451 ALPHA_COMB_MODULATE
); /* A = AfAt */
455 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
456 ALPHA_COMB_COPY_INPUT
); /* A = Af */
459 combine
|= (COLOR_COMB_COPY_INPUT
| /* C = Cf */
460 ALPHA_COMB_MODULATE
); /* A = AfAt */
463 combine
|= (COLOR_COMB_ADD
| /* C = Cf+Ct */
464 ALPHA_COMB_ADD
); /* A = Af+At */
476 if ( rmesa
->tex_combine
[unit
] != combine
) {
477 rmesa
->tex_combine
[unit
] = combine
;
478 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
483 static void disable_tex( GLcontext
*ctx
, int unit
)
485 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
487 FLUSH_BATCH( rmesa
);
489 if ( rmesa
->CurrentTexObj
[unit
] ) {
490 rmesa
->CurrentTexObj
[unit
]->base
.bound
&= ~(1 << unit
);
491 rmesa
->CurrentTexObj
[unit
] = NULL
;
494 rmesa
->setup
.tex_cntl_c
&= ~(R128_TEXMAP_ENABLE
<< unit
);
495 rmesa
->setup
.tex_size_pitch_c
&= ~(R128_TEX_SIZE_PITCH_MASK
<<
496 (R128_SEC_TEX_SIZE_PITCH_SHIFT
* unit
));
497 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
499 /* If either texture unit is disabled, then multitexturing is not
503 rmesa
->blend_flags
&= ~R128_BLEND_MULTITEX
;
506 static GLboolean
enable_tex_2d( GLcontext
*ctx
, int unit
)
508 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
509 const int source
= rmesa
->tmu_source
[unit
];
510 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
511 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
512 r128TexObjPtr t
= (r128TexObjPtr
) tObj
->DriverData
;
514 /* Need to load the 2d images associated with this unit.
516 if ( t
->base
.dirty_images
[0] ) {
517 /* FIXME: For Radeon, RADEON_FIREVERTICES is called here. Should
518 * FIXME: something similar be done for R128?
520 /* FLUSH_BATCH( rmesa ); */
522 r128SetTexImages( rmesa
, tObj
);
523 r128UploadTexImages( rmesa
, t
);
524 if ( !t
->base
.memBlock
)
531 static GLboolean
update_tex_common( GLcontext
*ctx
, int unit
)
533 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
534 const int source
= rmesa
->tmu_source
[unit
];
535 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
536 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
537 r128TexObjPtr t
= (r128TexObjPtr
) tObj
->DriverData
;
540 /* Fallback if there's a texture border */
541 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 ) {
546 /* Update state if this is a different texture object to last
549 if ( rmesa
->CurrentTexObj
[unit
] != t
) {
550 if ( rmesa
->CurrentTexObj
[unit
] != NULL
) {
551 /* The old texture is no longer bound to this texture unit.
555 rmesa
->CurrentTexObj
[unit
]->base
.bound
&=
559 rmesa
->CurrentTexObj
[unit
] = t
;
560 t
->base
.bound
|= (1UL << unit
);
561 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
563 driUpdateTextureLRU( (driTextureObject
*) t
); /* XXX: should be locked! */
566 /* FIXME: We need to update the texture unit if any texture parameters have
567 * changed, but this texture was already bound. This could be changed to
568 * work like the Radeon driver where the texture object has it's own
571 rmesa
->dirty
|= R128_UPLOAD_TEX0
<< unit
;
574 rmesa
->setup
.tex_size_pitch_c
&= ~(R128_TEX_SIZE_PITCH_MASK
<<
575 (R128_SEC_TEX_SIZE_PITCH_SHIFT
* unit
));
578 rmesa
->setup
.tex_cntl_c
|= R128_TEXMAP_ENABLE
;
579 rmesa
->setup
.tex_size_pitch_c
|= t
->setup
.tex_size_pitch
<< 0;
580 rmesa
->setup
.scale_3d_cntl
&= ~R128_TEX_CACHE_SPLIT
;
581 t
->setup
.tex_cntl
&= ~R128_SEC_SELECT_SEC_ST
;
584 rmesa
->setup
.tex_cntl_c
|= R128_SEC_TEXMAP_ENABLE
;
585 rmesa
->setup
.tex_size_pitch_c
|= t
->setup
.tex_size_pitch
<< 16;
586 rmesa
->setup
.scale_3d_cntl
|= R128_TEX_CACHE_SPLIT
;
587 t
->setup
.tex_cntl
|= R128_SEC_SELECT_SEC_ST
;
589 /* If the second TMU is enabled, then multitexturing is happening.
591 if ( R128_IS_PLAIN( rmesa
) )
592 rmesa
->blend_flags
|= R128_BLEND_MULTITEX
;
595 rmesa
->dirty
|= R128_UPLOAD_CONTEXT
;
598 /* FIXME: The Radeon has some cached state so that it can avoid calling
599 * FIXME: UpdateTextureEnv in some cases. Is that possible here?
601 return r128UpdateTextureEnv( ctx
, unit
);
604 static GLboolean
updateTextureUnit( GLcontext
*ctx
, int unit
)
606 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
607 const int source
= rmesa
->tmu_source
[unit
];
608 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
611 if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
612 return (enable_tex_2d( ctx
, unit
) &&
613 update_tex_common( ctx
, unit
));
615 else if ( texUnit
->_ReallyEnabled
) {
619 disable_tex( ctx
, unit
);
625 void r128UpdateTextureState( GLcontext
*ctx
)
627 r128ContextPtr rmesa
= R128_CONTEXT(ctx
);
631 /* This works around a quirk with the R128 hardware. If only OpenGL
632 * TEXTURE1 is enabled, then the hardware TEXTURE0 must be used. The
633 * hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
636 rmesa
->tmu_source
[0] = 0;
637 rmesa
->tmu_source
[1] = 1;
639 if ((ctx
->Texture
._EnabledUnits
& 0x03) == 0x02) {
640 /* only texture 1 enabled */
641 rmesa
->tmu_source
[0] = 1;
642 rmesa
->tmu_source
[1] = 0;
645 ok
= (updateTextureUnit( ctx
, 0 ) &&
646 updateTextureUnit( ctx
, 1 ));
648 FALLBACK( rmesa
, R128_FALLBACK_TEXTURE
, !ok
);