178 lines
5.0 KiB
C++
178 lines
5.0 KiB
C++
/*---------------------------------------------------------------------------------- */
|
|
/* Implement perspective correction. */
|
|
/* stack top contains the result of the divide */
|
|
/* Preserve: ecx,edx,esi */
|
|
/* */
|
|
mov edi,[iNextSubdivide]
|
|
mov eax,[iCacheNextSubdivide]
|
|
|
|
sub edi,eax
|
|
jz EXIT_BEGIN_NEXT_QUICK_END
|
|
|
|
fld [fGUInvZ] /* U/Z,Z */
|
|
fxch st(1) /* Z,U/Z */
|
|
fmul st(1),st(0) /* Z,U */
|
|
|
|
fmul [fGVInvZ] /* V,U */
|
|
|
|
/*---------------------------------------------------------------------------------- */
|
|
/* Clamp U and V */
|
|
fxch st(1)
|
|
fstp [f_u]
|
|
fstp [f_v]
|
|
|
|
mov ebp,[f_u]
|
|
mov ebx,[fTexEdgeTolerance]
|
|
mov eax,[f_v]
|
|
cmp eax,ebx
|
|
jge short V_NOT_LESS_END
|
|
mov eax,ebx
|
|
V_NOT_LESS_END:
|
|
cmp ebp,ebx
|
|
jge short U_NOT_LESS_END
|
|
mov ebp,ebx
|
|
U_NOT_LESS_END:
|
|
mov ebx,[fTexWidth]
|
|
cmp ebp,ebx
|
|
jle short U_NOT_GREATER_END
|
|
mov ebp,ebx
|
|
U_NOT_GREATER_END:
|
|
mov ebx,[fTexHeight]
|
|
cmp eax,ebx
|
|
jle short V_NOT_GREATER_END
|
|
mov eax,ebx
|
|
V_NOT_GREATER_END:
|
|
mov [f_u],ebp
|
|
mov [f_v],eax
|
|
|
|
fld [f_u]
|
|
fld [f_v]
|
|
|
|
/*---------------------------------------------------------------------------------- */
|
|
/* Initialize walking values */
|
|
fld st(1) /* U,V,U */
|
|
fsub [fU] /* U-fU,V,U */
|
|
fld st(1) /* V,U-fU,V,U */
|
|
fsub [fV] /* V-fV,U-fU,V,U */
|
|
fxch st(1) /* U-fU,V-fV,V,U */
|
|
fmul float ptr[fInverseIntTable+edi*4] /* (U-fU)*C,V-fV,V,U */
|
|
fxch st(2) /* V,V-fV,(U-fU)*C,U */
|
|
fstp [fV] /* V-fV,(U-fU)*C,U */
|
|
fmul float ptr[fInverseIntTable+edi*4] /* (V-fV)*C,(U-fU)*C,U */
|
|
fxch st(1) /* (U-fU)*C,(V-fV)*C,U */
|
|
fadd [dFastFixed16Conversion] /* f(U-fU)*C,(V-fV)*C,U */
|
|
fxch st(1) /* (V-fV)*C,f(U-fU)*C,U */
|
|
/* stall(1) */
|
|
fadd [dFastFixed16Conversion] /* f(V-fV)*C,f(U-fU)*C,U */
|
|
fxch st(2) /* U,f(U-fU)*C,f(V-fV)*C */
|
|
fstp [fU] /* f(U-fU)*C,f(V-fV)*C */
|
|
fstp [d_temp_a] /* f(V-fV)*C */
|
|
fstp [d_temp_b]
|
|
|
|
mov edi,dword ptr[d_temp_a] /* uslope */
|
|
mov eax,dword ptr[d_temp_b] /* vslope */
|
|
|
|
sar edi,16 /* integer part of uslope */
|
|
mov ebp,dword ptr[d_temp_a] /* uslope again */
|
|
|
|
shl ebp,16 /* fractional part of uslope */
|
|
mov ebx,eax /* vslope again */
|
|
|
|
sar eax,16 /* integer part of vslope */
|
|
mov [w2dDeltaTex.uUFrac],ebp /* store UFrac */
|
|
|
|
imul eax,[iTexWidth] /* ivslope*twidth */
|
|
|
|
shl ebx,16 /* fractional part of vslope */
|
|
mov ebp,[u4TextureTileMaskStepU] /* Load mask for integral U step */
|
|
|
|
and edi,ebp /* Mask integral U before adding. */
|
|
mov [w2dDeltaTex.uVFrac],ebx /* store VFrac */
|
|
|
|
add edi,eax /* ivslope*twidth + iuslope */
|
|
mov ebp,[iTexWidth] /* Load texture width. */
|
|
|
|
mov [w2dDeltaTex.iUVInt+4],edi /* store integer stride */
|
|
add edi,ebp /* add twidth to integer stride */
|
|
|
|
mov [w2dDeltaTex.iUVInt],edi /* store integer stride + twidth */
|
|
mov eax,[iCacheNextSubdivide]
|
|
|
|
/*---------------------------------------------------------------------------------- */
|
|
/* Begin Next Subdivision */
|
|
mov [iNextSubdivide],eax /* eax == iNextSubdivide */
|
|
mov ebx,[iSubdivideLen]
|
|
|
|
test eax,eax /* Next subdivision is zero length? */
|
|
jz SUBDIVISION_LOOP
|
|
|
|
/* scan line is +ve */
|
|
add eax,ebx
|
|
jle short DONE_DIVIDE_PIXEL_CACHE_END
|
|
|
|
/* calc the new +ve ratio */
|
|
fild iNextSubdivide
|
|
fld fInvSubdivideLen
|
|
fchs
|
|
|
|
/* Subdivision is smaller than iSubdivideLen */
|
|
fmulp st(1),st(0) /* st(0) = (-)fInvSubdivideLen * i_pixel; */
|
|
fld fDUInvZScanline /* U C */
|
|
|
|
xor eax,eax
|
|
|
|
fmul st(0),st(1) /* U*C C */
|
|
fxch st(1) /* C U*C */
|
|
fld fDVInvZScanline /* V C U*C */
|
|
fxch st(1) /* C V U*C */
|
|
fmul st(1),st(0) /* C V*C U*C */
|
|
|
|
mov [iCacheNextSubdivide],eax
|
|
|
|
fmul fDInvZScanline /* Z*C V*C U*C */
|
|
fxch st(2) /* U*C V*C Z*C */
|
|
fst fDUInvZScanline /* U V Z */
|
|
fadd fGUInvZ
|
|
fxch st(1) /* V U Z */
|
|
fst fDVInvZScanline
|
|
fadd fGVInvZ
|
|
fxch st(2) /* Z U V */
|
|
fst fDInvZScanline
|
|
fadd fGInvZ
|
|
fxch st(2) /* V U Z */
|
|
fstp fGVInvZ
|
|
fstp fGUInvZ
|
|
fst fGInvZ
|
|
fdivr fOne /* Start the next division. */
|
|
|
|
jmp SUBDIVISION_LOOP
|
|
|
|
DONE_DIVIDE_PIXEL_CACHE_END:
|
|
mov [iCacheNextSubdivide],eax
|
|
mov ebx,[iNextSubdivide]
|
|
|
|
cmp eax,ebx
|
|
je SUBDIVISION_LOOP
|
|
|
|
fld fDUInvZScanline /* U */
|
|
fadd fGUInvZ
|
|
fld fDVInvZScanline /* V U */
|
|
fadd fGVInvZ
|
|
fld fDInvZScanline /* Z V U */
|
|
fadd fGInvZ
|
|
fxch st(2) /* U V Z */
|
|
fstp fGUInvZ
|
|
fstp fGVInvZ
|
|
fst fGInvZ
|
|
fdivr fOne /* Start the next division. */
|
|
|
|
jmp SUBDIVISION_LOOP
|
|
|
|
/* When the sub divide equals the cached sub-divide we end up here but */
|
|
/* there is an element left on the fp stack. This sould never happen. */
|
|
EXIT_BEGIN_NEXT_QUICK_END:
|
|
|
|
/* Dump value on stack */
|
|
fcomp st(0)
|
|
jmp SUBDIVISION_LOOP
|