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>
40 #include "texformat.h"
42 #include "sis_context.h"
43 #include "sis_state.h"
46 #include "sis_alloc.h"
48 static GLint
TransferTexturePitch (GLint dwPitch
);
50 /* Handle texenv stuff, called from validate_texture (renderstart) */
52 sis_set_texture_env0( GLcontext
*ctx
, struct gl_texture_object
*texObj
,
55 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
58 __GLSiSHardware
*prev
= &smesa
->prev
;
59 __GLSiSHardware
*current
= &smesa
->current
;
61 struct gl_texture_unit
*texture_unit
= &ctx
->Texture
.Unit
[unit
];
63 sisTexObjPtr t
= texObj
->DriverData
;
65 switch (texture_unit
->EnvMode
)
71 current
->hwTexBlendColor0
= STAGE0_C_CF
;
72 current
->hwTexBlendAlpha0
= STAGE0_A_AS
;
77 current
->hwTexBlendColor0
= STAGE0_C_CS
;
78 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
81 case GL_LUMINANCE_ALPHA
:
83 current
->hwTexBlendColor0
= STAGE0_C_CS
;
84 current
->hwTexBlendAlpha0
= STAGE0_A_AS
;
87 sis_fatal_error("unknown base format 0x%x\n", t
->format
);
95 current
->hwTexBlendColor0
= STAGE0_C_CF
;
96 current
->hwTexBlendAlpha0
= STAGE0_A_AFAS
;
101 current
->hwTexBlendColor0
= STAGE0_C_CFCS
;
102 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
105 case GL_LUMINANCE_ALPHA
:
107 current
->hwTexBlendColor0
= STAGE0_C_CFCS
;
108 current
->hwTexBlendAlpha0
= STAGE0_A_AFAS
;
111 sis_fatal_error("unknown base format 0x%x\n", t
->format
);
120 current
->hwTexBlendColor0
= STAGE0_C_CS
;
121 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
124 current
->hwTexBlendColor0
= STAGE0_C_CFOMAS_CSAS
;
125 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
128 sis_fatal_error("unknown base format 0x%x\n", t
->format
);
133 UNCLAMPED_FLOAT_TO_RGBA_CHAN(c
, texture_unit
->EnvColor
);
134 current
->hwTexEnvColor
= ((GLint
) (c
[3])) << 24 |
135 ((GLint
) (c
[0])) << 16 |
136 ((GLint
) (c
[1])) << 8 |
141 current
->hwTexBlendColor0
= STAGE0_C_CF
;
142 current
->hwTexBlendAlpha0
= STAGE0_A_AFAS
;
147 current
->hwTexBlendColor0
= STAGE0_C_CFOMCS_CCCS
;
148 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
151 current
->hwTexBlendColor0
= STAGE0_C_CFOMCS_CCCS
;
152 current
->hwTexBlendAlpha0
= STAGE0_A_AFOMAS_ACAS
;
154 case GL_LUMINANCE_ALPHA
:
156 current
->hwTexBlendColor0
= STAGE0_C_CFOMCS_CCCS
;
157 current
->hwTexBlendAlpha0
= STAGE0_A_AFAS
;
160 sis_fatal_error("unknown base format 0x%x\n", t
->format
);
165 sis_fatal_error("unknown env mode 0x%x\n", texture_unit
->EnvMode
);
168 if ((current
->hwTexBlendColor0
!= prev
->hwTexBlendColor0
) ||
169 (current
->hwTexBlendAlpha0
!= prev
->hwTexBlendAlpha0
) ||
170 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
172 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
173 prev
->hwTexBlendColor0
= current
->hwTexBlendColor0
;
174 prev
->hwTexBlendAlpha0
= current
->hwTexBlendAlpha0
;
175 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV
;
179 /* Handle texenv stuff, called from validate_texture (renderstart) */
181 sis_set_texture_env1( GLcontext
*ctx
, struct gl_texture_object
*texObj
,
184 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
187 __GLSiSHardware
*prev
= &smesa
->prev
;
188 __GLSiSHardware
*current
= &smesa
->current
;
190 struct gl_texture_unit
*texture_unit
= &ctx
->Texture
.Unit
[unit
];
192 sisTexObjPtr t
= texObj
->DriverData
;
194 switch (texture_unit
->EnvMode
)
200 current
->hwTexBlendColor1
= STAGE1_C_CF
;
201 current
->hwTexBlendAlpha1
= STAGE1_A_AS
;
206 current
->hwTexBlendColor1
= STAGE1_C_CS
;
207 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
210 case GL_LUMINANCE_ALPHA
:
212 current
->hwTexBlendColor1
= STAGE1_C_CS
;
213 current
->hwTexBlendAlpha1
= STAGE1_A_AS
;
216 sis_fatal_error("unknown base format 0x%x\n", t
->format
);
224 current
->hwTexBlendColor1
= STAGE1_C_CF
;
225 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
230 current
->hwTexBlendColor1
= STAGE1_C_CFCS
;
231 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
234 case GL_LUMINANCE_ALPHA
:
236 current
->hwTexBlendColor1
= STAGE1_C_CFCS
;
237 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
240 sis_fatal_error("unknown base format 0x%x\n", t
->format
);
249 current
->hwTexBlendColor1
= STAGE1_C_CS
;
250 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
253 current
->hwTexBlendColor1
= STAGE1_C_CFOMAS_CSAS
;
254 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
257 sis_fatal_error("unknown base format 0x%x\n", t
->format
);
262 UNCLAMPED_FLOAT_TO_RGBA_CHAN(c
, texture_unit
->EnvColor
);
263 current
->hwTexEnvColor
= ((GLint
) (c
[3])) << 24 |
264 ((GLint
) (c
[0])) << 16 |
265 ((GLint
) (c
[1])) << 8 |
270 current
->hwTexBlendColor1
= STAGE1_C_CF
;
271 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
276 current
->hwTexBlendColor1
= STAGE1_C_CFOMCS_CCCS
;
277 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
280 current
->hwTexBlendColor1
= STAGE1_C_CFOMCS_CCCS
;
281 current
->hwTexBlendAlpha1
= STAGE1_A_AFOMAS_ACAS
;
283 case GL_LUMINANCE_ALPHA
:
285 current
->hwTexBlendColor1
= STAGE1_C_CFOMCS_CCCS
;
286 current
->hwTexBlendAlpha1
= STAGE1_A_AFAS
;
289 sis_fatal_error("unknown base format 0x%x\n", t
->format
);
294 sis_fatal_error("unknown env mode 0x%x\n", texture_unit
->EnvMode
);
297 if ((current
->hwTexBlendColor1
!= prev
->hwTexBlendColor1
) ||
298 (current
->hwTexBlendAlpha1
!= prev
->hwTexBlendAlpha1
) ||
299 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
301 prev
->hwTexBlendColor1
= current
->hwTexBlendColor1
;
302 prev
->hwTexBlendAlpha1
= current
->hwTexBlendAlpha1
;
303 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
304 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV_1
;
308 /* Returns 0 if a software fallback is necessary */
310 sis_set_texobj_parm( GLcontext
*ctx
, struct gl_texture_object
*texObj
,
313 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
316 __GLSiSHardware
*prev
= &smesa
->prev
;
317 __GLSiSHardware
*current
= &smesa
->current
;
319 sisTexObjPtr t
= texObj
->DriverData
;
321 GLint firstLevel
, lastLevel
;
324 current
->texture
[hw_unit
].hwTextureMip
= 0UL;
325 current
->texture
[hw_unit
].hwTextureSet
= t
->hwformat
;
327 if ((texObj
->MinFilter
== GL_NEAREST
) || (texObj
->MinFilter
== GL_LINEAR
)) {
328 firstLevel
= lastLevel
= texObj
->BaseLevel
;
330 /* Compute which mipmap levels we really want to send to the hardware.
331 * This depends on the base image size, GL_TEXTURE_MIN_LOD,
332 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL and GL_TEXTURE_MAX_LEVEL.
333 * Yes, this looks overly complicated, but it's all needed.
336 firstLevel
= texObj
->BaseLevel
+ (GLint
)(texObj
->MinLod
+ 0.5);
337 firstLevel
= MAX2(firstLevel
, texObj
->BaseLevel
);
338 lastLevel
= texObj
->BaseLevel
+ (GLint
)(texObj
->MaxLod
+ 0.5);
339 lastLevel
= MAX2(lastLevel
, texObj
->BaseLevel
);
340 lastLevel
= MIN2(lastLevel
, texObj
->BaseLevel
+
341 texObj
->Image
[0][texObj
->BaseLevel
]->MaxLog2
);
342 lastLevel
= MIN2(lastLevel
, texObj
->MaxLevel
);
343 lastLevel
= MAX2(firstLevel
, lastLevel
); /* need at least one level */
346 current
->texture
[hw_unit
].hwTextureSet
|= (lastLevel
<< 8);
348 switch (texObj
->MagFilter
)
351 current
->texture
[hw_unit
].hwTextureMip
|= TEXTURE_FILTER_NEAREST
;
354 current
->texture
[hw_unit
].hwTextureMip
|= (TEXTURE_FILTER_LINEAR
<< 3);
361 /* The mipmap lod biasing is based on experiment. It seems there's a
362 * limit of around +4/-4 to the bias value; we're being conservative.
364 b
= (GLint
) (ctx
->Texture
.Unit
[hw_unit
].LodBias
* 32.0);
370 current
->texture
[hw_unit
].hwTextureMip
|= ((b
<< 4) &
371 MASK_TextureMipmapLodBias
);
374 switch (texObj
->MinFilter
)
377 current
->texture
[hw_unit
].hwTextureMip
|= TEXTURE_FILTER_NEAREST
;
380 current
->texture
[hw_unit
].hwTextureMip
|= TEXTURE_FILTER_LINEAR
;
382 case GL_NEAREST_MIPMAP_NEAREST
:
383 current
->texture
[hw_unit
].hwTextureMip
|=
384 TEXTURE_FILTER_NEAREST_MIP_NEAREST
;
386 case GL_NEAREST_MIPMAP_LINEAR
:
387 current
->texture
[hw_unit
].hwTextureMip
|=
388 TEXTURE_FILTER_NEAREST_MIP_LINEAR
;
390 case GL_LINEAR_MIPMAP_NEAREST
:
391 current
->texture
[hw_unit
].hwTextureMip
|=
392 TEXTURE_FILTER_LINEAR_MIP_NEAREST
;
394 case GL_LINEAR_MIPMAP_LINEAR
:
395 current
->texture
[hw_unit
].hwTextureMip
|=
396 TEXTURE_FILTER_LINEAR_MIP_LINEAR
;
400 switch (texObj
->WrapS
)
403 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureWrapU
;
405 case GL_MIRRORED_REPEAT
:
406 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureMirrorU
;
409 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureClampU
;
410 /* XXX: GL_CLAMP isn't conformant, but falling back makes the situation
411 * worse in other programs at the moment.
415 case GL_CLAMP_TO_EDGE
:
416 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureClampU
;
418 case GL_CLAMP_TO_BORDER
:
419 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureBorderU
;
423 switch (texObj
->WrapT
)
426 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureWrapV
;
428 case GL_MIRRORED_REPEAT
:
429 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureMirrorV
;
432 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureClampV
;
433 /* XXX: GL_CLAMP isn't conformant, but falling back makes the situation
434 * worse in other programs at the moment.
438 case GL_CLAMP_TO_EDGE
:
439 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureClampV
;
441 case GL_CLAMP_TO_BORDER
:
442 current
->texture
[hw_unit
].hwTextureSet
|= MASK_TextureBorderV
;
446 current
->texture
[hw_unit
].hwTextureBorderColor
=
447 ((GLuint
) texObj
->_BorderChan
[3] << 24) +
448 ((GLuint
) texObj
->_BorderChan
[0] << 16) +
449 ((GLuint
) texObj
->_BorderChan
[1] << 8) +
450 ((GLuint
) texObj
->_BorderChan
[2]);
452 if (current
->texture
[hw_unit
].hwTextureBorderColor
!=
453 prev
->texture
[hw_unit
].hwTextureBorderColor
)
455 prev
->texture
[hw_unit
].hwTextureBorderColor
=
456 current
->texture
[hw_unit
].hwTextureBorderColor
;
458 smesa
->GlobalFlag
|= GFLAG_TEXBORDERCOLOR_1
;
460 smesa
->GlobalFlag
|= GFLAG_TEXBORDERCOLOR
;
463 current
->texture
[hw_unit
].hwTextureSet
|=
464 texObj
->Image
[0][firstLevel
]->WidthLog2
<< 4;
465 current
->texture
[hw_unit
].hwTextureSet
|=
466 texObj
->Image
[0][firstLevel
]->HeightLog2
;
469 smesa
->GlobalFlag
|= GFLAG_TEXTUREADDRESS
;
471 smesa
->GlobalFlag
|= GFLAG_TEXTUREADDRESS_1
;
473 for (i
= firstLevel
; i
<= lastLevel
; i
++)
475 GLuint texOffset
= 0;
476 GLuint texPitch
= TransferTexturePitch( t
->image
[i
].pitch
);
478 switch (t
->image
[i
].memType
)
481 texOffset
= ((unsigned long)t
->image
[i
].Data
- (unsigned long)smesa
->FbBase
);
484 texOffset
= ((unsigned long)t
->image
[i
].Data
- (unsigned long)smesa
->AGPBase
) +
485 (unsigned long) smesa
->AGPAddr
;
486 current
->texture
[hw_unit
].hwTextureMip
|=
487 (MASK_TextureLevel0InSystem
<< i
);
494 prev
->texture
[hw_unit
].texOffset0
= texOffset
;
495 prev
->texture
[hw_unit
].texPitch01
= texPitch
<< 16;
498 prev
->texture
[hw_unit
].texOffset1
= texOffset
;
499 prev
->texture
[hw_unit
].texPitch01
|= texPitch
;
502 prev
->texture
[hw_unit
].texOffset2
= texOffset
;
503 prev
->texture
[hw_unit
].texPitch23
= texPitch
<< 16;
506 prev
->texture
[hw_unit
].texOffset3
= texOffset
;
507 prev
->texture
[hw_unit
].texPitch23
|= texPitch
;
510 prev
->texture
[hw_unit
].texOffset4
= texOffset
;
511 prev
->texture
[hw_unit
].texPitch45
= texPitch
<< 16;
514 prev
->texture
[hw_unit
].texOffset5
= texOffset
;
515 prev
->texture
[hw_unit
].texPitch45
|= texPitch
;
518 prev
->texture
[hw_unit
].texOffset6
= texOffset
;
519 prev
->texture
[hw_unit
].texPitch67
= texPitch
<< 16;
522 prev
->texture
[hw_unit
].texOffset7
= texOffset
;
523 prev
->texture
[hw_unit
].texPitch67
|= texPitch
;
526 prev
->texture
[hw_unit
].texOffset8
= texOffset
;
527 prev
->texture
[hw_unit
].texPitch89
= texPitch
<< 16;
530 prev
->texture
[hw_unit
].texOffset9
= texOffset
;
531 prev
->texture
[hw_unit
].texPitch89
|= texPitch
;
534 prev
->texture
[hw_unit
].texOffset10
= texOffset
;
535 prev
->texture
[hw_unit
].texPitch10
= texPitch
<< 16;
538 prev
->texture
[hw_unit
].texOffset11
= texOffset
;
539 prev
->texture
[hw_unit
].texPitch10
|= texPitch
;
544 if (current
->texture
[hw_unit
].hwTextureSet
!=
545 prev
->texture
[hw_unit
].hwTextureSet
)
547 prev
->texture
[hw_unit
].hwTextureSet
=
548 current
->texture
[hw_unit
].hwTextureSet
;
550 smesa
->GlobalFlag
|= CFLAG_TEXTURERESET_1
;
552 smesa
->GlobalFlag
|= CFLAG_TEXTURERESET
;
554 if (current
->texture
[hw_unit
].hwTextureMip
!=
555 prev
->texture
[hw_unit
].hwTextureMip
)
557 prev
->texture
[hw_unit
].hwTextureMip
=
558 current
->texture
[hw_unit
].hwTextureMip
;
560 smesa
->GlobalFlag
|= GFLAG_TEXTUREMIPMAP_1
;
562 smesa
->GlobalFlag
|= GFLAG_TEXTUREMIPMAP
;
568 /* Disable a texture unit, called from validate_texture */
570 sis_reset_texture_env (GLcontext
*ctx
, int hw_unit
)
572 sisContextPtr smesa
= SIS_CONTEXT(ctx
);
574 __GLSiSHardware
*prev
= &smesa
->prev
;
575 __GLSiSHardware
*current
= &smesa
->current
;
579 current
->hwTexBlendColor1
= STAGE1_C_CF
;
580 current
->hwTexBlendAlpha1
= STAGE1_A_AF
;
582 if ((current
->hwTexBlendColor1
!= prev
->hwTexBlendColor1
) ||
583 (current
->hwTexBlendAlpha1
!= prev
->hwTexBlendAlpha1
) ||
584 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
586 prev
->hwTexBlendColor1
= current
->hwTexBlendColor1
;
587 prev
->hwTexBlendAlpha1
= current
->hwTexBlendAlpha1
;
588 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
589 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV_1
;
592 current
->hwTexBlendColor0
= STAGE0_C_CF
;
593 current
->hwTexBlendAlpha0
= STAGE0_A_AF
;
595 if ((current
->hwTexBlendColor0
!= prev
->hwTexBlendColor0
) ||
596 (current
->hwTexBlendAlpha0
!= prev
->hwTexBlendAlpha0
) ||
597 (current
->hwTexEnvColor
!= prev
->hwTexEnvColor
))
599 prev
->hwTexBlendColor0
= current
->hwTexBlendColor0
;
600 prev
->hwTexBlendAlpha0
= current
->hwTexBlendAlpha0
;
601 prev
->hwTexEnvColor
= current
->hwTexEnvColor
;
602 smesa
->GlobalFlag
|= GFLAG_TEXTUREENV
;
607 static void updateTextureUnit( GLcontext
*ctx
, int unit
)
609 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
610 const struct gl_texture_unit
*texUnit
= &ctx
->Texture
.Unit
[unit
];
611 struct gl_texture_object
*texObj
= texUnit
->_Current
;
615 fallbackbit
= SIS_FALLBACK_TEXTURE0
;
617 fallbackbit
= SIS_FALLBACK_TEXTURE1
;
619 if (texUnit
->_ReallyEnabled
& (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
)) {
620 if (smesa
->TexStates
[unit
] & NEW_TEXTURING
) {
623 ok
= sis_set_texobj_parm (ctx
, texObj
, unit
);
624 FALLBACK( smesa
, fallbackbit
, !ok
);
626 if (smesa
->TexStates
[unit
] & NEW_TEXTURE_ENV
) {
628 sis_set_texture_env0( ctx
, texObj
, unit
);
630 sis_set_texture_env1( ctx
, texObj
, unit
);
632 smesa
->TexStates
[unit
] = 0;
633 } else if ( texUnit
->_ReallyEnabled
) {
635 FALLBACK( smesa
, fallbackbit
, 1 );
637 sis_reset_texture_env( ctx
, unit
);
638 FALLBACK( smesa
, fallbackbit
, 0 );
643 void sisUpdateTextureState( GLcontext
*ctx
)
645 sisContextPtr smesa
= SIS_CONTEXT( ctx
);
647 __GLSiSHardware
*current
= &smesa
->current
;
650 /* TODO : if unmark these, error in multitexture */ /* XXX */
651 for (i
= 0; i
< SIS_MAX_TEXTURES
; i
++)
652 smesa
->TexStates
[i
] |= (NEW_TEXTURING
| NEW_TEXTURE_ENV
);
655 updateTextureUnit( ctx
, 0 );
656 updateTextureUnit( ctx
, 1 );
658 /* XXX Issues with the 2nd unit but not the first being enabled? */
659 if ( ctx
->Texture
.Unit
[0]._ReallyEnabled
&
660 (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) ||
661 ctx
->Texture
.Unit
[1]._ReallyEnabled
&
662 (TEXTURE_1D_BIT
| TEXTURE_2D_BIT
) )
664 current
->hwCapEnable
|= MASK_TextureEnable
;
665 current
->hwCapEnable
&= ~MASK_TextureNumUsed
;
666 if (ctx
->Texture
.Unit
[1]._ReallyEnabled
)
667 current
->hwCapEnable
|= 0x00002000;
669 current
->hwCapEnable
|= 0x00001000;
671 current
->hwCapEnable
&= ~MASK_TextureEnable
;
676 BitScanForward( GLshort w
)
680 for (i
= 0; i
< 16; i
++) {
688 TransferTexturePitch( GLint dwPitch
)
692 i
= BitScanForward( (GLshort
)dwPitch
);
693 dwRet
= dwPitch
>> i
;