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.
 
 
 
 
 
 

527 lines
19 KiB

/*==========================================================================;
*
* Copyright (C) 1997 Microsoft Corporation. All Rights Reserved.
*
* File: clip.h
* Content: Template for functions to clip primitives
*
* The following symbol should be defined before included this file:
* __PROCESS_LINE_NAME - name for a function to clip triangles
* __INDEX_PRIM - name for a function to clip lines
*
* All these symbols are undefined at the end of this file
***************************************************************************/
#ifdef __INDEX_PRIM
#define __DRAW DRAW_INDEX_PRIM
#else
#define __DRAW DRAW_PRIM
#endif
//*********************************************************************
HRESULT __PROCESS_TRI_LIST_NAME(D3DFE_PROCESSVERTICES *pv)
{
int vertexSize3;
DWORD clipMaskOffScreen;
D3DFE_CLIPCODE *clipCode;
DWORD i;
int interpolate;
HRESULT ret;
BYTE *vertex;
#ifdef __INDEX_PRIM
LPWORD startVertex = pv->lpwIndices;
LPWORD index = pv->lpwIndices;
DWORD triangleSize; // 3 for DrawPrimitives,
// 4 for ExecuteBuffers (include wFlags)
if (pv->dwFlags & D3DPV_INSIDEEXECUTE)
triangleSize = 4;
else
triangleSize = 3;
#else
BYTE *startVertex = (BYTE*)pv->lpvOut;
#endif
int primitiveCount;
DWORD vertexSize;
ClipVertex cv[3];
BOOL vertexTransformed;
vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP;
clipCode = pv->lpClipFlags;
interpolate = SetInterpolationFlags(pv);
vertex = (BYTE*)pv->lpvOut;
vertexSize = pv->dwOutputSize;
primitiveCount = 0;
if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
{
clipMaskOffScreen = ~__D3DCLIP_INGUARDBAND;
}
else
{
clipMaskOffScreen = 0xFFFFFFFF;
}
vertexSize3 = vertexSize*3;
for (i = pv->dwNumPrimitives; i; i--)
{
DWORD f1, f2, f3; // vertex clip flags
#ifdef __INDEX_PRIM
DWORD v1, v2, v3;
v1 = index[0];
v2 = index[1];
v3 = index[2];
f1 = clipCode[v1];
f2 = clipCode[v2];
f3 = clipCode[v3];
// PSGP implementation should not implement INSIDEEXECUTE
if (pv->dwFlags & D3DPV_INSIDEEXECUTE)
// Offset to the current triangle in the execute buffer
((LPDIRECT3DDEVICEI)pv)->dwClipIns_offset =
(DWORD)((BYTE*)index - (BYTE*)((LPDIRECT3DDEVICEI)pv)->lpbClipIns_base);
#else
f1 = clipCode[0];
f2 = clipCode[1];
f3 = clipCode[2];
#endif
BOOL needClip = FALSE;
BOOL offFrustum = FALSE;
if (f1 & f2 & f3)
offFrustum = TRUE;
else
if ((f1 | f2 | f3) & clipMaskOffScreen)
needClip = TRUE;
if (offFrustum || needClip)
{// This tri does need clipping
if (primitiveCount)
{ // first draw the ones that didn't need clipping
DWORD vertexCount = primitiveCount*3;
ret = __DRAW(pv, D3DPT_TRIANGLELIST, startVertex,
vertexCount, primitiveCount);
if (ret)
return ret;
#ifndef __INDEX_PRIM
pv->dwVertexBase += vertexCount;
#endif
}
// reset count and start ptr
primitiveCount = 0;
#ifdef __INDEX_PRIM
startVertex = index + triangleSize;
#else
pv->dwVertexBase += 3;
D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase);
startVertex = vertex + vertexSize3;
#endif
// now deal with the single clipped triangle
// first check if it should just be tossed or if it should be clipped
if (!offFrustum)
{
BYTE *p1;
BYTE *p2;
BYTE *p3;
#ifdef __INDEX_PRIM
p1 = vertex + v1*vertexSize;
p2 = vertex + v2*vertexSize;
p3 = vertex + v3*vertexSize;
#else
p1 = vertex;
p2 = vertex + vertexSize;
p3 = p2 + vertexSize;
#endif
MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed, clipMaskOffScreen);
MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed, clipMaskOffScreen);
MAKE_CLIP_VERTEX_FVF(pv, cv[2], p3, f3, vertexTransformed, clipMaskOffScreen);
#ifdef __INDEX_PRIM
if (pv->dwFlags & D3DPV_INSIDEEXECUTE)
// Pass triangle flags for execute buffers
ret = Clip(pv, interpolate, cv, index[3]);
else
#endif
ret = Clip(pv, interpolate, cv);
if (ret) return ret;
}
}
else
primitiveCount++;
#ifdef __INDEX_PRIM
index += triangleSize;
#else
clipCode += 3;
vertex += vertexSize3;
#endif
}
// draw final batch, if any
if (primitiveCount)
{
ret = __DRAW(pv, D3DPT_TRIANGLELIST, startVertex,
primitiveCount*3, primitiveCount);
if (ret)
return ret;
}
return D3D_OK;
}
//------------------------------------------------------------------------------
HRESULT __PROCESS_TRI_STRIP_NAME(D3DFE_PROCESSVERTICES *pv)
{
DWORD lastIndex;
DWORD clipMaskOffScreen;
D3DFE_CLIPCODE *clipCode;
DWORD i;
int interpolate;
HRESULT ret;
BYTE *vertex;
#ifdef __INDEX_PRIM
LPWORD startVertex = pv->lpwIndices;
LPWORD index = pv->lpwIndices;
#else
BYTE *startVertex = (BYTE*)pv->lpvOut;
#endif
int primitiveCount;
DWORD vertexSize;
ClipVertex cv[3];
BOOL vertexTransformed;
vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP;
clipCode = pv->lpClipFlags;
interpolate = SetInterpolationFlags(pv);
vertex = (BYTE*)pv->lpvOut;
vertexSize = pv->dwOutputSize;
primitiveCount = 0;
if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
{
clipMaskOffScreen = ~__D3DCLIP_INGUARDBAND;
}
else
{
clipMaskOffScreen = 0xFFFFFFFF;
}
lastIndex = pv->dwNumPrimitives;
for (i=0; i < lastIndex; i++)
{
DWORD f1, f2, f3; // vertex clip flags
#ifdef __INDEX_PRIM
DWORD v1, v2, v3;
v1 = index[0];
v2 = index[1];
v3 = index[2];
f1 = clipCode[v1];
f2 = clipCode[v2];
f3 = clipCode[v3];
#else
f1 = clipCode[0];
f2 = clipCode[1];
f3 = clipCode[2];
#endif
BOOL needClip = FALSE;
BOOL offFrustum = FALSE;
if (f1 & f2 & f3)
offFrustum = TRUE;
else
if ((f1 | f2 | f3) & clipMaskOffScreen)
needClip = TRUE;
if (offFrustum || needClip)
{ // if this tri does need clipping
if (primitiveCount)
{ // first draw the ones that didn't need clipping
ret = __DRAW(pv, D3DPT_TRIANGLESTRIP, startVertex,
primitiveCount+2, primitiveCount);
if (ret)
return ret;
#ifndef __INDEX_PRIM
pv->dwVertexBase += primitiveCount;
#endif
}
// reset count and start ptr
primitiveCount = 0;
#ifdef __INDEX_PRIM
startVertex = &index[1];
#else
pv->dwVertexBase++;
D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase);
startVertex = vertex + vertexSize;
#endif
// now deal with the single clipped triangle
// first check if it should just be tossed or if it should be clipped
if (!offFrustum)
{
BYTE *p1;
BYTE *p2;
BYTE *p3;
#ifdef __INDEX_PRIM
if (i & 1)
{ // For odd triangles we have to change orientation
// First vertex should remain the first, because it defines
// the color in FLAT shade mode
DWORD tmp = f2;
f2 = f3;
f3 = tmp;
p1 = vertex + v1*vertexSize;
p2 = vertex + v3*vertexSize;
p3 = vertex + v2*vertexSize;
}
else
{
p1 = vertex + v1*vertexSize;
p2 = vertex + v2*vertexSize;
p3 = vertex + v3*vertexSize;
}
#else
p1 = vertex;
if (i & 1)
{ // For odd triangles we have to change orientation
DWORD tmp = f2;
f2 = f3;
f3 = tmp;
p3 = vertex + vertexSize;
p2 = p3 + vertexSize;
}
else
{
p2 = vertex + vertexSize;
p3 = p2 + vertexSize;
}
#endif
MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed, clipMaskOffScreen);
MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed, clipMaskOffScreen);
MAKE_CLIP_VERTEX_FVF(pv, cv[2], p3, f3, vertexTransformed, clipMaskOffScreen);
ret = Clip(pv, interpolate, cv);
if (ret) return ret;
}
}
else
{
if (primitiveCount == 0 && i & 1)
{ // Triangle strip can not start from an odd triangle
// Because we use triangle fan, first vertex in the strip
// should be the second in the fan.
// This vertex defines the color in FLAT shading case.
BYTE tmp[__MAX_VERTEX_SIZE*3];
BYTE *p = tmp;
#ifdef __INDEX_PRIM
BYTE *saveVer = (BYTE*)pv->lpvOut;
DWORD numVer = pv->dwNumVertices;
memcpy (p, vertex + v2*vertexSize, vertexSize);
p += vertexSize;
memcpy (p, vertex + v1*vertexSize, vertexSize);
p += vertexSize;
memcpy (p, vertex + v3*vertexSize, vertexSize);
#else
memcpy(p, vertex + vertexSize, vertexSize);
p += vertexSize;
memcpy(p, vertex, vertexSize);
p += vertexSize;
memcpy(p, vertex + vertexSize + vertexSize, vertexSize);
#endif
pv->dwFlags |= D3DPV_CLIPPERPRIM | D3DPV_NONCLIPPED; // Mark this call as gen by clipper
ret = DRAW_PRIM(pv, D3DPT_TRIANGLEFAN, tmp, 3, 1);
pv->dwFlags &= ~(D3DPV_CLIPPERPRIM | D3DPV_NONCLIPPED);
if (ret)
return ret;
primitiveCount = 0;
#ifdef __INDEX_PRIM
startVertex = &index[1];
pv->lpvOut = saveVer;
pv->dwNumVertices = numVer;
#else
pv->dwVertexBase++;
D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase);
startVertex = vertex + vertexSize;
#endif
}
else
primitiveCount++;
}
#ifdef __INDEX_PRIM
index++;
#else
clipCode++;
vertex += vertexSize;
#endif
}
// draw final batch, if any
if (primitiveCount)
{
ret = __DRAW(pv, D3DPT_TRIANGLESTRIP, startVertex,
primitiveCount+2, primitiveCount);
if (ret)
return ret;
#ifndef __INDEX_PRIM
pv->dwVertexBase += primitiveCount;
#endif
}
return D3D_OK;
}
//-----------------------------------------------------------------------------
// The same functions is used for line lists and line strips
//
HRESULT __PROCESS_LINE_NAME(D3DFE_PROCESSVERTICES *pv)
{
DWORD nextLineOffset; // How many vertices to skip, when going to
// next primitive (1 for strips, 2 for lists)
DWORD countAdd; // Used to compute "real" number of vertices
// from the vertexCount
D3DPRIMITIVETYPE primType;
int numPrim = 0;
DWORD clipMaskOffScreen;
D3DFE_CLIPCODE *clipCode;
DWORD i;
int interpolate;
HRESULT ret;
BYTE *vertex;
#ifdef __INDEX_PRIM
LPWORD startVertex = pv->lpwIndices;
LPWORD index = pv->lpwIndices;
#else
BYTE *startVertex = (BYTE*)pv->lpvOut;
#endif
int vertexCount; // Primitive count for line strips,
// vertex count for line lists
DWORD vertexSize;
ClipVertex cv[3];
BOOL vertexTransformed;
vertexTransformed = pv->dwFlags & D3DPV_TLVCLIP;
clipCode = pv->lpClipFlags;
interpolate = SetInterpolationFlags(pv);
vertex = (BYTE*)pv->lpvOut;
vertexSize = pv->dwOutputSize;
vertexCount = 0;
if (pv->dwDeviceFlags & D3DDEV_GUARDBAND)
{
clipMaskOffScreen = ~__D3DCLIP_INGUARDBAND;
}
else
{
clipMaskOffScreen = 0xFFFFFFFF;
}
primType = pv->primType;
if (primType == D3DPT_LINESTRIP)
{
nextLineOffset = 1;
countAdd = 1;
}
else
{
nextLineOffset = 2;
countAdd = 0;
}
for (i = pv->dwNumPrimitives; i; i--)
{
WORD f1, f2;
#ifdef __INDEX_PRIM
WORD v1, v2;
v1 = index[0];
v2 = index[1];
f1 = clipCode[v1];
f2 = clipCode[v2];
#else
f1 = clipCode[0];
f2 = clipCode[1];
#endif
BOOL needClip = FALSE;
BOOL offFrustum = FALSE;
if (f1 & f2)
offFrustum = TRUE;
else
if ((f1 | f2) & clipMaskOffScreen)
needClip = TRUE;
if (offFrustum || needClip)
{ // if this line does need clipping
if (vertexCount)
{ // first draw the ones that didn't need clipping
ret = __DRAW(pv, primType, startVertex, vertexCount+countAdd, numPrim);
if (ret)
return ret;
#ifndef __INDEX_PRIM
pv->dwVertexBase += vertexCount;
#endif
}
// reset count and start ptr
vertexCount = 0;
numPrim = 0;
#ifdef __INDEX_PRIM
startVertex = &index[nextLineOffset];
#else
pv->dwVertexBase += nextLineOffset;
D3D_INFO(7, "VertexBase:%08lx", pv->dwVertexBase);
startVertex = vertex + nextLineOffset*vertexSize;
#endif
// now deal with the single clipped line
// first check if it should just be tossed or if it should be clipped
if (!offFrustum)
{
#ifdef __INDEX_PRIM
BYTE *p1 = vertex + v1*vertexSize;
BYTE *p2 = vertex + v2*vertexSize;
#else
BYTE *p1 = vertex;
BYTE *p2 = vertex + vertexSize;
#endif
ClipTriangle newline;
MAKE_CLIP_VERTEX_FVF(pv, cv[0], p1, f1, vertexTransformed, clipMaskOffScreen);
MAKE_CLIP_VERTEX_FVF(pv, cv[1], p2, f2, vertexTransformed, clipMaskOffScreen);
newline.v[0] = &cv[0];
newline.v[1] = &cv[1];
if (ClipSingleLine(pv, &newline, &pv->rExtents, interpolate))
{
BYTE *pTLV = (BYTE*)pv->ClipperState.clipBuf.GetAddress();
BYTE *p = pTLV;
#ifdef __INDEX_PRIM
BYTE *saveVer = (BYTE*)pv->lpvOut;
DWORD numVer = pv->dwNumVertices;
#endif
MAKE_TL_VERTEX_FVF(pv, p, newline.v[0]);
p += vertexSize;
MAKE_TL_VERTEX_FVF(pv, p, newline.v[1]);
pv->dwFlags |= D3DPV_CLIPPERPRIM; // Mark this call as gen by clipper
ret = DRAW_PRIM(pv, D3DPT_LINELIST, pTLV, 2, 1);
pv->dwFlags &= ~D3DPV_CLIPPERPRIM;
if (ret)
return ret;
#ifdef __INDEX_PRIM
pv->lpvOut = saveVer;
pv->dwNumVertices = numVer;
#endif
}
}
}
else
{
vertexCount += nextLineOffset;
numPrim++;
}
#ifdef __INDEX_PRIM
index += nextLineOffset;
#else
vertex += nextLineOffset*vertexSize;
clipCode += nextLineOffset;
#endif
}
// draw final batch, if any
if (vertexCount)
{
ret = __DRAW(pv, primType, startVertex, vertexCount+countAdd, numPrim);
if (ret)
return ret;
}
return D3D_OK;
}
#undef __DRAW
#undef __INDEX_PRIM
#undef __PROCESS_LINE_NAME
#undef __PROCESS_TRI_LIST_NAME
#undef __PROCESS_TRI_STRIP_NAME