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

1956 lines
51 KiB
NASM

;---------------------------Module-Header------------------------------;
; Module Name: so_prim.asm
;
; xform routines.
;
; Created: 10/14/1996
; Author: Otto Berkes [ottob]
;
; Copyright (c) 1996 Microsoft Corporation
;----------------------------------------------------------------------;
.386
.model small,pascal
assume cs:FLAT,ds:FLAT,es:FLAT,ss:FLAT
assume fs:nothing,gs:nothing
.xlist
include gli386.inc
.list
PROFILE = 0
include profile.inc
.data
extrn ___glClipCodes :DWORD
extrn ___glOne:DWORD
extrn ___glHalf:DWORD
extrn ___glZero:DWORD
;------------------------------------------------------------------------------------------
; Internal definitions:
;
_R_ = 0
_G_ = 4
_B_ = 8
_A_ = 12
_X_ = 0
_Y_ = 4
_Z_ = 8
_W_ = 12
;------------------------------------------------------------------------------------------
; pdLast is passed as parameter
;
pdLast equ [ebp+8]
;
; Temporary data
;
gc equ -4[ebp]
pa equ -8[ebp]
.code
extrn @__glNormalize@8:NEAR
;------------------------------------------------------------------------------------------
; Makes clip code for frustum clip planes
; General case
;
; Input:
; edx = pointer to POLYARRAY
; ecx = pointer to graphics context
; pdLast = pointer to the last vertex
; pa = pointer to POLYARRAY
; gc = pointer to graphics context
; ReuseClipCode if set to 1, new clip code is combined using OR with existing one
;
; Returns:
; eax = andClipCodes for POLYARRAY
;
PAClipCheckFrustum MACRO ReuseClipCode
mov edx, DWORD PTR [edx+PA_pd0]
vertexLoop:
mov esi, DWORD PTR [edx+PD_clip+_W_] ; esi = clipW
or esi, esi ; if (clipW == 0) go to special case
jz @WEqZero
fld ___glOne
fdiv DWORD PTR [edx+PD_clip+_W_] ; start division
; edi will accumulate index to clip table
; bit 6 - 1 if clipW < 0
; bit 5 - 1 if clipX < 0
; bit 4 - 1 if abs(clipX) < abs(clipW)
; bit 3 - 1 if clipY < 0
; bit 2 - 1 if abs(clipY) < abs(clipW)
; bit 1 - 1 if clipZ < 0
; bit 0 - 1 if abs(clipZ) < abs(clipW)
xor edi, edi
add esi, esi ; esi = abs(clipW) shifted left 1 bit
mov ebx, [edx+PD_clip+_X_] ; ebx = clipX
adc edi, edi ; edi = sign clipW
add esi, 1 ; X-W bit should be set when X-W <= 0 !!!
add ebx, ebx ; ebx = abs(clipX) shifted left 1 bit
adc edi, edi ; edi = edi << 1 + sign(clipX)
sub ebx, esi
adc edi, edi ; edi = edi << 1 + sign(abs(clipX) - abs(clipW))
mov ebx, [edx+PD_clip+_Y_]
mov ecx, pa
add ebx, ebx
adc edi, edi ; edi = edi << 1 + sign(clipY)
sub ebx, esi
adc edi, edi ; edi = edi << 1 + sign(abs(clipY) - abs(clipW))
mov ebx, [edx+PD_clip+_Z_]
add edx, sizeof_POLYDATA ; advance vertex ptr
add ebx, ebx ; edi = edi << 1 + sign(clipZ)
adc edi, edi
sub ebx, esi
adc edi, edi ; edi = edi << 1 + sign(abs(clipZ) - abs(clipW))
mov esi, [ecx+PA_orClipCodes] ; get prim OR code
mov ebx, [ecx+PA_andClipCodes] ; get prim AND code
mov ecx, ___glClipCodes[edi*4] ; ecx = clip code
mov edi, pa
if ReuseClipCode eq 1
or ecx, [edx+PD_clipCode-sizeof_POLYDATA] ; update vertex clip code
endif
mov [edx+PD_clipCode-sizeof_POLYDATA], ecx ; store vertex clip code
or esi, ecx ; compute prim OR
and ebx, ecx ; " " AND
mov [edi+PA_orClipCodes], esi ; store prim OR
mov [edi+PA_andClipCodes], ebx ; store prim AND
mov ebx, gc
mov edi, pdLast
;; Save invW in window.w:
fstp DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA]
or ecx, ecx
jnz @Done
fld DWORD PTR [edx+PD_clip+_X_ - sizeof_POLYDATA]
fmul DWORD PTR [ebx+GC_VIEWPORT_xScale]
fld DWORD PTR [edx+PD_clip+_Y_ - sizeof_POLYDATA]
fmul DWORD PTR [ebx+GC_VIEWPORT_yScale]
fld DWORD PTR [edx+PD_clip+_Z_ - sizeof_POLYDATA]
fmul DWORD PTR [ebx+GC_VIEWPORT_zScale] ; z y x
fxch st(2) ; x y z
fmul DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA] ; X y z
fxch st(1) ; y X z
fmul DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA] ; Y X z
fxch st(2) ; z X Y
fmul DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA] ; Z X Y
fxch st(1) ; X Z Y
fadd DWORD PTR [ebx+GC_VIEWPORT_xCenter] ; x Z Y
fxch st(2) ; Y Z x
fadd DWORD PTR [ebx+GC_VIEWPORT_yCenter] ; y Z x
fxch st(1) ; Z y x
fadd DWORD PTR [ebx+GC_VIEWPORT_zCenter] ; z y x
fxch st(2) ; x y z
fstp DWORD PTR [edx+PD_window+_X_ - sizeof_POLYDATA]
fstp DWORD PTR [edx+PD_window+_Y_ - sizeof_POLYDATA]
fstp DWORD PTR [edx+PD_window+_Z_ - sizeof_POLYDATA]
@Done:
cmp edx, edi ; pd > pdLast?
jbe vertexLoop ; yes -> process next vertex
@Exit:
mov edx, pa
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
mov eax, [edx + PA_andClipCodes] ; return value
ret 4
;
; W == 0
;
@WEqZero:
xor edi, edi
mov ebx, [edx+PD_clip+_X_] ; ebx = clipX
add ebx, ebx ; ebx = abs(clipX) shifted left 1 bit
adc edi, edi ; edi = edi << 1 + sign(clipX)
add edi, edi ; edi = edi << 1
mov ebx, [edx+PD_clip+_Y_]
mov ecx, pa
add ebx, ebx
adc edi, edi ; edi = edi << 1 + sign(clipY)
add edi, edi ; edi = edi << 1
mov ebx, [edx+PD_clip+_Z_]
add edx, sizeof_POLYDATA ; advance vertex ptr
add ebx, ebx ; edi = edi << 1 + sign(clipZ)
adc edi, edi
add edi, edi ; edi = edi << 1
mov esi, [ecx+PA_orClipCodes] ; get prim OR code
mov ebx, [ecx+PA_andClipCodes] ; get prim AND code
mov ecx, ___glClipCodes[edi*4] ; ecx = clip code
mov edi, pa
if ReuseClipCode eq 1
or ecx, [edx+PD_clipCode-sizeof_POLYDATA] ; update vertex clip code
endif
mov [edx+PD_clipCode-sizeof_POLYDATA], ecx ; store vertex clip code
or esi, ecx ; compute prim OR
and ebx, ecx ; " " AND
mov [edi+PA_orClipCodes], esi ; store prim OR
mov [edi+PA_andClipCodes], ebx ; store prim AND
mov ebx, gc
mov edi, pdLast
;; Save invW in window.w:
mov DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA], 0
or ecx, ecx
jnz @Done
mov ecx, DWORD PTR [ebx+GC_VIEWPORT_xCenter]
mov ebx, DWORD PTR [ebx+GC_VIEWPORT_yCenter]
mov DWORD PTR [edx+PD_window+_X_ - sizeof_POLYDATA], ecx
mov ecx, DWORD PTR [ebx+GC_VIEWPORT_zCenter]
mov DWORD PTR [edx+PD_window+_Y_ - sizeof_POLYDATA], ebx
mov DWORD PTR [edx+PD_window+_Z_ - sizeof_POLYDATA], ecx
jmp @Done
ENDM
;------------------------------------------------------------------------------------------
; Make clip code for frustum clip planes
; General case
;
; Prototype:
; GLuint FASTCALL PAClipCheckFrustum(__GLcontext *gc, POLYARRAY *pa,
; POLYDATA *pdLast);
; Input:
; edx = pa pointer to POLYARRAY
; ecx = gc pointer to graphics context
; [esp+4] = pointer to the last vertex
; andClipCodes for POLYARRAY is set to -1
; orClipCodes for POLYARRAY is set to 0
;
; Returns:
; andClipCodes for POLYARRAY
;
@PAClipCheckFrustum@12 PROC NEAR
push ebp
mov ebp, esp
sub esp, 12
mov DWORD PTR pa, edx
mov DWORD PTR gc, ecx
push ebx
push esi
push edi
PAClipCheckFrustum 0
@PAClipCheckFrustum@12 ENDP
;------------------------------------------------------------------------------------------
; Makes clip code for frustum clip planes
; Case when vertices have W == 1.0
;
; Input:
; edx = pa pointer to POLYARRAY
; ecx = gc pointer to graphics context
; pa = pointer to POLYARRAY
; gc = pointer to graphics context
; pdLast = pointer to the last vertex
; ReuseClipCode if set to 1, new clip code is combined using OR with existing one
;
; Returns:
; eax = andClipCodes for POLYARRAY
;
PAClipCheckFrustumWOne MACRO ReuseClipCode
mov edx, DWORD PTR [edx+PA_pd0]
vertexLoop:
; edi will accumulate index to clip table
; bit 6 - 1 if clipW < 0 --- always 0 for this case
; bit 5 - 1 if clipX < 0
; bit 4 - 1 if abs(clipX) < abs(clipW)
; bit 3 - 1 if clipY < 0
; bit 2 - 1 if abs(clipY) < abs(clipW)
; bit 1 - 1 if clipZ < 0
; bit 0 - 1 if abs(clipZ) < abs(clipW)
xor edi, edi
mov ebx, [edx+PD_clip+_X_] ; ebx = clipX
mov esi, (__FLOAT_ONE*2) + 1
add ebx, ebx ; ebx = abs(clipX) shifted left 1 bit
adc edi, edi ; edi = edi << 1 + sign(clipX)
sub ebx, esi
adc edi, edi ; edi = edi << 1 + sign(abs(clipX) - abs(clipW))
mov ebx, [edx+PD_clip+_Y_]
mov ecx, pa
add ebx, ebx
adc edi, edi ; edi = edi << 1 + sign(clipY)
sub ebx, esi
adc edi, edi ; edi = edi << 1 + sign(abs(clipY) - abs(clipW))
mov ebx, [edx+PD_clip+_Z_]
add edx, sizeof_POLYDATA ; advance vertex ptr
add ebx, ebx ; edi = edi << 1 + sign(clipZ)
adc edi, edi
sub ebx, esi
adc edi, edi ; edi = edi << 1 + sign(abs(clipZ) - abs(clipW))
mov esi, [ecx+PA_orClipCodes] ; get prim OR code
mov ebx, [ecx+PA_andClipCodes] ; get prim AND code
mov ecx, ___glClipCodes[edi*4] ; ecx = clip code
mov edi, pa
if ReuseClipCode eq 1
or ecx, [edx+PD_clipCode-sizeof_POLYDATA] ; update vertex clip code
endif
mov [edx+PD_clipCode-sizeof_POLYDATA], ecx ; store vertex clip code
or esi, ecx ; compute prim OR
and ebx, ecx ; " " AND
mov [edi+PA_orClipCodes], esi ; store prim OR
mov [edi+PA_andClipCodes], ebx ; store prim AND
mov ebx, gc
mov edi, pdLast
;; Save invW in window.w:
mov DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA], __FLOAT_ONE
or ecx, ecx
jnz @Done
fld DWORD PTR [edx+PD_clip+_X_ - sizeof_POLYDATA]
fmul DWORD PTR [ebx+GC_VIEWPORT_xScale]
fld DWORD PTR [edx+PD_clip+_Y_ - sizeof_POLYDATA]
fmul DWORD PTR [ebx+GC_VIEWPORT_yScale]
fld DWORD PTR [edx+PD_clip+_Z_ - sizeof_POLYDATA]
fmul DWORD PTR [ebx+GC_VIEWPORT_zScale] ; z y x
fxch st(2) ; x y z
fadd DWORD PTR [ebx+GC_VIEWPORT_xCenter] ; x y z
fxch st(1) ; y x z
fadd DWORD PTR [ebx+GC_VIEWPORT_yCenter] ; y x z
fxch st(2) ; z x y
fadd DWORD PTR [ebx+GC_VIEWPORT_zCenter] ; z x y
fxch st(1) ; x z y
fstp DWORD PTR [edx+PD_window+_X_ - sizeof_POLYDATA]
fstp DWORD PTR [edx+PD_window+_Z_ - sizeof_POLYDATA]
fstp DWORD PTR [edx+PD_window+_Y_ - sizeof_POLYDATA]
@Done:
cmp edx, edi ; pd > pdLast?
jbe vertexLoop ; yes -> process next vertex
@Exit:
mov edx, pa
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
mov eax, [edx + PA_andClipCodes] ; return value
ret 4
ENDM
;------------------------------------------------------------------------------------------
; Makes clip code for frustum clip planes
; Case when vertices have W == 1.0
;
; Prototype:
; GLuint FASTCALL PAClipCheckFrustumWOne(__GLcontext *gc, POLYARRAY *pa,
; POLYDATA *pdLast);
; Input:
; edx = pa pointer to POLYARRAY
; ecx = gc pointer to graphics context
; [esp+4] = pointer to the last vertex
; andClipCodes for POLYARRAY is set to -1
; orClipCodes for POLYARRAY is set to 0
;
; Returns:
; eax = andClipCodes for POLYARRAY
;
@PAClipCheckFrustumWOne@12 PROC NEAR
push ebp
mov ebp, esp
sub esp, 12
mov DWORD PTR pa, edx
mov DWORD PTR gc, ecx
push ebx
push esi
push edi
PAClipCheckFrustumWOne 0
@PAClipCheckFrustumWOne@12 ENDP
;------------------------------------------------------------------------------------------
; Makes clip code for frustum clip planes
; Case when vertices have W == 1.0 and Z == 0.0
;
; Input:
; edx = pa pointer to POLYARRAY
; ecx = gc pointer to graphics context
; pa = pointer to POLYARRAY
; gc = pointer to graphics context
; pdLast = pointer to the last vertex
; ReuseClipCode if set to 1, new clip code is combined using OR with existing one
;
; Returns:
; eax = andClipCodes for POLYARRAY
;
PAClipCheckFrustum2D MACRO ReuseClipCode
mov edx, DWORD PTR [edx+PA_pd0]
vertexLoop:
; edi will accumulate index to clip table
; bit 6 - 1 if clipW < 0 --- always 0 for this case
; bit 5 - 1 if clipX < 0
; bit 4 - 1 if abs(clipX) < abs(clipW)
; bit 3 - 1 if clipY < 0
; bit 2 - 1 if abs(clipY) < abs(clipW)
; bit 1 - 1 if clipZ < 0
; bit 0 - 1 if abs(clipZ) < abs(clipW)
xor edi, edi
mov ebx, [edx+PD_clip+_X_] ; ebx = clipX
mov esi, (__FLOAT_ONE*2) + 1
add ebx, ebx ; ebx = abs(clipX) shifted left 1 bit
adc edi, edi ; edi = edi << 1 + sign(clipX)
sub ebx, esi
adc edi, edi ; edi = edi << 1 + sign(abs(clipX) - abs(clipW))
mov ebx, [edx+PD_clip+_Y_]
mov ecx, pa
add ebx, ebx
adc edi, edi ; edi = edi << 1 + sign(clipY)
sub ebx, esi
adc edi, edi ; edi = edi << 1 + sign(abs(clipY) - abs(clipW))
add edx, sizeof_POLYDATA ; advance vertex ptr
add edi, edi ; sign(clipZ) = 0
lea edi, [edi+edi+1] ; sign(abs(clipZ) - abs(clipW)) = 0
mov esi, [ecx+PA_orClipCodes] ; get prim OR code
mov ebx, [ecx+PA_andClipCodes] ; get prim AND code
mov ecx, ___glClipCodes[edi*4] ; ecx = clip code
mov edi, pa
if ReuseClipCode eq 1
or ecx, [edx+PD_clipCode-sizeof_POLYDATA] ; update vertex clip code
endif
mov [edx+PD_clipCode-sizeof_POLYDATA], ecx ; store vertex clip code
or esi, ecx ; compute prim OR
and ebx, ecx ; " " AND
mov [edi+PA_orClipCodes], esi ; store prim OR
mov [edi+PA_andClipCodes], ebx ; store prim AND
mov ebx, gc
mov edi, pdLast
;; Save invW in window.w:
mov DWORD PTR [edx+PD_window+_W_ - sizeof_POLYDATA], __FLOAT_ONE
or ecx, ecx
jnz @Done
fld DWORD PTR [edx+PD_clip+_X_ - sizeof_POLYDATA]
fmul DWORD PTR [ebx+GC_VIEWPORT_xScale]
fld DWORD PTR [edx+PD_clip+_Y_ - sizeof_POLYDATA]
fmul DWORD PTR [ebx+GC_VIEWPORT_yScale]
fxch st(1) ; x y
fadd DWORD PTR [ebx+GC_VIEWPORT_xCenter] ; x y
fxch st(1) ; y x
fadd DWORD PTR [ebx+GC_VIEWPORT_yCenter] ; y x
fxch st(1) ; x y
mov ecx, DWORD PTR [ebx+GC_VIEWPORT_zCenter]
mov DWORD PTR [edx+PD_window+_Z_ - sizeof_POLYDATA], ecx
fstp DWORD PTR [edx+PD_window+_X_ - sizeof_POLYDATA]
fstp DWORD PTR [edx+PD_window+_Y_ - sizeof_POLYDATA]
@Done:
cmp edx, edi ; pd > pdLast?
jbe vertexLoop ; yes -> process next vertex
@Exit:
mov edx, pa
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
mov eax, [edx + PA_andClipCodes] ; return value
ret 4
ENDM
;------------------------------------------------------------------------------------------
; Makes clip code for frustum clip planes
; Case when vertices have W == 1.0
;
; Prototype:
; GLuint FASTCALL PAClipCheckFrustum2D(__GLcontext *gc, POLYARRAY *pa,
; POLYDATA *pdLast);
; Input:
; edx = pa pointer to POLYARRAY
; ecx = gc pointer to graphics context
; [esp+4] = pointer to the last vertex
; andClipCodes for POLYARRAY is set to -1
; orClipCodes for POLYARRAY is set to 0
;
; Returns:
; eax = andClipCodes for POLYARRAY
;
@PAClipCheckFrustum2D@12 PROC NEAR
push ebp
mov ebp, esp
sub esp, 12
xor eax, eax
mov pa, edx
mov [edx+PA_orClipCodes], eax ; PA orClipCodes = 0
dec eax
push ebx
mov [edx+PA_andClipCodes], eax ; PA andClipCodes = -1
push esi
mov DWORD PTR gc, ecx
push edi
PAClipCheckFrustum2D 0
@PAClipCheckFrustum2D@12 ENDP
;------------------------------------------------------------------------------------------
; Makes clip code for user planes
;
; Input:
; edx = pa
; ecx = gc
; pdLast = pointer to the last vertex
; ReuseClipCode if set to 1, new clip code is combined using OR with existing one
;
PAClipCheckUser MACRO ReuseClipCode
result equ -16[ebp]
cwSave equ -20[ebp]
cwTemp equ -24[ebp]
clipPlaneMask equ -28[ebp]
firstPlane equ -32[ebp]
;; We have to turn on rounding with double precision. There is
;; too much error in the dot product otherwise (test with tlogo).
fnstcw WORD PTR cwSave
mov edi, DWORD PTR cwSave
and edi, 0f0ffh
or edi, 00200h
mov cwTemp, edi
fldcw WORD PTR cwTemp
mov edi, pdLast ; edi will store POLYARRAY pointer
mov edx, DWORD PTR [edx+PA_pd0]
mov esi, DWORD PTR [ecx+GC_STATE_enablesClipPlanes] ; esi = clipPlaneMask
mov ebx, [ecx+GC_STATE_clipPlanes0] ; ebx points to the current user plane
or esi, esi
jz @Exit1 ; No user planes
mov clipPlaneMask, esi ; save clipPlaneMask
mov firstPlane, ebx ; save pointer to the first clip plane
@vertexLoop:
mov esi, clipPlaneMask ; reload clipPlaneMask
xor eax, eax ; prepare clip code
mov ecx, __GL_CLIP_USER0 ; ecx stores __GL_CLIP_USER bits
mov ebx, firstPlane ; reload pointer to the first clip plane
@doAnotherPlane:
test esi, 1 ; if (clipPlanesMask & 1 == 0) skip the plane
je SHORT @noClipTest
;
; Dot the vertex clip coordinate against the clip plane and see
; if the sign is negative. If so, then the point is out.
;
; if (x * plane->x + y * plane->y + z * plane->z + w * plane->w <
; __glZero)
;
fld DWORD PTR [ebx+_X_]
fmul DWORD PTR [edx+PD_eye+_X_]
fld DWORD PTR [ebx+_Y_]
fmul DWORD PTR [edx+PD_eye+_Y_]
fld DWORD PTR [ebx+_Z_]
fmul DWORD PTR [edx+PD_eye+_Z_] ; z y x
fxch ST(2) ; x y z
faddp ST(1), ST(0) ; xy z
fld DWORD PTR [ebx+_W_] ; w xy z
fmul DWORD PTR [edx+PD_eye+_W_]
fxch ST(2) ; z xy w
faddp ST(1), ST(0) ; zxy w
faddp ST(1), ST(0) ; zxyw
fstp DWORD PTR result
cmp result, 0
jge @noClipTest
or eax, ecx ; code |= bit;
@noClipTest:
add ecx, ecx ; bit <<= 1;
add ebx, 16 ; plane++;
shr esi, 1 ; clipPlanesMask >>= 1;
jne SHORT @doAnotherPlane
if ReuseClipCode eq 1
or [edx+PD_clipCode], eax ; store vertex clip code
else
mov [edx+PD_clipCode], eax ; store vertex clip code
endif
add edx, sizeof_POLYDATA ; advance vertex ptr
cmp edx, edi
jbe @vertexLoop ; process next vertex
;; restore FP state:
fldcw WORD PTR cwSave
@Exit1:
ENDM
;-------------------------------------------------------------------------------------------
; Make clip code when user clip planes are present
;
; Prototype:
; GLuint FASTCALL PAClipCheckFrustumAll(__GLcontext *gc, POLYARRAY *pa,
; POLYDATA *pdLast);
; Input:
; edx = pa pointer to POLYARRAY
; ecx = gc pointer to graphics context
; [esp+4] = pointer to the last vertex
; andClipCodes for POLYARRAY is set to -1
; orClipCodes for POLYARRAY is set to 0
;
; Returns:
; eax = andClipCodes for POLYARRAY
;
@PAClipCheckAll@12 PROC NEAR
push ebp
mov ebp, esp
sub esp, 32
mov DWORD PTR pa, edx
mov DWORD PTR gc, ecx
push ebx
push esi
push edi
PAClipCheckUser 0 ; Check user clip planes first
mov edx, pa
PAClipCheckFrustum 1 ; Check frustum clip planes. We have to use OR when
; updating vertex clip code
@PAClipCheckAll@12 ENDP
;--------------------------------------------------------------------------------------------
pd equ -4[ebp]
pdLast equ -8[ebp]
@PolyArrayPropagateSameColor@8 PROC NEAR
push ebp
mov eax, DWORD PTR [edx+PA_pdNextVertex]
mov ebp, esp
sub eax, sizeof_POLYDATA
sub esp, 8
mov DWORD PTR pdLast, eax
push ebx
push esi
mov ebx, DWORD PTR [edx+PA_pd0]
push edi
; EAX = pdLast = pa->pdNextVertex-1;
; EBX = pd = pa->pd0;
mov DWORD PTR pd, ebx
; if (pd > pdLast)
cmp eax, ebx
jb @Done
mov eax, [edx+PA_flags]
lea edi, DWORD PTR [ebx+PD_colors0]
; if (pa->flags & POLYARRAY_CLAMP_COLOR) {
test eax, POLYARRAY_CLAMP_COLOR
je @ClampDone
mov eax, [edi+_R_]
mov ebx, [ecx+GC_redVertexScale]
sub ebx, eax
mov [ecx+GC_redClampTable], eax
shr eax, 31
add ebx, ebx
mov edx, [edi+_G_]
adc eax, eax
mov ebx, [ecx+GC_greenVertexScale]
sub ebx, edx
mov eax, [4*eax+ecx+GC_redClampTable]
mov [ecx+GC_greenClampTable], edx
shr edx, 31
add ebx, ebx
mov [edi+_R_], eax
adc edx, edx
mov eax, [edi+_B_]
mov ebx, [ecx+GC_blueVertexScale]
sub ebx, eax
mov edx, [4*edx+ecx+GC_greenClampTable]
mov [ecx+GC_blueClampTable], eax
shr eax, 31
add ebx, ebx
mov [edi+_G_], edx
adc eax, eax
mov edx, [edi+_A_]
mov ebx, [ecx+GC_alphaVertexScale]
sub ebx, edx
mov eax, [4*eax+ecx+GC_blueClampTable]
mov [ecx+GC_alphaClampTable], edx
shr edx, 31
add ebx, ebx
adc edx, edx
mov [edi+_B_], eax
mov edx, [4*edx+ecx+GC_alphaClampTable]
mov [edi+_A_], edx
@ClampDone:
;; Register usage.
;; EAX: r, EBX: g, ECX: b, EDX: a
;; ESI: &pdLast->colors[0]
;; EDI: &pd->colors[0]
mov edi, pd
mov esi, pdLast
lea edi, [edi+PD_colors0+sizeof_POLYDATA]
lea esi, [esi+PD_colors0]
mov eax, [edi+_R_-sizeof_POLYDATA]
cmp edi, esi
ja @Done
mov ebx, [edi+_G_-sizeof_POLYDATA]
mov ecx, [edi+_B_-sizeof_POLYDATA]
mov edx, [edi+_A_-sizeof_POLYDATA]
@DoLoop:
mov [edi+_R_], eax
mov [edi+_G_], ebx
mov [edi+_B_], ecx
mov [edi+_A_], edx
add edi, sizeof_POLYDATA
cmp edi, esi
jbe @DoLoop
@Done:
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 0
@PolyArrayPropagateSameColor@8 ENDP
;------------------------------------------------------------------------
; Copy cached non lit color from GC to a polydata
;
; Input:
; PDreg - register with POLYDATA address
; GCreg - register with GC address
; GC_LIGHT_value - front or back light (0 or 1)
; face - 0 for front face, 1 for back face
; tmpreg1,
; tmpreg2 - temporary registers
;
COPY_CACHED_NON_LIT MACRO PDreg, GCreg, GC_LIGHT_value, face, tmpreg1, tmpreg2
mov eax, [ebx+GC_LIGHT_value+MATERIAL_cachedNonLit+_R_]
mov ecx, [ebx+GC_LIGHT_value+MATERIAL_cachedNonLit+_G_]
mov [esi+PD_colors0+(face*16)+_R_], eax
mov [esi+PD_colors0+(face*16)+_G_], ecx
mov eax, [ebx+GC_LIGHT_value+MATERIAL_cachedNonLit+_B_]
mov ecx, [ebx+GC_LIGHT_value+MATERIAL_alpha]
mov [esi+PD_colors0+(face*16)+_B_], eax
mov [esi+PD_colors0+(face*16)+_A_], ecx
ENDM
;------------------------------------------------------------------------
; No lights case
;
POLYARRAYZIPPYCALCRGBCOLOR0 MACRO GC_LIGHT_value, face
push ebp
mov ebp, esp
sub esp, 56
push ebx
push esi
push edi
mov esi, pdFirst
mov edi, pdLast
mov ebx, ecx ; ebx = gc
;
; for (pd = pdFirst; pd <= pdLast; pd++)
;
@lightVertexLoop:
COPY_CACHED_NON_LIT <esi>, <ebx>, GC_LIGHT_value, face, <eax>, <ecx>
add esi, sizeof_POLYDATA
cmp edi, esi
jae @lightVertexLoop
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 12
ENDM
;------------------------------------------------------------------------
; Parameters:
;
; ecx - GC
; NUMBER_OF_LIGHTS - 1 for one light, 2 for more than one light
;
pdFirst equ 12[ebp]
pdLast equ 16[ebp]
pd equ pdFirst
face equ -4[ebp]
nonBack equ -4[ebp]
nxi equ DWORD PTR -8[ebp]
nyi equ DWORD PTR -12[ebp]
nzi equ DWORD PTR -16[ebp]
n1 equ DWORD PTR -20[ebp]
n2 equ DWORD PTR -24[ebp]
ifx equ -28[ebp]
msm equ -32[ebp]
baseEmissiveAmbientR equ DWORD PTR -36[ebp]
baseEmissiveAmbientG equ DWORD PTR -40[ebp]
baseEmissiveAmbientB equ DWORD PTR -44[ebp]
rsi equ DWORD PTR -48[ebp]
gsi equ DWORD PTR -52[ebp]
bsi equ DWORD PTR -56[ebp]
;;
;; We will handle infinite lights with special cases for front and
;; back faces.
;;
POLYARRAYZIPPYCALCRGBCOLOR MACRO GC_LIGHT_value, LIGHTSOURCE_value, face, NUMBER_OF_LIGHTS
;; GL_LIGHT_value = GL_LIGHT_front or GC_LIGHT_back
;; LIGHTSOURCE_value = LIGHTSOURCE_front or LIGHTSOURCE_back
;; face = __GL_FRONTFACE or __GL_BACKFACE
push ebp
mov ebp, esp
sub esp, 56
if NUMBER_OF_LIGHTS eq 2
xor eax, eax
endif
push ebx
push esi
push edi
;; NOTE: esi, ebx held constant in this routine.
;; esi = pd
;; ebx = gc
mov esi, pdFirst
mov ebx, ecx
;; Start the vertex-processing loop
;;
;; for (pd = pdFirst; pd <= pdLast; pd++)
@lightVertexLoop:
;; If normal has not changed for this vertex, use the previously computed color.
;; if (!(pd->flags & POLYDATA_NORMAL_VALID))
mov edx, [esi+PD_flags]
test edx, POLYDATA_NORMAL_VALID
jne @normalIsValid
mov eax, [(face*16) + esi + (PD_colors0 - sizeof_POLYDATA)+_R_]
mov ecx, [(face*16) + esi + (PD_colors0 - sizeof_POLYDATA)+_G_]
mov [(face*16) + esi + PD_colors0+_R_], eax
mov [(face*16) + esi + PD_colors0+_G_], ecx
mov eax, [(face*16) + esi + (PD_colors0 - sizeof_POLYDATA)+_B_]
mov ecx, [(face*16) + esi + (PD_colors0 - sizeof_POLYDATA)+_A_]
mov [(face*16) + esi + PD_colors0+_B_], eax
mov [(face*16) + esi + PD_colors0+_A_], ecx
;; loop to next pd
mov edi, pdLast
add esi, sizeof_POLYDATA
if NUMBER_OF_LIGHTS eq 2
xor eax, eax
endif
cmp edi, esi
jae @lightVertexLoop
jmp @lightsDone
@normalIsValid:
if NUMBER_OF_LIGHTS eq 2
mov nonBack, eax
endif
mov edi, [ebx+GC_LIGHT_sources]
if face eq __GL_FRONTFACE
else
mov eax, [esi+PD_normal+_X_]
mov ecx, [esi+PD_normal+_Y_]
mov edx, [esi+PD_normal+_Z_]
xor eax, 80000000h
xor ecx, 80000000h
xor edx, 80000000h
mov nxi, eax
mov nyi, ecx
mov nzi, edx
endif
if NUMBER_OF_LIGHTS eq 2
test edi, edi
je @lightSourcesDone
@lightSourcesLoop:
endif
;; for (lsm = gc->light.sources; lsm; lsm = lsm->next)
;; edi = lsm (light source pointer)
;; n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
;; nzi * lsm->unitVPpli.z;
if face eq __GL_FRONTFACE
fld DWORD PTR [esi+PD_normal+_X_]
fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_X_]
fld DWORD PTR [esi+PD_normal+_Y_]
fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_Y_]
fld DWORD PTR [esi+PD_normal+_Z_]
fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_Z_]
else
fld nxi
fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_X_]
fld nyi
fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_Y_]
fld nzi
fmul DWORD PTR [edi+LIGHTSOURCE_unitVPpli+_Z_]
endif
fxch ST(2)
faddp ST(1), ST
faddp ST(1), ST
fstp n1
;; if (__GL_FLOAT_GTZ(n1))
if NUMBER_OF_LIGHTS eq 2
mov ecx, nonBack
endif
cmp n1, 0
jg @f
if NUMBER_OF_LIGHTS eq 2
mov edi, [edi+LIGHTSOURCE_next]
test edi, edi
je @lightSourcesDone
jmp @lightSourcesLoop
else
COPY_CACHED_NON_LIT <esi>, <ebx>, GC_LIGHT_value, face, <eax>, <ecx>
;; loop to next pd
mov edi, pdLast
add esi, sizeof_POLYDATA
cmp edi, esi
jae @lightVertexLoop
jmp @lightsDone
endif
@@:
if NUMBER_OF_LIGHTS eq 2
test ecx, ecx ; Has lighting been computed
jne @f
endif
fld DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_cachedEmissiveAmbient+_B_]
if NUMBER_OF_LIGHTS eq 2
inc ecx
endif
fld DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_cachedEmissiveAmbient+_G_]
if NUMBER_OF_LIGHTS eq 2
mov nonBack, ecx
endif
fld DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_cachedEmissiveAmbient+_R_]
@@:
;; n2 = (nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z)
;; - msm_threshold;
if face eq __GL_FRONTFACE
fld DWORD PTR [esi+PD_normal+_X_]
fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_X_]
fld DWORD PTR [esi+PD_normal+_Y_]
fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_Y_]
fxch ST(1)
fsub DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_threshold]
fld DWORD PTR [esi+PD_normal+_Z_]
fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_Z_]
else
fld nxi
fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_X_]
fld nyi
fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_Y_]
fxch ST(1)
fsub DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_threshold]
fld nzi
fmul DWORD PTR [edi+LIGHTSOURCE_hHat+_Z_]
endif
fxch ST(2)
faddp ST(1), ST
faddp ST(1), ST
fstp n2
;; if (__GL_FLOAT_GEZ(n2))
mov eax, n2
or eax, eax
js @noSpecularEffect
;; ifx = (GLint)(n2 * msm_scale + __glHalf);
fld n2
fmul DWORD PTR [ebx+GC_LIGHT_value+MATERIAL_scale]
mov edx, __FLOAT_ONE
;; Note: we don't have to do this add since we can assume that rounding
;; enabled:
;; fadd ___glHalf
mov ecx, [ebx+GC_LIGHT_value+MATERIAL_specTable]
fistp DWORD PTR ifx
;; if (ifx < __GL_SPEC_LOOKUP_TABLE_SIZE )
mov eax, ifx
cmp eax, __GL_SPEC_LOOKUP_TABLE_SIZE
jge @specularSaturate
;; n2 = msm_specTable[ifx];
mov edx, DWORD PTR [ecx+eax*4]
@specularSaturate:
mov n2, edx
fld n2
fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_specular+_R_]
fld n2
fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_specular+_G_]
fld n2
fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_specular+_B_]
fxch ST(2) ; r g b R G B
faddp ST(3), ST ; g b R G B
faddp ST(3), ST ; b R G B
faddp ST(3), ST ; R G B
@noSpecularEffect:
;; now handle diffuse affect:
fld n1
fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_diffuse+_R_]
fld n1
fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_diffuse+_G_]
fld n1
fmul DWORD PTR [edi+LIGHTSOURCE_value+LIGHTSOURCEPERMATERIAL_diffuse+_B_]
fxch ST(2) ; r g b R G B
faddp ST(3), ST ; g b R G B
if NUMBER_OF_LIGHTS eq 2
mov edi, [edi+LIGHTSOURCE_next]
endif
faddp ST(3), ST ; b R G B
if NUMBER_OF_LIGHTS eq 2
test edi, edi
endif
faddp ST(3), ST ; R G B
if NUMBER_OF_LIGHTS eq 2
jne @lightSourcesLoop
@lightSourcesDone:
mov eax, nonBack
test eax,eax
jne @f
COPY_CACHED_NON_LIT <esi>, <ebx>, GC_LIGHT_value, face, <eax>, <ecx>
;; loop to next pd
mov edi, pdLast
add esi, sizeof_POLYDATA
xor eax, eax
cmp edi, esi
jae @lightVertexLoop
jmp @lightsDone
@@:
endif ; NUMBER_OF_LIGHTS eq 2
;; OK, we had some lighting for this vertex. Now, handle clamping:
fstp rsi
mov eax, [ebx+GC_redVertexScale]
fstp gsi
mov edx, rsi
fstp bsi
mov ecx, [ebx+GC_greenVertexScale]
mov edi, gsi
sub eax, edx
sub ecx, edi
or eax, edx
or ecx, edi
mov edx, [ebx+GC_blueVertexScale]
or eax, ecx
mov edi, bsi
or eax, edi
sub edx, edi
or eax, edx
jns @noClamp
mov eax, rsi
mov ecx, [ebx+GC_redVertexScale]
sub ecx, eax
mov [ebx+GC_redClampTable], eax
shr eax, 31
add ecx, ecx
mov edx, gsi
adc eax, eax
mov ecx, [ebx+GC_greenVertexScale]
sub ecx, edx
mov eax, [4*eax+ebx+GC_redClampTable]
mov [ebx+GC_greenClampTable], edx
shr edx, 31
add ecx, ecx
mov rsi, eax
adc edx, edx
mov eax, bsi
mov ecx, [ebx+GC_blueVertexScale]
sub ecx, eax
mov edx, [4*edx+ebx+GC_greenClampTable]
mov [ebx+GC_blueClampTable], eax
shr eax, 31
add ecx, ecx
mov gsi, edx
adc eax, eax
mov eax, [4*eax+ebx+GC_blueClampTable]
mov bsi, eax
@noClamp:
;; store colors
mov eax, [ebx+GC_LIGHT_value+MATERIAL_alpha]
mov ecx, rsi
mov edx, gsi
mov edi, bsi
mov [esi+PD_colors0+(face*16)+_A_], eax
mov [esi+PD_colors0+(face*16)+_R_], ecx
mov [esi+PD_colors0+(face*16)+_G_], edx
mov [esi+PD_colors0+(face*16)+_B_], edi
;; loop to next pd
mov edi, pdLast
add esi, sizeof_POLYDATA
xor eax, eax
cmp edi, esi
jae @lightVertexLoop
@lightsDone:
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 12
ENDM
;--------------------------------------------------------------------------------
@PolyArrayZippyCalcRGBColorFront@20 PROC NEAR
POLYARRAYZIPPYCALCRGBCOLOR GC_LIGHT_front, LIGHTSOURCE_front, __GL_FRONTFACE, 2
@PolyArrayZippyCalcRGBColorFront@20 ENDP
@PolyArrayZippyCalcRGBColorBack@20 PROC NEAR
POLYARRAYZIPPYCALCRGBCOLOR GC_LIGHT_back, LIGHTSOURCE_back, __GL_BACKFACE, 2
@PolyArrayZippyCalcRGBColorBack@20 ENDP
;
; Functions for the one light source
;
@PolyArrayZippyCalcRGBColorFront1@20 PROC NEAR
POLYARRAYZIPPYCALCRGBCOLOR GC_LIGHT_front, LIGHTSOURCE_front, __GL_FRONTFACE, 1
@PolyArrayZippyCalcRGBColorFront1@20 ENDP
@PolyArrayZippyCalcRGBColorBack1@20 PROC NEAR
POLYARRAYZIPPYCALCRGBCOLOR GC_LIGHT_back, LIGHTSOURCE_back, __GL_BACKFACE, 1
@PolyArrayZippyCalcRGBColorBack1@20 ENDP
;
; Functions for the no light sources
;
@PolyArrayZippyCalcRGBColorFront0@20 PROC NEAR
POLYARRAYZIPPYCALCRGBCOLOR0 GC_LIGHT_front, __GL_FRONTFACE
@PolyArrayZippyCalcRGBColorFront0@20 ENDP
@PolyArrayZippyCalcRGBColorBack0@20 PROC NEAR
POLYARRAYZIPPYCALCRGBCOLOR0 GC_LIGHT_back, __GL_BACKFACE
@PolyArrayZippyCalcRGBColorBack0@20 ENDP
;--------------------------------------------------------------------------------
; void FASTCALL PolyArrayZippyCalcRGBColor(__GLcontext* gc, int face, POLYARRAY* pa,
; POLYDATA* pdFirst, POLYDATA* pdLast)
;
; Input:
; ecx = gc
; edx = face (0 - front, 1 - back)
; [esp+4] = pa
; [esp+8] = pdFirst
; [esp+12] = pdLast
;
@PolyArrayZippyCalcRGBColor@20 PROC NEAR
push edi
mov edi, [ecx+GC_LIGHT_sources]
or edi, edi
jz @noLights
cmp [edi+LIGHTSOURCE_next], 0
jne @multipleLights
;
; one lignt case
;
pop edi
test edx, edx
je @PolyArrayZippyCalcRGBColorFront1@20
jmp @PolyArrayZippyCalcRGBColorBack1@20
@noLights:
pop edi
test edx, edx
je @PolyArrayZippyCalcRGBColorFront0@20
jmp @PolyArrayZippyCalcRGBColorBack0@20
@multipleLights:
pop edi
test edx, edx
je @PolyArrayZippyCalcRGBColorFront@20
jmp @PolyArrayZippyCalcRGBColorBack@20
@PolyArrayZippyCalcRGBColor@20 ENDP
;--------------------------------------------------------------------------------
; void FASTCALL PolyArrayZippyCalcRGBColor(__GLcontext* gc, int face, POLYARRAY* pa,
; POLYDATA* pdFirst, POLYDATA* pdLast)
;
; Input:
; ecx = gc
; edx = face (0 - front, 1 - back)
; [esp+4] = pa
; [esp+8] = pdFirst
; [esp+12] = pdLast
;
emissiveAmbientR equ DWORD PTR -60[ebp]
emissiveAmbientG equ DWORD PTR -64[ebp]
emissiveAmbientB equ DWORD PTR -68[ebp]
colorMaterialChange equ -72[ebp]
alpha equ DWORD PTR -76[ebp]
ri equ DWORD PTR -80[ebp]
gi equ DWORD PTR -84[ebp]
bi equ DWORD PTR -88[ebp]
diffuseSpecularR equ DWORD PTR -92[ebp]
diffuseSpecularG equ DWORD PTR -96[ebp]
diffuseSpecularB equ DWORD PTR -100[ebp]
@PolyArrayFastCalcRGBColor@20 PROC NEAR
mov eax, [ecx+GC_LIGHT_front+MATERIAL_colorMaterialChange]
test edx, edx
je @f
mov eax, [ecx+GC_LIGHT_back+MATERIAL_colorMaterialChange]
@@:
test eax, eax
je @PolyArrayZippyCalcRGBColor@20
push ebp
mov ebp, esp
sub esp, 100
test edx, edx
push ebx
mov ebx, ecx
push esi
;; if (face == __GL_FRONTFACE)
;; msm = &gc->light.front;
;; else
;; msm = &gc->light.back;
lea ecx, DWORD PTR [ebx+GC_LIGHT_front]
je short @f
lea ecx, DWORD PTR [ebx+GC_LIGHT_back]
@@:
push edi
mov DWORD PTR face, edx
mov msm, ecx
mov eax, [ecx+MATERIAL_colorMaterialChange]
mov colorMaterialChange, eax
test eax, __GL_MATERIAL_AMBIENT
jne @baseEmissiveSimple
mov eax, [ecx+MATERIAL_cachedEmissiveAmbient+_R_]
mov edx, [ecx+MATERIAL_cachedEmissiveAmbient+_G_]
mov baseEmissiveAmbientR, eax
mov emissiveAmbientR, eax
mov baseEmissiveAmbientG, edx
mov emissiveAmbientG, edx
mov eax, [ecx+MATERIAL_cachedEmissiveAmbient+_B_]
mov esi, pdFirst
mov edi, pdLast
mov baseEmissiveAmbientB, eax
cmp edi, esi
mov emissiveAmbientB, eax
jb @lightsDone
jmp @baseEmissiveDone
@baseEmissiveSimple:
mov eax, [ecx+MATERIAL_paSceneColor+_R_]
mov edx, [ecx+MATERIAL_paSceneColor+_G_]
mov baseEmissiveAmbientR, eax
mov emissiveAmbientR, eax
mov baseEmissiveAmbientG, edx
mov emissiveAmbientG, edx
mov eax, [ecx+MATERIAL_paSceneColor+_B_]
mov esi, pdFirst
mov edi, pdLast
mov baseEmissiveAmbientB, eax
cmp edi, esi
mov emissiveAmbientB, eax
jb @lightsDone
@baseEmissiveDone:
; If there is no emissive or ambient color material change, this
; will be the emissive and ambient components.
;
; emissiveAmbientI.r = baseEmissiveAmbient.r;
; emissiveAmbientI.g = baseEmissiveAmbient.g;
; emissiveAmbientI.b = baseEmissiveAmbient.b;
;;
;;
;; Vertex loop follows:
;;
;;
;; for (pd = pdFirst; pd <= pdLast; pd++)
@lightVertexLoop:
;; If normal has not changed for this vertex, use the previously
;; computed color.
;; [if !(pd->flags & (POLYDATA_NORMAL_VALID | POLYDATA_COLOR_VALID))]
mov edx, [esi+PD_flags]
test edx, POLYDATA_NORMAL_VALID OR POLYDATA_COLOR_VALID
jne @normalOrColorIsValid
mov eax, face
shl eax, 4
lea edi, [eax + esi + PD_colors0]
lea esi, [eax + esi + (PD_colors0 - sizeof_POLYDATA)]
movsd
movsd
movsd
movsd
mov esi, pd
mov edi, pdLast
add esi, sizeof_POLYDATA
cmp edi, esi
mov pd, esi
jae @lightVertexLoop
jmp @lightsDone
@normalOrColorIsValid:
;; if (pd->flags & POLYDATA_COLOR_VALID)
;; ri = pd->colors[0].r * gc->oneOverRedVertexScale;
;; gi = pd->colors[0].g * gc->oneOverGreenVertexScale;
;; bi = pd->colors[0].b * gc->oneOverBlueVertexScale;
;; alpha = pd->colors[0].a;
test edx, POLYDATA_COLOR_VALID
je @usePreviousColors
mov eax, [esi+PD_colors0+_A_]
mov alpha, eax
mov eax, colorMaterialChange
fld DWORD PTR [esi+PD_colors0+_R_]
fmul DWORD PTR [ebx+GC_oneOverRedVertexScale]
fld DWORD PTr [esi+PD_colors0+_G_]
fmul DWORD PTR [ebx+GC_oneOverGreenVertexScale]
fld DWORD PTR [esi+PD_colors0+_B_]
fmul DWORD PTR [ebx+GC_oneOverBlueVertexScale] ;; b g r
fxch ST(2) ;; r g b
fstp ri
fstp gi
fstp bi ;; FPU stack empty
test eax, __GL_MATERIAL_AMBIENT
je @noMaterialAmbient
;;
;; Handle ambient color changes:
;;
;; if (msm_colorMaterialChange & __GL_MATERIAL_AMBIENT) {
;; emissiveAmbient.r = baseEmissiveAmbient.r + ri * lm_ambient.r;
;; emissiveAmbient.g = baseEmissiveAmbient.g + gi * lm_ambient.g;
;; emissiveAmbient.b = baseEmissiveAmbient.b + bi * lm_ambient.b;
;; }
fld ri
fmul DWORD PTR [ebx+GC_STATE_lightModelAmbient+_R_]
fld gi
mov edi, [ebx+GC_LIGHT_sources]
fmul DWORD PTR [ebx+GC_STATE_lightModelAmbient+_G_]
fld bi
test edi, edi
fmul DWORD PTR [ebx+GC_STATE_lightModelAmbient+_B_] ; b g r
fxch ST(1) ; g b r
fadd baseEmissiveAmbientG ; G b r
fxch ST(1) ; b G r
fadd baseEmissiveAmbientB ; B G r
fxch ST(2) ; r G B
fadd baseEmissiveAmbientR ; R G B
jne @ambientLoop
fstp emissiveAmbientR ;; If we don't have to process
fstp emissiveAmbientG ;; the lights, pop the FPU stack
fstp emissiveAmbientB ;; and continue
jmp @emissiveAmbientDone
@ambientLoop:
;; Add per-light per-material ambient values.
;; We will start with the current basEmissiveAmbient values
;; already on the stack.
;; for (lsm = gc->light.sources; lsm; lsm = lsm->next) {
;; emissiveAmbientI.r += ri * lsm->state.ambient.r;
;; emissiveAmbientI.g += gi * lsm->stats.ambient.g;
;; emissiveAmbientI.b += bi * lsm->state.ambient.b;
;; }
mov edx, [edi+LIGHTSOURCE_state] ; lss
fld ri
fmul DWORD PTR [edx+LIGHTSOURCESTATE_ambient+_R_]
fld gi
fmul DWORD PTR [edx+LIGHTSOURCESTATE_ambient+_G_]
fld bi
fmul DWORD PTR [edx+LIGHTSOURCESTATE_ambient+_B_] ;; b g r R G B
fxch ST(2) ;; r g b R G B
faddp ST(3), ST(0)
mov edi, [edi+LIGHTSOURCE_next]
faddp ST(3), ST(0)
test edi, edi
faddp ST(3), ST(0)
jne @ambientLoop
;; There are no lights, so pop the emissive result at this point
;; and continue:
fstp emissiveAmbientR
fstp emissiveAmbientG
fstp emissiveAmbientB
jmp @emissiveAmbientDone
@noMaterialAmbient:
;;
;; Handle emissive material changes if needed:
;;
test eax, __GL_MATERIAL_EMISSIVE
je @emissiveAmbientDone
;; emissiveAmbientR = baseEmissiveAmbientR + pd->colors[0].r;
;; emissiveAmbientG = baseEmissiveAmbientG + pd->colors[0].g;
;; emissiveAmbientB = baseEmissiveAmbientB + pd->colors[0].b;
fld baseEmissiveAmbientR
fadd DWORD PTR [esi+PD_colors0+_R_]
fld baseEmissiveAmbientG
fadd DWORD PTR [esi+PD_colors0+_G_]
fld baseEmissiveAmbientB
fadd DWORD PTR [esi+PD_colors0+_B_] ; b g r
fxch ST(2) ; r g b
fstp emissiveAmbientR
fstp emissiveAmbientG
fstp emissiveAmbientB
@emissiveAmbientDone:
@usePreviousColors:
;;
;; OK, we're done handling emissive and diffuse color changes, or
;; we're simply using the previous values. Now, handle portion of
;; lighting which depends on the vertex normals (diffuse + specular):
;;
;; if (pd->flags & POLYDATA_NORMAL_VALID)
mov edx, [esi+PD_flags]
test edx, POLYDATA_NORMAL_VALID
je @normalNotValid
mov eax, face
;; if (face == __GL_FRONTFACE)
mov ecx, [esi+PD_normal+_X_]
mov edx, [esi+PD_normal+_Y_]
mov esi, [esi+PD_normal+_Z_]
test eax, eax
je @notBackFace
;; negate the floating-point normal values
xor ecx, 80000000h
xor edx, 80000000h
xor esi, 80000000h
@notBackFace:
mov nxi, ecx
mov nyi, edx
mov nzi, esi
jmp @calcColor
@normalNotValid:
;; if (!(msm_colorMaterialChange & (__GL_MATERIAL_SPECULAR | __GL_MATERIAL_DIFFUSE)))
;; goto store_color;
test eax, __GL_MATERIAL_SPECULAR OR __GL_MATERIAL_DIFFUSE
je @storeColor
@calcColor:
fld ___glZero
mov esi, [ebx+GC_LIGHT_sources]
fld ___glZero
test esi, esi
fld ___glZero
je @lightSourcesDone
@lightSourcesLoop:
;; for (lsm = gc->light.sources; lsm; lsm = lsm->next)
mov eax, face
;; lspmm = &lsm->front + face;
lea ecx, [esi+LIGHTSOURCE_front]
test eax, eax
je @f
lea ecx, [esi+LIGHTSOURCE_back]
@@:
;; esi = lsm
;; ecx = lspmm
;; n1 = nxi * lsm->unitVPpli.x + nyi * lsm->unitVPpli.y +
;; nzi * lsm->unitVPpli.z;
fld nxi
mov edi, msm
fmul DWORD PTR [esi+LIGHTSOURCE_unitVPpli+_X_]
fld nyi
fmul DWORD PTR [esi+LIGHTSOURCE_unitVPpli+_Y_]
fld nzi
fmul DWORD PTR [esi+LIGHTSOURCE_unitVPpli+_Z_]
fxch ST(2)
faddp ST(1), ST
faddp ST(1), ST
fstp n1
;; if (__GL_FLOAT_GTZ(n1))
mov eax, n1
cmp eax, 0
jg @f
mov esi, [esi+LIGHTSOURCE_next]
test esi, esi
jne @lightSourcesLoop
jmp @lightSourcesDone
@@:
;; n2 = (nxi * lsm->hHat.x + nyi * lsm->hHat.y + nzi * lsm->hHat.z)
;; - msm_threshold;
fld nxi
fmul DWORD PTR [esi+LIGHTSOURCE_hHat+_X_]
fld nyi
fmul DWORD PTR [esi+LIGHTSOURCE_hHat+_Y_]
fxch ST(1)
fsub DWORD PTR [edi+MATERIAL_threshold]
fld nzi
fmul DWORD PTR [esi+LIGHTSOURCE_hHat+_Z_]
fxch ST(2)
faddp ST(1), ST
faddp ST(1), ST
fstp n2
;; if (__GL_FLOAT_GEZ(n2))
mov eax, n2
or eax, eax
js @noSpecularEffect
;; ifx = (GLint)(n2 * msm_scale + __glHalf);
fld n2
fmul DWORD PTR [edi+MATERIAL_scale]
mov edx, __FLOAT_ONE
;; Note: we don't have to do this add since we can assume that rounding
;; enabled:
;; fadd ___glHalf
mov edi, [edi+MATERIAL_specTable]
fistp DWORD PTR ifx
;; if (ifx < __GL_SPEC_LOOKUP_TABLE_SIZE )
mov eax, ifx
cmp eax, __GL_SPEC_LOOKUP_TABLE_SIZE
jge @specularSaturate
;; n2 = msm_specTable[ifx];
mov edx, DWORD PTR [edi+eax*4]
@specularSaturate:
mov eax, colorMaterialChange
mov n2, edx
test eax, __GL_MATERIAL_SPECULAR
je @noSpecularMaterialChange
fld n2
mov edx, [esi+LIGHTSOURCE_state]
fmul ri
fld n2
fmul gi
fld n2
fmul bi ; b g r
fxch ST(2) ; r g b
fmul DWORD PTR [edx+LIGHTSOURCESTATE_specular+_R_]
fxch ST(1) ; g r b
fmul DWORD PTR [edx+LIGHTSOURCESTATE_specular+_G_]
fxch ST(2) ; b r g
fmul DWORD PTR [edx+LIGHTSOURCESTATE_specular+_B_]
fxch ST(1) ; r b g R G B
faddp ST(3), ST(0) ; b g R G B
fxch ST(1) ; g b R G B
faddp ST(3), ST(0) ; b R G B
faddp ST(3), ST(0) ; R G B
jmp short @noSpecularEffect
@noSpecularMaterialChange:
fld n2
fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_specular+_R_]
fld n2
fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_specular+_G_]
fld n2
fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_specular+_B_]
fxch ST(2) ; r g b R G B
faddp ST(3), ST ; g b R G B
faddp ST(3), ST ; b R G B
faddp ST(3), ST ; R G B
@noSpecularEffect:
;; now handle diffuse affect:
mov eax, colorMaterialChange
test eax, __GL_MATERIAL_DIFFUSE
je @noDiffuseMaterialChange
fld n1
mov edx, [esi+LIGHTSOURCE_state]
fmul ri
fld n1
fmul gi
fld n1
fmul bi ; b g r
fxch ST(2) ; r g b
fmul DWORD PTR [edx+LIGHTSOURCESTATE_diffuse+_R_]
fxch ST(1) ; g r b
fmul DWORD PTR [edx+LIGHTSOURCESTATE_diffuse+_G_]
fxch ST(2) ; b r g
fmul DWORD PTR [edx+LIGHTSOURCESTATE_diffuse+_B_]
fxch ST(1) ; r b g R G B
faddp ST(3), ST(0) ; b g R G B
fxch ST(1) ; g b R G B
faddp ST(3), ST(0) ; b R G B
faddp ST(3), ST(0) ; R G B
jmp short @lightSourcesDone
@noDiffuseMaterialChange:
fld n1
fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_diffuse+_R_]
fld n1
fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_diffuse+_G_]
fld n1
fmul DWORD PTR [ecx+LIGHTSOURCEPERMATERIAL_diffuse+_B_]
fxch ST(2) ; r g b R G B
faddp ST(3), ST ; g b R G B
mov esi, [esi+LIGHTSOURCE_next]
faddp ST(3), ST ; b R G B
test esi, esi
faddp ST(3), ST ; R G B
jne @lightSourcesLoop
@lightSourcesDone:
fst diffuseSpecularR
fadd emissiveAmbientR ; R g b
fxch ST(1) ; g R b
fst diffuseSpecularG
fadd emissiveAmbientG ; G R b
fxch ST(2) ; b R G
fst diffuseSpecularB
fadd emissiveAmbientB ; B R G
fxch ST(1) ; R B G
fstp rsi
mov eax, [ebx+GC_redVertexScale]
fstp bsi
mov ecx, [ebx+GC_greenVertexScale]
fstp gsi
mov edx, rsi
jmp short @handleClamp
@storeColor:
;; Now add emissiveAmbient (on FP stack) and diffuseSpecular.
;; Interleave with start of clamping:
fld emissiveAmbientR
mov eax, [ebx+GC_redVertexScale]
fadd diffuseSpecularR
mov ecx, [ebx+GC_greenVertexScale]
fld emissiveAmbientG
fadd diffuseSpecularG
fld emissiveAmbientB
fadd diffuseSpecularB
fxch ST(2) ; r g b
fstp rsi
fstp gsi
mov edx, rsi
fstp bsi
@handleClamp:
;; handle clamping:
mov edi, gsi
sub eax, edx
sub ecx, edi
or eax, edx
or ecx, edi
mov edx, [ebx+GC_blueVertexScale]
or eax, ecx
mov edi, bsi
or eax, edi
sub edx, edi
or eax, edx
jns @noClamp
mov eax, rsi
mov ecx, [ebx+GC_redVertexScale]
sub ecx, eax
mov [ebx+GC_redClampTable], eax
shr eax, 31
add ecx, ecx
mov edx, gsi
adc eax, eax
mov ecx, [ebx+GC_greenVertexScale]
sub ecx, edx
mov eax, [4*eax+ebx+GC_redClampTable]
mov [ebx+GC_greenClampTable], edx
shr edx, 31
add ecx, ecx
mov rsi, eax
adc edx, edx
mov eax, bsi
mov ecx, [ebx+GC_blueVertexScale]
sub ecx, eax
mov edx, [4*edx+ebx+GC_greenClampTable]
mov [ebx+GC_blueClampTable], eax
shr eax, 31
add ecx, ecx
mov gsi, edx
adc eax, eax
mov eax, [4*eax+ebx+GC_blueClampTable]
mov bsi, eax
@noClamp:
;; ecx = pd->colors[face]
mov edx, msm
mov eax, face
mov esi, pd
shl eax, 4
lea ecx, [esi+PD_colors0]
mov edi, colorMaterialChange
add ecx, eax
test edi, __GL_MATERIAL_DIFFUSE
je @noAlphaChange
mov edx, alpha
mov eax, [ebx+GC_alphaVertexScale]
test edx, edx
jns @f
xor edx, edx
@@:
sub eax, edx
jge @alphaDone
mov edx, [ebx+GC_alphaVertexScale]
jmp short @alphaDone
@noAlphaChange:
mov edx, [edx+MATERIAL_alpha]
@alphaDone:
mov edi, pdLast
add esi, sizeof_POLYDATA
;; store colors
mov [ecx+_A_], edx
mov eax, rsi
mov edx, gsi
mov [ecx+_R_], eax
mov pd, esi
mov eax, bsi
mov [ecx+_G_], edx
mov [ecx+_B_], eax
;; loop to next pd
cmp edi, esi
jae @lightVertexLoop
@lightsDone:
pop edi
pop esi
pop ebx
mov esp, ebp
pop ebp
ret 12
@PolyArrayFastCalcRGBColor@20 ENDP
END