1 /**************************************************************************
3 Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
4 Copyright 2003 Eric Anholt
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 ERIC ANHOLT OR SILICON INTEGRATED SYSTEMS CORP 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 **************************************************************************/
31 * Sung-Ching Lin <sclin@sis.com.tw>
32 * Eric Anholt <anholt@FreeBSD.org>
39 #include "texformat.h"
41 #include "sis_context.h"
42 #include "sis_state.h"
45 #include "sis_alloc.h"
47 static GLint
TransferTexturePitch (GLint dwPitch
);
49 /* Handle texenv stuff, called from validate_texture (renderstart) */
51 sis_set_texture_env0( GLcontext
*ctx
, struct gl_texture_object
*texObj
,
54 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
56 __GLSiSHardware
*prev
= &smesa
->prev
;
57 __GLSiSHardware
*current
= &smesa
->current
;
59 struct gl_texture_unit
*texture_unit
= &ctx
->Texture
.Unit
[unit
];
61 sisTexObjPtr t
= texObj
->DriverData
;
63 switch (texture_unit
->EnvMode
)
66 FALLBACK(smesa
, SIS_FALLBACK_TEXENV0
, 0);
70 current
->hwTexBlendColor0
= STAGE0_C_CF
;
71 current
->hwTexBlendAlpha0
= STAGE0_A_AS
;
75 current
->hwTexBlendColor0
= STAGE0_C_CS
;
76 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
79 case GL_LUMINANCE_ALPHA
:
81 current
->hwTexBlendColor0
= STAGE0_C_CS
;
82 current
->hwTexBlendAlpha0
= STAGE0_A_AS
;
88 FALLBACK(smesa
, SIS_FALLBACK_TEXENV0
, 0);
92 current
->hwTexBlendColor0
= STAGE0_C_CF
;
93 current
->hwTexBlendAlpha0
= STAGE0_A_AFAS
;
97 current
->hwTexBlendColor0
= STAGE0_C_CFCS
;
98 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
101 case GL_LUMINANCE_ALPHA
:
103 current
->hwTexBlendColor0
= STAGE0_C_CFCS
;
104 current
->hwTexBlendAlpha0
= STAGE0_A_AFAS
;
110 FALLBACK(smesa
, SIS_FALLBACK_TEXENV0
, 0);
114 current
->hwTexBlendColor0
= STAGE0_C_CS
;
115 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
118 current
->hwTexBlendColor0
= STAGE0_C_CFOMAS_CSAS
;
119 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
125 #if 1 /* XXX Blending broken */
126 FALLBACK(smesa
, SIS_FALLBACK_TEXENV0
, 1);
128 FALLBACK(smesa
, SIS_FALLBACK_TEXENV0
, 0);
129 current
->hwTexEnvColor
=
130 ((GLint
) (texture_unit
->EnvColor
[3])) << 24 |
131 ((GLint
) (texture_unit
->EnvColor
[0])) << 16 |
132 ((GLint
) (texture_unit
->EnvColor
[1])) << 8 |
133 ((GLint
) (texture_unit
->EnvColor
[2]));
137 current
->hwTexBlendColor0
= STAGE0_C_CF
;
138 current
->hwTexBlendAlpha0
= STAGE0_A_AFAS
;
142 current
->hwTexBlendColor0
= STAGE0_C_CFOMCS_CCCS
;
143 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
146 current
->hwTexBlendColor0
= STAGE0_C_CFOMCS_CCCS
;
147 current
->hwTexBlendAlpha0
= STAGE0_A_AFOMAS_ACAS
;
149 case GL_LUMINANCE_ALPHA
:
151 current
->hwTexBlendColor0
= STAGE0_C_CFOMCS_CCCS
;
152 current
->hwTexBlendAlpha0
= STAGE0_A_AFAS
;
159 if ((current
->hwTexBlendColor0
!= prev
->hwTexBlendColor0
) ||
160 (current
->hwTexBlendAlpha0
!= prev
->hwTexBlendAlpha0
) ||
161 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
163 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
164 prev
->hwTexBlendColor0
= current
->hwTexBlendColor0
;
165 prev
->hwTexBlendAlpha0
= current
->hwTexBlendAlpha0
;
166 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV
;
170 /* Handle texenv stuff, called from validate_texture (renderstart) */
172 sis_set_texture_env1( GLcontext
*ctx
, struct gl_texture_object
*texObj
,
175 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
177 __GLSiSHardware
*prev
= &smesa
->prev
;
178 __GLSiSHardware
*current
= &smesa
->current
;
180 struct gl_texture_unit
*texture_unit
= &ctx
->Texture
.Unit
[unit
];
182 sisTexObjPtr t
= texObj
->DriverData
;
184 switch (texture_unit
->EnvMode
)
187 FALLBACK(smesa
, SIS_FALLBACK_TEXENV1
, 0);
191 current
->hwTexBlendColor1
= STAGE1_C_CF
;
192 current
->hwTexBlendAlpha1
= STAGE1_A_AS
;
196 current
->hwTexBlendColor1
= STAGE1_C_CS
;
197 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
200 case GL_LUMINANCE_ALPHA
:
202 current
->hwTexBlendColor1
= STAGE1_C_CS
;
203 current
->hwTexBlendAlpha1
= STAGE1_A_AS
;
209 FALLBACK(smesa
, SIS_FALLBACK_TEXENV1
, 0);
213 current
->hwTexBlendColor1
= STAGE1_C_CF
;
214 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
218 current
->hwTexBlendColor1
= STAGE1_C_CFCS
;
219 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
222 case GL_LUMINANCE_ALPHA
:
224 current
->hwTexBlendColor1
= STAGE1_C_CFCS
;
225 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
231 FALLBACK(smesa
, SIS_FALLBACK_TEXENV1
, 0);
235 current
->hwTexBlendColor1
= STAGE1_C_CS
;
236 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
239 current
->hwTexBlendColor1
= STAGE1_C_CFOMAS_CSAS
;
240 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
246 FALLBACK(smesa
, SIS_FALLBACK_TEXENV1
, 1);
247 #if 0 /* XXX Blending broken */
248 current
->hwTexEnvColor
=
249 ((GLint
) (texture_unit
->EnvColor
[3])) << 24 |
250 ((GLint
) (texture_unit
->EnvColor
[0])) << 16 |
251 ((GLint
) (texture_unit
->EnvColor
[1])) << 8 |
252 ((GLint
) (texture_unit
->EnvColor
[2]));
256 current
->hwTexBlendColor1
= STAGE1_C_CF
;
257 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
261 current
->hwTexBlendColor1
= STAGE1_C_CFOMCS_CCCS
;
262 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
265 current
->hwTexBlendColor1
= STAGE1_C_CFOMCS_CCCS
;
266 current
->hwTexBlendAlpha1
= STAGE1_A_AFOMAS_ACAS
;
268 case GL_LUMINANCE_ALPHA
:
270 current
->hwTexBlendColor1
= STAGE1_C_CFOMCS_CCCS
;
271 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
278 if ((current
->hwTexBlendColor1
!= prev
->hwTexBlendColor1
) ||
279 (current
->hwTexBlendAlpha1
!= prev
->hwTexBlendAlpha1
) ||
280 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
282 prev
->hwTexBlendColor1
= current
->hwTexBlendColor1
;
283 prev
->hwTexBlendAlpha1
= current
->hwTexBlendAlpha1
;
284 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
285 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV_1
;
289 /* Returns 0 if a software fallback is necessary */
291 sis_set_texobj_parm( GLcontext
*ctx
, struct gl_texture_object
*texObj
,
294 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
297 __GLSiSHardware
*prev
= &smesa
->prev
;
298 __GLSiSHardware
*current
= &smesa
->current
;
300 sisTexObjPtr t
= texObj
->DriverData
;
302 GLint firstLevel
, lastLevel
;
305 current
->texture
[hw_unit
].hwTextureMip
= 0UL;
306 current
->texture
[hw_unit
].hwTextureSet
= t
->hwformat
;
308 if ((texObj
->MinFilter
== GL_NEAREST
) || (texObj
->MinFilter
== GL_LINEAR
)) {
309 firstLevel
= lastLevel
= texObj
->BaseLevel
;
311 /* Compute which mipmap levels we really want to send to the hardware.
312 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
313 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL and GL_TEXTURE_MAX_LEVEL.
314 * Yes, this looks overly complicated, but it's all needed.
317 firstLevel
= texObj
->BaseLevel
+ (GLint
)(texObj
->MinLod
+ 0.5);
318 firstLevel
= MAX2(firstLevel
, texObj
->BaseLevel
);
319 lastLevel
= texObj
->BaseLevel
+ (GLint
)(texObj
->MaxLod
+ 0.5);
320 lastLevel
= MAX2(lastLevel
, texObj
->BaseLevel
);
321 lastLevel
= MIN2(lastLevel
, texObj
->BaseLevel
+
322 texObj
->Image
[0][texObj
->BaseLevel
]->MaxLog2
);
323 lastLevel
= MIN2(lastLevel
, texObj
->MaxLevel
);
324 lastLevel
= MAX2(firstLevel
, lastLevel
); /* need at least one level */
327 current
->texture
[hw_unit
].hwTextureSet
|= (lastLevel
<< 8);
329 switch (texObj
->MagFilter
)
332 current
->texture
[hw_unit
].hwTextureMip
|= TEXTURE_FILTER_NEAREST
;
335 current
->texture
[hw_unit
].hwTextureMip
|= (TEXTURE_FILTER_LINEAR
<< 3);
342 /* The mipmap lod biasing is based on experiment. It seems there's a
343 * limit of around +4/-4 to the bias value; we're being conservative.
345 b
= (GLint
) (ctx
->Texture
.Unit
[hw_unit
].LodBias
* 32.0);
351 current
->texture
[hw_unit
].hwTextureMip
|= ((b
<< 4) &
352 MASK_TextureMipmapLodBias
);
355 switch (texObj
->MinFilter
)
358 current
->texture
[hw_unit
].hwTextureMip
|= TEXTURE_FILTER_NEAREST
;
361 current
->texture
[hw_unit
].hwTextureMip
|= TEXTURE_FILTER_LINEAR
;
363 case GL_NEAREST_MIPMAP_NEAREST
:
364 current
->texture
[hw_unit
].hwTextureMip
|=
365 TEXTURE_FILTER_NEAREST_MIP_NEAREST
;
367 case GL_NEAREST_MIPMAP_LINEAR
:
368 current
->texture
[hw_unit
].hwTextureMip
|=
369 TEXTURE_FILTER_NEAREST_MIP_LINEAR
;
371 case GL_LINEAR_MIPMAP_NEAREST
:
372 current
->texture
[hw_unit
].hwTextureMip
|=
373 TEXTURE_FILTER_LINEAR_MIP_NEAREST
;
375 case GL_LINEAR_MIPMAP_LINEAR
:
376 current
->texture
[hw_unit
].hwTextureMip
|=
377 TEXTURE_FILTER_LINEAR_MIP_LINEAR
;
381 switch (texObj
->WrapS
)
384 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureWrapU
;
387 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureClampU
;
389 case GL_CLAMP_TO_EDGE
:
397 switch (texObj
->WrapT
)
400 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureWrapV
;
403 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureClampV
;
405 case GL_CLAMP_TO_EDGE
:
414 if (current->texture[hw_unit].hwTextureSet & MASK_TextureClampU) {
415 current->texture[hw_unit].hwTextureSet &= ~MASK_TextureClampU;
416 current->texture[hw_unit].hwTextureSet |= MASK_TextureBorderU;
419 if (current->texture[hw_unit].hwTextureSet & MASK_TextureClampV) {
420 current->texture[hw_unit].hwTextureSet &= ~MASK_TextureClampV;
421 current->texture[hw_unit].hwTextureSet |= MASK_TextureBorderV;
424 current
->texture
[hw_unit
].hwTextureBorderColor
=
425 ((GLuint
) texObj
->BorderColor
[3] << 24) +
426 ((GLuint
) texObj
->BorderColor
[0] << 16) +
427 ((GLuint
) texObj
->BorderColor
[1] << 8) +
428 ((GLuint
) texObj
->BorderColor
[2]);
430 if (current
->texture
[hw_unit
].hwTextureBorderColor
!=
431 prev
->texture
[hw_unit
].hwTextureBorderColor
)
433 prev
->texture
[hw_unit
].hwTextureBorderColor
=
434 current
->texture
[hw_unit
].hwTextureBorderColor
;
436 smesa
->GlobalFlag
|= GFLAG_TEXBORDERCOLOR_1
;
438 smesa
->GlobalFlag
|= GFLAG_TEXBORDERCOLOR
;
441 current
->texture
[hw_unit
].hwTextureSet
|=
442 texObj
->Image
[0][firstLevel
]->WidthLog2
<< 4;
443 current
->texture
[hw_unit
].hwTextureSet
|=
444 texObj
->Image
[0][firstLevel
]->HeightLog2
;
447 smesa
->GlobalFlag
|= GFLAG_TEXTUREADDRESS
;
449 smesa
->GlobalFlag
|= GFLAG_TEXTUREADDRESS_1
;
451 for (i
= firstLevel
; i
<= lastLevel
; i
++)
453 GLuint texOffset
= 0;
454 GLuint texPitch
= TransferTexturePitch( t
->image
[i
].pitch
);
456 switch (t
->image
[i
].memType
)
459 texOffset
= ((unsigned long)t
->image
[i
].Data
- (unsigned long)smesa
->FbBase
);
462 texOffset
= ((unsigned long)t
->image
[i
].Data
- (unsigned long)smesa
->AGPBase
) +
463 (unsigned long) smesa
->AGPAddr
;
464 current
->texture
[hw_unit
].hwTextureMip
|=
465 (MASK_TextureLevel0InSystem
<< i
);
472 prev
->texture
[hw_unit
].texOffset0
= texOffset
;
473 prev
->texture
[hw_unit
].texPitch01
= texPitch
<< 16;
476 prev
->texture
[hw_unit
].texOffset1
= texOffset
;
477 prev
->texture
[hw_unit
].texPitch01
|= texPitch
;
480 prev
->texture
[hw_unit
].texOffset2
= texOffset
;
481 prev
->texture
[hw_unit
].texPitch23
= texPitch
<< 16;
484 prev
->texture
[hw_unit
].texOffset3
= texOffset
;
485 prev
->texture
[hw_unit
].texPitch23
|= texPitch
;
488 prev
->texture
[hw_unit
].texOffset4
= texOffset
;
489 prev
->texture
[hw_unit
].texPitch45
= texPitch
<< 16;
492 prev
->texture
[hw_unit
].texOffset5
= texOffset
;
493 prev
->texture
[hw_unit
].texPitch45
|= texPitch
;
496 prev
->texture
[hw_unit
].texOffset6
= texOffset
;
497 prev
->texture
[hw_unit
].texPitch67
= texPitch
<< 16;
500 prev
->texture
[hw_unit
].texOffset7
= texOffset
;
501 prev
->texture
[hw_unit
].texPitch67
|= texPitch
;
504 prev
->texture
[hw_unit
].texOffset8
= texOffset
;
505 prev
->texture
[hw_unit
].texPitch89
= texPitch
<< 16;
508 prev
->texture
[hw_unit
].texOffset9
= texOffset
;
509 prev
->texture
[hw_unit
].texPitch89
|= texPitch
;
512 prev
->texture
[hw_unit
].texOffset10
= texOffset
;
513 prev
->texture
[hw_unit
].texPitch10
= texPitch
<< 16;
516 prev
->texture
[hw_unit
].texOffset11
= texOffset
;
517 prev
->texture
[hw_unit
].texPitch10
|= texPitch
;
522 if (current
->texture
[hw_unit
].hwTextureSet
!=
523 prev
->texture
[hw_unit
].hwTextureSet
)
525 prev
->texture
[hw_unit
].hwTextureSet
=
526 current
->texture
[hw_unit
].hwTextureSet
;
528 smesa
->GlobalFlag
|= CFLAG_TEXTURERESET_1
;
530 smesa
->GlobalFlag
|= CFLAG_TEXTURERESET
;
532 if (current
->texture
[hw_unit
].hwTextureMip
!=
533 prev
->texture
[hw_unit
].hwTextureMip
)
535 prev
->texture
[hw_unit
].hwTextureMip
=
536 current
->texture
[hw_unit
].hwTextureMip
;
538 smesa
->GlobalFlag
|= GFLAG_TEXTUREMIPMAP_1
;
540 smesa
->GlobalFlag
|= GFLAG_TEXTUREMIPMAP
;
546 /* Disable a texture unit, called from validate_texture */
548 sis_reset_texture_env (GLcontext
*ctx
, int hw_unit
)
550 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
552 __GLSiSHardware
*prev
= &smesa
->prev
;
553 __GLSiSHardware
*current
= &smesa
->current
;
557 current
->hwTexBlendColor1
= STAGE1_C_CF
;
558 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
560 if ((current
->hwTexBlendColor1
!= prev
->hwTexBlendColor1
) ||
561 (current
->hwTexBlendAlpha1
!= prev
->hwTexBlendAlpha1
) ||
562 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
564 prev
->hwTexBlendColor1
= current
->hwTexBlendColor1
;
565 prev
->hwTexBlendAlpha1
= current
->hwTexBlendAlpha1
;
566 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
567 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV_1
;
570 current
->hwTexBlendColor0
= STAGE0_C_CF
;
571 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
573 if ((current
->hwTexBlendColor0
!= prev
->hwTexBlendColor0
) ||
574 (current
->hwTexBlendAlpha0
!= prev
->hwTexBlendAlpha0
) ||
575 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
577 prev
->hwTexBlendColor0
= current
->hwTexBlendColor0
;
578 prev
->hwTexBlendAlpha0
= current
->hwTexBlendAlpha0
;
579 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
580 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV
;
585 static void updateTextureUnit( GLcontext
*ctx
, int unit
)
587 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
588 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
589 struct gl_texture_object
*texObj
= texUnit
->_Current
;
593 fallbackbit
= SIS_FALLBACK_TEXTURE0
;
595 fallbackbit
= SIS_FALLBACK_TEXTURE1
;
597 if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
598 if (smesa
->TexStates
[unit
] & NEW_TEXTURING
) {
601 ok
= sis_set_texobj_parm (ctx
, texObj
, unit
);
602 FALLBACK( smesa
, fallbackbit
, !ok
);
604 if (smesa
->TexStates
[unit
] & NEW_TEXTURE_ENV
) {
606 sis_set_texture_env0( ctx
, texObj
, unit
);
608 sis_set_texture_env1( ctx
, texObj
, unit
);
610 smesa
->TexStates
[unit
] = 0;
611 } else if ( texUnit
->_ReallyEnabled
) {
613 FALLBACK( smesa
, fallbackbit
, 1 );
615 sis_reset_texture_env( ctx
, unit
);
616 FALLBACK( smesa
, fallbackbit
, 0 );
621 void sisUpdateTextureState( GLcontext
*ctx
)
623 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
625 __GLSiSHardware
*current
= &smesa
->current
;
628 /* TODO : if unmark these, error in multitexture */ /* XXX */
629 for (i
= 0; i
< SIS_MAX_TEXTURES
; i
++)
630 smesa
->TexStates
[i
] |= (NEW_TEXTURING
| NEW_TEXTURE_ENV
);
633 updateTextureUnit( ctx
, 0 );
634 updateTextureUnit( ctx
, 1 );
636 /* XXX Issues with the 2nd unit but not the first being enabled? */
637 if ( ctx
->Texture
.Unit
[0]._ReallyEnabled
&
638 (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) ||
639 ctx
->Texture
.Unit
[1]._ReallyEnabled
&
640 (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) )
642 current
->hwCapEnable
|= MASK_TextureEnable
;
643 current
->hwCapEnable
&= ~MASK_TextureNumUsed
;
644 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
)
645 current
->hwCapEnable
|= 0x00002000;
647 current
->hwCapEnable
|= 0x00001000;
649 current
->hwCapEnable
&= ~MASK_TextureEnable
;
654 BitScanForward( GLshort w
)
658 for (i
= 0; i
< 16; i
++) {
666 TransferTexturePitch( GLint dwPitch
)
670 i
= BitScanForward( (GLshort
)dwPitch
);
671 dwRet
= dwPitch
>> i
;