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.
 
 
 
 
 
 

679 lines
24 KiB

/******************************Module*Header**********************************\
*
* *********************
* * DDraw SAMPLE CODE *
* *********************
*
* Module Name: ddcpyblt.c
*
* Content: several copy and clear blits for Permedia 2
*
* Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
* Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
\*****************************************************************************/
#include "precomp.h"
#include "directx.h"
#include "dd.h"
//-----------------------------------------------------------------------------
//
// PermediaPackedCopyBlt
//
// Does a packed blit, allowing for different source and destination
// partial products.
//
// ppdev----------- the ppdev
// dwDestPitch----- pitch of destination surface
// dwSourcePitch--- pitch of source surface
// pDest----------- pointer to private data structure of dest. surface
// pSource--------- pointer to private data structure of source surface
// *rDest---------- dest. rectangle of blit
// *rSrc----------- source rectangle of blit
// dwWindowBase---- offset of dest. window in frame buffer
// lWindowOffset--- offset of source window in frame buffer
//
//-----------------------------------------------------------------------------
VOID
PermediaPackedCopyBlt( PPDev ppdev, // ppdev
DWORD dwDestPitch, // pitch of dest
DWORD dwSourcePitch,
PermediaSurfaceData* pDest,
PermediaSurfaceData* pSource,
RECTL *rDest,
RECTL *rSrc,
DWORD dwWindowBase,
LONG lWindowOffset
)
{
PERMEDIA_DEFS(ppdev);
LONG lOffset;
LONG lSourceOffset;
LONG lPixelSize=pDest->SurfaceFormat.PixelSize;
LONG lPixelMask=3>>pDest->SurfaceFormat.PixelShift;
LONG lPixelShift=2-pDest->SurfaceFormat.PixelShift;
DBG_DD(( 5, "DDraw:PermediaPackedCopyBlt "
"From %08lx %08lx %08lx %08lx %08lx %08lx %08lx "
"To %08lx %08lx %08lx %08lx %08lx %08lx %08lx",
dwSourcePitch,pSource,rSrc->bottom,rSrc->left,
rSrc->right,rSrc->top,lWindowOffset,
dwDestPitch,pDest,rDest->bottom,rDest->left,
rDest->right,rDest->top,dwWindowBase));
ASSERTDD(!(rSrc->top<0) && !(rSrc->left<0),
"PermediaPackedCopyBlt: cannot handle neg. src coordinates");
ASSERTDD(!(rDest->top<0) && !(rDest->left<0),
"PermediaPackedCopyBlt: cannot handle neg. src coordinates");
lOffset = (((rDest->left & lPixelMask)-(rSrc->left & lPixelMask)) & 7);
lSourceOffset = lWindowOffset +
RECTS_PIXEL_OFFSET(rSrc, rDest,
dwSourcePitch, dwDestPitch,
lPixelMask ) +
LINEAR_FUDGE(dwSourcePitch, dwDestPitch, rDest);
RESERVEDMAPTR(14);
SEND_PERMEDIA_DATA( FBPixelOffset, 0x0);
SEND_PERMEDIA_DATA( FBReadPixel, pDest->SurfaceFormat.FBReadPixel);
// set packed with offset
SEND_PERMEDIA_DATA( FBWindowBase, dwWindowBase);
SEND_PERMEDIA_DATA( FBReadMode,
PM_FBREADMODE_PARTIAL(pSource->ulPackedPP) |
PM_FBREADMODE_READSOURCE(__PERMEDIA_ENABLE) |
PM_FBREADMODE_PACKEDDATA(__PERMEDIA_ENABLE) |
PM_FBREADMODE_RELATIVEOFFSET(lOffset));
SEND_PERMEDIA_DATA( FBWriteConfig,
PM_FBREADMODE_PARTIAL(pDest->ulPackedPP) |
PM_FBREADMODE_READSOURCE(__PERMEDIA_ENABLE) |
PM_FBREADMODE_PACKEDDATA(__PERMEDIA_ENABLE) |
PM_FBREADMODE_RELATIVEOFFSET(lOffset));
SEND_PERMEDIA_DATA( LogicalOpMode, __PERMEDIA_DISABLE);
SEND_PERMEDIA_DATA( FBSourceOffset, lSourceOffset);
// Render the rectangle
if (lSourceOffset >= 0) {
// Use left to right and top to bottom
SEND_PERMEDIA_DATA( StartXDom,
INTtoFIXED(rDest->left >> lPixelShift));
SEND_PERMEDIA_DATA( StartXSub,
INTtoFIXED((rDest->right >> lPixelShift) + lPixelMask));
SEND_PERMEDIA_DATA( PackedDataLimits,
PM_PACKEDDATALIMITS_OFFSET(lOffset) |
PM_PACKEDDATALIMITS_XSTART(rDest->left) |
PM_PACKEDDATALIMITS_XEND(rDest->right));
SEND_PERMEDIA_DATA( StartY, INTtoFIXED(rDest->top));
SEND_PERMEDIA_DATA( dY, INTtoFIXED(1));
}
else {
// Use right to left and bottom to top
SEND_PERMEDIA_DATA( StartXDom,
INTtoFIXED(((rDest->right) >> lPixelShift) + lPixelMask));
SEND_PERMEDIA_DATA( StartXSub,
INTtoFIXED(rDest->left >> lPixelShift));
SEND_PERMEDIA_DATA( PackedDataLimits,
PM_PACKEDDATALIMITS_OFFSET(lOffset) |
PM_PACKEDDATALIMITS_XSTART(rDest->right) |
PM_PACKEDDATALIMITS_XEND(rDest->left));
SEND_PERMEDIA_DATA( StartY, INTtoFIXED(rDest->bottom - 1));
SEND_PERMEDIA_DATA( dY, (DWORD)INTtoFIXED(-1));
}
SEND_PERMEDIA_DATA( Count, rDest->bottom - rDest->top);
SEND_PERMEDIA_DATA( Render, __RENDER_TRAPEZOID_PRIMITIVE);
COMMITDMAPTR();
FLUSHDMA();
} // PermediaPackedCopyBlt
//-----------------------------------------------------------------------------
//
// PermediaPatchedCopyBlt
//
// Does a patched blit, i.e. blits from source to destination and
// turns on patching. Note that this method cannot use packed blits.
//
// ppdev----------- the ppdev
// dwDestPitch----- pitch of destination surface
// dwSourcePitch--- pitch of source surface
// pDest----------- pointer to private data structure of dest. surface
// pSource--------- pointer to private data structure of source surface
// *rDest---------- dest. rectangle of blit
// *rSrc----------- source rectangle of blit
// dwWindowBase---- offset of dest. window in frame buffer
// lWindowOffset--- offset of source window in frame buffer
//
//-----------------------------------------------------------------------------
VOID
PermediaPatchedCopyBlt( PPDev ppdev,
DWORD dwDestPitch,
DWORD dwSourcePitch,
PermediaSurfaceData* pDest,
PermediaSurfaceData* pSource,
RECTL *rDest,
RECTL *rSrc,
DWORD dwWindowBase,
LONG lWindowOffset
)
{
PERMEDIA_DEFS(ppdev);
LONG lSourceOffset;
LONG lPixelSize=pDest->SurfaceFormat.PixelSize;
LONG lPixelMask=pDest->SurfaceFormat.PixelMask;
LONG lPixelShift=pDest->SurfaceFormat.PixelShift;
ASSERTDD(!(rSrc->top<0) && !(rSrc->left<0),
"PermediaPackedCopyBlt: cannot handle neg. src coordinates");
ASSERTDD(!(rDest->top<0) && !(rDest->left<0),
"PermediaPackedCopyBlt: cannot handle neg. src coordinates");
DBG_DD(( 5, "DDraw:PermediaPatchedCopyBlt"));
lSourceOffset = lWindowOffset +
RECTS_PIXEL_OFFSET(rSrc, rDest,
dwSourcePitch, dwDestPitch, lPixelMask) +
LINEAR_FUDGE(dwSourcePitch, dwDestPitch, rDest);
RESERVEDMAPTR(13);
SEND_PERMEDIA_DATA( FBPixelOffset, 0x0);
SEND_PERMEDIA_DATA( FBReadPixel, pDest->SurfaceFormat.FBReadPixel);
// Patching isn't symetric, so we need to reverse the patch code depending
// on the direction of the patch
SEND_PERMEDIA_DATA( FBWindowBase, dwWindowBase);
if (pDest->dwFlags & P2_CANPATCH)
{
pDest->dwFlags |= P2_ISPATCHED;
SEND_PERMEDIA_DATA( FBReadMode,
pSource->ulPackedPP |
__FB_READ_SOURCE);
SEND_PERMEDIA_DATA( FBWriteConfig,
pDest->ulPackedPP |
PM_FBREADMODE_PATCHENABLE(__PERMEDIA_ENABLE) |
PM_FBREADMODE_PATCHMODE(__PERMEDIA_SUBPATCH));
} else
{
pDest->dwFlags &= ~P2_ISPATCHED;
SEND_PERMEDIA_DATA( FBReadMode,
pSource->ulPackedPP |
__FB_READ_SOURCE |
PM_FBREADMODE_PATCHENABLE(__PERMEDIA_ENABLE) |
PM_FBREADMODE_PATCHMODE(__PERMEDIA_SUBPATCH) );
SEND_PERMEDIA_DATA(FBWriteConfig, (pDest->ulPackedPP ));
}
SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
SEND_PERMEDIA_DATA(FBSourceOffset, lSourceOffset);
// Render the rectangle
if (lSourceOffset >= 0)
{
// Use left to right and top to bottom
SEND_PERMEDIA_DATA(StartXDom, INTtoFIXED(rDest->left));
SEND_PERMEDIA_DATA(StartXSub, INTtoFIXED(rDest->right));
SEND_PERMEDIA_DATA(StartY, INTtoFIXED(rDest->top));
SEND_PERMEDIA_DATA(dY, INTtoFIXED(1));
} else
{
// Use right to left and bottom to top
SEND_PERMEDIA_DATA(StartXDom, INTtoFIXED(rDest->right));
SEND_PERMEDIA_DATA(StartXSub, INTtoFIXED(rDest->left));
SEND_PERMEDIA_DATA(StartY, INTtoFIXED(rDest->bottom - 1));
SEND_PERMEDIA_DATA(dY, (DWORD)INTtoFIXED(-1));
}
SEND_PERMEDIA_DATA(Count, rDest->bottom - rDest->top);
SEND_PERMEDIA_DATA(Render, __RENDER_TRAPEZOID_PRIMITIVE);
COMMITDMAPTR();
FLUSHDMA();
} // PermediaPatchedCopyBlt
//-----------------------------------------------------------------------------
//
// PermediaFastClear
//
// Does a fast clear of a surface. Supports all color depths
// Can clear depth or Frame buffer.
//
// ppdev---------the ppdev
// pPrivateData--pointer to private data structure of dest. surface
// rDest---------rectangle for colorfill in dest. surface
// dwWindowBase--offset of dest. surface in frame buffer
// dwColor-------color for fill
//
//-----------------------------------------------------------------------------
VOID
PermediaFastClear(PPDev ppdev,
PermediaSurfaceData* pPrivateData,
RECTL *rDest,
DWORD dwWindowBase,
DWORD dwColor)
{
PERMEDIA_DEFS(ppdev);
ULONG ulRenderBits;
BOOL bFastFill=TRUE;
LONG lPixelSize=pPrivateData->SurfaceFormat.PixelSize;
DBG_DD(( 5, "DDraw:PermediaFastClear"));
ASSERTDD(CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData),
"Private Surface data not valid in clear");
ASSERTDD((pPrivateData->dwFlags & P2_PPVALID),
"PermediaFastClear called with invalid PP codes");
ulRenderBits = __RENDER_FAST_FILL_ENABLE
| __RENDER_TRAPEZOID_PRIMITIVE;
// Clear depending on depth
switch (lPixelSize)
{
case __PERMEDIA_4BITPIXEL:
dwColor &= 0xF;
dwColor |= dwColor << 4;
// fall through...
case __PERMEDIA_8BITPIXEL:
dwColor &= 0xFF;
dwColor |= dwColor << 8;
// fall through
case __PERMEDIA_16BITPIXEL:
dwColor &= 0xFFFF;
dwColor |= (dwColor << 16);
break;
case __PERMEDIA_24BITPIXEL:
dwColor &= 0xFFFFFF;
dwColor |= ((dwColor & 0xFF) << 24);
// Can't use SGRAM fast block fills on any color, only on grey.
if (((dwColor & 0xFF) == ((dwColor & 0xFF00) >> 8)) &&
((dwColor & 0xFF) == ((dwColor & 0xFF0000) >> 16))) {
bFastFill = TRUE;
} else {
bFastFill = FALSE;
}
break;
default:
break;
}
RESERVEDMAPTR(15);
SEND_PERMEDIA_DATA( dXDom, 0x0);
SEND_PERMEDIA_DATA( dXSub, 0x0);
SEND_PERMEDIA_DATA( FBPixelOffset, 0);
SEND_PERMEDIA_DATA( FBReadPixel,
pPrivateData->SurfaceFormat.FBReadPixel);
if (bFastFill)
{
SEND_PERMEDIA_DATA(FBBlockColor, dwColor);
} else
{
ulRenderBits &= ~__RENDER_FAST_FILL_ENABLE;
SEND_PERMEDIA_DATA(FBWriteData, dwColor);
}
SEND_PERMEDIA_DATA(FBReadMode,
PM_FBREADMODE_PARTIAL(pPrivateData->ulPackedPP)|
PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE));
SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_CONSTANT_FB_WRITE);
SEND_PERMEDIA_DATA(FBWindowBase, dwWindowBase);
// Render the rectangle
SEND_PERMEDIA_DATA(StartXDom, INTtoFIXED(rDest->left));
SEND_PERMEDIA_DATA(StartXSub, INTtoFIXED(rDest->right));
SEND_PERMEDIA_DATA(StartY, INTtoFIXED(rDest->top));
SEND_PERMEDIA_DATA(dY, INTtoFIXED(1));
SEND_PERMEDIA_DATA(Count, rDest->bottom - rDest->top);
SEND_PERMEDIA_DATA(Render, ulRenderBits);
// Reset our pixel values.
SEND_PERMEDIA_DATA(LogicalOpMode, __PERMEDIA_DISABLE);
COMMITDMAPTR();
FLUSHDMA();
} //PermediaFastClear
//-----------------------------------------------------------------------------
//
// PermediaClearManagedSurface
//
// Does a clear of a managed surface. Supports all color depths
//
// PixelSize-----surface color depth
// rDest---------rectangle for colorfill in dest. surface
// fpVidMem------pointer to fill
// lPitch--------Surface Pitch
// dwColor-------color for fill
//
//-----------------------------------------------------------------------------
VOID
PermediaClearManagedSurface(DWORD PixelSize,
RECTL *rDest,
FLATPTR fpVidMem,
LONG lPitch,
DWORD dwColor)
{
BYTE* pDestStart;
LONG i;
DBG_DD(( 5, "DDraw:PermediaClearManagedSurface"));
LONG lByteWidth = rDest->right - rDest->left;
LONG lHeight = rDest->bottom - rDest->top;
// Calculate the start pointer for the dest
pDestStart = (BYTE*)(fpVidMem + (rDest->top * lPitch));
// Clear depending on depth
switch (PixelSize)
{
case __PERMEDIA_4BITPIXEL:
{
DWORD right=rDest->right,left=rDest->left;
dwColor &= 0x0F;
dwColor |= dwColor << 4;
if (right & 1)
{
pDestStart = (BYTE*)(fpVidMem + (rDest->top * lPitch));
pDestStart += right/2;
for (i=0;i<lHeight;i++)
{
pDestStart[i*lPitch] = (pDestStart[i*lPitch] & 0xF0) |
(BYTE)(dwColor & 0x0F);
}
right--;
}
if (left & 1)
{
pDestStart = (BYTE*)(fpVidMem + (rDest->top * lPitch));
pDestStart += left/2;
for (i=0;i<lHeight;i++)
{
pDestStart[i*lPitch] = (pDestStart[i*lPitch] & 0x0F) |
(BYTE)(dwColor << 4);
}
left++;
}
pDestStart = (BYTE*)(fpVidMem + (rDest->top * lPitch));
while (--lHeight >= 0)
{
while (left<right)
{
pDestStart[left/2]=(BYTE)dwColor;
left +=2;
}
pDestStart += lPitch;
}
}
break;
case __PERMEDIA_8BITPIXEL:
pDestStart += rDest->left;
while (--lHeight >= 0)
{
for (i=0;i<lByteWidth;i++)
pDestStart[i]=(BYTE)dwColor;
pDestStart += lPitch;
}
break;
// fall through
case __PERMEDIA_16BITPIXEL:
pDestStart += rDest->left*2;
while (--lHeight >= 0)
{
LPWORD lpWord=(LPWORD)pDestStart;
for (i=0;i<lByteWidth;i++)
lpWord[i]=(WORD)dwColor;
pDestStart += lPitch;
}
break;
case __PERMEDIA_24BITPIXEL:
dwColor &= 0xFFFFFF;
dwColor |= ((dwColor & 0xFF) << 24);
default:
pDestStart += rDest->left*4;
while (--lHeight >= 0)
{
LPDWORD lpDWord=(LPDWORD)pDestStart;
for (i=0;i<lByteWidth;i++)
lpDWord[i]=(WORD)dwColor;
pDestStart += lPitch;
}
break;
}
}
//-----------------------------------------------------------------------------
//
// PermediaFastLBClear
//
// Does a fast clear of the Permedia Z (local) Buffer. The Permedia Z Buffer
// is always 16 bit wide...
//
// ppdev---------the ppdev
// pPrivateData--pointer to private data structure of dest. surface
// rDest---------rectangle for colorfill in dest. surface
// dwWindowBase--offset of dest. surface in frame buffer
// dwColor-------color for fill
//
//-----------------------------------------------------------------------------
VOID
PermediaFastLBClear(PPDev ppdev,
PermediaSurfaceData* pPrivateData,
RECTL *rDest,
DWORD dwWindowBase,
DWORD dwColor)
{
PERMEDIA_DEFS(ppdev);
DBG_DD(( 5, "DDraw:PermediaFastLBClear"));
ASSERTDD(CHECK_P2_SURFACEDATA_VALIDITY(pPrivateData),
"Private Surface data not valid in clear");
ASSERTDD((pPrivateData->dwFlags & P2_PPVALID),
"PermediaFastClear called with invalid PP codes");
// Clear according to Z-Buffer depth
dwColor &= 0xFFFF;
dwColor |= dwColor << 16;
RESERVEDMAPTR(15);
SEND_PERMEDIA_DATA( dXDom, 0x0);
SEND_PERMEDIA_DATA( dXSub, 0x0);
SEND_PERMEDIA_DATA( FBPixelOffset, 0);
SEND_PERMEDIA_DATA( FBReadPixel, __PERMEDIA_16BITPIXEL);
SEND_PERMEDIA_DATA( FBBlockColor, dwColor);
SEND_PERMEDIA_DATA( FBReadMode,
PM_FBREADMODE_PARTIAL(pPrivateData->ulPackedPP) |
PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE));
SEND_PERMEDIA_DATA( LogicalOpMode, __PERMEDIA_CONSTANT_FB_WRITE);
SEND_PERMEDIA_DATA( FBWindowBase, dwWindowBase);
SEND_PERMEDIA_DATA( StartXDom, INTtoFIXED(rDest->left));
SEND_PERMEDIA_DATA( StartXSub, INTtoFIXED(rDest->right));
SEND_PERMEDIA_DATA( StartY, INTtoFIXED(rDest->top));
SEND_PERMEDIA_DATA( dY, INTtoFIXED(1));
SEND_PERMEDIA_DATA( Count, rDest->bottom - rDest->top);
SEND_PERMEDIA_DATA( Render, __RENDER_FAST_FILL_ENABLE
|__RENDER_TRAPEZOID_PRIMITIVE);
// Reset our pixel values.
SEND_PERMEDIA_DATA( LogicalOpMode, __PERMEDIA_DISABLE);
COMMITDMAPTR();
FLUSHDMA();
} // PermediaFastLBClear
//-----------------------------------------------------------------------------
//
// SysMemToSysMemSurfaceCopy
//
// Does a copy from System memory to System memory (either from or to an
// AGP surface, or any other system memory surface)
//
//-----------------------------------------------------------------------------
VOID
SysMemToSysMemSurfaceCopy(FLATPTR fpSrcVidMem,
LONG lSrcPitch,
DWORD dwSrcBitCount,
FLATPTR fpDstVidMem,
LONG lDstPitch,
DWORD dwDstBitCount,
RECTL* rSource,
RECTL* rDest)
{
BYTE* pSourceStart;
BYTE* pDestStart;
BYTE pixSource;
BYTE* pNewDest;
BYTE* pNewSource;
DBG_DD(( 5, "DDraw:SysMemToSysMemSurfaceCopy"));
LONG lByteWidth = rSource->right - rSource->left;
LONG lHeight = rSource->bottom - rSource->top;
if (NULL == fpSrcVidMem || NULL == fpDstVidMem)
{
DBG_DD(( 0, "DDraw:SysMemToSysMemSurfaceCopy unexpected 0 fpVidMem"));
return;
}
// Calculate the start pointer for the source and the dest
pSourceStart = (BYTE*)(fpSrcVidMem + (rSource->top * lSrcPitch));
pDestStart = (BYTE*)(fpDstVidMem + (rDest->top * lDstPitch));
// Be careful if the source is 4 bits deep.
if(4 == dwSrcBitCount)
{
// May have to handle horrible single pixel edges. Check if we need to
if (!((1 & (rSource->left ^ rDest->left)) == 1))
{
pSourceStart += rSource->left / 2;
pDestStart += rDest->left / 2;
lByteWidth /= 2;
// Do we have to account for the odd pixel at the start?
if (rSource->left & 0x1)
{
lByteWidth--;
}
// If the end is odd then miss of the last nibble (do it later).
if (rSource->right & 0x1)
{
lByteWidth--;
}
while (--lHeight >= 0)
{
// Potentially copy the left hand pixel
if (rSource->left & 0x1) {
*pDestStart &= 0x0F;
*pDestStart |= (*pSourceStart & 0xF0);
pNewDest = pDestStart + 1;
pNewSource = pSourceStart + 1;
} else {
pNewDest = pDestStart;
pNewSource = pSourceStart;
}
// Byte copy the rest of the field
memcpy(pNewDest, pNewSource, lByteWidth);
// Potentially copy the right hand pixel
if (rSource->right & 0x1) {
*(pNewDest + lByteWidth) &= 0xF0;
*(pNewDest + lByteWidth) |=
(*(pNewSource + lByteWidth) & 0xF);
}
pDestStart += lDstPitch;
pSourceStart += lSrcPitch;
}
} else
{
// Do it the hard way - copy single pixels one at a time
pSourceStart += rSource->left / 2;
pDestStart += rDest->left / 2;
while (--lHeight >= 0)
{
BOOL bOddSource = rSource->left & 0x1;
BOOL bOddDest = rDest->left & 0x1;
pNewDest = pDestStart;
pNewSource = pSourceStart;
for (INT i = 0; i < lByteWidth; i++)
{
if (bOddSource) {
pixSource = (*pNewSource & 0xF0) >> 4;
pNewSource++;
} else {
pixSource = (*pNewSource & 0x0F);
}
if (bOddDest) {
*pNewDest &= 0x0F;
*pNewDest |= pixSource << 4;
pNewDest++;
} else {
*pNewDest &= 0xF0;
*pNewDest |= pixSource;
}
bOddSource = !bOddSource;
bOddDest = !bOddDest;
}
// Step onto the next line
pDestStart += lDstPitch;
pSourceStart += lSrcPitch;
}
}
}
else // The simple 8, 16 or 24 bit copy
{
pSourceStart += rSource->left * (dwSrcBitCount >> 3);
pDestStart += rDest->left * (dwDstBitCount >> 3);
lByteWidth *= (dwSrcBitCount >> 3);
while (--lHeight >= 0)
{
memcpy(pDestStart, pSourceStart, lByteWidth);
pDestStart += lDstPitch;
pSourceStart += lSrcPitch;
};
}
} // SysMemToSysMemSurfaceCopy