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 FALLBACK(smesa
, SIS_FALLBACK_TEXENV0
, 1);
126 #if 0 /* XXX Blending broken */
127 current
->hwTexEnvColor
=
128 ((GLint
) (texture_unit
->EnvColor
[3])) << 24 |
129 ((GLint
) (texture_unit
->EnvColor
[0])) << 16 |
130 ((GLint
) (texture_unit
->EnvColor
[1])) << 8 |
131 ((GLint
) (texture_unit
->EnvColor
[2]));
135 current
->hwTexBlendColor0
= STAGE0_C_CF
;
136 current
->hwTexBlendAlpha0
= STAGE0_A_AFAS
;
140 current
->hwTexBlendColor0
= STAGE0_C_CFOMCS_CCCS
;
141 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
144 current
->hwTexBlendColor0
= STAGE0_C_CFOMCS_CCCS
;
145 current
->hwTexBlendAlpha0
= STAGE0_A_AFOMAS_ACAS
;
147 case GL_LUMINANCE_ALPHA
:
149 current
->hwTexBlendColor0
= STAGE0_C_CFOMCS_CCCS
;
150 current
->hwTexBlendAlpha0
= STAGE0_A_AFAS
;
157 if ((current
->hwTexBlendColor0
!= prev
->hwTexBlendColor0
) ||
158 (current
->hwTexBlendAlpha0
!= prev
->hwTexBlendAlpha0
) ||
159 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
161 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
162 prev
->hwTexBlendColor0
= current
->hwTexBlendColor0
;
163 prev
->hwTexBlendAlpha0
= current
->hwTexBlendAlpha0
;
164 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV
;
168 /* Handle texenv stuff, called from validate_texture (renderstart) */
170 sis_set_texture_env1( GLcontext
*ctx
, struct gl_texture_object
*texObj
,
173 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
175 __GLSiSHardware
*prev
= &smesa
->prev
;
176 __GLSiSHardware
*current
= &smesa
->current
;
178 struct gl_texture_unit
*texture_unit
= &ctx
->Texture
.Unit
[unit
];
180 sisTexObjPtr t
= texObj
->DriverData
;
182 switch (texture_unit
->EnvMode
)
185 FALLBACK(smesa
, SIS_FALLBACK_TEXENV1
, 0);
189 current
->hwTexBlendColor1
= STAGE1_C_CF
;
190 current
->hwTexBlendAlpha1
= STAGE1_A_AS
;
194 current
->hwTexBlendColor1
= STAGE1_C_CS
;
195 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
198 case GL_LUMINANCE_ALPHA
:
200 current
->hwTexBlendColor1
= STAGE1_C_CS
;
201 current
->hwTexBlendAlpha1
= STAGE1_A_AS
;
207 FALLBACK(smesa
, SIS_FALLBACK_TEXENV1
, 0);
211 current
->hwTexBlendColor1
= STAGE1_C_CF
;
212 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
216 current
->hwTexBlendColor1
= STAGE1_C_CFCS
;
217 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
220 case GL_LUMINANCE_ALPHA
:
222 current
->hwTexBlendColor1
= STAGE1_C_CFCS
;
223 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
229 FALLBACK(smesa
, SIS_FALLBACK_TEXENV1
, 0);
233 current
->hwTexBlendColor1
= STAGE1_C_CS
;
234 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
237 current
->hwTexBlendColor1
= STAGE1_C_CFOMAS_CSAS
;
238 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
244 FALLBACK(smesa
, SIS_FALLBACK_TEXENV1
, 1);
245 #if 0 /* XXX Blending broken */
246 current
->hwTexEnvColor
=
247 ((GLint
) (texture_unit
->EnvColor
[3])) << 24 |
248 ((GLint
) (texture_unit
->EnvColor
[0])) << 16 |
249 ((GLint
) (texture_unit
->EnvColor
[1])) << 8 |
250 ((GLint
) (texture_unit
->EnvColor
[2]));
254 current
->hwTexBlendColor1
= STAGE1_C_CF
;
255 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
259 current
->hwTexBlendColor1
= STAGE1_C_CFOMCS_CCCS
;
260 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
263 current
->hwTexBlendColor1
= STAGE1_C_CFOMCS_CCCS
;
264 current
->hwTexBlendAlpha1
= STAGE1_A_AFOMAS_ACAS
;
266 case GL_LUMINANCE_ALPHA
:
268 current
->hwTexBlendColor1
= STAGE1_C_CFOMCS_CCCS
;
269 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
276 if ((current
->hwTexBlendColor1
!= prev
->hwTexBlendColor1
) ||
277 (current
->hwTexBlendAlpha1
!= prev
->hwTexBlendAlpha1
) ||
278 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
280 prev
->hwTexBlendColor1
= current
->hwTexBlendColor1
;
281 prev
->hwTexBlendAlpha1
= current
->hwTexBlendAlpha1
;
282 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
283 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV_1
;
287 /* Returns 0 if a software fallback is necessary */
289 sis_set_texobj_parm( GLcontext
*ctx
, struct gl_texture_object
*texObj
,
292 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
295 __GLSiSHardware
*prev
= &smesa
->prev
;
296 __GLSiSHardware
*current
= &smesa
->current
;
298 sisTexObjPtr t
= texObj
->DriverData
;
300 GLint firstLevel
, lastLevel
;
303 current
->texture
[hw_unit
].hwTextureMip
= 0UL;
304 current
->texture
[hw_unit
].hwTextureSet
= t
->hwformat
;
306 if ((texObj
->MinFilter
== GL_NEAREST
) || (texObj
->MinFilter
== GL_LINEAR
)) {
307 firstLevel
= lastLevel
= texObj
->BaseLevel
;
309 /* Compute which mipmap levels we really want to send to the hardware.
310 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
311 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL and GL_TEXTURE_MAX_LEVEL.
312 * Yes, this looks overly complicated, but it's all needed.
315 firstLevel
= texObj
->BaseLevel
+ (GLint
)(texObj
->MinLod
+ 0.5);
316 firstLevel
= MAX2(firstLevel
, texObj
->BaseLevel
);
317 lastLevel
= texObj
->BaseLevel
+ (GLint
)(texObj
->MaxLod
+ 0.5);
318 lastLevel
= MAX2(lastLevel
, texObj
->BaseLevel
);
319 lastLevel
= MIN2(lastLevel
, texObj
->BaseLevel
+
320 texObj
->Image
[texObj
->BaseLevel
]->MaxLog2
);
321 lastLevel
= MIN2(lastLevel
, texObj
->MaxLevel
);
322 lastLevel
= MAX2(firstLevel
, lastLevel
); /* need at least one level */
325 current
->texture
[hw_unit
].hwTextureSet
|= (lastLevel
<< 8);
327 switch (texObj
->MagFilter
)
330 current
->texture
[hw_unit
].hwTextureMip
|= TEXTURE_FILTER_NEAREST
;
333 current
->texture
[hw_unit
].hwTextureMip
|= (TEXTURE_FILTER_LINEAR
<< 3);
340 /* The mipmap lod biasing is based on experiment. It seems there's a
341 * limit of around +4/-4 to the bias value; we're being conservative.
343 b
= (GLint
) (ctx
->Texture
.Unit
[hw_unit
].LodBias
* 32.0);
349 current
->texture
[hw_unit
].hwTextureMip
|= ((b
<< 4) &
350 MASK_TextureMipmapLodBias
);
353 switch (texObj
->MinFilter
)
356 current
->texture
[hw_unit
].hwTextureMip
|= TEXTURE_FILTER_NEAREST
;
359 current
->texture
[hw_unit
].hwTextureMip
|= TEXTURE_FILTER_LINEAR
;
361 case GL_NEAREST_MIPMAP_NEAREST
:
362 current
->texture
[hw_unit
].hwTextureMip
|=
363 TEXTURE_FILTER_NEAREST_MIP_NEAREST
;
365 case GL_NEAREST_MIPMAP_LINEAR
:
366 current
->texture
[hw_unit
].hwTextureMip
|=
367 TEXTURE_FILTER_NEAREST_MIP_LINEAR
;
369 case GL_LINEAR_MIPMAP_NEAREST
:
370 current
->texture
[hw_unit
].hwTextureMip
|=
371 TEXTURE_FILTER_LINEAR_MIP_NEAREST
;
373 case GL_LINEAR_MIPMAP_LINEAR
:
374 current
->texture
[hw_unit
].hwTextureMip
|=
375 TEXTURE_FILTER_LINEAR_MIP_LINEAR
;
379 switch (texObj
->WrapS
)
382 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureWrapU
;
385 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureClampU
;
387 case GL_CLAMP_TO_EDGE
:
395 switch (texObj
->WrapT
)
398 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureWrapV
;
401 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureClampV
;
403 case GL_CLAMP_TO_EDGE
:
412 if (current->texture[hw_unit].hwTextureSet & MASK_TextureClampU) {
413 current->texture[hw_unit].hwTextureSet &= ~MASK_TextureClampU;
414 current->texture[hw_unit].hwTextureSet |= MASK_TextureBorderU;
417 if (current->texture[hw_unit].hwTextureSet & MASK_TextureClampV) {
418 current->texture[hw_unit].hwTextureSet &= ~MASK_TextureClampV;
419 current->texture[hw_unit].hwTextureSet |= MASK_TextureBorderV;
422 current
->texture
[hw_unit
].hwTextureBorderColor
=
423 ((GLuint
) texObj
->BorderColor
[3] << 24) +
424 ((GLuint
) texObj
->BorderColor
[0] << 16) +
425 ((GLuint
) texObj
->BorderColor
[1] << 8) +
426 ((GLuint
) texObj
->BorderColor
[2]);
428 if (current
->texture
[hw_unit
].hwTextureBorderColor
!=
429 prev
->texture
[hw_unit
].hwTextureBorderColor
)
431 prev
->texture
[hw_unit
].hwTextureBorderColor
=
432 current
->texture
[hw_unit
].hwTextureBorderColor
;
434 smesa
->GlobalFlag
|= GFLAG_TEXBORDERCOLOR_1
;
436 smesa
->GlobalFlag
|= GFLAG_TEXBORDERCOLOR
;
439 current
->texture
[hw_unit
].hwTextureSet
|=
440 texObj
->Image
[firstLevel
]->WidthLog2
<< 4;
441 current
->texture
[hw_unit
].hwTextureSet
|=
442 texObj
->Image
[firstLevel
]->HeightLog2
;
445 smesa
->GlobalFlag
|= GFLAG_TEXTUREADDRESS
;
447 smesa
->GlobalFlag
|= GFLAG_TEXTUREADDRESS_1
;
449 for (i
= firstLevel
; i
<= lastLevel
; i
++)
451 GLuint texOffset
= 0;
452 GLuint texPitch
= TransferTexturePitch( t
->image
[i
].pitch
);
454 switch (t
->image
[i
].memType
)
457 texOffset
= ((unsigned long)t
->image
[i
].Data
- (unsigned long)smesa
->FbBase
);
460 texOffset
= ((unsigned long)t
->image
[i
].Data
- (unsigned long)smesa
->AGPBase
) +
461 (unsigned long) smesa
->AGPAddr
;
462 current
->texture
[hw_unit
].hwTextureMip
|=
463 (MASK_TextureLevel0InSystem
<< i
);
470 prev
->texture
[hw_unit
].texOffset0
= texOffset
;
471 prev
->texture
[hw_unit
].texPitch01
= texPitch
<< 16;
474 prev
->texture
[hw_unit
].texOffset1
= texOffset
;
475 prev
->texture
[hw_unit
].texPitch01
|= texPitch
;
478 prev
->texture
[hw_unit
].texOffset2
= texOffset
;
479 prev
->texture
[hw_unit
].texPitch23
= texPitch
<< 16;
482 prev
->texture
[hw_unit
].texOffset3
= texOffset
;
483 prev
->texture
[hw_unit
].texPitch23
|= texPitch
;
486 prev
->texture
[hw_unit
].texOffset4
= texOffset
;
487 prev
->texture
[hw_unit
].texPitch45
= texPitch
<< 16;
490 prev
->texture
[hw_unit
].texOffset5
= texOffset
;
491 prev
->texture
[hw_unit
].texPitch45
|= texPitch
;
494 prev
->texture
[hw_unit
].texOffset6
= texOffset
;
495 prev
->texture
[hw_unit
].texPitch67
= texPitch
<< 16;
498 prev
->texture
[hw_unit
].texOffset7
= texOffset
;
499 prev
->texture
[hw_unit
].texPitch67
|= texPitch
;
502 prev
->texture
[hw_unit
].texOffset8
= texOffset
;
503 prev
->texture
[hw_unit
].texPitch89
= texPitch
<< 16;
506 prev
->texture
[hw_unit
].texOffset9
= texOffset
;
507 prev
->texture
[hw_unit
].texPitch89
|= texPitch
;
510 prev
->texture
[hw_unit
].texOffset10
= texOffset
;
511 prev
->texture
[hw_unit
].texPitch10
= texPitch
<< 16;
514 prev
->texture
[hw_unit
].texOffset11
= texOffset
;
515 prev
->texture
[hw_unit
].texPitch10
|= texPitch
;
520 if (current
->texture
[hw_unit
].hwTextureSet
!=
521 prev
->texture
[hw_unit
].hwTextureSet
)
523 prev
->texture
[hw_unit
].hwTextureSet
=
524 current
->texture
[hw_unit
].hwTextureSet
;
526 smesa
->GlobalFlag
|= CFLAG_TEXTURERESET_1
;
528 smesa
->GlobalFlag
|= CFLAG_TEXTURERESET
;
530 if (current
->texture
[hw_unit
].hwTextureMip
!=
531 prev
->texture
[hw_unit
].hwTextureMip
)
533 prev
->texture
[hw_unit
].hwTextureMip
=
534 current
->texture
[hw_unit
].hwTextureMip
;
536 smesa
->GlobalFlag
|= GFLAG_TEXTUREMIPMAP_1
;
538 smesa
->GlobalFlag
|= GFLAG_TEXTUREMIPMAP
;
544 /* Disable a texture unit, called from validate_texture */
546 sis_reset_texture_env (GLcontext
*ctx
, int hw_unit
)
548 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
550 __GLSiSHardware
*prev
= &smesa
->prev
;
551 __GLSiSHardware
*current
= &smesa
->current
;
555 current
->hwTexBlendColor1
= STAGE1_C_CF
;
556 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
558 if ((current
->hwTexBlendColor1
!= prev
->hwTexBlendColor1
) ||
559 (current
->hwTexBlendAlpha1
!= prev
->hwTexBlendAlpha1
) ||
560 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
562 prev
->hwTexBlendColor1
= current
->hwTexBlendColor1
;
563 prev
->hwTexBlendAlpha1
= current
->hwTexBlendAlpha1
;
564 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
565 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV_1
;
568 current
->hwTexBlendColor0
= STAGE0_C_CF
;
569 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
571 if ((current
->hwTexBlendColor0
!= prev
->hwTexBlendColor0
) ||
572 (current
->hwTexBlendAlpha0
!= prev
->hwTexBlendAlpha0
) ||
573 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
575 prev
->hwTexBlendColor0
= current
->hwTexBlendColor0
;
576 prev
->hwTexBlendAlpha0
= current
->hwTexBlendAlpha0
;
577 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
578 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV
;
583 static void updateTextureUnit( GLcontext
*ctx
, int unit
)
585 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
586 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
587 struct gl_texture_object
*texObj
= texUnit
->_Current
;
591 fallbackbit
= SIS_FALLBACK_TEXTURE0
;
593 fallbackbit
= SIS_FALLBACK_TEXTURE1
;
595 if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
596 if (smesa
->TexStates
[unit
] & NEW_TEXTURING
) {
599 ok
= sis_set_texobj_parm (ctx
, texObj
, unit
);
600 FALLBACK( smesa
, fallbackbit
, !ok
);
602 if (smesa
->TexStates
[unit
] & NEW_TEXTURE_ENV
) {
604 sis_set_texture_env0( ctx
, texObj
, unit
);
606 sis_set_texture_env1( ctx
, texObj
, unit
);
608 smesa
->TexStates
[unit
] = 0;
609 } else if ( texUnit
->_ReallyEnabled
) {
611 FALLBACK( smesa
, fallbackbit
, 1 );
613 sis_reset_texture_env( ctx
, unit
);
614 FALLBACK( smesa
, fallbackbit
, 0 );
619 void sisUpdateTextureState( GLcontext
*ctx
)
621 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
623 __GLSiSHardware
*current
= &smesa
->current
;
626 /* TODO : if unmark these, error in multitexture */ /* XXX */
627 for (i
= 0; i
< SIS_MAX_TEXTURES
; i
++)
628 smesa
->TexStates
[i
] |= (NEW_TEXTURING
| NEW_TEXTURE_ENV
);
631 updateTextureUnit( ctx
, 0 );
632 updateTextureUnit( ctx
, 1 );
634 /* XXX Issues with the 2nd unit but not the first being enabled? */
635 if ( ctx
->Texture
.Unit
[0]._ReallyEnabled
&
636 (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) ||
637 ctx
->Texture
.Unit
[1]._ReallyEnabled
&
638 (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) )
640 current
->hwCapEnable
|= MASK_TextureEnable
;
641 current
->hwCapEnable
&= ~MASK_TextureNumUsed
;
642 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
)
643 current
->hwCapEnable
|= 0x00002000;
645 current
->hwCapEnable
|= 0x00001000;
647 current
->hwCapEnable
&= ~MASK_TextureEnable
;
652 BitScanForward( GLshort w
)
656 for (i
= 0; i
< 16; i
++) {
664 TransferTexturePitch( GLint dwPitch
)
668 i
= BitScanForward( (GLshort
)dwPitch
);
669 dwRet
= dwPitch
>> i
;