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.
524 lines
18 KiB
524 lines
18 KiB
/******************************Module*Header**********************************\
|
|
*
|
|
* *********************
|
|
* * DDraw SAMPLE CODE *
|
|
* *********************
|
|
*
|
|
* Module Name: ddblt.c
|
|
*
|
|
* Content: DirectDraw Blt and AlphaBlt callbacks
|
|
*
|
|
* 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"
|
|
|
|
//
|
|
// lookup table to get shift values from Permedia format definition
|
|
DWORD ShiftLookup[5] = { 0, 0, 1, 0, 2};
|
|
|
|
//@@BEGIN_DDKSPLIT
|
|
#if DX7_ALPHABLT
|
|
//---------------------------------------------------------------------------
|
|
// BOOL Intersect
|
|
//
|
|
// Function:
|
|
// Check the integration of two input rectangles (RECTL* pRcl1,
|
|
// RECTL* pRcl2) and set the intersection result in (RECTL* pRclResult)
|
|
//
|
|
// Return:
|
|
// TRUE---If 'prcl1' and 'prcl2' intersect. The intersection will be in
|
|
// 'prclResult'
|
|
// FALSE--If they don't intersect. 'prclResult' is undefined.
|
|
//
|
|
//---------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
Intersect(RECTL* pRcl1,
|
|
RECT* pRcl2,
|
|
RECTL* pRclResult)
|
|
{
|
|
pRclResult->left = max(pRcl1->left, pRcl2->left);
|
|
pRclResult->right = min(pRcl1->right, pRcl2->right);
|
|
|
|
//
|
|
// Check if there is a horizontal intersection
|
|
//
|
|
if ( pRclResult->left < pRclResult->right )
|
|
{
|
|
pRclResult->top = max(pRcl1->top, pRcl2->top);
|
|
pRclResult->bottom = min(pRcl1->bottom, pRcl2->bottom);
|
|
|
|
//
|
|
// Check if there a vertical intersection
|
|
//
|
|
if (pRclResult->top < pRclResult->bottom)
|
|
return(TRUE);
|
|
|
|
}
|
|
|
|
//
|
|
// Return FALSE if there is no intersection
|
|
//
|
|
return(FALSE);
|
|
}// Intersect()
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// IsDstRectClipped
|
|
//
|
|
// check if the destination rectangle of a blit is clipped by the given clip
|
|
// rectangles. The function takes the rectangles as is and there can be cases
|
|
// where a dest. rectangle is not clipped, but do not detect it...
|
|
//
|
|
// pDstRect---destination rectangle for blt
|
|
// iClipRects-number of clip regions
|
|
// pClipRects-clipping regions
|
|
//
|
|
//Return:
|
|
// TRUE---dest rectangle is clipped
|
|
// FALSE--dest rectangle is not clipped
|
|
//-----------------------------------------------------------------------------
|
|
|
|
BOOL
|
|
IsDstRectClipped(RECTL *pDstRect,
|
|
INT iClipRects,
|
|
RECT *pClipRects)
|
|
{
|
|
INT i;
|
|
RECTL rClippedRect;
|
|
|
|
for ( i=0; i<iClipRects; i++)
|
|
{
|
|
if (Intersect( pDstRect, &pClipRects[i], &rClippedRect))
|
|
{
|
|
if (pDstRect->left==rClippedRect.left &&
|
|
pDstRect->right==rClippedRect.right &&
|
|
pDstRect->top==rClippedRect.top &&
|
|
pDstRect->bottom==rClippedRect.bottom
|
|
)
|
|
{
|
|
// dest rect is not clipped!!!
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
#endif
|
|
//@@END_DDKSPLIT
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// DdPermediaBlt
|
|
//
|
|
// implements DirectDraw Blt callback
|
|
//
|
|
// lpBlt----structure for passing information to DDHAL Blt
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
DWORD CALLBACK
|
|
DdBlt( LPDDHAL_BLTDATA lpBlt )
|
|
{
|
|
PPDev ppdev=(PPDev)lpBlt->lpDD->dhpdev;
|
|
PERMEDIA_DEFS(ppdev);
|
|
|
|
DWORD dwWindowBase;
|
|
RECTL rSrc;
|
|
RECTL rDest;
|
|
DWORD dwFlags;
|
|
LONG lPixPitchDest;
|
|
LONG lPixPitchSrc;
|
|
HRESULT ddrval;
|
|
LPDDRAWI_DDRAWSURFACE_LCL pSrcLcl;
|
|
LPDDRAWI_DDRAWSURFACE_LCL pDestLcl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL pSrcGbl;
|
|
LPDDRAWI_DDRAWSURFACE_GBL pDestGbl;
|
|
PermediaSurfaceData* pPrivateSource;
|
|
PermediaSurfaceData* pPrivateDest;
|
|
|
|
pDestLcl = lpBlt->lpDDDestSurface;
|
|
pSrcLcl = lpBlt->lpDDSrcSurface;
|
|
|
|
DBG_DD((2,"DDraw: Blt, ppdev: 0x%x",ppdev));
|
|
|
|
pDestGbl = pDestLcl->lpGbl;
|
|
pPrivateDest= (PermediaSurfaceData*)pDestGbl->dwReserved1;
|
|
|
|
DD_CHECK_PRIMARY_SURFACE_DATA(pDestLcl,pPrivateDest);
|
|
|
|
DBG_DD((10, "Dest Surface:"));
|
|
DUMPSURFACE(10, pDestLcl, NULL);
|
|
|
|
ULONG ulDestPixelShift=DDSurf_GetPixelShift(pDestLcl);
|
|
|
|
dwFlags = lpBlt->dwFlags;
|
|
|
|
// For the future, drivers should ignore the DDBLT_ASYNC
|
|
// flag, because its hardly used by applications and
|
|
// nowadays drivers can queue up lots of blits, so that
|
|
// the applications do not have to wait for it.
|
|
|
|
// get local copy of src and dest rect
|
|
rSrc = lpBlt->rSrc;
|
|
rDest = lpBlt->rDest;
|
|
|
|
// Switch to DirectDraw context
|
|
DDCONTEXT;
|
|
|
|
if (DDSurf_BitDepth(pDestLcl)==24)
|
|
{
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
|
|
dwWindowBase = (DWORD)((UINT_PTR)(pDestGbl->fpVidMem) >>
|
|
ulDestPixelShift);
|
|
|
|
// get pitch for destination in pixels
|
|
lPixPitchDest = pDestGbl->lPitch >> ulDestPixelShift;
|
|
|
|
if (dwFlags & DDBLT_ROP)
|
|
{
|
|
|
|
if ((lpBlt->bltFX.dwROP >> 16) != (SRCCOPY >> 16))
|
|
{
|
|
DBG_DD((1,"DDraw:Blt:BLT ROP case not supported!"));
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
|
|
LONG srcOffset;
|
|
|
|
DBG_DD((3,"DDBLT_ROP: SRCCOPY"));
|
|
|
|
if (pSrcLcl != NULL)
|
|
{
|
|
pSrcGbl = pSrcLcl->lpGbl;
|
|
|
|
pPrivateSource = (PermediaSurfaceData*)pSrcGbl->dwReserved1;
|
|
|
|
DD_CHECK_PRIMARY_SURFACE_DATA(pSrcLcl,pPrivateSource);
|
|
|
|
DBG_DD((10, "Source Surface:"));
|
|
DUMPSURFACE(10, pSrcLcl, NULL);
|
|
}
|
|
else
|
|
{
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
|
|
if (DDSurf_BitDepth(pSrcLcl)==24)
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
|
|
// determine src pitch in pixels
|
|
lPixPitchSrc = pSrcGbl->lPitch >> ulDestPixelShift;
|
|
|
|
|
|
// Operation is System -> Video memory blit,
|
|
// as a texture download or an image download.
|
|
if ((pSrcLcl->ddsCaps.dwCaps & DDSCAPS_SYSTEMMEMORY) &&
|
|
(pDestLcl->ddsCaps.dwCaps & DDSCAPS_VIDEOMEMORY))
|
|
{
|
|
ASSERTDD(!(pDestLcl->ddsCaps.dwCaps & DDSCAPS_NONLOCALVIDMEM),
|
|
"unsupported texture download to AGP memory");
|
|
|
|
if ((pDestLcl->lpSurfMore->ddsCapsEx.dwCaps2 &
|
|
DDSCAPS2_TEXTUREMANAGE)
|
|
&& (NULL != pPrivateDest)
|
|
)
|
|
{
|
|
// texture download
|
|
|
|
DBG_DD((3,"SYSMEM->MANAGED MEM Blit"
|
|
"(texture to system memory)"));
|
|
|
|
pPrivateDest->dwFlags |= P2_SURFACE_NEEDUPDATE;
|
|
SysMemToSysMemSurfaceCopy(
|
|
pSrcGbl->fpVidMem,
|
|
pSrcGbl->lPitch,
|
|
DDSurf_BitDepth(pSrcLcl),
|
|
pDestGbl->fpVidMem,
|
|
pDestGbl->lPitch,
|
|
DDSurf_BitDepth(pDestLcl),
|
|
&rSrc,
|
|
&rDest);
|
|
|
|
goto BltDone;
|
|
}
|
|
else
|
|
if (pPrivateDest!=NULL)
|
|
{
|
|
if ( (pDestLcl->ddsCaps.dwCaps & DDSCAPS_TEXTURE) &&
|
|
((rSrc.right-rSrc.left)==(LONG)pSrcGbl->wWidth) &&
|
|
((rSrc.bottom-rSrc.top)==(LONG)pSrcGbl->wHeight)
|
|
)
|
|
{
|
|
//
|
|
// patched texture download can only be done
|
|
// when the texture is downloaded as a whole!
|
|
//
|
|
|
|
DBG_DD((3,"SYSMEM->VIDMEM Blit (texture to videomemory)"));
|
|
|
|
PermediaPatchedTextureDownload(
|
|
ppdev,
|
|
pPrivateDest,
|
|
pSrcGbl->fpVidMem,
|
|
pSrcGbl->lPitch,
|
|
&rSrc,
|
|
pDestGbl->fpVidMem,
|
|
pDestGbl->lPitch,
|
|
&rDest);
|
|
}
|
|
else
|
|
{
|
|
// Image download
|
|
|
|
DBG_DD((3,"SYSMEM->VIDMEM Blit (system to videomemory)"));
|
|
|
|
PermediaPackedDownload(
|
|
ppdev,
|
|
pPrivateDest,
|
|
pSrcLcl,
|
|
&rSrc,
|
|
pDestLcl,
|
|
&rDest);
|
|
}
|
|
goto BltDone;
|
|
} else
|
|
{
|
|
DBG_DD((0,"DDraw: Blt, privatedest invalid"));
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
}
|
|
|
|
if (pPrivateSource == NULL ||
|
|
pPrivateDest == NULL)
|
|
{
|
|
DBG_DD((0,"DDraw: Blt, privatesource or dest invalid"));
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
|
|
BOOL bNonLocalToVideo=FALSE;
|
|
|
|
// set base of source
|
|
if ( DDSCAPS_NONLOCALVIDMEM & pSrcLcl->ddsCaps.dwCaps)
|
|
{
|
|
// turn on AGP bus texture source
|
|
srcOffset = (LONG) DD_AGPSURFACEPHYSICAL(pSrcGbl);
|
|
srcOffset |= 1 << 30;
|
|
|
|
bNonLocalToVideo=TRUE;
|
|
|
|
} else
|
|
{
|
|
srcOffset = (LONG)((pSrcGbl->fpVidMem) >>
|
|
pPrivateSource->SurfaceFormat.PixelSize);
|
|
}
|
|
|
|
// Operation is YUV->RGB conversion
|
|
if ((pPrivateSource != NULL) &&
|
|
(pPrivateSource->SurfaceFormat.Format == PERMEDIA_YUV422) &&
|
|
(pPrivateSource->SurfaceFormat.FormatExtension
|
|
== PERMEDIA_YUV422_EXTENSION))
|
|
{
|
|
DBG_DD((3,"YUV to RGB blt"));
|
|
|
|
// We are only doing blits from YUV422 to RGB !
|
|
|
|
if (pPrivateDest->SurfaceFormat.Format != PERMEDIA_YUV422)
|
|
{
|
|
DBG_DD((4,"Blitting from Source YUV to RGB"));
|
|
|
|
// YUV to RGB blt
|
|
PermediaYUVtoRGB( ppdev,
|
|
&lpBlt->bltFX,
|
|
pPrivateDest,
|
|
pPrivateSource,
|
|
&rDest,
|
|
&rSrc,
|
|
dwWindowBase,
|
|
srcOffset);
|
|
|
|
goto BltDone;
|
|
}
|
|
else
|
|
{
|
|
DBG_DD((0,"Couldn't handle YUV to YUV blt"));
|
|
|
|
lpBlt->ddRVal = DD_OK;
|
|
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
}
|
|
|
|
ASSERTDD(DDSurf_BitDepth(pSrcLcl)==DDSurf_BitDepth(pDestLcl),
|
|
"Blt between surfaces of different"
|
|
"color depths are not supported");
|
|
|
|
BOOL bMirror=(dwFlags & DDBLT_DDFX)==DDBLT_DDFX;
|
|
if (bMirror)
|
|
{
|
|
bMirror= (lpBlt->bltFX.dwDDFX & DDBLTFX_MIRRORUPDOWN) ||
|
|
(lpBlt->bltFX.dwDDFX & DDBLTFX_MIRRORLEFTRIGHT);
|
|
}
|
|
BOOL bStretched=((rSrc.right - rSrc.left) !=
|
|
(rDest.right - rDest.left) ||
|
|
(rSrc.bottom - rSrc.top) !=
|
|
(rDest.bottom - rDest.top));
|
|
|
|
// Is it a colorkey blt?
|
|
if (dwFlags & DDBLT_KEYSRCOVERRIDE)
|
|
{
|
|
DBG_DD((3,"DDBLT_KEYSRCOVERRIDE"));
|
|
|
|
// If the surface sizes don't match, then we are stretching.
|
|
if (bStretched || bMirror)
|
|
{
|
|
PermediaStretchCopyChromaBlt( ppdev,
|
|
lpBlt,
|
|
pPrivateDest,
|
|
pPrivateSource,
|
|
&rDest,
|
|
&rSrc,
|
|
dwWindowBase,
|
|
srcOffset);
|
|
}
|
|
else
|
|
{
|
|
PermediaSourceChromaBlt( ppdev,
|
|
lpBlt,
|
|
pPrivateDest,
|
|
pPrivateSource,
|
|
&rDest,
|
|
&rSrc,
|
|
dwWindowBase,
|
|
srcOffset);
|
|
}
|
|
|
|
goto BltDone;
|
|
|
|
}
|
|
else
|
|
{
|
|
// If the surface sizes don't match, then we are stretching.
|
|
// Also the blits from Nonlocal- to Videomemory have to go through
|
|
// the texture unit!
|
|
if ( bStretched || bMirror || bNonLocalToVideo)
|
|
{
|
|
DBG_DD((3,"DDBLT_ROP: STRETCHCOPYBLT OR "
|
|
"MIRROR OR BOTH OR AGPVIDEO"));
|
|
|
|
PermediaStretchCopyBlt( ppdev,
|
|
lpBlt,
|
|
pPrivateDest,
|
|
pPrivateSource,
|
|
&rDest,
|
|
&rSrc,
|
|
dwWindowBase,
|
|
srcOffset);
|
|
}
|
|
else
|
|
{
|
|
DBG_DD((3,"DDBLT_ROP: COPYBLT %08lx %08lx %08lx",
|
|
pSrcGbl->fpVidMem,pDestGbl->fpVidMem,ulDestPixelShift));
|
|
|
|
// Work out the source offset
|
|
// (offset in pixels from dst to src)
|
|
srcOffset = (LONG)((pSrcGbl->fpVidMem - pDestGbl->fpVidMem)
|
|
>> ulDestPixelShift);
|
|
// For some reason, the user might want
|
|
// to do a conversion on the data as it is
|
|
// blitted from VRAM->VRAM by turning on Patching.
|
|
// If Surf1Patch XOR Surf2Patch then
|
|
// do a special blit that isn't packed and does patching.
|
|
if (((pPrivateDest->dwFlags & P2_CANPATCH) ^
|
|
(pPrivateSource->dwFlags & P2_CANPATCH))
|
|
& P2_CANPATCH)
|
|
{
|
|
DBG_DD((4,"Doing Patch-Conversion!"));
|
|
|
|
PermediaPatchedCopyBlt( ppdev,
|
|
lPixPitchDest,
|
|
lPixPitchSrc,
|
|
pPrivateDest,
|
|
pPrivateSource,
|
|
&rDest,
|
|
&rSrc,
|
|
dwWindowBase,
|
|
srcOffset);
|
|
}
|
|
else
|
|
{
|
|
PermediaPackedCopyBlt( ppdev,
|
|
lPixPitchDest,
|
|
lPixPitchSrc,
|
|
pPrivateDest,
|
|
pPrivateSource,
|
|
&rDest,
|
|
&rSrc,
|
|
dwWindowBase,
|
|
srcOffset);
|
|
}
|
|
}
|
|
goto BltDone;
|
|
}
|
|
|
|
}
|
|
else if (pPrivateDest==NULL)
|
|
{
|
|
DBG_DD((0,"Private Surface data invalid!"));
|
|
DUMPSURFACE(0, pDestLcl, NULL);
|
|
} else if (dwFlags & DDBLT_COLORFILL)
|
|
{
|
|
DBG_DD((3,"DDBLT_COLORFILL: Color=0x%x", lpBlt->bltFX.dwFillColor));
|
|
if (pDestLcl->lpSurfMore->ddsCapsEx.dwCaps2 &
|
|
DDSCAPS2_TEXTUREMANAGE)
|
|
{
|
|
PermediaClearManagedSurface(pPrivateDest->SurfaceFormat.PixelSize,
|
|
&rDest,
|
|
pDestGbl->fpVidMem,
|
|
pDestGbl->lPitch,
|
|
lpBlt->bltFX.dwFillColor);
|
|
pPrivateDest->dwFlags |= P2_SURFACE_NEEDUPDATE;
|
|
}
|
|
else
|
|
{
|
|
PermediaFastClear( ppdev,
|
|
pPrivateDest,
|
|
&rDest,
|
|
dwWindowBase,
|
|
lpBlt->bltFX.dwFillColor);
|
|
}
|
|
}
|
|
else if (dwFlags & DDBLT_DEPTHFILL)
|
|
{
|
|
DBG_DD((3,"DDBLT_DEPTHFILL: Value=0x%x", lpBlt->bltFX.dwFillColor));
|
|
|
|
// Work out the window base for the LB clear, acount for the depth size
|
|
dwWindowBase = (DWORD)((UINT_PTR)(pDestGbl->fpVidMem)
|
|
>> __PERMEDIA_16BITPIXEL);
|
|
|
|
// Call the LB Solid Fill Function.
|
|
PermediaFastLBClear( ppdev,
|
|
pPrivateDest,
|
|
&rDest,
|
|
dwWindowBase,
|
|
lpBlt->bltFX.dwFillColor);
|
|
}
|
|
else
|
|
{
|
|
DBG_DD((1,"DDraw:Blt:Blt case not supported %08lx", dwFlags));
|
|
return DDHAL_DRIVER_NOTHANDLED;
|
|
}
|
|
|
|
BltDone:
|
|
|
|
lpBlt->ddRVal = DD_OK;
|
|
return DDHAL_DRIVER_HANDLED;
|
|
|
|
} // DdBlt ()
|
|
|