Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1117 lines
40 KiB

#include "pch.cpp"
#pragma hdrstop
#include "light.h"
#include "clipper.h"
#include "drawprim.hpp"
#define NEXT(pointer, stride, type) pointer = (type*)((char*)pointer + stride);
// We use power of 2 because it preserves the mantissa when we multiply
const D3DVALUE __HUGE_PWR2 = 1024.0f*1024.0f*2.0f;
const D3DVALUE __ONE_OVER_255 = 1.0f/255.0f;
//--------------------------------------------------------------------------
D3DVALUE ComputeDistance(LPD3DFE_PROCESSVERTICES pv, D3DVECTOR &v)
{
if (pv->dwFlags & D3DPV_RANGEBASEDFOG)
{
D3DVALUE x,y,z;
x = v.x*pv->mWV._11 + v.y*pv->mWV._21 + v.z*pv->mWV._31 + pv->mWV._41;
y = v.x*pv->mWV._12 + v.y*pv->mWV._22 + v.z*pv->mWV._32 + pv->mWV._42;
z = v.x*pv->mWV._13 + v.y*pv->mWV._23 + v.z*pv->mWV._33 + pv->mWV._43;
return SQRTF(x*x + y*y + z*z);
}
else
return v.x*pv->mWV._13 + v.y*pv->mWV._23 + v.z*pv->mWV._33 + pv->mWV._43;
}
//--------------------------------------------------------------------------
// Process vertices with flexible vertex format, if vertex is
// contiguous
//
// The following fields from pv are used:
// dwFlags
// dwNumVertices
// position.lpvData
// position.lpvStrides
// dwVIDIn
// dwVIDOut
// lpvOut
// lpClipFlags
// nTexCoord
// Returns:
// returns dwClipIntersection or 0 (if D3DDP_DONOTCLIP is set)
// Side effects:
// dwClipUnion, dwClipIntersection are set only if D3DDP_DONOTCLIP is not set
// rExtents is updated if D3DDP_DONOTUPDATEEXTENTS is not set
//
#undef DPF_MODNAME
#define DPF_MODNAME "ProcessVerticesFVF"
DWORD ProcessVerticesFVF (LPD3DFE_PROCESSVERTICES pv)
{
D3DVERTEX *in = (D3DVERTEX*)pv->position.lpvData;
DWORD in_size = pv->position.dwStride;
D3DTLVERTEX *out = (D3DTLVERTEX*)pv->lpvOut;
DWORD out_size = pv->dwOutputSize;
D3DFE_CLIPCODE *hout = pv->lpClipFlags;
DWORD flags = pv->dwFlags;
DWORD inVID = pv->dwVIDIn;
DWORD outVID = pv->dwVIDOut;
int nTex = pv->nTexCoord << 1;
int i;
int clip_intersection = ~0;
int clip_union = 0;
D3DVALUE minx, maxx, miny, maxy;
DWORD texOffset;
DWORD diffuseOffset;
DWORD specularOffset;
int count = pv->dwNumVertices;
BOOL bNoFVFandNoTexture = FALSE;
// Compute input offsets
i = sizeof(D3DVECTOR);
if (inVID & D3DFVF_NORMAL)
i += sizeof(D3DVECTOR);
if (inVID & D3DFVF_RESERVED1)
i += sizeof(D3DVALUE);
diffuseOffset = i;
if (inVID & D3DFVF_DIFFUSE)
i += sizeof(DWORD);
specularOffset = i;
if (inVID & D3DFVF_SPECULAR)
i += sizeof(DWORD);
texOffset = i;
if (!(pv->dwDeviceFlags & D3DDEV_FVF || pv->dwFlags & D3DPV_VBCALL))
{
if (nTex)
{
texOffset += pv->dwTextureIndexToCopy << 3;
}
else
{
// For non-FVF drivers we have to fill texture coordinates with
// zeros.
bNoFVFandNoTexture = TRUE;
}
}
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
minx = pv->rExtents.x1;
miny = pv->rExtents.y1;
maxx = pv->rExtents.x2;
maxy = pv->rExtents.y2;
}
pv->lighting.outDiffuse = __DEFAULT_DIFFUSE;
pv->lighting.outSpecular = __DEFAULT_SPECULAR;
for (i = count; i; i--)
{
DWORD clip;
float x, y, z, w, we;
x = in->x*pv->mCTM._11 + in->y*pv->mCTM._21 +
in->z*pv->mCTM._31 + pv->mCTM._41;
y = in->x*pv->mCTM._12 + in->y*pv->mCTM._22 +
in->z*pv->mCTM._32 + pv->mCTM._42;
z = in->x*pv->mCTM._13 + in->y*pv->mCTM._23 +
in->z*pv->mCTM._33 + pv->mCTM._43;
we= in->x*pv->mCTM._14 + in->y*pv->mCTM._24 +
in->z*pv->mCTM._34 + pv->mCTM._44;
clip = 0;
if (!(flags & D3DDP_DONOTCLIP))
{
D3DVALUE xx = we - x;
D3DVALUE yy = we - y;
D3DVALUE zz = we - z;
clip = ((ASINT32(x) & 0x80000000) >> (32-D3DCLIP_LEFTBIT)) |
((ASINT32(y) & 0x80000000) >> (32-D3DCLIP_BOTTOMBIT)) |
((ASINT32(z) & 0x80000000) >> (32-D3DCLIP_FRONTBIT)) |
((ASINT32(xx) & 0x80000000) >> (32-D3DCLIP_RIGHTBIT)) |
((ASINT32(yy) & 0x80000000) >> (32-D3DCLIP_TOPBIT)) |
((ASINT32(zz) & 0x80000000) >> (32-D3DCLIP_BACKBIT));
}
if (clip == 0)
{
int k;
DWORD *pOut = (DWORD*)((char*)out + 4*sizeof(D3DVALUE));
// We have to check this only for DONOTCLIP case, because otherwise
// "clip" is not zero, if we is zero.
if (!FLOAT_EQZ(we))
w = D3DVAL(1)/we;
else
w = __HUGE_PWR2;
clip_intersection = 0;
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
x = x * w * pv->vcache.scaleX + pv->vcache.offsetX;
y = y * w * pv->vcache.scaleY + pv->vcache.offsetY;
if (x < minx) minx = x;
if (x > maxx) maxx = x;
if (y < miny) miny = y;
if (y > maxy) maxy = y;
}
else
{
x = x * w * pv->vcache.scaleX + pv->vcache.offsetX;
y = y * w * pv->vcache.scaleY + pv->vcache.offsetY;
}
out->sx = x;
out->sy = y;
out->sz = z*w;
out->rhw = w;
if (flags & D3DPV_LIGHTING)
{
if (pv->dwFlags & D3DPV_COLORVERTEX)
{
DWORD color = *(D3DCOLOR*)((char*)in+diffuseOffset);
pv->lighting.alpha = color & 0xFF000000;
MakeColor(&pv->lighting.vertexDiffuse, color);
}
if (pv->dwFlags & D3DPV_COLORVERTEXS)
{
MakeColor(&pv->lighting.vertexSpecular,
*(D3DCOLOR*)((char*)in+specularOffset));
}
LIGHT_VERTEX(pv, in);
}
else
if (inVID & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR))
{
if (inVID & D3DFVF_DIFFUSE)
pv->lighting.outDiffuse = *(D3DCOLOR*)((char*)in+diffuseOffset);
if (inVID & D3DFVF_SPECULAR)
pv->lighting.outSpecular = *(D3DCOLOR*)((char*)in+specularOffset);
}
if (flags & D3DPV_FOG)
{
D3DVALUE d = ComputeDistance(pv, *(D3DVECTOR*)in);
FOG_VERTEX(&pv->lighting, d);
}
if (outVID & D3DFVF_DIFFUSE)
*pOut++ = pv->lighting.outDiffuse;
if (outVID & D3DFVF_SPECULAR)
*pOut++ = pv->lighting.outSpecular;
if (bNoFVFandNoTexture)
{
*(D3DVALUE*)pOut++ = 0;
*(D3DVALUE*)pOut = 0;
}
else
{
DWORD *pIn = (DWORD*)((char*)in+texOffset);
for (k=0; k < nTex; k++)
*pOut++ = *pIn++;
}
}
else
{
if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
{
D3DVALUE xnew = x * pv->vcache.gb11 + we * pv->vcache.gb41;
D3DVALUE ynew = y * pv->vcache.gb22 + we * pv->vcache.gb42;
D3DVALUE xx = we - xnew;
D3DVALUE yy = we - ynew;
clip |= ((ASINT32(xnew) & 0x80000000) >> (32-D3DCLIPGB_LEFTBIT)) |
((ASINT32(ynew) & 0x80000000) >> (32-D3DCLIPGB_BOTTOMBIT)) |
((ASINT32(xx) & 0x80000000) >> (32-D3DCLIPGB_RIGHTBIT)) |
((ASINT32(yy) & 0x80000000) >> (32-D3DCLIPGB_TOPBIT));
}
clip_intersection &= clip;
clip_union |= clip;
out->sx = x;
out->sy = y;
out->sz = z;
out->rhw = we;
}
if (!(flags & D3DDP_DONOTCLIP))
*hout++ = (D3DFE_CLIPCODE)clip;
in = (D3DVERTEX*) ((char*) in + in_size);
out = (D3DTLVERTEX*) ((char*) out + out_size);
}
if (!(flags & D3DDP_DONOTCLIP) && !clip_intersection && clip_union)
{ // We have to light all clipped vertices
int n;
D3DVERTEX *in = (D3DVERTEX*)pv->position.lpvData;
D3DTLVERTEX *out = (D3DTLVERTEX*)pv->lpvOut;
D3DFE_CLIPCODE *hout = pv->lpClipFlags;
for (n = count; n ; n--)
{
if (*hout)
{
// pOut pointes to the first D3DVALUE after W
DWORD *pOut = (DWORD*)((char*)out + 4*sizeof(D3DVALUE));
int k;
if (pv->dwDeviceFlags & D3DDEV_GUARDBAND &&
(*hout & ~__D3DCLIP_INGUARDBAND) == 0)
{ // This vertex is inside the guard band. We have to compute
// screen coordinates for it
D3DVALUE w = D3DVAL(1)/out->rhw;
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
D3DVALUE x = out->sx * w * pv->vcache.scaleX + pv->vcache.offsetX;
D3DVALUE y = out->sy * w * pv->vcache.scaleY + pv->vcache.offsetY;
if (x < minx) minx = x;
if (x > maxx) maxx = x;
if (y < miny) miny = y;
if (y > maxy) maxy = y;
out->sx = x;
out->sy = y;
}
else
{
out->sx = out->sx * w * pv->vcache.scaleX + pv->vcache.offsetX;
out->sy = out->sy * w * pv->vcache.scaleY + pv->vcache.offsetY;
}
out->sz *= w;
out->rhw = w;
}
if (flags & D3DPV_LIGHTING)
{
if (pv->dwFlags & D3DPV_COLORVERTEX)
{
DWORD color = *(D3DCOLOR*)((char*)in+diffuseOffset);
pv->lighting.alpha = color & 0xFF000000;
MakeColor(&pv->lighting.vertexDiffuse, color);
}
if (pv->dwFlags & D3DPV_COLORVERTEXS)
{
MakeColor(&pv->lighting.vertexSpecular,
*(D3DCOLOR*)((char*)in+specularOffset));
}
LIGHT_VERTEX(pv, in);
}
else
if (inVID & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR))
{
if (inVID & D3DFVF_DIFFUSE)
pv->lighting.outDiffuse = *(D3DCOLOR*)((char*)in+diffuseOffset);
if (inVID & D3DFVF_SPECULAR)
pv->lighting.outSpecular = *(D3DCOLOR*)((char*)in+specularOffset);
}
if (flags & D3DPV_FOG)
{
D3DVALUE d = ComputeDistance(pv, *(D3DVECTOR*)in);
FOG_VERTEX(&pv->lighting, d);
}
if (outVID & D3DFVF_DIFFUSE)
*pOut++ = pv->lighting.outDiffuse;
if (outVID & D3DFVF_SPECULAR)
*pOut++ = pv->lighting.outSpecular;
if (bNoFVFandNoTexture)
{
*(D3DVALUE*)pOut++ = 0;
*(D3DVALUE*)pOut = 0;
}
else
{
DWORD *pIn = (DWORD*)((char*)in+texOffset);
for (k=0; k < nTex; k++)
*pOut++ = *pIn++;
}
}
in = (D3DVERTEX*) ((char*) in + in_size);
out = (D3DTLVERTEX*) ((char*) out + out_size);
hout++;
}
}
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
/*
* extend to cover lines.
*/
maxx += pv->dvExtentsAdjust;
maxy += pv->dvExtentsAdjust;
minx -= pv->dvExtentsAdjust;
miny -= pv->dvExtentsAdjust;
/* Clamp to viewport */
if (minx < pv->vcache.minX)
minx = pv->vcache.minX;
if (miny < pv->vcache.minY)
miny = pv->vcache.minY;
if (maxx > pv->vcache.maxX)
maxx = pv->vcache.maxX;
if (maxy > pv->vcache.maxY)
maxy = pv->vcache.maxY;
pv->rExtents.x1 = minx;
pv->rExtents.y1 = miny;
pv->rExtents.x2 = maxx;
pv->rExtents.y2 = maxy;
}
if (!(flags & D3DDP_DONOTCLIP))
{
pv->dwClipIntersection = clip_intersection;
pv->dwClipUnion = clip_union;
}
else
{
pv->dwClipIntersection = 0;
pv->dwClipUnion = 0;
}
return 0;
}
//--------------------------------------------------------------------------
// Process vertices with flexible vertex format and strides
//
// The following fields from pv are used:
// dwFlags
// dwNumVertices
// all pointer and strides
// position.lpvStrides
// dwVIDIn
// dwVIDOut
// lpvOut
// lpClipFlags
// nTexCoord
// Returns:
// returns dwClipIntersection or 0 (if D3DDP_DONOTCLIP is set)
// Side effects:
// dwClipUnion, dwClipIntersection are set only if D3DDP_DONOTCLIP is not set
// rExtents is updated if D3DDP_DONOTUPDATEEXTENTS is not set
//
#undef DPF_MODNAME
#define DPF_MODNAME "ProcessVerticesFVFS"
DWORD ProcessVerticesFVFS (LPD3DFE_PROCESSVERTICES pv)
{
D3DVECTOR *in;
D3DVECTOR *inNormal;
DWORD *inDiffuse;
DWORD *inSpecular;
D3DVALUE *inTexture[8];
D3DTLVERTEX *out = (D3DTLVERTEX*)pv->lpvOut;
DWORD out_size = pv->dwOutputSize;
D3DFE_CLIPCODE *hout = pv->lpClipFlags;
DWORD flags = pv->dwFlags;
DWORD inVID = pv->dwVIDIn;
DWORD outVID = pv->dwVIDOut;
int nTex = pv->nTexCoord;
int i;
int clip_intersection = ~0;
int clip_union = 0;
D3DVALUE minx, maxx, miny, maxy;
int count = pv->dwNumVertices;
BOOL bNoFVFandNoTexture = FALSE;
D3DLIGHTINGELEMENT le;
in = (D3DVECTOR*)pv->position.lpvData;
inNormal = (D3DVECTOR*)pv->normal.lpvData;
inDiffuse = (DWORD*)pv->diffuse.lpvData;
inSpecular = (DWORD*)pv->specular.lpvData;
if (pv->dwDeviceFlags & D3DDEV_FVF || pv->dwFlags & D3DPV_VBCALL)
{
for (i=0; i < nTex; i++)
inTexture[i] = (D3DVALUE*)pv->textures[i].lpvData;
}
else
{
if (nTex)
inTexture[0] = (D3DVALUE*)pv->textures[pv->dwTextureIndexToCopy].lpvData;
else
{
// For non-FVF drivers we have to fill texture coordinates with
// zeros.
bNoFVFandNoTexture = TRUE;
}
}
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
minx = pv->rExtents.x1;
miny = pv->rExtents.y1;
maxx = pv->rExtents.x2;
maxy = pv->rExtents.y2;
}
pv->lighting.outDiffuse = __DEFAULT_DIFFUSE;
pv->lighting.outSpecular = __DEFAULT_SPECULAR;
for (i = count; i; i--)
{
int clip;
float x, y, z, w, we;
x = in->x*pv->mCTM._11 + in->y*pv->mCTM._21 +
in->z*pv->mCTM._31 + pv->mCTM._41;
y = in->x*pv->mCTM._12 + in->y*pv->mCTM._22 +
in->z*pv->mCTM._32 + pv->mCTM._42;
z = in->x*pv->mCTM._13 + in->y*pv->mCTM._23 +
in->z*pv->mCTM._33 + pv->mCTM._43;
we= in->x*pv->mCTM._14 + in->y*pv->mCTM._24 +
in->z*pv->mCTM._34 + pv->mCTM._44;
clip = 0;
if (!(flags & D3DDP_DONOTCLIP))
{
D3DVALUE xx = we - x;
D3DVALUE yy = we - y;
D3DVALUE zz = we - z;
clip = ((ASINT32(x) & 0x80000000) >> (32-D3DCLIP_LEFTBIT)) |
((ASINT32(y) & 0x80000000) >> (32-D3DCLIP_BOTTOMBIT)) |
((ASINT32(z) & 0x80000000) >> (32-D3DCLIP_FRONTBIT)) |
((ASINT32(xx) & 0x80000000) >> (32-D3DCLIP_RIGHTBIT)) |
((ASINT32(yy) & 0x80000000) >> (32-D3DCLIP_TOPBIT)) |
((ASINT32(zz) & 0x80000000) >> (32-D3DCLIP_BACKBIT));
}
if (clip == 0)
{
int k;
DWORD *pOut = (DWORD*)((char*)out + 4*sizeof(D3DVALUE));
// We have to check this only for DONOTCLIP case, because otherwise
// "clip" is not zero, if we is zero.
if (!FLOAT_EQZ(we))
w = D3DVAL(1)/we;
else
w = __HUGE_PWR2;
clip_intersection = 0;
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
x = x * w * pv->vcache.scaleX + pv->vcache.offsetX;
y = y * w * pv->vcache.scaleY + pv->vcache.offsetY;
if (x < minx) minx = x;
if (x > maxx) maxx = x;
if (y < miny) miny = y;
if (y > maxy) maxy = y;
}
else
{
x = x * w * pv->vcache.scaleX + pv->vcache.offsetX;
y = y * w * pv->vcache.scaleY + pv->vcache.offsetY;
}
out->sx = x;
out->sy = y;
out->sz = z*w;
out->rhw = w;
if (flags & D3DPV_LIGHTING)
{
le.dvPosition = *in;
le.dvNormal = *inNormal;
if (pv->dwFlags & D3DPV_COLORVERTEX)
{
pv->lighting.alpha = *inDiffuse & 0xFF000000;
MakeColor(&pv->lighting.vertexDiffuse, *inDiffuse);
}
if (pv->dwFlags & D3DPV_COLORVERTEXS)
{
MakeColor(&pv->lighting.vertexSpecular, *inSpecular);
}
LIGHT_VERTEX(pv, &le);
}
else
if (inVID & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR))
{
if (inVID & D3DFVF_DIFFUSE)
pv->lighting.outDiffuse = *inDiffuse;
if (inVID & D3DFVF_SPECULAR)
pv->lighting.outSpecular = *inSpecular;
}
if (flags & D3DPV_FOG)
{
D3DVALUE d = ComputeDistance(pv, *(D3DVECTOR*)in);
FOG_VERTEX(&pv->lighting, d);
}
if (outVID & D3DFVF_DIFFUSE)
*pOut++ = pv->lighting.outDiffuse;
if (outVID & D3DFVF_SPECULAR)
*pOut++ = pv->lighting.outSpecular;
// Fill zeros for non-FVF device
if (bNoFVFandNoTexture)
{
*(D3DVALUE*)pOut++ = 0;
*(D3DVALUE*)pOut = 0;
}
else
for (k=0; k < nTex; k++)
{
*(D3DVALUE*)pOut++ = *inTexture[k];
*(D3DVALUE*)pOut++ = *(inTexture[k] + 1);
}
}
else
{
if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
{
D3DVALUE xnew = x * pv->vcache.gb11 + we * pv->vcache.gb41;
D3DVALUE ynew = y * pv->vcache.gb22 + we * pv->vcache.gb42;
D3DVALUE xx = we - xnew;
D3DVALUE yy = we - ynew;
clip |= ((ASINT32(xnew) & 0x80000000) >> (32-D3DCLIPGB_LEFTBIT)) |
((ASINT32(ynew) & 0x80000000) >> (32-D3DCLIPGB_BOTTOMBIT)) |
((ASINT32(xx) & 0x80000000) >> (32-D3DCLIPGB_RIGHTBIT)) |
((ASINT32(yy) & 0x80000000) >> (32-D3DCLIPGB_TOPBIT));
}
clip_intersection &= clip;
clip_union |= clip;
out->sx = x;
out->sy = y;
out->sz = z;
out->rhw = we;
}
if (!(flags & D3DDP_DONOTCLIP))
*hout++ = (D3DFE_CLIPCODE)clip;
NEXT(in, pv->position.dwStride, D3DVECTOR);
NEXT(inNormal, pv->normal.dwStride, D3DVECTOR);
NEXT(inDiffuse, pv->diffuse.dwStride, DWORD);
NEXT(inSpecular, pv->specular.dwStride, DWORD);
{
int j;
for (j=0; j < nTex; j++)
NEXT(inTexture[j], pv->textures[j].dwStride, D3DVALUE);
}
NEXT(out, out_size, D3DTLVERTEX);
}
if (!(flags & D3DDP_DONOTCLIP) && !clip_intersection && clip_union)
{ // We have to light all clipped vertices
int n;
D3DVECTOR *in = (D3DVECTOR*)pv->position.lpvData;
D3DTLVERTEX *out = (D3DTLVERTEX*)pv->lpvOut;
D3DVECTOR *inNormal;
DWORD *inDiffuse;
DWORD *inSpecular;
D3DVALUE *inTexture[8];
D3DFE_CLIPCODE *hout = pv->lpClipFlags;
in = (D3DVECTOR*)pv->position.lpvData;
inNormal = (D3DVECTOR*)pv->normal.lpvData;
inDiffuse = (DWORD*)pv->diffuse.lpvData;
inSpecular = (DWORD*)pv->specular.lpvData;
for (i=0; i < nTex; i++)
inTexture[i] = (D3DVALUE*)pv->textures[i].lpvData;
for (n = count; n ; n--)
{
int j;
if (*hout)
{
DWORD *pOut = (DWORD*)((char*)out + 4*sizeof(D3DVALUE));
int k;
if (pv->dwDeviceFlags & D3DDEV_GUARDBAND &&
(*hout & ~__D3DCLIP_INGUARDBAND) == 0)
{ // This vertex is inside the guard band. We have to compute
// screen coordinates for it
D3DVALUE w = D3DVAL(1)/out->rhw;
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
D3DVALUE x = out->sx * w * pv->vcache.scaleX + pv->vcache.offsetX;
D3DVALUE y = out->sy * w * pv->vcache.scaleY + pv->vcache.offsetY;
if (x < minx) minx = x;
if (x > maxx) maxx = x;
if (y < miny) miny = y;
if (y > maxy) maxy = y;
out->sx = x;
out->sy = y;
}
else
{
out->sx = out->sx * w * pv->vcache.scaleX + pv->vcache.offsetX;
out->sy = out->sy * w * pv->vcache.scaleY + pv->vcache.offsetY;
}
out->sz *= w;
out->rhw = w;
}
if (flags & D3DPV_LIGHTING)
{
le.dvPosition = *in;
le.dvNormal = *inNormal;
if (pv->dwFlags & D3DPV_COLORVERTEX)
{
pv->lighting.alpha = *inDiffuse & 0xFF000000;
MakeColor(&pv->lighting.vertexDiffuse, *inDiffuse);
}
if (pv->dwFlags & D3DPV_COLORVERTEXS)
{
MakeColor(&pv->lighting.vertexSpecular, *inSpecular);
}
LIGHT_VERTEX(pv, &le);
}
else
if (inVID & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR))
{
if (inVID & D3DFVF_DIFFUSE)
pv->lighting.outDiffuse = *inDiffuse;
if (inVID & D3DFVF_SPECULAR)
pv->lighting.outSpecular = *inSpecular;
}
if (flags & D3DPV_FOG)
{
D3DVALUE d = ComputeDistance(pv, *(D3DVECTOR*)in);
FOG_VERTEX(&pv->lighting, d);
}
if (outVID & D3DFVF_DIFFUSE)
*pOut++ = pv->lighting.outDiffuse;
if (outVID & D3DFVF_SPECULAR)
*pOut++ = pv->lighting.outSpecular;
if (bNoFVFandNoTexture)
{
*(D3DVALUE*)pOut++ = 0;
*(D3DVALUE*)pOut = 0;
}
else
for (k=0; k < nTex; k++)
{
*(D3DVALUE*)pOut++ = *inTexture[k];
*(D3DVALUE*)pOut++ = *(inTexture[k] + 1);
}
}
NEXT(in, pv->position.dwStride, D3DVECTOR);
NEXT(inNormal, pv->normal.dwStride, D3DVECTOR);
NEXT(inDiffuse, pv->diffuse.dwStride, DWORD);
NEXT(inSpecular, pv->specular.dwStride, DWORD);
for (j=0; j < nTex; j++)
NEXT(inTexture[j], pv->textures[j].dwStride, D3DVALUE);
NEXT(out, out_size, D3DTLVERTEX);
hout++;
}
}
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
/*
* extend to cover lines. XXX
*/
maxx += pv->dvExtentsAdjust;
maxy += pv->dvExtentsAdjust;
minx -= pv->dvExtentsAdjust;
miny -= pv->dvExtentsAdjust;
/* Clamp to viewport */
if (minx < pv->vcache.minX)
minx = pv->vcache.minX;
if (miny < pv->vcache.minY)
miny = pv->vcache.minY;
if (maxx > pv->vcache.maxX)
maxx = pv->vcache.maxX;
if (maxy > pv->vcache.maxY)
maxy = pv->vcache.maxY;
pv->rExtents.x1 = minx;
pv->rExtents.y1 = miny;
pv->rExtents.x2 = maxx;
pv->rExtents.y2 = maxy;
}
if (!(flags & D3DDP_DONOTCLIP))
{
pv->dwClipIntersection = clip_intersection;
pv->dwClipUnion = clip_union;
}
else
{
pv->dwClipIntersection = 0;
pv->dwClipUnion = 0;
}
return 0;
}
//--------------------------------------------------------------------------
// Transform vertices, generate clip codes, apply light and fog.
// General unoptimized case
//
// This function is called for legacy vertices:
// D3DFVF_VERTEX or D3DFVF_LVERTEX as input
// D3DFVF_TLVERTEX as ouput
// The following fields from pv are used:
// dwFlags
// dwNumVertices
// position.lpvData
// lpvOut
// lpClipFlags
// nTexCoord
// Returns:
// returns dwClipIntersection or 0 (if D3DDP_DONOTCLIP is set)
// Side effects:
// dwClipUnion, dwClipIntersection are set only if D3DDP_DONOTCLIP is not set
// rExtents is updated if D3DDP_DONOTUPDATEEXTENTS is not set
//
#undef DPF_MODNAME
#define DPF_MODNAME "ProcessVerticesLegacy"
DWORD ProcessVerticesLegacy(LPD3DFE_PROCESSVERTICES pv)
{
const DWORD in_size = sizeof(D3DVERTEX);
const DWORD out_size = sizeof(D3DVERTEX);
D3DVERTEX *in = (LPD3DVERTEX)pv->position.lpvData;
D3DTLVERTEX *out =(LPD3DTLVERTEX)pv->lpvOut;
int i;
DWORD flags = pv->dwFlags;
D3DFE_CLIPCODE *hout = pv->lpClipFlags;
int clip_intersection = ~0;
int clip_union = 0;
D3DVALUE minx, maxx, miny, maxy;
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
minx = pv->rExtents.x1;
miny = pv->rExtents.y1;
maxx = pv->rExtents.x2;
maxy = pv->rExtents.y2;
}
for (i = pv->dwNumVertices; i; i--)
{
int clip;
float x, y, z, w, we;
x = in->x*pv->mCTM._11 + in->y*pv->mCTM._21 +
in->z*pv->mCTM._31 + pv->mCTM._41;
y = in->x*pv->mCTM._12 + in->y*pv->mCTM._22 +
in->z*pv->mCTM._32 + pv->mCTM._42;
z = in->x*pv->mCTM._13 + in->y*pv->mCTM._23 +
in->z*pv->mCTM._33 + pv->mCTM._43;
we= in->x*pv->mCTM._14 + in->y*pv->mCTM._24 +
in->z*pv->mCTM._34 + pv->mCTM._44;
if (!(flags & D3DDP_DONOTCLIP))
{
D3DVALUE xx = we - x;
D3DVALUE yy = we - y;
D3DVALUE zz = we - z;
clip = ((ASINT32(x) & 0x80000000) >> (32-D3DCLIP_LEFTBIT)) |
((ASINT32(y) & 0x80000000) >> (32-D3DCLIP_BOTTOMBIT)) |
((ASINT32(z) & 0x80000000) >> (32-D3DCLIP_FRONTBIT)) |
((ASINT32(xx) & 0x80000000) >> (32-D3DCLIP_RIGHTBIT)) |
((ASINT32(yy) & 0x80000000) >> (32-D3DCLIP_TOPBIT)) |
((ASINT32(zz) & 0x80000000) >> (32-D3DCLIP_BACKBIT));
}
else
clip = 0;
if (clip == 0)
{
// We have to check this only for DONOTCLIP case, because otherwise
// "clip" is not zero, if we is zero.
if (!FLOAT_EQZ(we))
w = D3DVAL(1)/we;
else
w = __HUGE_PWR2;
clip_intersection = 0;
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
x = x * w * pv->vcache.scaleX + pv->vcache.offsetX;
y = y * w * pv->vcache.scaleY + pv->vcache.offsetY;
if (x < minx) minx = x;
if (x > maxx) maxx = x;
if (y < miny) miny = y;
if (y > maxy) maxy = y;
}
else
{
x = x * w * pv->vcache.scaleX + pv->vcache.offsetX;
y = y * w * pv->vcache.scaleY + pv->vcache.offsetY;
}
out->sx = x;
out->sy = y;
out->sz = z*w;
out->rhw = w;
// In ramp mode pv->lighting.diffuse.r and pv->lighting.specular.r
// are used to store trhe result of lighting.
// Otherwise pv->lighting.outDiffuse and pv->lighting.outSpecular
// are used
if (flags & D3DPV_LIGHTING)
{
if (pv->dwDeviceFlags & D3DDEV_RAMP)
LIGHT_VERTEX_RAMP(pv, in);
else
LIGHT_VERTEX(pv, in);
}
else
if (pv->dwVIDIn & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR))
{
if (pv->dwDeviceFlags & D3DDEV_RAMP)
{
pv->lighting.alpha = ((D3DLVERTEX*)in)->color & 0xFF000000;
pv->lighting.diffuse.r = RGB_GETBLUE(((D3DLVERTEX*)in)->color)*__ONE_OVER_255;
pv->lighting.specular.r = RGB_GETBLUE(((D3DLVERTEX*)in)->specular)*__ONE_OVER_255;
}
else
{
pv->lighting.outDiffuse = ((D3DLVERTEX*)in)->color;
pv->lighting.outSpecular = ((D3DLVERTEX*)in)->specular;
}
}
else
{
if (pv->dwDeviceFlags & D3DDEV_RAMP)
{
pv->lighting.alpha = 0xFF000000;
pv->lighting.diffuse.r = D3DVAL(0);
pv->lighting.specular.r = D3DVAL(0);
}
else
{
pv->lighting.outDiffuse = __DEFAULT_DIFFUSE;
pv->lighting.outSpecular = __DEFAULT_SPECULAR;
}
}
if (flags & D3DPV_FOG)
{
D3DVALUE d;
if (pv->dwDeviceFlags & D3DDEV_PREDX6DEVICE)
d = we;
else
d = ComputeDistance(pv, *(D3DVECTOR*)in);
if (pv->dwDeviceFlags & D3DDEV_RAMP)
FOG_VERTEX_RAMP(&pv->lighting, d);
else
FOG_VERTEX(&pv->lighting, d);
}
if (pv->dwDeviceFlags & D3DDEV_RAMP)
{
MAKE_VERTEX_COLOR_RAMP(pv, out);
}
else
{
out->color = pv->lighting.outDiffuse;
out->specular = pv->lighting.outSpecular;
}
out->tu = in->tu;
out->tv = in->tv;
}
else
{
if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
{
D3DVALUE xnew = x * pv->vcache.gb11 + we * pv->vcache.gb41;
D3DVALUE ynew = y * pv->vcache.gb22 + we * pv->vcache.gb42;
D3DVALUE xx = we - xnew;
D3DVALUE yy = we - ynew;
clip |= ((ASINT32(xnew) & 0x80000000) >> (32-D3DCLIPGB_LEFTBIT)) |
((ASINT32(ynew) & 0x80000000) >> (32-D3DCLIPGB_BOTTOMBIT)) |
((ASINT32(xx) & 0x80000000) >> (32-D3DCLIPGB_RIGHTBIT)) |
((ASINT32(yy) & 0x80000000) >> (32-D3DCLIPGB_TOPBIT));
}
clip_intersection &= clip;
clip_union |= clip;
out->sx = x;
out->sy = y;
out->sz = z;
out->rhw = we;
}
if (!(flags & D3DDP_DONOTCLIP))
*hout++ = (D3DFE_CLIPCODE)clip;
in = (D3DVERTEX*) ((char*) in + in_size);
out = (D3DTLVERTEX*) ((char*) out + out_size);
}
if (!(flags & D3DDP_DONOTCLIP) && !clip_intersection && clip_union)
{ // There are vertices outside the screen as well as inside.
// We have to compute lighting for vertices that are outside the screen
int n;
D3DVERTEX* in = (LPD3DVERTEX)pv->position.lpvData;
D3DTLVERTEX *out = (LPD3DTLVERTEX)pv->lpvOut;
D3DFE_CLIPCODE *hout = pv->lpClipFlags;
for (n = pv->dwNumVertices; n ; n--)
{
if (*hout)
{
D3DVALUE rhw = out->rhw; // Save it for fog
if (pv->dwDeviceFlags & D3DDEV_GUARDBAND &&
(*hout & ~__D3DCLIP_INGUARDBAND) == 0)
{ // This vertex is inside the guard band. We have to compute
// screen coordinates for it
D3DVALUE w = D3DVAL(1)/out->rhw;
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
D3DVALUE x = out->sx * w * pv->vcache.scaleX + pv->vcache.offsetX;
D3DVALUE y = out->sy * w * pv->vcache.scaleY + pv->vcache.offsetY;
if (x < minx) minx = x;
if (x > maxx) maxx = x;
if (y < miny) miny = y;
if (y > maxy) maxy = y;
out->sx = x;
out->sy = y;
}
else
{
out->sx = out->sx * w * pv->vcache.scaleX + pv->vcache.offsetX;
out->sy = out->sy * w * pv->vcache.scaleY + pv->vcache.offsetY;
}
out->sz *= w;
out->rhw = w;
}
if (flags & D3DPV_LIGHTING)
{
if (pv->dwDeviceFlags & D3DDEV_RAMP)
LIGHT_VERTEX_RAMP(pv, in);
else
LIGHT_VERTEX(pv, in);
}
else
if (pv->dwVIDIn & (D3DFVF_DIFFUSE | D3DFVF_SPECULAR))
{
if (pv->dwDeviceFlags & D3DDEV_RAMP)
{
pv->lighting.alpha = ((D3DLVERTEX*)in)->color & 0xFF000000;
pv->lighting.diffuse.r = RGB_GETBLUE(((D3DLVERTEX*)in)->color)*__ONE_OVER_255;
pv->lighting.specular.r = RGB_GETBLUE(((D3DLVERTEX*)in)->specular)*__ONE_OVER_255;
}
else
{
pv->lighting.outDiffuse = ((D3DLVERTEX*)in)->color;
pv->lighting.outSpecular = ((D3DLVERTEX*)in)->specular;
}
}
else
{
if (pv->dwDeviceFlags & D3DDEV_RAMP)
{
pv->lighting.alpha = 0xFF000000;
pv->lighting.diffuse.r = D3DVAL(0);
pv->lighting.specular.r = D3DVAL(0);
}
else
{
pv->lighting.outDiffuse = __DEFAULT_DIFFUSE;
pv->lighting.outSpecular = __DEFAULT_SPECULAR;
}
}
if (flags & D3DPV_FOG)
{
D3DVALUE d;
if (pv->dwDeviceFlags & D3DDEV_PREDX6DEVICE)
d = rhw;
else
d = ComputeDistance(pv, *(D3DVECTOR*)in);
if (pv->dwDeviceFlags & D3DDEV_RAMP)
FOG_VERTEX_RAMP(&pv->lighting, d);
else
FOG_VERTEX(&pv->lighting, d);
}
if (pv->dwDeviceFlags & D3DDEV_RAMP)
{
MAKE_VERTEX_COLOR_RAMP(pv, out);
}
else
{
out->color = pv->lighting.outDiffuse;
out->specular = pv->lighting.outSpecular;
}
out->tu = in->tu;
out->tv = in->tv;
}
in = (D3DVERTEX*) ((char*) in + in_size);
out = (D3DTLVERTEX*) ((char*) out + out_size);
hout++;
}
}
if (!(flags & D3DDP_DONOTUPDATEEXTENTS))
{
//extend to cover lines. XXX
maxx += pv->dvExtentsAdjust;
maxy += pv->dvExtentsAdjust;
minx -= pv->dvExtentsAdjust;
miny -= pv->dvExtentsAdjust;
// Clamp to viewport
// Clamp for legacy apps
if (minx < pv->vcache.minX || miny < pv->vcache.minY ||
maxx > pv->vcache.maxX || maxy > pv->vcache.maxY)
{
// Clamp to viewport
if (minx < pv->vcache.minX)
minx = pv->vcache.minX;
if (miny < pv->vcache.minY)
miny = pv->vcache.minY;
if (maxx > pv->vcache.maxX)
maxx = pv->vcache.maxX;
if (maxy > pv->vcache.maxY)
maxy = pv->vcache.maxY;
if (flags & D3DDP_DONOTCLIP)
{
if(pv->dwDeviceFlags & D3DDEV_PREDX5DEVICE)
{ // Clamp vertices
int i;
D3D_WARN(4, "Old semantics: Clamping Vertices");
for (i = pv->dwNumVertices,
out = (LPD3DTLVERTEX)pv->lpvOut; i; i--)
{
if (out->sx < pv->vcache.minX) out->sx = pv->vcache.minX;
if (out->sx > pv->vcache.maxX) out->sx = pv->vcache.maxX;
if (out->sy < pv->vcache.minY) out->sy = pv->vcache.minY;
if (out->sy > pv->vcache.maxY) out->sy = pv->vcache.maxY;
out = (D3DTLVERTEX*) ((char*) out + out_size);
}
}
}
}
pv->rExtents.x1 = minx;
pv->rExtents.y1 = miny;
pv->rExtents.x2 = maxx;
pv->rExtents.y2 = maxy;
}
if (!(flags & D3DDP_DONOTCLIP))
{
pv->dwClipIntersection = clip_intersection;
pv->dwClipUnion = clip_union;
return clip_intersection;
}
return 0;
}
DWORD D3DFE_PVFUNCS::ProcessVertices(LPD3DFE_PROCESSVERTICES pv)
{
CD3DFPstate D3DFPstate; // Sets optimal FPU state for D3D.
if (!(pv->dwFlags & D3DPV_STRIDE))
{
if ((pv->dwVIDIn == D3DFVF_VERTEX ||
pv->dwVIDIn == D3DFVF_LVERTEX) &&
pv->dwVIDOut == D3DFVF_TLVERTEX)
{
ProcessVerticesLegacy(pv);
}
else
{
ProcessVerticesFVF(pv);
}
}
else
{
ProcessVerticesFVFS(pv);
}
return pv->dwClipIntersection;
}
HRESULT D3DFE_PVFUNCS::ProcessPrimitive(LPD3DFE_PROCESSVERTICES pv)
{
ProcessVertices(pv);
if (pv->dwClipIntersection)
{
// all vertices were offscreen
return D3D_OK;
}
pv->dwFlags |= D3DPV_WITHINPRIMITIVE;
// This should not be required as we should be able to change
// the parameter of DoDrawPrimtive and all it's children to pv
return (DoDrawPrimitive(pv));
}
HRESULT D3DFE_PVFUNCS::ProcessIndexedPrimitive(LPD3DFE_PROCESSVERTICES pv)
{
ProcessVertices(pv);
if (pv->dwClipIntersection)
{
// all vertices were offscreen
return D3D_OK;
}
pv->dwFlags |= D3DPV_WITHINPRIMITIVE;
// This should not be required as we should be able to change
// the parameter of DoDrawIndexedPrimtive and all it's children to pv
return (DoDrawIndexedPrimitive(pv));
}