windows-nt/Source/XPSP1/NT/multimedia/opengl/server/generic/i386/texspan.asm
2020-09-26 16:20:57 +08:00

1568 lines
31 KiB
NASM

;---------------------------Module-Header------------------------------;
; Module Name: texspan.asm
;
; Include file for "body" of texture routines.
;
; Created: 011/15/1995
; Author: Otto Berkes [ottob]
;
; Copyright (c) 1995 Microsoft Corporation
;----------------------------------------------------------------------;
rMask = ((1 SHL rBits) - 1) SHL rShift
gMask = ((1 SHL gBits) - 1) SHL gShift
bMask = ((1 SHL bBits) - 1) SHL bShift
if REPLACE
rRightShiftAdj = 16 - (rShift + rBits)
gRightShiftAdj = 16 - (gShift + gBits)
bRightShiftAdj = 16 - (bShift + bBits)
else
rRightShiftAdj = 16 - (rShift)
gRightShiftAdj = 16 - (gShift)
bRightShiftAdj = 16 - (bShift)
endif
TMASK_SUBDIV equ [esi].GENGC_tMaskSubDiv
TSHIFT_SUBDIV equ [esi].GENGC_tShiftSubDiv
if FAST_REPLACE
TEXPALETTE equ [esi].GENGC_texImageReplace
if (PALETTE_ONLY)
TEXIMAGE equ [esi].GENGC_texImage
else
TEXIMAGE equ [esi].GENGC_texImageReplace
endif
if PALETTE_ONLY
TEX_BPP_LOG2 = 0
elseif (BPP eq 8)
TEX_BPP_LOG2 = 0
else
TEX_BPP_LOG2 = 1
endif
else
TEXPALETTE equ [esi].GENGC_texPalette
TEXIMAGE equ [esi].GENGC_texImage
if PALETTE_ONLY
TEX_BPP_LOG2 = 0
else
TEX_BPP_LOG2 = 2
endif
endif
;;
;;
;; Macros for alpha modulation, and alpha reads
;;
;;
ALPHAMODULATE MACRO
mov ah, [esi].GENGC_aAccum+2
mov al, [edx+3]
and eax, 0ffffh
mov ch, _gbMulTable[eax]
mov [esi].GENGC_aDisplay, ch
ENDM
ALPHANOMODULATE MACRO
mov ch, [edx+3]
mov [esi].GENGC_aDisplay, ch
ENDM
;; There are AGIs and other nasties in the alpha-read code. There's
;; not much we can really do, unfortunately...
if (BPP eq 8)
ALPHAREAD MACRO
xor eax, eax
mov al, [ebx]
mov ebx, [esi].GENGC_pInvTranslateVector
mov cl, 0ffh
mov al, [ebx+eax]
mov ebx, eax
and ebx, rMask
sub cl, ch
shl ebx, gBits + bBits
mov bh, cl
mov ch, _gbMulTable[ebx]
mov ebx, eax
mov [esi].GENGC_rDisplay, ch
and ebx, gMask
shl ebx, bBits
mov bh, cl
mov ch, _gbMulTable[ebx]
mov ebx, eax
mov [esi].GENGC_gDisplay, ch
and ebx, bMask
mov bh, cl
mov ch, _gbMulTable[ebx]
mov [esi].GENGC_bDisplay, ch
ENDM
endif
if (BPP eq 16)
ALPHAREAD MACRO
mov ax, [ebx]
mov cl, 0ffh
mov ebx, eax
and ebx, rMask
sub cl, ch
shr ebx, rShift - (8 - rBits)
mov bh, cl
mov ch, _gbMulTable[ebx]
mov ebx, eax
mov [esi].GENGC_rDisplay, ch
and ebx, gMask
shr ebx, gShift - (8 - gBits)
mov bh, cl
mov ch, _gbMulTable[ebx]
mov ebx, eax
mov [esi].GENGC_gDisplay, ch
and ebx, bMask
shl ebx, (8 - bBits)
mov bh, cl
mov ch, _gbMulTable[ebx]
mov [esi].GENGC_bDisplay, ch
ENDM
elseif (BPP eq 32)
ALPHAREAD MACRO
xor eax, eax
mov cl, 0ffh
mov al, [ebx+2]
sub cl, ch
mov ah, cl
mov al, _gbMulTable[eax]
mov [esi].GENGC_rDisplay, al
mov al, [ebx+1]
mov ah, cl
mov al, _gbMulTable[eax]
mov [esi].GENGC_gDisplay, al
mov al, [ebx]
mov ah, cl
mov al, _gbMulTable[eax]
mov [esi].GENGC_bDisplay, al
ENDM
endif
;;
;;
;; Macros for advancing a single pixel unit
;;
;;
if (BPP eq 8)
PIXADVANCE MACRO var
inc var
ENDM
elseif (BPP eq 16)
PIXADVANCE MACRO var
add var, (BPP / 8)
ENDM
else
PIXADVANCE MACRO var
add var, [esi].GENGC_bytesPerPixel
ENDM
endif
if (BPP le 16)
PIXADVANCE2 MACRO var1, var2
lea var1, [var2 + (BPP / 8)]
ENDM
else
PIXADVANCE2 MACRO var1, var2
mov var1, var2
add var1, [esi].GENGC_bytesPerPixel
ENDM
endif
;;
;;
;; Macros for advancing the accumulators if the z-buffer test fails:
;;
;;
if FAST_REPLACE
ZBUFFER_FAIL_ADVANCE MACRO
mov ecx, [esi].GENGC_zAccum ;U
mov eax, [esi].GENGC_SPAN_dz ; V
mov ebx, [esi].GENGC_pixAccum ;U
add edi, 2 ; V
add ecx, eax ;U
PIXADVANCE ebx ; V
sub ebp, 010001h ;U
mov [esi].GENGC_zAccum, ecx ; V
mov [esi].GENGC_pixAccum, ebx ;U
jl doSubDiv ; V
test ebp, 08000h ;U
je loopTopNoDiv ; V
jmp spanExit
ENDM
elseif REPLACE
ZBUFFER_FAIL_ADVANCE MACRO
mov ecx, [esi].GENGC_zAccum ;U
mov eax, [esi].GENGC_SPAN_dz ; V
add edi, 2 ;U
add ecx, eax ; V
mov eax, [esi].GENGC_ditherAccum ;U
mov ebx, [esi].GENGC_pixAccum ; V
ror eax, 8 ;U
mov [esi].GENGC_zAccum, ecx ; V
PIXADVANCE ebx ;U
sub ebp, 010001h ; V
mov [esi].GENGC_pixAccum, ebx ;U
mov [esi].GENGC_ditherAccum, eax ; V
jl doSubDiv ;U
test ebp, 08000h ; V
je loopTopNoDiv ;U
jmp spanExit ; V
ENDM
elseif FLAT_SHADING
ZBUFFER_FAIL_ADVANCE MACRO
mov ecx, [esi].GENGC_zAccum ;U
mov eax, [esi].GENGC_SPAN_dz ; V
add edi, 2 ;U
add ecx, eax ; V
mov ebx, [esi].GENGC_pixAccum ;U
mov eax, [esi].GENGC_ditherAccum ; V
mov [esi].GENGC_zAccum, ecx ;U
PIXADVANCE ebx ; V
ror eax, 8 ;U
sub ebp, 010001h ; V
mov [esi].GENGC_pixAccum, ebx ;U
mov [esi].GENGC_ditherAccum, eax ; V
jl doSubDiv ;U
test ebp, 08000h ; V
je loopTopNoDiv ;U
jmp spanExit
ENDM
elseif SMOOTH_SHADING
ZBUFFER_FAIL_ADVANCE MACRO
mov ecx, [esi].GENGC_zAccum ;U
mov eax, [esi].GENGC_SPAN_dz ; V
add edi, 2 ;U
add ecx, eax ; V
mov eax, [esi].GENGC_rAccum ;U
mov [esi].GENGC_zAccum, ecx ; V
mov ebx, [esi].GENGC_SPAN_dr ;U
mov ecx, [esi].GENGC_gAccum ; V
add eax, ebx ;U
mov edx, [esi].GENGC_SPAN_dg ; V
mov [esi].GENGC_rAccum, eax ;U
add ecx, edx ; V
mov eax, [esi].GENGC_bAccum ;U
mov ebx, [esi].GENGC_SPAN_db ; V
mov [esi].GENGC_gAccum, ecx ;U
add ebx, eax ; V
mov eax, [esi].GENGC_ditherAccum ;U
mov [esi].GENGC_bAccum, ebx ; V
ror eax, 8 ;U
if ALPHA
mov ecx, [esi].GENGC_aAccum
endif
mov ebx, [esi].GENGC_pixAccum ;U
if ALPHA
add ecx, [esi].GENGC_SPAN_da
endif
PIXADVANCE ebx ;U
if ALPHA
mov [esi].GENGC_aAccum, ecx
endif
mov [esi].GENGC_pixAccum, ebx ; V
sub ebp, 010001h ;U
mov [esi].GENGC_ditherAccum, eax ; V
jl doSubDiv ;U
test ebp, 08000h ; V
je loopTopNoDiv ;U
jmp spanExit ; V
ENDM
endif
;;----------------------------------------------------------------------
;;
;; This is the start of the texture routine. Kick off the divide, and use
;; the dead time to set up all of the accumulators and other variables.
;;
;;----------------------------------------------------------------------
ZBUFFER_EARLY_OUT = 1
if ZBUFFER
push ebx ;U
push esi ; V
push edi ;U
push ebp ; V
if ZBUFFER_EARLY_OUT
mov edi, [ecx].GENGC_SPAN_zbuf ;U
mov esi, [ecx].GENGC_SPAN_z ; V
mov edx, [ecx].GENGC_SPAN_length ;U
mov ebp, [ecx].GENGC_SPAN_dz ; V
@zLoop:
mov ebx, esi ;U
mov eax, [edi] ; V
shr ebx, 16 ;U
and eax, 0ffffh ; V
cmp ebx, eax ;U
if ZCMP_L
jl @zFirstWrite ; V
else
jle @zFirstWrite ; V
endif
add edi, 2 ;U
add esi, ebp ; V
dec edx ;U
jne @zLoop ; V
pop ebp
pop edi
pop esi
pop ebx
ret 0
@zFirstWrite:
endif ;; ZBUFFER_EARLY_OUT
endif ;; ZBUFFER
;;
;; Start the divide:
;;
mov eax, [ecx].GENGC_flags
fld DWORD PTR [ecx].GENGC_SPAN_qw ;qwAccum
fld DWORD PTR [ecx].GENGC_SPAN_qw ;qwAccum qwAccum
test eax, GEN_TEXTURE_ORTHO
jne @f
fdivr __One ;1/qw qwAccum
@@:
;;
;; Save the registers that we need to:
;;
if ZBUFFER
else
push ebx ;U
push esi ; V
push edi ;U
push ebp ; V
endif
mov esi, ecx ;U
;;
;; Set up accumulators:
;;
if FAST_REPLACE
if ZBUFFER
mov eax, [esi].GENGC_SPAN_z ; V
endif
mov ebx, [esi].GENGC_SPAN_s ;U
mov ecx, [esi].GENGC_SPAN_t ; V
if ZBUFFER
mov [esi].GENGC_zAccum, eax ;U
endif
mov [esi].GENGC_sAccum, ebx ; V
mov [esi].GENGC_tAccum, ecx ;U
mov ebx, [esi].GENGC_SPAN_qw ; V
mov eax, [esi].GENGC_SPAN_y ;U
mov [esi].GENGC_qwAccum, ebx ; V
mov edx, [esi].GENGC_SPAN_ppix ;U
mov edi, [esi].GENGC_flags ; V
mov ebx, [esi].GENGC_SPAN_x ;U
test edi, SURFACE_TYPE_DIB ; V
jne @f ;U
mov edx, [esi].GENGC_ColorsBits ; V
jmp short @pixAccumDone
@@:
if (BPP eq 8)
add edx, ebx ;U
elseif (BPP eq 16)
lea edx, [edx + 2*ebx]
else
lea edx, [edx + 4*ebx]
cmp [esi].GENGC_bpp, 32
je @f
sub edx, ebx
@@:
endif
@pixAccumDone:
test edi, GEN_TEXTURE_ORTHO ; V
mov ebp, [esi].GENGC_SPAN_length ;U
je @f ; V
else
if REPLACE
else
;; Handle RGB accumulators
if FLAT_SHADING
mov eax, [ecx].GENGC_SPAN_r ;U
mov ebx, [ecx].GENGC_SPAN_g ; V
shr eax, rBits ;U
mov ecx, [esi].GENGC_SPAN_b ; V
shr ebx, gBits ;U
and eax, 0ff00h ; V
shr ecx, bBits ;U
and ebx, 0ff00h ; V
and ecx, 0ff00h ;U
mov [esi].GENGC_rAccum, eax ; V
mov [esi].GENGC_gAccum, ebx ;U
mov [esi].GENGC_bAccum, ecx ; V
else
mov eax, [ecx].GENGC_SPAN_r ;U
mov ebx, [ecx].GENGC_SPAN_g ; V
mov ecx, [esi].GENGC_SPAN_b ;U
mov [esi].GENGC_rAccum, eax ; V
mov [esi].GENGC_gAccum, ebx ;U
mov [esi].GENGC_bAccum, ecx ; V
endif ;; FLAT_SHADING
endif ;; NOT REPLACE
if ZBUFFER
mov eax, [esi].GENGC_SPAN_z ; V
endif
mov ebx, [esi].GENGC_SPAN_s ;U
mov ecx, [esi].GENGC_SPAN_t ; V
if ZBUFFER
mov [esi].GENGC_zAccum, eax ;U
endif
mov [esi].GENGC_sAccum, ebx ; V
mov [esi].GENGC_tAccum, ecx ;U
mov ebx, [esi].GENGC_SPAN_qw ; V
mov eax, [esi].GENGC_SPAN_y ;U
mov [esi].GENGC_qwAccum, ebx ; V
and eax, 03h ;U
mov ecx, [esi].GENGC_SPAN_x ; V
lea eax, [eax*4 + offset dither0] ;U
lea ecx, [ecx*8] ; V
mov edx, [esi].GENGC_SPAN_ppix ;U
mov edi, [esi].GENGC_flags ; V
mov ebx, [esi].GENGC_SPAN_x ;U
test edi, SURFACE_TYPE_DIB ; V
jne @f ;U
mov edx, [esi].GENGC_ColorsBits ; V
jmp short @pixAccumDone
@@:
if (BPP eq 8)
add edx, ebx ;U
elseif (BPP eq 16)
lea edx, [edx + 2*ebx]
else
lea edx, [edx + 4*ebx]
cmp [esi].GENGC_bpp, 32
je @f
sub edx, ebx
@@:
endif
@pixAccumDone:
mov eax, [eax] ; V
and ecx, 018h ;U
test edi, GEN_TEXTURE_ORTHO ; V
mov ebp, [esi].GENGC_SPAN_length ;U
je @f ; V
endif
mov edi, [esi].GENGC_sAccum ; V
mov ebx, [esi].GENGC_tAccum ;U
mov DWORD PTR [esi].GENGC_sResult, edi ; V
mov DWORD PTR [esi].GENGC_tResult, ebx ;U
mov edi, [esi].GENGC_flags ; V
jmp short @stResultDone1 ;U
;;
;; Kick off the next divide:
;;
@@:
fild DWORD PTR [esi].GENGC_sAccum ; s 1/qw qwAccum
fmul ST, ST(1) ; s/qw 1/qw qwAccum
fild DWORD PTr [esi].GENGC_tAccum ; t s/qw 1/qw qwAccum
fmulp ST(2), ST ; s/qw t/qw qwAccum
fistp QWORD PTR [esi].GENGC_sResult ; t/qw qwAccum
fistp QWORD PTR [esi].GENGC_tResult ; qwAccum
fadd DWORD PTR [esi].GENGC_qwStepX ; qwAccum
fld ST(0) ; qwAccum qwAccum
fdivr __One ; 1/qw qwAccum
@stResultDone1:
ror eax, cl ;UV (4)
add ebp, 070000h ;U
mov [esi].GENGC_ditherAccum, eax ; V
dec ebp ;U
mov [esi].GENGC_pixAccum, edx ; V
mov eax, [esi].GENGC_sAccum ;U
mov ebx, [esi].GENGC_tAccum ; V
add eax, [esi].GENGC_sStepX ;U
add ebx, [esi].GENGC_tStepX ; V
mov [esi].GENGC_sAccum, eax ;U
mov [esi].GENGC_tAccum, ebx ; V
mov eax, [esi].GENGC_sResult ;U
mov ebx, [esi].GENGC_tResult ; V
mov cl, TSHIFT_SUBDIV ;U
sar ebx, cl ;UV (4)
and ebx, NOT 7 ;U
if ALPHA
mov ecx, [esi].GENGC_SPAN_a
endif
test edi, GEN_TEXTURE_ORTHO ; V
mov [esi].GENGC_tResult, ebx ;U
if ALPHA
mov [esi].GENGC_aAccum, ecx
endif
je @f
mov ecx, [esi].GENGC_sAccum ; V
mov edx, [esi].GENGC_tAccum ;U
mov DWORD PTR [esi].GENGC_sResultNew, ecx ; V
mov DWORD PTR [esi].GENGC_tResultNew, edx ;U
jmp short @stResultDone2 ; V
@@:
;; We may have to burn some cycles here...
fild DWORD PTR [esi].GENGC_sAccum ; s 1/qw qwAccum
fmul ST, ST(1) ; s/qw 1/qw qwAccum
fild DWORD PTr [esi].GENGC_tAccum ; t s/qw 1/qw qwAccum
fmulp ST(2), ST ; s/qw t/qw qwAccum
fistp QWORD PTR [esi].GENGC_sResultNew; t/qw qwAccum
fistp QWORD PTR [esi].GENGC_tResultNew; qwAccum
fadd DWORD PTR [esi].GENGC_qwStepX ; qwAccum
@stResultDone2:
mov cl, TSHIFT_SUBDIV ;U
mov edx, [esi].GENGC_tResultNew ; V
sar edx, cl ;UV (4)
and edx, NOT 7 ;U
mov ecx, [esi].GENGC_sResultNew ; V
mov [esi].GENGC_tResultNew, edx ;U
sub ecx, eax ; V
sar ecx, 3 ;U
sub edx, ebx ; V
sar edx, 3 ;U
mov [esi].GENGC_subDs, ecx ; V
mov [esi].GENGC_subDt, edx ;U
mov eax, [esi].GENGC_flags ; V
mov edi, [esi].GENGC_SPAN_zbuf ;U
loopTop:
;;
;; This is the start of the outer loop. We come back here on each
;; subdivision. The key thing is to kick off the next divide:
;;
test eax, GEN_TEXTURE_ORTHO ; V
jne @f ;U
fld ST(0) ; qwAccum qwAccum
fadd DWORD PTR [esi].GENGC_qwStepX ; qwAccum+ qwAccum
fxch ST(1) ; qwAccum qwAccum+
fdivr __One ; 1/qw qwAccum+ -- let the divide rip!
@@:
loopTopNoDiv:
;;
;; This is the start of the inner loop. This is where the pixel-level
;; work happens:
;;
;;
;; First, do z-buffering is enabled:
;;
if ZBUFFER
mov eax, [edi] ;U
mov ebx, [esi].GENGC_zAccum ; V
shr ebx, 16 ;U
and eax, 0ffffh ; V
cmp ebx, eax ;U
if ZCMP_L
jl @zWrite ; V
else
jle @zWrite ; V
endif
ZBUFFER_FAIL_ADVANCE
@zWrite:
mov [edi], bx ;UV
endif ;;ZBUFFER
;;
;; Now, get pointer to current texel value in EDX. There are two cases,
;; one if there is a palette-lookup, and one if we index straight into
;; the texture.
;;
if PALETTE_ENABLED
mov ecx, TEXPALETTE ;U
mov eax, TMASK_SUBDIV ; V
test ecx, ecx ;U
je @noPalette ; V
mov edx, [esi].GENGC_tResult ; V
mov ebx, [esi].GENGC_sResult ;U
and edx, eax ; V
mov eax, [esi].GENGC_sMask ;U
and ebx, eax ; V
shr edx, 6 ;U
mov eax, DWORD PTR [esi].GENGC_sResult ; V
shr ebx, 16 ;U
mov ecx, TEXIMAGE ; V
add edx, ecx ;U
add eax, [esi].GENGC_subDs ; V
mov ecx, DWORD PTR [esi].GENGC_tResult ;U
add edx, ebx ; V
add ecx, [esi].GENGC_subDt ;U
mov DWORD PTR [esi].GENGC_sResult, eax ; V
xor eax, eax ;U
mov ebx, TEXPALETTE ; V
mov DWORD PTR [esi].GENGC_tResult, ecx ;U
mov al, [edx] ; V
lea edx, [ebx+4*eax] ;U
jmp short @paletteDone ; V
@noPalette:
endif ;;PALETTE_ENABLED
mov eax, TMASK_SUBDIV ;U
mov edx, [esi].GENGC_tResult ; V
mov ebx, [esi].GENGC_sResult ;U
and edx, eax ; V
shr edx, (6-TEX_BPP_LOG2) ;U
mov ecx, [esi].GENGC_sMask ; V
and ebx, ecx ;U
mov eax, DWORD PTR [esi].GENGC_sResult ; V
shr ebx, (16-TEX_BPP_LOG2) ;U
mov ecx, [esi].GENGC_subDs ; V
add eax, ecx ;U
add edx, ebx ; V
mov ecx, TEXIMAGE ;U
mov ebx, [esi].GENGC_subDt ; V
add edx, ecx ;U
mov ecx, DWORD PTR [esi].GENGC_tResult ; V
add ecx, ebx ;U
mov DWORD PTR [esi].GENGC_sResult, eax ; V
mov DWORD PTR [esi].GENGC_tResult, ecx ;U
if (PALETTE_ONLY)
mov al, [edx] ; V
and eax, 0ffh ;U
mov ebx, TEXPALETTE ; V
lea edx, [ebx+4*eax] ;U
endif
@paletteDone:
;;
;; We are now ready to handle each of the 4 basic modes on a case-by-case
;; basis. We will generally try to adhere to the following register
;; usage:
;; eax - red
;; ebx - green
;; ecx - blue
;; ebx, edx - framebuffer pointers
;;
if FAST_REPLACE
;;----------------------------------------------------------------------
;;
;; ** Replace mode (compressed)
;;
;;----------------------------------------------------------------------
if ALPHA
cmp BYTE PTR [edx+3], 0ffh ;U
je @noAlpha ; V
mov ebx, [esi].GENGC_pixAccum ;U ;; get ready to do read
cmp BYTE PTR [edx+3], 0 ; V
jne @alphaRead ;U
;; Alpha is 0 in the texture, so just increment all the accumulators
if ZBUFFER
mov ecx, [esi].GENGC_zAccum ;U
add edi, 2 ; V
add ecx, [esi].GENGC_SPAN_dz ;U
endif
PIXADVANCE ebx ;U
if ZBUFFER
mov [esi].GENGC_zAccum, ecx ;U
endif
ror eax, 8 ; V
sub ebp, 010001h ;U
mov [esi].GENGC_pixAccum, ebx ; V
mov [esi].GENGC_ditherAccum, eax ;U
;; Finish incrementing all of our accumulators
jl doSubDiv ; V
test ebp, 08000h ;U
je loopTopNoDiv ; V
jmp spanExit
@alphaRead:
;;
;; Get pixel value and calculate total effect with alpha
;;
;; To make this easy on ourselves, we'll use the uncompressed palette
;; to do the alpha modulation:
ALPHANOMODULATE
sub edx, [esi].GENGC_texImageReplace
add edx, [esi].GENGC_texPalette
ALPHAREAD
mov al, [edx+2] ;U get texel value
mov ah, [esi].GENGC_aDisplay
mov bl, [edx+1] ;U
mov bh, [esi].GENGC_aDisplay
mov cl, [edx] ; V
mov ch, [esi].GENGC_aDisplay
and eax, 0ffffh
and ebx, 0ffffh
and ecx, 0ffffh
mov ah, _gbMulTable[eax]
mov bh, _gbMulTable[ebx]
mov ch, _gbMulTable[ecx]
add ah, [esi].GENGC_rDisplay
add bh, [esi].GENGC_gDisplay
add ch, [esi].GENGC_bDisplay
if (BPP eq 32)
shl eax, -rRightShiftAdj
else
shr eax, rRightShiftAdj ;U
endif
mov edx, [esi].GENGC_pixAccum ; V
shr ebx, gRightShiftAdj ;U
and eax, rMask ; V
shr ecx, bRightShiftAdj ;U
and ebx, gMask ; V
and ecx, bMask ;U
or eax, ebx ; V
or eax, ecx ;U
PIXADVANCE2 ebx, edx ; V
if ZBUFFER
mov ecx, [esi].GENGC_zAccum ; V
add edi, 2 ;U
add ecx, [esi].GENGC_SPAN_dz ; V
endif
mov [esi].GENGC_pixAccum, ebx ;U
if ZBUFFER
mov [esi].GENGC_zAccum, ecx ;U
endif
if (BPP eq 8)
sub ebp, 010001h ; V
mov al, [esi].GENGC_xlatPalette[eax];U ;; AGI without z-buffering
mov [edx], al ;U
elseif (BPP eq 16)
sub ebp, 010001h
mov [edx], ax
else
mov [edx], ax
shr eax, 16
sub ebp, 010001h
mov [edx+2], al
endif
;; Finish the loop:
jl doSubDiv ; V
test ebp, 08000h ;U
je loopTopNoDiv ; V
jmp spanExit
endif ;;ALPHA
@noAlpha:
mov ebx, [esi].GENGC_pixAccum ;U
if (BPP eq 8)
mov al, [edx] ; V get texel value
elseif (BPP eq 16)
mov ax, [edx]
else
mov eax, [edx]
endif
PIXADVANCE2 ecx, ebx ;U
if ZBUFFER
mov edx, [esi].GENGC_zAccum ; V
add edi, 2 ;U
add edx, [esi].GENGC_SPAN_dz ; V
mov [esi].GENGC_zAccum, edx ;U
endif
mov [esi].GENGC_pixAccum, ecx ; V
if (BPP eq 8)
sub ebp, 010001h ;U
mov [ebx], al ; V
elseif (BPP eq 16)
sub ebp, 010001h
mov [ebx], ax
else
mov [ebx], ax
shr eax, 16
sub ebp, 010001h
mov [ebx+2], al
endif
;; Finish incrementing all of our accumulators
jl doSubDiv ;U
test ebp, 08000h ; V
je loopTopNoDiv ;U
jmp spanExit
elseif REPLACE
;;----------------------------------------------------------------------
;;
;; ** Replace mode (non-compressed)
;;
;;----------------------------------------------------------------------
if ALPHA
cmp BYTE PTR [edx+3], 0ffh ;U
je @noAlpha ; V
mov ebx, [esi].GENGC_pixAccum ;U ;; get ready to do read
cmp BYTE PTR [edx+3], 0 ; V
jne @alphaRead ;U
;; Alpha is 0 in the texture, so just increment all the accumulators
if ZBUFFER
mov ecx, [esi].GENGC_zAccum ;U
add edi, 2 ; V
add ecx, [esi].GENGC_SPAN_dz ;U
endif
mov eax, [esi].GENGC_ditherAccum ; V
if ZBUFFER
mov [esi].GENGC_zAccum, ecx ;U
endif
PIXADVANCE ebx ;U
ror eax, 8 ; V
sub ebp, 010001h ;U
mov [esi].GENGC_pixAccum, ebx ; V
mov [esi].GENGC_ditherAccum, eax ;U
;; Finish incrementing all of our accumulators
jl doSubDiv ; V
test ebp, 08000h ;U
je loopTopNoDiv ; V
jmp spanExit
@alphaRead:
;;
;; Get pixel value and calculate total effect with alpha
;;
ALPHANOMODULATE
ALPHAREAD
mov al, [edx+2] ;U get texel value
mov ah, [esi].GENGC_aDisplay
mov bl, [edx+1] ;U
mov bh, [esi].GENGC_aDisplay
mov cl, [edx] ; V
mov ch, [esi].GENGC_aDisplay
and eax, 0ffffh
and ebx, 0ffffh
and ecx, 0ffffh
mov ah, _gbMulTable[eax]
mov bh, _gbMulTable[ebx]
mov ch, _gbMulTable[ecx]
add ah, [esi].GENGC_rDisplay
add bh, [esi].GENGC_gDisplay
add ch, [esi].GENGC_bDisplay
if (BPP eq 32)
shl eax, -rRightShiftAdj
else
shr eax, rRightShiftAdj ;U
endif
mov edx, [esi].GENGC_pixAccum ; V
shr ebx, gRightShiftAdj ;U
and eax, rMask ; V
shr ecx, bRightShiftAdj ;U
and ebx, gMask ; V
and ecx, bMask ;U
or eax, ebx ; V
or eax, ecx ;U
PIXADVANCE2 ebx, edx ; V
if ZBUFFER
mov ecx, [esi].GENGC_zAccum ; V
add edi, 2 ;U
add ecx, [esi].GENGC_SPAN_dz ; V
endif
mov [esi].GENGC_pixAccum, ebx ;U
if ZBUFFER
mov [esi].GENGC_zAccum, ecx ;U
endif
if (BPP eq 8)
sub ebp, 010001h ; V
mov al, [esi].GENGC_xlatPalette[eax];U ;; AGI without z-buffering
mov [edx], al ;U
elseif (BPP eq 16)
sub ebp, 010001h
mov [edx], ax
else
mov [edx], ax
shr eax, 16
sub ebp, 010001h
mov [edx+2], al
endif
;; Finish the loop:
jl doSubDiv ; V
test ebp, 08000h ;U
je loopTopNoDiv ; V
jmp spanExit
endif ;;ALPHA
@noAlpha:
mov ah, [edx+2] ;U get texel value
mov bh, [edx+1] ; V
if (BPP eq 32)
shl eax, -rRightShiftAdj
else
shr eax, rRightShiftAdj ;U
endif
mov ch, [edx] ; V
shr ebx, gRightShiftAdj ;U
and eax, rMask ; V
shr ecx, bRightShiftAdj ;U
and ebx, gMask ; V
or eax, ebx ;U
and ecx, bMask ; V
mov edx, [esi].GENGC_pixAccum ;U
or eax, ecx ; V
PIXADVANCE2 ebx, edx ;U
if ZBUFFER
mov ecx, [esi].GENGC_zAccum ; V
add edi, 2 ;U
add ecx, [esi].GENGC_SPAN_dz ; V
mov [esi].GENGC_zAccum, ecx ;U
endif
if (BPP eq 8)
sub ebp, 010001h ; V
mov [esi].GENGC_pixAccum, ebx ;U
mov al, [esi].GENGC_xlatPalette[eax]; V
mov [edx], al ;U
elseif (BPP eq 16)
sub ebp, 010001h
mov [esi].GENGC_pixAccum, ebx
mov [edx], ax
else
mov [edx], ax
shr eax, 16
mov [esi].GENGC_pixAccum, ebx
sub ebp, 010001h
mov [edx+2], al
endif
;; Finish the loop:
jl doSubDiv ; V
test ebp, 08000h ;U
je loopTopNoDiv ; V
jmp spanExit
elseif FLAT_SHADING
;;----------------------------------------------------------------------
;;
;; ** Flat shading
;;
;;----------------------------------------------------------------------
if ALPHA
mov ebx, [esi].GENGC_pixAccum ;; get ready to do read
cmp BYTE PTR [edx+3], 0
jne @alphaRead
;; Alpha is 0 in the texture, so just increment all the accumulators
if ZBUFFER
mov ecx, [esi].GENGC_zAccum
mov eax, [esi].GENGC_SPAN_dz
add edi, 2
add ecx, eax
endif
mov eax, [esi].GENGC_ditherAccum
if ZBUFFER
mov [esi].GENGC_zAccum, ecx
endif
ror eax, 8 ;U
PIXADVANCE ebx ; V
sub ebp, 010001h ;U
mov [esi].GENGC_pixAccum, ebx ; V
mov [esi].GENGC_ditherAccum, eax ;U
;; Finish incrementing all of our accumulators
jl doSubDiv ; V
test ebp, 08000h ;U
je loopTopNoDiv ; V
jmp spanExit
@alphaRead:
cmp BYTE PTR [edx+3], 0ffh
jne @doAlpha
cmp BYTE PTR [esi].GENGC_aAccum+2, 0ffh
jne @doAlpha
;; Set mix color to 1, 0, 0, 0
mov DWORD PTR [esi].GENGC_rDisplay, 0ff000000h
jmp short @doneAlpha
;;
;; Get pixel value and calculate total effect with alpha
;;
@doAlpha:
ALPHAMODULATE
ALPHAREAD
@doneAlpha:
endif ;;ALPHA
mov ebx, [edx] ;U
mov ecx, ebx ; V
shr ebx, 16 ;U
mov edx, ecx ; V
shr ecx, 8 ;U
mov eax, [esi].GENGC_rAccum ; V
and ebx, 0ffh ;U
and ecx, 0ffh ; V
or ebx, eax ;U
mov eax, [esi].GENGC_gAccum ; V
and edx, 0ffh ;U
or ecx, eax ; V
mov eax, [esi].GENGC_bAccum ;U
or edx, eax ; V
mov ebx, DWORD PTR _gbMulTable[ebx] ;U
mov ecx, DWORD PTR _gbMulTable[ecx] ; V
mov edx, DWORD PTR _gbMulTable[edx] ;U
if ALPHA
mov bh, [esi].GENGC_aDisplay
mov ch, bh
mov dh, bh
and ebx, 0ffffh
and ecx, 0ffffh
and edx, 0ffffh
mov bl, _gbMulTable[ebx]
mov cl, _gbMulTable[ecx]
mov dl, _gbMulTable[edx]
add bl, [esi].GENGC_rDisplay
add cl, [esi].GENGC_gDisplay
add dl, [esi].GENGC_bDisplay
endif
;; do the dithering
shl ebx, (rBits+8) ;U
mov eax, [esi].GENGC_ditherAccum ; V
shl ecx, (gBits+8) ;U
and eax, 0f800h ; V
shl edx, (bBits+8) ;U
add ebx, eax ; V
add ecx, eax ;U
add edx, eax ; V
;;
;; Compose the final pixel:
;;
if (BPP eq 32)
shl ebx, -rRightShiftAdj
else
shr ebx, rRightShiftAdj ;U
endif
mov eax, [esi].GENGC_ditherAccum ; V
ror eax, 8 ;U
and ebx, rMask ; V
shr ecx, gRightShiftAdj ;U
mov [esi].GENGC_ditherAccum, eax ; V
shr edx, bRightShiftAdj ;U
and ecx, gMask ; V
or ebx, ecx ;U
and edx, bMask ; V
or ebx, edx ;U
;;
;; Advance the frame buffer pointer:
;;
mov ecx, [esi].GENGC_pixAccum ; V
mov edx, ecx ;U
if (BPP le 16)
add ecx, (BPP / 8) ; V
else
add ecx, [esi].GENGC_bytesPerPixel ; V
endif
mov [esi].GENGC_pixAccum, ecx ;U
;;
;; A good time to start incrementing all of our accumulators:
;;
if ZBUFFER
mov ecx, [esi].GENGC_zAccum ; V
mov eax, [esi].GENGC_SPAN_dz ;U
add ecx, eax ; V
add edi, 2 ;U
mov [esi].GENGC_zAccum, ecx ; V
endif
;;
;; Write the pixel into the frame buffer
;;
if (BPP eq 8)
mov al, [esi].GENGC_xlatPalette[ebx]; V
sub ebp, 010001h ;U
mov [edx], al ; V
elseif (BPP eq 16)
sub ebp, 010001h
mov [edx], bx
else
mov [edx], bx
shr ebx, 16
sub ebp, 010001h
mov [edx+2], bl
endif
;; Finish incrementing all of our accumulators
jl doSubDiv ;U
test ebp, 08000h ; V
je loopTopNoDiv ;U
elseif SMOOTH_SHADING
;;----------------------------------------------------------------------
;;
;; ** Smooth shading
;;
;;----------------------------------------------------------------------
if ALPHA
mov ebx, [esi].GENGC_pixAccum ;; get ready to do read
cmp BYTE PTR [edx+3], 0
jne @alphaRead
;; Alpha is 0 in the texture, so just increment all the accumulators
if ZBUFFER
mov ecx, [esi].GENGC_zAccum
mov eax, [esi].GENGC_SPAN_dz
add eax, ecx
add edi, 2
mov [esi].GENGC_zAccum, eax
endif
mov eax, [esi].GENGC_rAccum
mov ebx, [esi].GENGC_gAccum
mov ecx, [esi].GENGC_bAccum
add eax, [esi].GENGC_SPAN_dr
add ebx, [esi].GENGC_SPAN_dg
add ecx, [esi].GENGC_SPAN_db
mov [esi].GENGC_rAccum, eax
mov [esi].GENGC_gAccum, ebx
mov [esi].GENGC_bAccum, ecx
mov eax, [esi].GENGC_ditherAccum
mov ecx, [esi].GENGC_aAccum
ror eax, 8
mov ebx, [esi].GENGC_pixAccum
add ecx, [esi].GENGC_SPAN_da
PIXADVANCE ebx
mov [esi].GENGC_aAccum, ecx
mov [esi].GENGC_pixAccum, ebx
sub ebp, 010001h
mov [esi].GENGC_ditherAccum, eax
;; Finish incrementing all of our accumulators
jl doSubDiv ;U
test ebp, 08000h ; V
je loopTopNoDiv ;U
jmp spanExit
@alphaRead:
cmp BYTE PTR [edx+3], 0ffh
jne @doAlpha
cmp BYTE PTR [esi].GENGC_aAccum+2, 0ffh
jne @doAlpha
;; Set mix color to 1, 0, 0, 0
mov DWORD PTR [esi].GENGC_rDisplay, 0ff000000h
jmp short @doneAlpha
;;
;; Get pixel value and calculate total effect with alpha
;;
@doAlpha:
ALPHAMODULATE
ALPHAREAD
@doneAlpha:
endif ;;ALPHA
mov ebx, [esi].GENGC_rAccum ;U
mov eax, [edx] ; V
shr ebx, rBits ;U
and eax, 0ff0000h ; V
shr eax, 16 ;U
mov ecx, [esi].GENGC_gAccum ; V
shr ecx, gBits ;U
and ebx, 0ff00h ; V
or ebx, eax ;U
mov eax, [edx] ; V
shr eax, 8 ;U
mov edx, [edx] ; V
and eax, 0ffh ;U
and ecx, 0ff00h ; V
or ecx, eax ;U
mov eax, [esi].GENGC_bAccum ; V
shr eax, bBits ;U
and edx, 0ffh ; V
and eax, 0ff00h ;U
mov ebx, DWORD PTR _gbMulTable[ebx] ; V get multiplied 8-bit R value
or edx, eax ;U
mov ecx, DWORD PTR _gbMulTable[ecx] ; V get multiplied 8-bit G value
mov eax, [esi].GENGC_ditherAccum ;U
mov edx, DWORD PTR _gbMulTable[edx] ; V get multiplied 8-bit B value
if ALPHA
mov bh, [esi].GENGC_aDisplay
mov ch, bh
mov dh, bh
and ebx, 0ffffh
and ecx, 0ffffh
and edx, 0ffffh
mov bl, _gbMulTable[ebx]
mov cl, _gbMulTable[ecx]
mov dl, _gbMulTable[edx]
add bl, [esi].GENGC_rDisplay
add cl, [esi].GENGC_gDisplay
add dl, [esi].GENGC_bDisplay
endif
shl ebx, (rBits+8) ;U
and eax, 0f800h ; V
shl ecx, (gBits+8) ;U
add ebx, eax ; V
shl edx, (bBits+8) ;U
add ecx, eax ; V
if (BPP eq 32)
shl ebx, -rRightShiftAdj
else
shr ebx, rRightShiftAdj ;U
endif
add edx, eax ; V
shr ecx, gRightShiftAdj ;U
and ebx, rMask ; V
shr edx, bRightShiftAdj ;U
and ecx, gMask ; V
or ebx, ecx ;U
and edx, bMask ; V
or ebx, edx ;U
;;
;; A good time to start incrementing all of our accumulators
;;
if ZBUFFER
mov ecx, [esi].GENGC_zAccum ; V
mov eax, [esi].GENGC_SPAN_dz ;U
add eax, ecx ; V
add edi, 2 ;U
mov [esi].GENGC_zAccum, eax ; V
endif
mov eax, [esi].GENGC_rAccum ;U
mov ecx, [esi].GENGC_SPAN_dr ; V
mov edx, [esi].GENGC_gAccum ;U
add eax, ecx ; V
mov ecx, [esi].GENGC_SPAN_dg ;U
mov [esi].GENGC_rAccum, eax ; V
add edx, ecx ;U
mov eax, [esi].GENGC_bAccum ; V
mov ecx, [esi].GENGC_SPAN_db ;U
add eax, ecx ; V
mov [esi].GENGC_gAccum, edx ;U
mov [esi].GENGC_bAccum, eax ; V
mov eax, [esi].GENGC_ditherAccum ;U
mov ecx, [esi].GENGC_pixAccum ; V
ror eax, 8 ;U
mov edx, ecx ; V
if (BPP le 16)
add ecx, (BPP / 8) ;U
else
add ecx, [esi].GENGC_bytesPerPixel ;U
endif
mov [esi].GENGC_ditherAccum, eax ; V
mov [esi].GENGC_pixAccum, ecx ;U
if ALPHA
mov ecx, [esi].GENGC_aAccum
add ecx, [esi].GENGC_SPAN_da
mov [esi].GENGC_aAccum, ecx
endif
if (BPP eq 8)
mov al, [esi].GENGC_xlatPalette[ebx]; V
sub ebp, 010001h ;U
mov [edx], al ; V
elseif (BPP eq 16)
sub ebp, 010001h
mov [edx], bx
else
mov [edx], bx
shr ebx, 16
sub ebp, 010001h
mov [edx+2], bl
endif
;; Finish incrementing all of our accumulators
jl doSubDiv ;U
test ebp, 08000h ; V
je loopTopNoDiv ;U
endif ;;SMOOTH_SHADING
;;
;; This is the exit point. We need to pop the unused floating-point
;; registers off the stack, and return:
;;
spanExit:
fstp ST(0)
fstp ST(0)
pop ebp
pop edi
pop esi
pop ebx
ret 0
;;
;; This is the subdivision code. After the required number of steps, the
;; routine will jump here to calculate the next set of interpolants based
;; on subdivision:
;;
doSubDiv:
add ebp, 080000h
mov ecx, [esi].GENGC_flags
;;
;; Increment the big S and T steps:
;;
mov edx, [esi].GENGC_sAccum
test ebp, 08000h
jne short spanExit
mov ebx, [esi].GENGC_tAccum
add edx, [esi].GENGC_sStepX
add ebx, [esi].GENGC_tStepX
mov [esi].GENGC_sAccum, edx
mov [esi].GENGC_tAccum, ebx
mov eax, [esi].GENGC_sResultNew
mov ebx, [esi].GENGC_tResultNew
test ecx, GEN_TEXTURE_ORTHO
je @f
mov ecx, DWORD PTR [esi].GENGC_tAccum
mov DWORD PTR [esi].GENGC_sResultNew, edx
mov DWORD PTR [esi].GENGC_tResultNew, ecx
jmp short @stResultDone3
;;
;; Do the floating-point computation for perspective:
;;
@@:
fild DWORD PTR [esi].GENGC_sAccum ; s 1/qw qwAccum
fmul ST, ST(1) ; s/qw 1/qw qwAccum
fild DWORD PTr [esi].GENGC_tAccum ; t s/qw 1/qw qwAccum
fmulp ST(2), ST ; s/qw t/qw qwAccum
fistp QWORD PTR [esi].GENGC_sResultNew; t/qw qwAccum
fistp QWORD PTR [esi].GENGC_tResultNew; qwAccum
@stResultDone3:
;;
;; Now, calculate the per-pixel deltas:
;;
mov cl, TSHIFT_SUBDIV ;U
mov edx, [esi].GENGC_tResultNew ; V
sar edx, cl ;UV (4)
mov ecx, [esi].GENGC_sResultNew ;U
and edx, NOT 7 ; V
sub ecx, eax ;U
mov [esi].GENGC_tResultNew, edx ; V
sar ecx, 3 ;U
sub edx, ebx ; V
sar edx, 3 ;U
mov [esi].GENGC_subDs, ecx ; V
mov [esi].GENGC_subDt, edx ;U
mov [esi].GENGC_sResult, eax ; V
mov [esi].GENGC_tResult, ebx ;U
mov eax, [esi].GENGC_flags ; V
jmp loopTop ;U