Windows NT 4.0 source code leak
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.
 
 
 
 
 
 

743 lines
16 KiB

/******************************Module*Header*******************************\
* Module Name: tranblt.cxx
*
* Transparent BLT
*
* Created: 21-Jun-1996
* Author: Mark Enstrom [marke]
*
* Copyright (c) 1996 Microsoft Corporation
\**************************************************************************/
#include "precomp.hxx"
/******************************Public*Routine******************************\
* TriangleMesh
*
* Arguments:
*
* hdc - device context
* pVertex - List of all vertexs
* pMesh - triples that define each tiangle
* nCount - number of triangles
*
* Return Value:
*
* Status
*
* History:
*
* 16-Jul-1996 -by- Mark Enstrom [marke]
*
\**************************************************************************/
typedef LONG PTFX8;
typedef USHORT COLOR16;
typedef struct _VERTEX
{
PTFX8 x;
PTFX8 y;
COLOR16 Red;
COLOR16 Green;
COLOR16 Blue;
COLOR16 Alpha;
}VERTEX,*PVERTEX;
typedef struct _TRIEDGE
{
PTFX8 xLeft;
COLOR16 RedLeft;
COLOR16 GreenLeft;
COLOR16 BlueLeft;
COLOR16 AlphaLeft;
PTFX8 xRight;
COLOR16 RedRight;
COLOR16 GreenRight;
COLOR16 BlueRight;
COLOR16 AlphaRight;
}TRIEDGE,*PTRIEDGE;
typedef struct _TRIANGLEDATA
{
LONG y0;
LONG yMax;
TRIEDGE TriEdge[1];
}TRIANGLEDATA,*PTRIANGLEDATA;
#define SWAP_VERTEX(pv0,pv1,pvt) \
{ \
pvt = pv0; \
pv0 = pv1; \
pv1 = pvt; \
}
extern "C" {
BOOL
NtGdiTriangleMesh(
HDC hdc,
PVERTEX pVertex,
ULONG nVertex,
PULONG pMesh,
ULONG nTriangle
);
}
BOOL
GreTriangleMesh(
HDC hdc,
PVERTEX pLocalVertex,
ULONG nVertex,
PULONG pLocalMesh,
ULONG nMesh
);
BOOL GradientFill1(SURFACE *,LONG,PTRIEDGE);
BOOL GradientFill4(SURFACE *,LONG,PTRIEDGE);
BOOL GradientFill8(SURFACE *,LONG,PTRIEDGE);
BOOL GradientFill16(SURFACE *,LONG,PTRIEDGE);
BOOL GradientFill24(SURFACE *,LONG,PTRIEDGE);
BOOL GradientFill32(SURFACE *,LONG,PTRIEDGE);
typedef BOOL (*PFN_GRADIENT)(SURFACE *,LONG,PTRIEDGE);
PFN_GRADIENT gpfnGradient[] = {GradientFill1,GradientFill4,
GradientFill8,GradientFill16,
GradientFill24,GradientFill32
};
ULONG DbgRecord = 0;
/******************************Public*Routine******************************\
*
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 17-Jul-1996 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
GradientFill1(
SURFACE *pSurfDst,
LONG y,
PTRIEDGE pTriEdge
)
{
return(TRUE);
}
BOOL
GradientFill4(
SURFACE *pSurfDst,
LONG y,
PTRIEDGE pTriEdge
)
{
return(TRUE);
}
BOOL
GradientFill8(
SURFACE *pSurfDst,
LONG y,
PTRIEDGE pTriEdge
)
{
return(TRUE);
}
BOOL
GradientFill16(
SURFACE *pSurfDst,
LONG y,
PTRIEDGE pTriEdge
)
{
if (DbgRecord)
{
DbgPrint("\nGradientFill16:\n");
DbgPrint("y = %8lx, x from %8lx to %08lx\n",y,pTriEdge->xLeft,pTriEdge->xRight);
}
LONG lDelta = pSurfDst->lDelta();
PUSHORT pDstLine = (PUSHORT)((PBYTE)pSurfDst->pvScan0() + y * lDelta);
PUSHORT pDstX,pDstLast;
pDstX = pDstLine + pTriEdge->xLeft;
pDstLast = pDstLine + pTriEdge->xRight;
LONG dx = pTriEdge->xRight - pTriEdge->xLeft;
if (dx != 0)
{
ULONG r = (ULONG)pTriEdge->RedLeft;
ULONG g = (ULONG)pTriEdge->GreenLeft;
ULONG b = (ULONG)pTriEdge->BlueLeft;
ULONG a = (ULONG)pTriEdge->AlphaLeft;
LONG dr = (LONG)(pTriEdge->RedRight - r)/dx;
LONG dg = (LONG)(pTriEdge->GreenRight - g)/dx;
LONG db = (LONG)(pTriEdge->BlueRight - b)/dx;
LONG da = (LONG)(pTriEdge->AlphaRight - a)/dx;
if (DbgRecord)
{
DbgPrint("rl = %8lx, gl = %8lx, , bl = %8lx\n",r,g,b);
DbgPrint("rr = %8lx, gr = %8lx, , br = %8lx\n",pTriEdge->RedRight,pTriEdge->GreenRight,pTriEdge->BlueRight);
DbgPrint("dr = %8lx, dg = %8lx, , db = %8lx\n",dr,dg,db);
}
while (pDstX <= pDstLast)
{
USHORT Color = (((USHORT) r >> 11) << 10) |
(((USHORT) g >> 11) << 5) |
((USHORT) b >> 11);
*pDstX = Color;
r += dr;
g += dg;
b += db;
pDstX++;
}
}
return(TRUE);
}
BOOL
GradientFill24(
SURFACE *pSurfDst,
LONG y,
PTRIEDGE pTriEdge
)
{
return(TRUE);
}
BOOL
GradientFill32(
SURFACE *pSurfDst,
LONG y,
PTRIEDGE pTriEdge
)
{
//
// calculate offset to destination scan line
//
//
// calc starting colors,positions and DDA values
//
//
// fill across line
//
return(TRUE);
}
VOID
RECORD_VERTEX(
PTRIANGLEDATA ptData,
LONG x,
LONG y,
LONG r,
LONG g,
LONG b,
LONG a
)
{
LONG ulIndex = y - ptData->y0;
if (DbgRecord)
{
DbgPrint("\nRECORD_LINE(0x%lx,0x%lx,0x%lx,0x%lx,0x%lx,0x%lx\n",x,y,r,g,b,a);
}
if ((ulIndex >= 0) && (ulIndex < ptData->yMax))
{
if (x < ptData->TriEdge[ulIndex].xLeft)
{
ptData->TriEdge[ulIndex].xLeft = x;
ptData->TriEdge[ulIndex].RedLeft = (COLOR16)r;
ptData->TriEdge[ulIndex].GreenLeft = (COLOR16)g;
ptData->TriEdge[ulIndex].BlueLeft = (COLOR16)b;
ptData->TriEdge[ulIndex].AlphaLeft = (COLOR16)a;
}
if (x > ptData->TriEdge[ulIndex].xRight)
{
ptData->TriEdge[ulIndex].xRight = x;
ptData->TriEdge[ulIndex].RedRight = (COLOR16)r;
ptData->TriEdge[ulIndex].GreenRight = (COLOR16)g;
ptData->TriEdge[ulIndex].BlueRight = (COLOR16)b;
ptData->TriEdge[ulIndex].AlphaRight = (COLOR16)a;
}
}
}
/******************************Public*Routine******************************\
*
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 17-Jul-1996 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
bRecordLine(
PVERTEX pv0,
PVERTEX pv1,
PTRIANGLEDATA ptData
)
{
//
// run line from pv0 to pv1. Record min and max x for each value of y.
//
// Must also run interpolation on color values along line and record
// color values for each x.
//
// Note that bith color and position end points are fractional.
//
if (DbgRecord)
{
DbgPrint("\nbRecordLine: draw line from \n");
DbgPrint("x = 0x%08lx,y = 0x%08lx, 0x%08lx 0x%08lx 0x%08lx 0x%08lx to \n" ,
pv0->x,
pv0->y,
pv0->Red,
pv0->Green,
pv0->Blue,
pv0->Alpha
);
DbgPrint("x = 0x%08lx,y = 0x%08lx, 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n",
pv1->x,
pv1->y,
pv1->Red,
pv1->Green,
pv1->Blue,
pv1->Alpha
);
}
ULONG r = (ULONG)pv0->Red;
ULONG g = (ULONG)pv0->Green;
ULONG b = (ULONG)pv0->Blue;
ULONG a = (ULONG)pv0->Alpha;
LONG x = (LONG)pv0->x;
LONG y = pv0->y;
LONG dy = pv1->y - pv0->y;
if (dy == 0)
{
//
// record the two endpoints of the horizontal line
//
RECORD_VERTEX(ptData,x,y,r,g,b,a);
RECORD_VERTEX(ptData,
pv1->x,
y,
pv1->Red,
pv1->Green,
pv1->Blue,
pv1->Alpha
);
}
else
{
LONG ldr = (LONG)((pv1->Red - r)) / dy;
LONG ldg = (LONG)((pv1->Green - g)) / dy;
LONG ldb = (LONG)((pv1->Blue - b)) / dy;
LONG lda = (LONG)((pv1->Alpha - a)) / dy;
LONGLONG ldx = ((pv1->x - x) << 16) / dy;
LONGLONG lx = x << 16;
ULONG lr = r;
ULONG lg = g;
ULONG lb = b;
ULONG la = a;
if (DbgRecord)
{
DbgPrint("\n: begin line dda:\n");
DbgPrint("lx = 0x%08lx,lr = 0x%08lx,lg = 0x%08lx,lb = 0x%08lx,la = 0x%08lx\n",lx,lr,lg,lb,la);
DbgPrint("ldx = 0x%08lx,ldr = 0x%08lx,ldg = 0x%08lx,ldb = 0x%08lx,lda = 0x%08lx\n",ldx,ldr,ldg,ldb,lda);
DbgPrint("\n");
}
for (y = pv0->y;y<pv1->y;y++)
{
x = (LONG)(lx >> 16);
RECORD_VERTEX(ptData,x,y,lr,lg,lb,la);
lx += ldx;
lr += ldr;
lg += ldg;
lb += ldb;
la += lda;
}
}
return(TRUE);
}
/******************************Public*Routine******************************\
*
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 17-Jul-1996 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
bFillTriangle(
XDCOBJ &dcoDst,
CLIPOBJ *pco,
PVERTEX pv0,
PVERTEX pv1,
PVERTEX pv2
)
{
SURFACE *pSurfDst = dcoDst.pSurface();
PFN_GRADIENT pfnG = gpfnGradient[pSurfDst->iFormat() - 1];
//
// already sorted in y
//
LONG dy = pv2->y - pv0->y;
LONG iy;
PTRIANGLEDATA ptData = (PTRIANGLEDATA)PALLOCMEM(sizeof(TRIANGLEDATA) + (dy-1) * sizeof(TRIEDGE),'gdEg');
if (ptData)
{
ptData->y0 = pv0->y;
ptData->yMax = dy;
for (LONG iy=0;iy<dy;iy++)
{
ptData->TriEdge[iy].xLeft = LONG_MAX;
ptData->TriEdge[iy].xRight = LONG_MIN;
}
bRecordLine(pv0,pv1,ptData);
bRecordLine(pv0,pv2,ptData);
bRecordLine(pv1,pv2,ptData);
//
// fill each edge
//
for (iy=pv0->y;iy<pv2->y;iy++)
{
pfnG(pSurfDst,iy,&ptData->TriEdge[iy - pv0->y]);
}
VFREEMEM(ptData);
}
return(TRUE);
}
/******************************Public*Routine******************************\
* NtGdiTriangleMesh
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 17-Jul-1996 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
NtGdiTriangleMesh(
HDC hdc,
PVERTEX pVertex,
ULONG nVertex,
PULONG pMesh,
ULONG nTriangle
)
{
PVERTEX pLocalVertex;
PULONG pLocalMesh;
ULONG ulSizeV = nVertex * sizeof(VERTEX);
ULONG ulSizeM = nTriangle * 3 * sizeof(ULONG);
BOOL bRet = TRUE;
//
// alloc memory for data buffers
//
pLocalVertex = (PVERTEX)PALLOCNOZ(ulSizeV + ulSizeM,'pmtG');
if (pLocalVertex)
{
pLocalMesh = (PULONG)((PBYTE)pLocalVertex + ulSizeV);
//
// probe then copy buffers
//
__try
{
ProbeForRead(pVertex,ulSizeV,sizeof(BYTE));
RtlCopyMemory(pLocalVertex,pVertex,ulSizeV);
ProbeForRead(pMesh,ulSizeM,sizeof(BYTE));
RtlCopyMemory(pLocalMesh,pMesh,ulSizeM);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
WARNINGX(2);
bRet = FALSE;
}
if (bRet)
{
bRet = GreTriangleMesh(
hdc,
pLocalVertex,
nVertex,
pLocalMesh,
nTriangle
);
}
VFREEMEM(pLocalVertex);
}
else
{
bRet = FALSE;
}
return(bRet);
}
/******************************Public*Routine******************************\
*
*
* Arguments:
*
*
*
* Return Value:
*
*
*
* History:
*
* 16-Jul-1996 -by- Mark Enstrom [marke]
*
\**************************************************************************/
BOOL
GreTriangleMesh(
HDC hdc,
PVERTEX pLocalVertex,
ULONG nVertex,
PULONG pLocalMesh,
ULONG nMesh
)
{
BOOL bStatus = FALSE;
//
// validate DST DC
//
DCOBJ dcoDst(hdc);
if (dcoDst.bValid())
{
DEVLOCKBLTOBJ dlo;
if (dlo.bLock(dcoDst))
{
EXFORMOBJ xoDst(dcoDst, WORLD_TO_DEVICE);
ULONG ulIndex;
ERECTL erclDst(0,0,0,0);
//
// translate to device space, remember extents
//
for (ulIndex=0;ulIndex<nVertex;ulIndex++)
{
EPOINTL eptl(pLocalVertex[ulIndex].x,pLocalVertex[ulIndex].y);
xoDst.bXform(eptl);
pLocalVertex[ulIndex].x = eptl.x + dcoDst.eptlOrigin().x;
pLocalVertex[ulIndex].y = eptl.y + dcoDst.eptlOrigin().y;
if (pLocalVertex[ulIndex].x < erclDst.left)
{
erclDst.left = pLocalVertex[ulIndex].x;
}
if (pLocalVertex[ulIndex].x > erclDst.right)
{
erclDst.right = pLocalVertex[ulIndex].x;
}
if (pLocalVertex[ulIndex].y < erclDst.top)
{
erclDst.top = pLocalVertex[ulIndex].y;
}
if (pLocalVertex[ulIndex].y > erclDst.bottom)
{
erclDst.bottom = pLocalVertex[ulIndex].y;
}
}
//
// set up clipping, check if totally excluded
//
ECLIPOBJ eco(dcoDst.prgnEffRao(), erclDst);
if (!(eco.erclExclude().bEmpty()))
{
SURFACE *pSurfDst;
if ((pSurfDst = dcoDst.pSurface()) != NULL)
{
DEVEXCLUDEOBJ dxo(dcoDst,&erclDst,&eco);
//
// Inc the target surface uniqueness
//
INC_SURF_UNIQ(pSurfDst);
//
// sync with driver !!!must go in eng call!!!
//
if (pSurfDst->flags() & HOOK_SYNCHRONIZE)
{
PDEVOBJ po(pSurfDst->hdev());
(po.pfnSync())(pSurfDst->dhpdev(),NULL);
}
//
// parse into triangles sorted by y
//
ULONG ulTri;
for (ulIndex=0,ulTri=0;ulIndex<nMesh;ulIndex++,ulTri+=3)
{
PVERTEX pv0 = &pLocalVertex[pLocalMesh[ulTri ]];
PVERTEX pv1 = &pLocalVertex[pLocalMesh[ulTri+1]];
PVERTEX pv2 = &pLocalVertex[pLocalMesh[ulTri+2]];
PVERTEX pvt;
if (pv0->y > pv1->y)
{
SWAP_VERTEX(pv0,pv1,pvt);
}
if (pv1->y > pv2->y)
{
SWAP_VERTEX(pv1,pv2,pvt);
}
if (pv0->y > pv1->y)
{
SWAP_VERTEX(pv0,pv1,pvt);
}
bFillTriangle(dcoDst,&eco,pv0,pv1,pv2);
}
}
else
{
bStatus = TRUE;
}
}
else
{
bStatus = TRUE;
}
}
else
{
bStatus = dcoDst.bFullScreen();
}
}
else
{
bStatus = FALSE;
}
return(bStatus);
}