1 /* $XFree86$ */ /* -*- mode: c; c-basic-offset: 3 -*- */
3 * Copyright 2000 Gareth Hughes
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice (including the next
14 * paragraph) shall be included in all copies or substantial portions of the
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * GARETH HUGHES BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 * Gareth Hughes <gareth@valinux.com>
28 * Leif Delgass <ldelgass@retinalburn.net>
29 * José Fonseca <j_r_fonseca@yahoo.co.uk>
36 #include "texformat.h"
38 #include "mach64_context.h"
39 #include "mach64_ioctl.h"
40 #include "mach64_state.h"
41 #include "mach64_vb.h"
42 #include "mach64_tris.h"
43 #include "mach64_tex.h"
45 static void mach64SetTexImages( mach64ContextPtr mmesa
,
46 const struct gl_texture_object
*tObj
)
48 mach64TexObjPtr t
= (mach64TexObjPtr
) tObj
->DriverData
;
49 struct gl_texture_image
*baseImage
= tObj
->Image
[0][tObj
->BaseLevel
];
51 int log2Pitch
, log2Height
, log2Size
, log2MinSize
;
53 GLint firstLevel
, lastLevel
;
60 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
)
61 fprintf( stderr
, "%s( %p )\n", __FUNCTION__
, tObj
);
63 switch (baseImage
->TexFormat
->MesaFormat
) {
64 case MESA_FORMAT_ARGB8888
:
65 t
->textureFormat
= MACH64_DATATYPE_ARGB8888
;
67 case MESA_FORMAT_ARGB4444
:
68 t
->textureFormat
= MACH64_DATATYPE_ARGB4444
;
70 case MESA_FORMAT_RGB565
:
71 t
->textureFormat
= MACH64_DATATYPE_RGB565
;
73 case MESA_FORMAT_ARGB1555
:
74 t
->textureFormat
= MACH64_DATATYPE_ARGB1555
;
76 case MESA_FORMAT_RGB332
:
77 t
->textureFormat
= MACH64_DATATYPE_RGB332
;
79 case MESA_FORMAT_RGB888
:
80 t
->textureFormat
= MACH64_DATATYPE_RGB8
;
83 t
->textureFormat
= MACH64_DATATYPE_CI8
;
85 case MESA_FORMAT_YCBCR
:
86 t
->textureFormat
= MACH64_DATATYPE_YVYU422
;
88 case MESA_FORMAT_YCBCR_REV
:
89 t
->textureFormat
= MACH64_DATATYPE_VYUY422
;
92 _mesa_problem(mmesa
->glCtx
, "Bad texture format in %s", __FUNCTION__
);
96 /* Compute which mipmap levels we really want to send to the hardware.
97 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
98 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
99 * Yes, this looks overly complicated, but it's all needed.
101 firstLevel
= tObj
->BaseLevel
+ (GLint
) (tObj
->MinLod
+ 0.5);
102 firstLevel
= MAX2(firstLevel
, tObj
->BaseLevel
);
103 lastLevel
= tObj
->BaseLevel
+ (GLint
) (tObj
->MaxLod
+ 0.5);
104 lastLevel
= MAX2(lastLevel
, tObj
->BaseLevel
);
105 lastLevel
= MIN2(lastLevel
, tObj
->BaseLevel
+ baseImage
->MaxLog2
);
106 lastLevel
= MIN2(lastLevel
, tObj
->MaxLevel
);
107 lastLevel
= MAX2(firstLevel
, lastLevel
); /* need at least one level */
109 log2Pitch
= tObj
->Image
[firstLevel
]->WidthLog2
;
110 log2Height
= tObj
->Image
[firstLevel
]->HeightLog2
;
111 log2Size
= MAX2(log2Pitch
, log2Height
);
112 log2MinSize
= log2Size
;
116 for ( i
= firstLevel
; i
<= lastLevel
; i
++ ) {
117 const struct gl_texture_image
*texImage
;
119 texImage
= tObj
->Image
[i
];
120 if ( !texImage
|| !texImage
->Data
) {
125 log2MinSize
= texImage
->MaxLog2
;
127 t
->image
[i
- firstLevel
].offset
= totalSize
;
128 t
->image
[i
- firstLevel
].width
= tObj
->Image
[i
]->Width
;
129 t
->image
[i
- firstLevel
].height
= tObj
->Image
[i
]->Height
;
131 t
->dirty
|= (1 << i
);
133 totalSize
+= (tObj
->Image
[i
]->Height
*
134 tObj
->Image
[i
]->Width
*
135 tObj
->Image
[i
]->TexFormat
->TexelBytes
);
137 /* Offsets must be 32-byte aligned for host data blits and tiling */
138 totalSize
= (totalSize
+ 31) & ~31;
141 t
->totalSize
= totalSize
;
142 t
->firstLevel
= firstLevel
;
143 t
->lastLevel
= lastLevel
;
145 /* Set the texture format */
146 t
->setup
.tex_cntl
&= ~(0xf << 16);
147 t
->setup
.tex_cntl
|= t
->textureFormat
;
149 t
->setup
.tex_combine_cntl
= 0x00000000; /* XXX is this right? */
151 t
->setup
.tex_size_pitch
= ((log2Pitch
<< R128_TEX_PITCH_SHIFT
) |
152 (log2Size
<< R128_TEX_SIZE_SHIFT
) |
153 (log2Height
<< R128_TEX_HEIGHT_SHIFT
) |
154 (log2MinSize
<< R128_TEX_MIN_SIZE_SHIFT
));
156 for ( i
= 0 ; i
< R128_MAX_TEXTURE_LEVELS
; i
++ ) {
157 t
->setup
.tex_offset
[i
] = 0x00000000;
160 if (firstLevel
== lastLevel
)
161 t
->setup
.tex_cntl
|= R128_MIP_MAP_DISABLE
;
163 t
->setup
.tex_cntl
&= ~R128_MIP_MAP_DISABLE
;
166 if ( ( baseImage
->Format
== GL_RGBA
) ||
167 ( baseImage
->Format
== GL_ALPHA
) ||
168 ( baseImage
->Format
== GL_LUMINANCE_ALPHA
) ) {
174 totalSize
= ( baseImage
->Width
* baseImage
->Height
*
175 baseImage
->TexFormat
->TexelBytes
);
176 totalSize
= (totalSize
+ 31) & ~31;
178 t
->widthLog2
= baseImage
->WidthLog2
;
179 t
->heightLog2
= baseImage
->HeightLog2
;
180 t
->maxLog2
= baseImage
->MaxLog2
;
185 static void mach64UpdateTextureEnv( GLcontext
*ctx
, int unit
)
187 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
188 GLint source
= mmesa
->tmu_source
[unit
];
189 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
190 const struct gl_texture_object
*tObj
= texUnit
->_Current
;
191 const GLenum format
= tObj
->Image
[0][tObj
->BaseLevel
]->Format
;
192 GLuint s
= mmesa
->setup
.scale_3d_cntl
;
194 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
195 fprintf( stderr
, "%s( %p, %d )\n",
196 __FUNCTION__
, ctx
, unit
);
199 /* REPLACE MODULATE DECAL GL_BLEND
201 * ALPHA C = Cf C = Cf undef C = Cf
202 * A = At A = AfAt A = AfAt
204 * LUMINANCE C = Ct C = CfCt undef C = Cf(1-Ct)+CcCt
205 * A = Af A = Af A = Af
207 * LUMINANCE_ALPHA C = Ct C = CfCt undef C = Cf(1-Ct)+CcCt
208 * A = At A = AfAt A = AfAt
210 * INTENSITY C = Ct C = CfCt undef C = Cf(1-Ct)+CcCt
211 * A = At A = AfAt A = Af(1-At)+AcAt
213 * RGB C = Ct C = CfCt C = Ct C = Cf(1-Ct)+CcCt
214 * A = Af A = Af A = Af A = Af
216 * RGBA C = Ct C = CfCt C = Cf(1-At)+CtAt C = Cf(1-Ct)+CcCt
217 * A = At A = AfAt A = Af A = AfAt
222 s
&= ~MACH64_TEX_LIGHT_FCN_MASK
;
224 /* Set the texture environment state
225 * Need to verify these are working correctly, but the
226 * texenv Mesa demo seems to work.
228 switch ( texUnit
->EnvMode
) {
232 case GL_LUMINANCE_ALPHA
:
234 /* Not compliant - can't get At */
235 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
236 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
239 s
|= MACH64_TEX_LIGHT_FCN_REPLACE
;
245 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
246 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
250 /* These should be compliant */
251 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
253 case GL_LUMINANCE_ALPHA
:
255 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
256 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
259 /* Should fallback when blending enabled for complete compliance */
260 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
263 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
269 s
|= MACH64_TEX_LIGHT_FCN_ALPHA_DECAL
;
272 s
|= MACH64_TEX_LIGHT_FCN_REPLACE
;
275 case GL_LUMINANCE_ALPHA
:
276 /* undefined - disable texturing, pass fragment unmodified */
277 /* Also, pass fragment alpha instead of texture alpha */
278 s
&= ~MACH64_TEX_MAP_AEN
;
279 s
|= MACH64_TEXTURE_DISABLE
;
280 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
284 /* undefined - disable texturing, pass fragment unmodified */
285 s
|= MACH64_TEXTURE_DISABLE
;
286 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
289 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
293 /* GL_BLEND not supported by RagePRO, use software */
294 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
295 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
299 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
300 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
303 s
|= MACH64_TEX_LIGHT_FCN_MODULATE
;
306 if ( mmesa
->setup
.scale_3d_cntl
!= s
) {
307 mmesa
->setup
.scale_3d_cntl
= s
;
308 mmesa
->dirty
|= MACH64_UPLOAD_SCALE_3D_CNTL
;
312 /* blend = 0, modulate = 1 - initialize to blend */
313 mmesa
->setup
.tex_cntl
&= ~MACH64_COMP_COMBINE_MODULATE
;
314 /* Set the texture composite function for multitexturing*/
315 switch ( texUnit
->EnvMode
) {
317 /* GL_BLEND not supported by RagePRO, use software */
318 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
319 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
322 /* Should fallback when blending enabled for complete compliance */
323 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
328 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
330 default: /* not supported by RagePRO */
331 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
332 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
339 case GL_LUMINANCE_ALPHA
:
341 /* undefined, disable compositing and pass fragment unmodified */
342 mmesa
->setup
.tex_cntl
&= ~MACH64_TEXTURE_COMPOSITE
;
344 default: /* not supported by RagePRO */
345 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
346 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
351 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
352 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
355 mmesa
->setup
.tex_cntl
|= MACH64_COMP_COMBINE_MODULATE
;
361 static void mach64UpdateTextureUnit( GLcontext
*ctx
, int unit
)
363 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
364 int source
= mmesa
->tmu_source
[unit
];
365 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[source
];
366 const struct gl_texture_object
*tObj
= ctx
->Texture
.Unit
[source
]._Current
;
367 mach64TexObjPtr t
= tObj
->DriverData
;
368 GLuint d
= mmesa
->setup
.dp_pix_width
;
369 GLuint s
= mmesa
->setup
.scale_3d_cntl
;
371 assert(unit
== 0 || unit
== 1); /* only two tex units */
373 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
374 fprintf( stderr
, "%s( %p, %d ) enabled=0x%x 0x%x\n",
375 __FUNCTION__
, ctx
, unit
, ctx
->Texture
.Unit
[0]._ReallyEnabled
,
376 ctx
->Texture
.Unit
[1]._ReallyEnabled
);
379 if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
381 assert(t
); /* should have driver tex data by now */
383 /* Fallback if there's a texture border */
384 if ( tObj
->Image
[0][tObj
->BaseLevel
]->Border
> 0 ) {
385 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
389 /* Upload teximages */
391 mach64SetTexImages( mmesa
, tObj
);
392 mmesa
->dirty
|= (MACH64_UPLOAD_TEX0IMAGE
<< unit
);
395 /* Bind to the given texture unit */
396 mmesa
->CurrentTexObj
[unit
] = t
;
397 t
->bound
|= (1 << unit
);
400 mach64UpdateTexLRU( mmesa
, t
);
404 d
&= ~MACH64_SCALE_PIX_WIDTH_MASK
;
405 d
|= (t
->textureFormat
<< 28);
407 s
&= ~(MACH64_TEXTURE_DISABLE
|
408 MACH64_TEX_CACHE_SPLIT
|
409 MACH64_TEX_BLEND_FCN_MASK
|
412 if ( mmesa
->multitex
) {
413 s
|= MACH64_TEX_BLEND_FCN_TRILINEAR
| MACH64_TEX_CACHE_SPLIT
;
414 } else if ( t
->BilinearMin
) {
415 s
|= MACH64_TEX_BLEND_FCN_LINEAR
;
417 s
|= MACH64_TEX_BLEND_FCN_NEAREST
;
419 if ( t
->BilinearMag
) {
420 s
|= MACH64_BILINEAR_TEX_EN
;
422 s
&= ~MACH64_BILINEAR_TEX_EN
;
426 s
|= MACH64_TEX_MAP_AEN
;
429 mmesa
->setup
.tex_cntl
&= ~(MACH64_TEXTURE_CLAMP_S
|
430 MACH64_TEXTURE_CLAMP_T
|
431 MACH64_SECONDARY_STW
);
434 mmesa
->setup
.tex_cntl
|= MACH64_TEXTURE_CLAMP_S
;
437 mmesa
->setup
.tex_cntl
|= MACH64_TEXTURE_CLAMP_T
;
440 mmesa
->setup
.tex_size_pitch
|= ((t
->widthLog2
<< 0) |
442 (t
->heightLog2
<< 8));
445 /* Enable texture mapping mode */
446 s
&= ~MACH64_TEXTURE_DISABLE
;
448 d
&= ~MACH64_COMPOSITE_PIX_WIDTH_MASK
;
449 d
|= (t
->textureFormat
<< 4);
451 mmesa
->setup
.tex_cntl
&= ~(MACH64_COMP_ALPHA
|
452 MACH64_SEC_TEX_CLAMP_S
|
453 MACH64_SEC_TEX_CLAMP_T
);
454 mmesa
->setup
.tex_cntl
|= (MACH64_TEXTURE_COMPOSITE
|
455 MACH64_SECONDARY_STW
);
457 if ( t
->BilinearMin
) {
458 mmesa
->setup
.tex_cntl
|= MACH64_COMP_BLEND_BILINEAR
;
460 mmesa
->setup
.tex_cntl
&= ~MACH64_COMP_BLEND_BILINEAR
;
462 if ( t
->BilinearMag
) {
463 mmesa
->setup
.tex_cntl
|= MACH64_COMP_FILTER_BILINEAR
;
465 mmesa
->setup
.tex_cntl
&= ~MACH64_COMP_FILTER_BILINEAR
;
469 mmesa
->setup
.tex_cntl
|= MACH64_COMP_ALPHA
;
472 mmesa
->setup
.tex_cntl
|= MACH64_SEC_TEX_CLAMP_S
;
475 mmesa
->setup
.tex_cntl
|= MACH64_SEC_TEX_CLAMP_T
;
478 mmesa
->setup
.tex_size_pitch
|= ((t
->widthLog2
<< 16) |
480 (t
->heightLog2
<< 24));
483 if ( mmesa
->setup
.scale_3d_cntl
!= s
) {
484 mmesa
->setup
.scale_3d_cntl
= s
;
485 mmesa
->dirty
|= MACH64_UPLOAD_SCALE_3D_CNTL
;
488 if ( mmesa
->setup
.dp_pix_width
!= d
) {
489 mmesa
->setup
.dp_pix_width
= d
;
490 mmesa
->dirty
|= MACH64_UPLOAD_DP_PIX_WIDTH
;
493 else if (texUnit
->_ReallyEnabled
) {
494 /* 3D or cube map texture enabled - fallback */
495 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_TRUE
);
498 /* texture unit disabled */
503 /* Update the hardware texture state */
504 void mach64UpdateTextureState( GLcontext
*ctx
)
506 mach64ContextPtr mmesa
= MACH64_CONTEXT(ctx
);
508 if ( MACH64_DEBUG
& DEBUG_VERBOSE_API
) {
509 fprintf( stderr
, "%s( %p ) en=0x%x 0x%x\n",
510 __FUNCTION__
, ctx
, ctx
->Texture
.Unit
[0]._ReallyEnabled
,
511 ctx
->Texture
.Unit
[1]._ReallyEnabled
);
514 /* Clear any texturing fallbacks */
515 FALLBACK( mmesa
, MACH64_FALLBACK_TEXTURE
, GL_FALSE
);
517 /* Unbind any currently bound textures */
518 if ( mmesa
->CurrentTexObj
[0] ) mmesa
->CurrentTexObj
[0]->bound
= 0;
519 if ( mmesa
->CurrentTexObj
[1] ) mmesa
->CurrentTexObj
[1]->bound
= 0;
520 mmesa
->CurrentTexObj
[0] = NULL
;
521 mmesa
->CurrentTexObj
[1] = NULL
;
523 /* Disable all texturing until it is known to be good */
524 mmesa
->setup
.scale_3d_cntl
|= MACH64_TEXTURE_DISABLE
;
525 mmesa
->setup
.scale_3d_cntl
&= ~MACH64_TEX_MAP_AEN
;
526 mmesa
->setup
.tex_cntl
&= ~MACH64_TEXTURE_COMPOSITE
;
528 mmesa
->setup
.tex_size_pitch
= 0x00000000;
530 mmesa
->tmu_source
[0] = 0;
531 mmesa
->tmu_source
[1] = 1;
534 if (ctx
->Texture
._EnabledUnits
& 0x2) {
536 if (ctx
->Texture
._EnabledUnits
& 0x1) {
537 /* units 0 and 1 enabled */
539 mach64UpdateTextureUnit( ctx
, 0 );
540 mach64UpdateTextureEnv( ctx
, 0 );
541 mach64UpdateTextureUnit( ctx
, 1 );
542 mach64UpdateTextureEnv( ctx
, 1 );
544 mmesa
->tmu_source
[0] = 1;
545 mmesa
->tmu_source
[1] = 0;
546 mach64UpdateTextureUnit( ctx
, 0 );
547 mach64UpdateTextureEnv( ctx
, 0 );
549 } else if (ctx
->Texture
._EnabledUnits
& 0x1) {
550 /* only unit 0 enabled */
551 mach64UpdateTextureUnit( ctx
, 0 );
552 mach64UpdateTextureEnv( ctx
, 0 );
555 mmesa
->dirty
|= (MACH64_UPLOAD_SCALE_3D_CNTL
|
556 MACH64_UPLOAD_TEXTURE
);