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.
 
 
 
 
 
 

4213 lines
167 KiB

/******************************Module*Header*******************************\
* Module Name: COPYBITS.c
*
* Author: Noel VanHook
* Date: May. 31, 1995
* Purpose: Handle calls to DrvCopyBits
*
* Copyright (c) 1997 Cirrus Logic, Inc.
*
* $Log: X:/log/laguna/nt35/displays/cl546x/COPYBITS.C $
*
* Rev 1.50 Mar 04 1998 15:22:54 frido
* Added new shadow macros.
*
* Rev 1.49 Feb 25 1998 16:43:48 frido
* Fixed a 16-bpp color translation problem for NT 5.0.
*
* Rev 1.48 Feb 24 1998 13:19:10 frido
* Removed a few warning messages for NT 5.0.
*
* Rev 1.47 Dec 10 1997 13:29:54 frido
* Merged from 1.62 branch.
*
* Rev 1.46.1.0 Nov 10 1997 14:58:46 frido
* PDR#10893: With monochrome color translations in 8-bpp (palette) NT
* decides that a 2-color translation table with values 0 and 1 is a TRIVIAL
* translation table. But this breaks our assumption that the background is
* always black (0) and the foreground if white (FF). Lucky for us NT sets
* an extra bit in this case: the translation table is both TRIVIAL and has a
* TABLE.
*
* Rev 1.46 Nov 04 1997 17:36:58 frido
* Fixed 8-bpp path when no color translation is required.
*
* Rev 1.45 Nov 04 1997 09:41:10 frido
* Added COLOR_TRANSLATE switches around hardware color translation code.
* Removed unaccessed local variables.
*
* Rev 1.44 Nov 03 1997 15:09:24 frido
* Added REQUIRE and WRITE_STRING macros.
*
* Rev 1.43 15 Oct 1997 12:02:26 noelv
* Added host to screen color translation
*
* Rev 1.42 08 Aug 1997 17:23:34 FRIDO
*
* Updatded SWAT7 code for monochrome hardware bug.
*
* Rev 1.41 25 Jun 1997 16:01:36 noelv
* Check for NULL translation table before using it.
*
* Rev 1.40 12 Jun 1997 14:46:12 noelv
* Frido's optimized workaround for MONO HOSTDATA bug (SWAT7)
* SWAT:
* SWAT: Rev 1.3 06 Jun 1997 10:42:34 frido
* SWAT: Changed 896 pixel width into 888.
* SWAT:
* SWAT: Rev 1.2 05 Jun 1997 14:48:14 frido
* SWAT: Added SWAT7 code (monochrome bitblt cut-off).
*
* Rev 1.39 08 Apr 1997 12:14:16 einkauf
*
* add SYNC_W_3D to coordinate MCD/2D HW access
*
* Rev 1.38 21 Mar 1997 10:54:16 noelv
*
* Combined 'do_flag' and 'sw_test_flag' together into 'pointer_switch'
*
* Rev 1.37 19 Feb 1997 13:14:50 noelv
* Moved default xlate table to xlate.c
*
* Rev 1.36 06 Feb 1997 10:37:38 noelv
*
* Put device to device stuff in it's own file.
*
* Rev 1.35 28 Jan 1997 11:13:42 noelv
*
* Removed extra dword requirements from 5465 driver.
*
* Rev 1.34 23 Jan 1997 17:26:36 bennyn
* Modified to support 5465 DD
*
* Rev 1.33 23 Jan 1997 11:26:10 noelv
*
* Modified the '62 workaround to only happen on the '62
*
* Rev 1.32 17 Jan 1997 10:10:30 noelv
* Workaround (punt) for HOSTDATA lockup on '62
*
* Rev 1.31 18 Dec 1996 11:35:30 noelv
* Official workaround for mono hostdata bug.
*
* Rev 1.30 17 Dec 1996 17:05:48 SueS
* Added test for writing to log file based on cursor at (0,0). Added more
* information to the log file.
*
* Rev 1.29 11 Dec 1996 14:18:54 noelv
*
* Punt 24bpp mono host to screen with rop=66 (hw bug?)
*
* Rev 1.28 26 Nov 1996 10:47:34 SueS
* Changed WriteLogFile parameters for buffering.
*
* Rev 1.27 13 Nov 1996 17:21:38 SueS
* Changed WriteFile calls to WriteLogFile. Ifdef'ed out YUVBlt code
* if USE_ASM is turned off.
*
* Rev 1.26 04 Oct 1996 16:52:00 bennyn
*
* Added DirectDraw YUV support
*
* Rev 1.25 06 Sep 1996 09:14:46 noelv
*
* Cleaned up NULL driver code.
*
* Rev 1.24 20 Aug 1996 11:03:20 noelv
* Bugfix release from Frido 8-19-96
*
* Rev 1.3 18 Aug 1996 20:39:08 frido
* Changed DrvCopyBits' detection of memory bitmaps. This fixes some GPF's.
*
* Rev 1.2 17 Aug 1996 13:18:14 frido
* New release from Bellevue.
*
* Rev 1.1 15 Aug 1996 11:44:08 frido
* Added precompiled header.
*
* Rev 1.0 14 Aug 1996 17:16:16 frido
* Initial revision.
*
* Rev 1.22 28 May 1996 15:11:18 noelv
* Updated data logging.
*
* Rev 1.21 24 Apr 1996 20:41:46 noelv
* Fixed syntax error in C code (not used when using inline assembler)
*
* Rev 1.20 16 Apr 1996 22:48:42 noelv
* accelerated color xlate for device to device.
*
* Rev 1.22 15 Apr 1996 17:26:46 frido
* Added color translation in DeviceToDevice.
*
* Rev 1.21 12 Apr 1996 11:27:00 frido
* Fixed a type in DeviceToHost24.
*
* Rev 1.20 08 Apr 1996 16:45:08 frido
* Added call to PuntBitBlt.
* Added check for translation in ScreenToHost.
* Added SolidBrush cache.
*
* Rev 1.19 04 Apr 1996 09:57:10 frido
* Added test for bitmap format in ScreenToHost.
*
* Rev 1.18 30 Mar 1996 22:12:16 frido
* Refined checking for invalid translation flags.
*
* Rev 1.17 29 Mar 1996 14:53:52 frido
* Fixed problem with grayed icons.
*
* Rev 1.16 27 Mar 1996 16:56:14 frido
* Added return values to Do... routines.
* Added check for undocumented translation flags.
* Added check for translation tables.
* Removed OP0 field in BLTDEF.
*
* Rev 1.15 25 Mar 1996 12:03:58 frido
* Changed #ifdef frido into #if frido.
*
* Rev 1.14 25 Mar 1996 11:53:30 frido
* Removed assembly for DoDeviceToDevice.
*
* Rev 1.13 25 Mar 1996 11:52:38 frido
* Bellevue 102B03.
*
* Rev 1.9 20 Mar 1996 17:16:08 BENNYN
* Fixed the BPR910 & BPR920 Phostone problems
*
* Rev 1.8 20 Mar 1996 14:17:42 bennyn
*
*
* Rev 1.7 19 Mar 1996 11:37:32 noelv
*
* Added data logging.
*
* Rev 1.6 14 Mar 1996 09:38:46 andys
*
* Added if def on DoDeviceToDevice
*
* Rev 1.5 07 Mar 1996 18:20:58 bennyn
* Removed read/modify/write on CONTROL reg
*
* Rev 1.4 06 Mar 1996 12:51:30 noelv
* Frido ver 19b
*
* Rev 1.9 06 Mar 1996 14:59:06 frido
* Added 'striping' wide bitmaps in 16-bpp and higher.
*
* Rev 1.8 04 Mar 1996 20:22:50 frido
* Cached grCONTROL register.
*
* Rev 1.7 01 Mar 1996 17:48:12 frido
* Added in-line assembly.
*
* Rev 1.6 29 Feb 1996 20:23:46 frido
* Added 8-bpp source translation in 24- and 32-bpp HostToScreen.
*
* Rev 1.5 28 Feb 1996 22:35:20 frido
* Added 8-bpp source translation in 16-bpp HostToScreen.
*
* Rev 1.4 27 Feb 1996 16:38:06 frido
* Added device bitmap store/restore.
*
* Rev 1.3 26 Feb 1996 23:37:08 frido
* Added comments.
* Rewritten ScreenToHost and HostToScreen routines.
* Removed several other bugs.
*
\**************************************************************************/
#include "precomp.h"
#include "SWAT.h"
#define COPYBITS_DBG_LEVEL 1
#if LOG_CALLS
void LogCopyBits(
int acc,
SURFOBJ* psoSrc,
SURFOBJ* psoDest,
CLIPOBJ* pco,
XLATEOBJ* pxlo);
#else
#define LogCopyBits(acc, psoSrc, psoDest, pco, pxlo)
#endif
//
// Top level BLT functions.
//
#if (defined(i386) && USE_ASM)
BOOL YUVBlt(SURFOBJ* psoTrg, SURFOBJ* psoSrc, CLIPOBJ* pco,
XLATEOBJ* pxlo, RECTL* prclTrg, POINTL* pptlSrc);
#endif
BOOL CopyDeviceBitmap(SURFOBJ* psoTrg, SURFOBJ* psoSrc, CLIPOBJ* pco,
XLATEOBJ* pxlo, RECTL* prclTrg, POINTL* pptlSrc,
ULONG ulDRAWBLTDEF, COPYFN* pfn);
BOOL DoDeviceToDevice(SURFOBJ* psoTrg, SURFOBJ* psoSrc, XLATEOBJ* pxlo,
RECTL* prclTrg, POINTL* pptlSrc, ULONG ulDRAWBLTDEF);
BOOL PuntBitBlt(SURFOBJ* psoDest, SURFOBJ* psoSrc, SURFOBJ* psoMask,
CLIPOBJ* pco, XLATEOBJ* pxlo, RECTL* prclDest, POINTL* pptlSrc,
POINTL* pptlMask, BRUSHOBJ* pbo, POINTL* pptlBrush, ROP4 rop4);
BOOL DoDeviceToDeviceWithXlate(SURFOBJ* psoTrg, SURFOBJ* psoSrc, ULONG* pulXlate,
RECTL* prclTrg, POINTL* pptlSrc, ULONG ulDRAWBLTDEF);
#if SOLID_CACHE
VOID CacheSolid(PDEV* ppdev);
#endif
/******************************************************************************\
* *
* DrvCopyBits *
* *
\******************************************************************************/
BOOL DrvCopyBits(
SURFOBJ* psoTrg,
SURFOBJ* psoSrc,
CLIPOBJ* pco,
XLATEOBJ* pxlo,
RECTL* prclTrg,
POINTL* pptlSrc)
{
BOOL fSrc, fDest;
PDEV* ppdev;
#if NULL_COPYBITS
{
if (pointer_switch) return(TRUE);
}
#endif
DISPDBG((COPYBITS_DBG_LEVEL, "DrvCopyBits\n"));
// Determine if the source and target are the screen or a device bitmap. I
// have seen several cases where memory bitmaps are created with the dhpdev
// set to the screen, so we must check if the surface handles to the screen
// match.
fDest = (psoTrg->dhpdev != 0);
if (fDest)
{
// The destination must be either the screen or a device bitmap.
if ((psoTrg->hsurf != ((PDEV*)(psoTrg->dhpdev))->hsurfEng) &&
(psoTrg->iType != STYPE_DEVBITMAP))
{
fDest = FALSE; // The destination is a memory bitmap.
}
}
fSrc = (psoSrc->dhpdev != 0);
if (fSrc)
{
// The source must be either the screen or a device bitmap.
if ((psoSrc->hsurf != ((PDEV*)(psoSrc->dhpdev))->hsurfEng) &&
(psoSrc->iType != STYPE_DEVBITMAP))
{
fSrc = FALSE; // The source is a memory bitmap.
}
}
ppdev = (PDEV*) (fSrc ? psoSrc->dhpdev : (fDest ? psoTrg->dhpdev : NULL));
SYNC_W_3D(ppdev);
#if (defined(i386) && USE_ASM)
if (ppdev->dwLgDevID < CL_GD5465)
{
if (YUVBlt(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc))
return TRUE;
};
#endif
// If the destination is a DIB device bitmap, try copying it into
// off-screen memory.
if ( fDest && // Is destination valid?
(psoTrg->iType == STYPE_DEVBITMAP) && // Is it a device bitmap?
((DSURF*) psoTrg->dhsurf)->pso ) // Has it a surface?
{
if ( !bCreateScreenFromDib(ppdev, (DSURF*) psoTrg->dhsurf) )
{
psoTrg = ((DSURF*) psoTrg->dhsurf)->pso;
fDest = FALSE; // Destination is memory.
}
}
// If the source is a DIB device bitmap, try copying it into off-screen
// memory.
if ( fSrc && // Is source valid?
(psoSrc->iType == STYPE_DEVBITMAP) && // Is it a device bitmap?
((DSURF*) psoSrc->dhsurf)->pso ) // Has it a surface?
{
if ( !bCreateScreenFromDib(ppdev, (DSURF*) psoSrc->dhsurf) )
{
psoSrc = ((DSURF*) psoSrc->dhsurf)->pso;
fSrc = FALSE; // Source is memory.
}
}
if (fDest)
{
// The target is the screen.
if (fSrc)
{
// The source is the screen.
if (CopyDeviceBitmap(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc,
0x000000CC, DoDeviceToDevice))
{
LogCopyBits(0, psoSrc, psoTrg, pco, pxlo);
return(TRUE);
}
}
else if ( (psoSrc->iBitmapFormat <= BMF_8BPP) ||
(psoSrc->iBitmapFormat == psoTrg->iBitmapFormat) )
{
// Ths source is main memory. We only support 1-bpp, 4-bpp, 8-bpp,
// or the device-bpp formats.
if (CopyDeviceBitmap(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc,
0x000000CC, ppdev->pfnHostToScreen))
{
LogCopyBits(0, psoSrc, psoTrg, pco, pxlo);
return(TRUE);
}
}
}
else if (fSrc)
{
// The source is the screen.
if (CopyDeviceBitmap(psoTrg, psoSrc, pco, pxlo, prclTrg, pptlSrc,
0x000000CC, ppdev->pfnScreenToHost))
{
LogCopyBits(0, psoSrc, psoTrg, pco, pxlo);
return(TRUE);
}
}
// We have a memory to memory blit. Let NT handle it!
LogCopyBits(1, psoSrc, psoTrg, pco, pxlo);
return PuntBitBlt(psoTrg, psoSrc, NULL, pco, pxlo, prclTrg, pptlSrc, NULL,
NULL, NULL, 0x0000CCCC);
}
#if LOG_CALLS
// ****************************************************************************
//
// LogCopyBlt()
// This routine is called only from DrvCopyBits()
// Dump information to a file about what is going on in CopyBit land.
//
// ****************************************************************************
void LogCopyBits(
int acc,
SURFOBJ* psoSrc,
SURFOBJ* psoDest,
CLIPOBJ* pco,
XLATEOBJ* pxlo)
{
PPDEV dppdev,sppdev,ppdev;
char buf[256];
int i;
BYTE fg_rop, bg_rop;
ULONG iDComplexity;
dppdev = (PPDEV) (psoDest ? psoDest->dhpdev : 0);
sppdev = (PPDEV) (psoSrc ? psoSrc->dhpdev : 0);
ppdev = dppdev ? dppdev : sppdev;
#if ENABLE_LOG_SWITCH
if (pointer_switch == 0) return;
#endif
i = sprintf(buf,"DCB: ");
WriteLogFile(ppdev->pmfile, buf, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
switch(acc)
{
case 0: // Accelerated
i = sprintf(buf, "ACCL ");
break;
case 1: // Punted
i = sprintf(buf, "PUNT BitBlt ");
break;
default:
i = sprintf(buf, "PUNT unknown ");
break;
}
WriteLogFile(ppdev->pmfile, buf, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
//
// Check the SRC
//
if (psoSrc)
{
if (psoSrc->iType == STYPE_DEVBITMAP)
{
i = sprintf(buf, "Src Id=%p ", psoSrc->dhsurf);
WriteLogFile(ppdev->pmfile, buf, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
if ( ((PDSURF)psoSrc->dhsurf)->pso )
i = sprintf(buf,"S=DH ");
else
i = sprintf(buf,"S=DF ");
}
else if (psoSrc->hsurf == ppdev->hsurfEng)
i = sprintf(buf,"S=S ");
else
i = sprintf(buf,"S=H ");
}
else
i = sprintf(buf,"S=N ");
WriteLogFile(ppdev->pmfile, buf, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
//
// Check the DEST
//
if (psoDest)
{
if (psoDest->iType == STYPE_DEVBITMAP)
{
i = sprintf(buf, "Dst Id=%p ", psoDest->dhsurf);
WriteLogFile(ppdev->pmfile, buf, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
if ( ((PDSURF)psoDest->dhsurf)->pso )
i = sprintf(buf,"D=DH ");
else
i = sprintf(buf,"D=DF ");
}
else if (psoDest->hsurf == ppdev->hsurfEng)
i = sprintf(buf,"D=S ");
else
i = sprintf(buf,"D=H ");
}
else
i = sprintf(buf,"D=N ");
WriteLogFile(ppdev->pmfile, buf, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
//
// Check the type of clipping.
//
iDComplexity = (pco ? pco->iDComplexity : DC_TRIVIAL);
i = sprintf(buf,"C=%s ",
(iDComplexity==DC_TRIVIAL ? "T":
(iDComplexity == DC_RECT ? "R" : "C" )));
WriteLogFile(ppdev->pmfile, buf, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
//
// Type of translation
//
if (!pxlo)
{
i = sprintf(buf,"T=N ");
WriteLogFile(ppdev->pmfile, buf, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
else if (pxlo->flXlate & XO_TRIVIAL)
{
i = sprintf(buf,"T=T ");
WriteLogFile(ppdev->pmfile, buf, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
else
{
i = sprintf(buf,"T=NT ");
WriteLogFile(ppdev->pmfile, buf, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
i = sprintf(buf,"\r\n");
WriteLogFile(ppdev->pmfile, buf, i, ppdev->TxtBuff, &ppdev->TxtBuffIndex);
}
#endif
/*****************************************************************************\
* CopyDeviceBitmap
*
* This is the main entry routine for all bitblt functions. It will dispatch
* the blit to the correct handler and performs the clipping.
*
* On entry: psoTrg Pointer to target surface object.
* psoSrc Pointer to source surface object.
* pco Pointer to clip object.
* pxlo Pointer to translation object.
* prclTrg Destination rectangle.
* pptlSrc Source offset.
* ulDRAWBLTDEF Value for grDRAWBLTDEF register. This value has
* the ROP and the brush flags. It will be filled
* by the dispatch routine.
* pfn Pointer to dispatch function.
*
* Returns: TRUE if successful, FALSE if we cannot handle this blit.
\*****************************************************************************/
BOOL CopyDeviceBitmap(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
CLIPOBJ *pco,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF,
COPYFN *pfn
)
{
// Check for no clipping.
if ( (pco == NULL) || (pco->iDComplexity == DC_TRIVIAL) )
{
return(pfn(psoTrg, psoSrc, pxlo, prclTrg, pptlSrc, ulDRAWBLTDEF));
}
// Check for single rectangle clipping.
else if (pco->iDComplexity == DC_RECT)
{
RECTL rcl;
POINTL ptl;
// Intersect the destination rectangle with the clipping rectangle.
rcl.left = max(prclTrg->left, pco->rclBounds.left);
rcl.top = max(prclTrg->top, pco->rclBounds.top);
rcl.right = min(prclTrg->right, pco->rclBounds.right);
rcl.bottom = min(prclTrg->bottom, pco->rclBounds.bottom);
// Do we have a valid rectangle?
if ( (rcl.left < rcl.right) && (rcl.top < rcl.bottom) )
{
// Setup the source offset.
ptl.x = pptlSrc->x + (rcl.left - prclTrg->left);
ptl.y = pptlSrc->y + (rcl.top - prclTrg->top);
// Dispatch the blit.
return(pfn(psoTrg, psoSrc, pxlo, &rcl, &ptl, ulDRAWBLTDEF));
}
}
// Complex clipping.
else
{
BOOL bMore;
ENUMRECTS8 ce;
RECTL* prcl;
ULONG ulDirClip = CD_ANY;
// If we have a screen to screen blit, we must specify the sorting of
// the rectangles since we must take care not to draw on a destination
// before that destination itself may be used as the source for a blit.
// This only accounts for the same physical surface, not between
// different device bitmaps.
if ( (pfn == DoDeviceToDevice) && (psoSrc->dhsurf == psoTrg->dhsurf) )
{
if (prclTrg->left > pptlSrc->x)
{
ulDirClip =
(prclTrg->top > pptlSrc->y) ? CD_LEFTUP : CD_LEFTDOWN;
}
else
{
ulDirClip =
(prclTrg->top > pptlSrc->y) ? CD_RIGHTUP : CD_RIGHTDOWN;
}
}
// Start the enumeration process.
CLIPOBJ_cEnumStart(pco, FALSE, CT_RECTANGLES, ulDirClip, 0);
do
{
// Get a bunch of clipping rectangles.
bMore = CLIPOBJ_bEnum(pco, sizeof(ce), (ULONG *) &ce);
// Loop through all clipping rectangles.
for (prcl = ce.arcl; ce.c--; prcl++)
{
RECTL rcl;
POINTL ptl;
// Intersect the destination rectangle with the clipping
// rectangle.
rcl.left = max(prclTrg->left, prcl->left);
rcl.top = max(prclTrg->top, prcl->top);
rcl.right = min(prclTrg->right, prcl->right);
rcl.bottom = min(prclTrg->bottom, prcl->bottom);
if ( (rcl.left < rcl.right) && (rcl.top < rcl.bottom) )
{
// Setup the source offset.
ptl.x = pptlSrc->x + (rcl.left - prclTrg->left);
ptl.y = pptlSrc->y + (rcl.top - prclTrg->top);
// Dispatch the blit.
if (!pfn(psoTrg, psoSrc, pxlo, &rcl, &ptl, ulDRAWBLTDEF))
{
return(FALSE);
}
}
}
}
while (bMore);
}
// Always return TRUE.
return(TRUE);
}
/*****************************************************************************\
* *
* 8 - B P P *
* *
\*****************************************************************************/
/*****************************************************************************\
* DoHost8ToDevice
*
* This routine performs a HostToScreen or HostToDevice blit. The host data
* can be either monochrome, 4-bpp, or 8-bpp. Color translation is supported.
*
* On entry: psoTrg Pointer to target surface object.
* psoSrc Pointer to source surface object.
* pxlo Pointer to translation object.
* prclTrg Destination rectangle.
* pptlSrc Source offset.
* ulDRAWBLTDEF Value for grDRAWBLTDEF register. This value has
* the ROP and the brush flags.
\*****************************************************************************/
BOOL DoHost8ToDevice(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF
)
{
POINTL ptlDest, ptlSrc;
SIZEL sizl;
PPDEV ppdev;
PBYTE pBits;
LONG lDelta, i, n, lLeadIn, lExtra;
ULONG *pulXlate;
FLONG flXlate;
// Calculate the source offset.
ptlSrc.x = pptlSrc->x;
ptlSrc.y = pptlSrc->y;
// Determine the destination type and calculate the destination offset.
if (psoTrg->iType == STYPE_DEVBITMAP)
{
PDSURF pdsurf = (PDSURF) psoTrg->dhsurf;
ptlDest.x = prclTrg->left + pdsurf->ptl.x;
ptlDest.y = prclTrg->top + pdsurf->ptl.y;
ppdev = pdsurf->ppdev;
}
else
{
ptlDest.x = prclTrg->left;
ptlDest.y = prclTrg->top;
ppdev = (PPDEV) psoTrg->dhpdev;
}
// Calculate the size of the blit.
sizl.cx = prclTrg->right - prclTrg->left;
sizl.cy = prclTrg->bottom - prclTrg->top;
// Get the source variables and offset into source bits.
lDelta = psoSrc->lDelta;
pBits = (PBYTE)psoSrc->pvScan0 + (ptlSrc.y * lDelta);
/* -----------------------------------------------------------------------
Test for monochrome source.
*/
if (psoSrc->iBitmapFormat == BMF_1BPP)
{
ULONG bgColor, fgColor;
#if SWAT7
SIZEL sizlTotal;
#endif
// Get the pointer to the translation table.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if ( (flXlate & XO_TRIVIAL) && !(flXlate & XO_TABLE) )
{
pulXlate = NULL;
}
else if (flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
// Set background and foreground colors.
if (pulXlate == NULL)
{
bgColor = 0x00000000;
fgColor = 0xFFFFFFFF;
}
else
{
bgColor = pulXlate[0];
fgColor = pulXlate[1];
// Expand the colors.
bgColor |= bgColor << 8;
fgColor |= fgColor << 8;
bgColor |= bgColor << 16;
fgColor |= fgColor << 16;
}
//
// Special case: when we are expanding monochrome sources and we
// already have a colored brush, we must make sure the monochrome color
// translation can be achived by setting the saturation bit (expanding
// 0's to 0 and 1's to 1). If the monochrome source also requires color
// translation, we simply punt this blit back to GDI.
//
if (ulDRAWBLTDEF & 0x00040000)
{
if ( (bgColor == 0x00000000) && (fgColor == 0xFFFFFFFF) )
{
// Enable saturation for source (OP1).
ulDRAWBLTDEF |= 0x00008000;
}
#if SOLID_CACHE
else if ( ((ulDRAWBLTDEF & 0x000F0000) == 0x00070000) &&
ppdev->Bcache )
{
CacheSolid(ppdev);
ulDRAWBLTDEF ^= (0x00070000 ^ 0x00090000);
REQUIRE(4);
LL_BGCOLOR(bgColor, 2);
LL_FGCOLOR(fgColor, 2);
}
#endif
else
{
// Punt this call to the GDI.
return(FALSE);
}
}
else
{
REQUIRE(4);
LL_BGCOLOR(bgColor, 2);
LL_FGCOLOR(fgColor, 2);
}
REQUIRE(9);
#if SWAT7
// Setup the Laguna registers for the blit. We also set the bit swizzle
// bit in the grCONTROL register.
ppdev->grCONTROL |= SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10600000, 2);
sizlTotal = sizl;
while (sizlTotal.cx)
{
sizl.cx = min(sizlTotal.cx, 864);
sizl.cy = sizlTotal.cy;
#if 1 // SWAT: 08/08/97
// In 8-bpp the 5465AD has a hardware bug when 64 < width < 128.
if (sizl.cx > 64 && sizl.cx < 128)
{
sizl.cx = 64;
}
#endif
#endif
// Calculate the source parameters. We are going to DWORD adjust the
// source, so we must setup the source phase.
lLeadIn = ptlSrc.x & 31;
pBits += (ptlSrc.x >> 3) & ~3;
n = (sizl.cx + lLeadIn + 31) >> 5;
#if !SWAT7
// Setup the Laguna registers for the blit. We also set the bit swizzle
// bit in the grCONTROL register.
ppdev->grCONTROL |= SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10600000, 2);
#endif
// Start the blit.
// added REQUIRE above
// REQUIRE(7);
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
// Copy all the bits to the screen, 32-bits at a time. We don't have to
// worry about crossing any boundary since NT is always DWORD aligned.
while (sizl.cy--)
{
WRITE_STRING(pBits, n);
pBits += lDelta;
}
#if SWAT7
sizlTotal.cx -= sizl.cx;
ptlSrc.x += sizl.cx;
ptlDest.x += sizl.cx;
// Reload pBits.
pBits = (PBYTE) psoSrc->pvScan0 + (ptlSrc.y * lDelta);
}
#endif
// Disable the swizzle bit in the grCONTROL register.
ppdev->grCONTROL = ppdev->grCONTROL & ~SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
}
/* -----------------------------------------------------------------------
Test for 4-bpp source.
*/
else if (psoSrc->iBitmapFormat == BMF_4BPP)
{
// Get the pointer to the translation table.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if (flXlate & XO_TRIVIAL)
{
pulXlate = NULL;
}
else if (flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
// Calculate the source parameters. We are going to BYTE adjust the
// source, so we also set the source phase.
lLeadIn = ptlSrc.x & 1;
pBits += ptlSrc.x >> 1;
n = sizl.cx + (ptlSrc.x & 1);
#if ! DRIVER_5465
// Get the number of extra DWORDS per line for the HOSTDATA hardware
// bug.
if (ppdev->dwLgDevID == CL_GD5462)
{
if (MAKE_HD_INDEX(sizl.cx, lLeadIn, ptlDest.x) == 3788)
{
// We have a problem with the HOSTDATA TABLE.
// Punt till we can figure it out.
return FALSE;
}
lExtra = ExtraDwordTable[MAKE_HD_INDEX(sizl.cx, lLeadIn, ptlDest.x)];
}
else
lExtra = 0;
#endif
// Start the blit.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
// If there is no translation table, use the default translation table.
if (pulXlate == NULL)
{
pulXlate = ulXlate;
}
// Now we are ready to copy all the pixels to the hardware.
while (sizl.cy--)
{
BYTE *p = pBits;
BYTE data[4];
// First, we convert 4 pixels at a time to create a 32-bit value to
// write to the hardware.
for (i = n; i >= 4; i -= 4)
{
data[0] = (BYTE) pulXlate[p[0] >> 4];
data[1] = (BYTE) pulXlate[p[0] & 0x0F];
data[2] = (BYTE) pulXlate[p[1] >> 4];
data[3] = (BYTE) pulXlate[p[1] & 0x0F];
REQUIRE(1);
LL32(grHOSTDATA[0], *(DWORD *)data);
p += 2;
}
// Now, write any remaining pixels.
switch (i)
{
case 1:
REQUIRE(1);
LL32(grHOSTDATA[0], pulXlate[p[0] >> 4]);
break;
case 2:
data[0] = (BYTE) pulXlate[p[0] >> 4];
data[1] = (BYTE) pulXlate[p[0] & 0x0F];
REQUIRE(1);
LL32(grHOSTDATA[0], *(DWORD *)data);
break;
case 3:
data[0] = (BYTE) pulXlate[p[0] >> 4];
data[1] = (BYTE) pulXlate[p[0] & 0x0F];
data[2] = (BYTE) pulXlate[p[1] >> 4];
REQUIRE(1);
LL32(grHOSTDATA[0], *(DWORD *)data);
break;
}
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[0], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
/* -----------------------------------------------------------------------
Source is in same color depth as screen.
*/
else
{
//
// If color translation is required, attempt to load the translation
// table into the chip.
//
#if COLOR_TRANSLATE
ULONG UseHWxlate = bCacheXlateTable(ppdev, &pulXlate, psoTrg, psoSrc,
pxlo, (BYTE)(ulDRAWBLTDEF & 0xCC));
#else
if ( (pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL) )
{
pulXlate = NULL;
}
else if (pxlo->flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
#endif
// pulXlate == NULL if there is no color translation is required.
// pulXlate == translation table if color translation is required.
// UseHWxlate == FALSE if the hardware will do the xlate for us.
// UseHWxlate == TRUE if we must do the translation in software.
// If we have invalid translation flags, punt the blit.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if (flXlate & 0x10)
{
return(FALSE);
}
// Calculate the source parameters. We are going to DWORD adjust the
// source, so we also set the source phase.
pBits += ptlSrc.x;
lLeadIn = (DWORD)pBits & 3;
pBits -= lLeadIn;
n = (sizl.cx + lLeadIn + 3) >> 2;
#if !DRIVER_5465
// Get the number of extra DWORDS per line for the HOSTDATA hardware
// bug.
if (ppdev->dwLgDevID == CL_GD5462)
{
if (MAKE_HD_INDEX(sizl.cx, lLeadIn, ptlDest.x) == 3788)
{
// We have a problem with the HOSTDATA TABLE.
// Punt till we can figure it out.
return(FALSE);
}
lExtra =
ExtraDwordTable[MAKE_HD_INDEX(sizl.cx, lLeadIn, ptlDest.x)];
}
else
{
lExtra = 0;
}
#endif
// Setup the Laguna registers.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
// Start the blit.
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
// Test for SW color translation.
#if COLOR_TRANSLATE
if (UseHWxlate)
#else
if (pulXlate == NULL)
#endif
{ // HW color translate, or no translate required.
if (pulXlate)
{
DISPDBG((COPYBITS_DBG_LEVEL, "Host8ToDevice: "
"Attempting HW color translation on 8bpp Host to Screen.\n"));
LL_BLTEXT_XLATE(8, sizl.cx, sizl.cy); // HW xlate.
}
else
{
DISPDBG((COPYBITS_DBG_LEVEL, "Host8ToDevice: "
"No color translation required on 8bpp Host to Screen.\n"));
LL_BLTEXT(sizl.cx, sizl.cy); // No xlate.
}
while (sizl.cy--)
{
// Copy all data in 32-bit. We don't have to worry about
// crossing any boundaries, since within NT everything is DWORD
// aligned.
WRITE_STRING(pBits, n);
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[0], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
else // Software color translation is required.
{
DISPDBG((COPYBITS_DBG_LEVEL, "Host8ToDevice: "
"Attempting SW color translation on 8bpp Host to Screen.\n"));
ASSERTMSG(pulXlate,
"Host8ToDevice: No translation table for SW color translation.\n");
LL_BLTEXT(sizl.cx, sizl.cy);
while (sizl.cy--)
{
BYTE *p = pBits;
// We copy 4 pixels to fill an entire 32-bit DWORD.
for (i = 0; i < n; i++)
{
BYTE data[4];
data[0] = (BYTE) pulXlate[p[0]];
data[1] = (BYTE) pulXlate[p[1]];
data[2] = (BYTE) pulXlate[p[2]];
data[3] = (BYTE) pulXlate[p[3]];
REQUIRE(1);
LL32(grHOSTDATA[0], *(DWORD *)data);
p += 4;
}
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[0], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
}
return(TRUE);
}
/*****************************************************************************\
* DoDeviceToHost8
*
* This routine performs a DeviceToHost for either monochrome or 8-bpp
* destinations.
*
* On entry: psoTrg Pointer to target surface object.
* psoSrc Pointer to source surface object.
* pxlo Pointer to translation object.
* prclTrg Destination rectangle.
* pptlSrc Source offset.
* ulDRAWBLTDEF Value for grDRAWBLTDEF register. This value has
* the ROP and the brush flags.
\*****************************************************************************/
BOOL DoDeviceToHost8(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF
)
{
POINTL ptlSrc;
PPDEV ppdev;
SIZEL sizl;
PBYTE pBits;
#if !S2H_USE_ENGINE
PBYTE pjScreen;
#endif
LONG lDelta;
ULONG i, n;
// Determine the source type and calculate the offset.
if (psoSrc->iType == STYPE_DEVBITMAP)
{
PDSURF pdsurf = (PDSURF)psoSrc->dhsurf;
ppdev = pdsurf->ppdev;
ptlSrc.x = pptlSrc->x + pdsurf->ptl.x;
ptlSrc.y = pptlSrc->y + pdsurf->ptl.y;
}
else
{
ppdev = (PPDEV)psoSrc->dhpdev;
ptlSrc.x = pptlSrc->x;
ptlSrc.y = pptlSrc->y;
}
// Calculate the size of the blit.
sizl.cx = prclTrg->right - prclTrg->left;
sizl.cy = prclTrg->bottom - prclTrg->top;
// Calculate the destination variables.
lDelta = psoTrg->lDelta;
pBits = (PBYTE)psoTrg->pvScan0 + (prclTrg->top * lDelta);
#if S2H_USE_ENGINE
// Setup the Laguna registers.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x20100000, 0);
LL_OP0(0, 0);
#else
// Calculate the screen address.
pjScreen = ppdev->pjScreen + ptlSrc.x + ptlSrc.y * ppdev->lDeltaScreen;
// Wait for the hardware to become idle.
while (LLDR_SZ(grSTATUS) != 0) ;
#endif
// Test for monochrome destination.
if (psoTrg->iBitmapFormat == BMF_1BPP)
{
BYTE data, leftMask, rightMask, fgColor;
DWORD *pulXlate;
LONG leftCount, rightCount, leftSkip;
#if S2H_USE_ENGINE
BYTE pixels[4];
#endif
// Calculate the monochrome masks.
pBits += prclTrg->left >> 3;
leftSkip = prclTrg->left & 7;
leftCount = (8 - leftSkip) & 7;
leftMask = 0xFF >> leftSkip;
rightCount = prclTrg->right & 7;
rightMask = 0xFF << (8 - rightCount);
// If we only have pixels in one byte, we combine rightMask with
// leftMask and set the routines to skip everything but the rightMask.
if (leftCount > sizl.cx)
{
rightMask &= leftMask;
leftMask = 0xFF;
n = 0;
}
else
{
n = (sizl.cx - leftCount) >> 3;
}
// Lookup the foreground color in the translation table. We scan from
// the back since in most cases it will be entry 255.
pulXlate = pxlo->pulXlate;
for (fgColor = 255; pulXlate[fgColor] != 1; fgColor--);
#if S2H_USE_ENGINE
// Start the blit.
LL_OP1(ptlSrc.x - leftSkip, ptlSrc.y);
LL_BLTEXT(sizl.cx + leftSkip, sizl.cy);
#else
pjScreen -= leftSkip;
#endif
while (sizl.cy--)
{
PBYTE pDest = pBits;
#if !S2H_USE_ENGINE
PBYTE pSrc = pjScreen;
#endif
// If we have a left mask specified, we get the pixels and store
// them with the destination.
if (leftMask != 0xFF)
{
data = 0;
#if S2H_USE_ENGINE
*(ULONG *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (pixels[0] == fgColor) data |= 0x80;
if (pixels[1] == fgColor) data |= 0x40;
if (pixels[2] == fgColor) data |= 0x20;
if (pixels[3] == fgColor) data |= 0x10;
*(ULONG *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (pixels[0] == fgColor) data |= 0x08;
if (pixels[1] == fgColor) data |= 0x04;
if (pixels[2] == fgColor) data |= 0x02;
if (pixels[3] == fgColor) data |= 0x01;
#else
if (pSrc[0] == fgColor) data |= 0x80;
if (pSrc[1] == fgColor) data |= 0x40;
if (pSrc[2] == fgColor) data |= 0x20;
if (pSrc[3] == fgColor) data |= 0x10;
if (pSrc[4] == fgColor) data |= 0x08;
if (pSrc[5] == fgColor) data |= 0x04;
if (pSrc[6] == fgColor) data |= 0x02;
if (pSrc[7] == fgColor) data |= 0x01;
pSrc += 8;
#endif
*pDest++ = (*pDest & ~leftMask) | (data & leftMask);
}
// Translate all pixels that don't require masking.
for (i = 0; i < n; i++)
{
data = 0;
#if S2H_USE_ENGINE
*(ULONG *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (pixels[0] == fgColor) data |= 0x80;
if (pixels[1] == fgColor) data |= 0x40;
if (pixels[2] == fgColor) data |= 0x20;
if (pixels[3] == fgColor) data |= 0x10;
*(ULONG *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (pixels[0] == fgColor) data |= 0x08;
if (pixels[1] == fgColor) data |= 0x04;
if (pixels[2] == fgColor) data |= 0x02;
if (pixels[3] == fgColor) data |= 0x01;
#else
if (pSrc[0] == fgColor) data |= 0x80;
if (pSrc[1] == fgColor) data |= 0x40;
if (pSrc[2] == fgColor) data |= 0x20;
if (pSrc[3] == fgColor) data |= 0x10;
if (pSrc[4] == fgColor) data |= 0x08;
if (pSrc[5] == fgColor) data |= 0x04;
if (pSrc[6] == fgColor) data |= 0x02;
if (pSrc[7] == fgColor) data |= 0x01;
pSrc += 8;
#endif
*pDest++ = data;
}
// If we have a right mask specified, we get the pixels and store
// them with the destination.
if (rightMask != 0x00)
{
data = 0;
#if S2H_USE_ENGINE
*(ULONG *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (pixels[0] == fgColor) data |= 0x80;
if (pixels[1] == fgColor) data |= 0x40;
if (pixels[2] == fgColor) data |= 0x20;
if (pixels[3] == fgColor) data |= 0x10;
*(ULONG *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (pixels[0] == fgColor) data |= 0x08;
if (pixels[1] == fgColor) data |= 0x04;
if (pixels[2] == fgColor) data |= 0x02;
if (pixels[3] == fgColor) data |= 0x01;
#else
if (pSrc[0] == fgColor) data |= 0x80;
if (pSrc[1] == fgColor) data |= 0x40;
if (pSrc[2] == fgColor) data |= 0x20;
if (pSrc[3] == fgColor) data |= 0x10;
if (pSrc[4] == fgColor) data |= 0x08;
if (pSrc[5] == fgColor) data |= 0x04;
if (pSrc[6] == fgColor) data |= 0x02;
if (pSrc[7] == fgColor) data |= 0x01;
#endif
*pDest = (*pDest & ~rightMask) | (data & rightMask);
}
// Next line.
#if !S2H_USE_ENGINE
pjScreen += ppdev->lDeltaScreen;
#endif
pBits += lDelta;
}
}
// We only support destination bitmaps with the same color depth and we
// do not support any color translation.
else if ( (psoTrg->iBitmapFormat != BMF_8BPP) ||
(pxlo && !(pxlo->flXlate & XO_TRIVIAL)) )
{
return(FALSE);
}
/*
If the GetPixel routine is being called, we get here with both cx and
cy set to 1 and the ROP to 0xCC (source copy). In this special case we
read the pixel directly from memory. Of course, we must be sure the
blit engine is finished working since it may still update the very
pixel we are going to read! We could use the hardware for this, but it
seems there is a HARDWARE BUG that doesn't seem to like the 1-pixel
ScreenToHost very much.
*/
#if S2H_USE_ENGINE
else if ( (sizl.cx == 1) && (sizl.cy == 1) && (ulDRAWBLTDEF == 0x000000CC) )
{
// Wait for the hardware to become idle.
while (LLDR_SZ(grSTATUS) != 0) ;
// Get the pixel from screen.
pBits[prclTrg->left] =
ppdev->pjScreen[ptlSrc.x + ptlSrc.y * ppdev->lDeltaScreen];
}
#endif
else
{
#if S2H_USE_ENGINE
// The hardware requires us to get QWORDS.
BOOL fExtra = ((sizl.cx + 3) >> 2) & 1;
#endif
pBits += prclTrg->left;
#if S2H_USE_ENGINE
// Start the blit.
LL_OP1(ptlSrc.x, ptlSrc.y);
LL_BLTEXT(sizl.cx, sizl.cy);
#endif
while (sizl.cy--)
{
#if S2H_USE_ENGINE
DWORD *p = (DWORD *)pBits;
// First, we get pixels in chunks of 4 so the 32-bit HOSTDATA is
// happy.
for (i = sizl.cx; i >= 4; i -= 4)
{
*p++ = LLDR_SZ(grHOSTDATA[0]);
}
// Then, we have to do the remainig pixel(s).
switch (i)
{
case 1:
*(BYTE *)p = (BYTE)LLDR_SZ(grHOSTDATA[0]);
break;
case 2:
*(WORD *)p = (WORD)LLDR_SZ(grHOSTDATA[0]);
break;
case 3:
i = LLDR_SZ(grHOSTDATA[0]);
((WORD *)p)[0] = (WORD)i;
((BYTE *)p)[2] = (BYTE)(i >> 16);
break;
}
// Get the extra pixel required for QWORD alignment.
if (fExtra)
{
LLDR_SZ(grHOSTDATA[0]);
}
#else
// Copy all pixels from screen to memory.
memcpy(pBits, pjScreen, sizl.cx);
// Next line.
pjScreen += ppdev->lDeltaScreen;
#endif
pBits += lDelta;
}
}
return(TRUE);
}
/*****************************************************************************\
* *
* 1 6 - B P P *
* *
\*****************************************************************************/
/*****************************************************************************\
* DoHost16ToDevice
*
* This routine performs a HostToScreen or HostToDevice blit. The host data
* can be either monochrome, 4-bpp, or 16-bpp. Color translation is only
* supported for monochrome and 4-bpp modes.
*
* On entry: psoTrg Pointer to target surface object.
* psoSrc Pointer to source surface object.
* pxlo Pointer to translation object.
* prclTrg Destination rectangle.
* pptlSrc Source offset.
* ulDRAWBLTDEF Value for grDRAWBLTDEF register. This value has
* the ROP and the brush flags.
\*****************************************************************************/
BOOL DoHost16ToDevice(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF
)
{
POINTL ptlDest, ptlSrc;
SIZEL sizl;
PPDEV ppdev;
PBYTE pBits;
LONG lDelta, i, n, lLeadIn, lExtra, i1;
ULONG *pulXlate;
FLONG flXlate;
// Calculate te source offset.
ptlSrc.x = pptlSrc->x;
ptlSrc.y = pptlSrc->y;
// Determine the destination type and calculate the destination offset.
if (psoTrg->iType == STYPE_DEVBITMAP)
{
PDSURF pdsurf = (PDSURF) psoTrg->dhsurf;
ptlDest.x = prclTrg->left + pdsurf->ptl.x;
ptlDest.y = prclTrg->top + pdsurf->ptl.y;
ppdev = pdsurf->ppdev;
}
else
{
ptlDest.x = prclTrg->left;
ptlDest.y = prclTrg->top;
ppdev = (PPDEV) psoTrg->dhpdev;
}
// Calculate the size of the blit.
sizl.cx = prclTrg->right - prclTrg->left;
sizl.cy = prclTrg->bottom - prclTrg->top;
// Get the source variables and offset into source bits.
lDelta = psoSrc->lDelta;
pBits = (PBYTE)psoSrc->pvScan0 + (ptlSrc.y * lDelta);
/* -----------------------------------------------------------------------
Test for monochrome source.
*/
if (psoSrc->iBitmapFormat == BMF_1BPP)
{
ULONG bgColor, fgColor;
#if SWAT7
SIZEL sizlTotal;
#endif
// Get the pointer to the translation table.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if (flXlate & XO_TRIVIAL)
{
pulXlate = NULL;
}
else if (flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
// Set background and foreground colors.
if (pulXlate == NULL)
{
bgColor = 0x00000000;
fgColor = 0xFFFFFFFF;
}
else
{
bgColor = pulXlate[0];
fgColor = pulXlate[1];
// Expand the colors.
bgColor |= bgColor << 16;
fgColor |= fgColor << 16;
}
//
// Special case: when we are expanding monochrome sources and we
// already have a colored brush, we must make sure the monochrome color
// translation can be achived by setting the saturation bit (expanding
// 0's to 0 and 1's to 1). If the monochrome source also requires color
// translation, we simply punt this blit back to GDI.
//
if (ulDRAWBLTDEF & 0x00040000)
{
if ( (bgColor == 0x00000000) && (fgColor == 0xFFFFFFFF) )
{
// Enable saturation for source (OP1).
ulDRAWBLTDEF |= 0x00008000;
}
#if SOLID_CACHE
else if ( ((ulDRAWBLTDEF & 0x000F0000) == 0x00070000) &&
ppdev->Bcache )
{
CacheSolid(ppdev);
ulDRAWBLTDEF ^= (0x00070000 ^ 0x00090000);
REQUIRE(4);
LL_BGCOLOR(bgColor, 2);
LL_FGCOLOR(fgColor, 2);
}
#endif
else
{
// Punt this call to the GDI.
return(FALSE);
}
}
else
{
REQUIRE(4);
LL_BGCOLOR(bgColor, 2);
LL_FGCOLOR(fgColor, 2);
}
REQUIRE(9);
#if SWAT7
// Setup the Laguna registers for the blit. We also set the bit swizzle
// bit in the grCONTROL register.
ppdev->grCONTROL |= SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10600000, 2);
sizlTotal = sizl;
while (sizlTotal.cx)
{
sizl.cx = min(sizlTotal.cx, 864);
sizl.cy = sizlTotal.cy;
#endif
// Calculate the source parameters. We are going to DWORD adjust the
// source, so we must setup the source phase.
lLeadIn = ptlSrc.x & 31;
pBits += (ptlSrc.x >> 3) & ~3;
n = (sizl.cx + lLeadIn + 31) >> 5;
#if !SWAT7
// Setup the Laguna registers for the blit. We also set the bit swizzle
// bit in the grCONTROL register.
ppdev->grCONTROL |= SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10600000, 2);
#endif
// Start the blit.
// added REQUIRE above
// REQUIRE(7);
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
// Copy all the bits to the screen, 32-bits at a time. We don't have to
// worry about crossing any boundary since NT is always DWORD aligned.
while (sizl.cy--)
{
WRITE_STRING(pBits, n);
pBits += lDelta;
}
#if SWAT7
sizlTotal.cx -= sizl.cx;
ptlSrc.x += sizl.cx;
ptlDest.x += sizl.cx;
// Reload pBits.
pBits = (PBYTE) psoSrc->pvScan0 + (ptlSrc.y * lDelta);
}
#endif
// Disable the swizzle bit in the grCONTROL register.
ppdev->grCONTROL = ppdev->grCONTROL & ~SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
}
/* -----------------------------------------------------------------------
Test for 4-bpp source.
*/
else if (psoSrc->iBitmapFormat == BMF_4BPP)
{
// Get the pointer to the translation table.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if (flXlate & XO_TRIVIAL)
{
pulXlate = NULL;
}
else if (flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
// Calculate the source parameters. We are going to BYTE adjust the
// source, so we also set the source phase.
lLeadIn = (ptlSrc.x & 1) * 2;
pBits += ptlSrc.x >> 1;
n = sizl.cx + (ptlSrc.x & 1);
#if !DRIVER_5465
// Get the number of extra DWORDS per line for the HOSTDATA hardware
// bug.
if (ppdev->dwLgDevID == CL_GD5462)
{
if (MAKE_HD_INDEX(sizl.cx * 2, lLeadIn, ptlDest.x * 2) == 3788)
{
// We have a problem with the HOSTDATA TABLE.
// Punt till we can figure it out.
return FALSE;
}
lExtra = ExtraDwordTable[
MAKE_HD_INDEX(sizl.cx * 2, lLeadIn, ptlDest.x * 2)];
}
else
{
lExtra = 0;
}
#endif
// Start the blit.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
// If there is no translation table, use the default translation table.
if (pulXlate == NULL)
{
pulXlate = ulXlate;
}
// Now we are ready to copy all the pixels to the hardware.
while (sizl.cy--)
{
BYTE *p = pBits;
// First, we convert 2 pixels at a time to create a 32-bit value
// to write to the hardware.
for (i = n; i >= 2; i -= 2)
{
REQUIRE(1);
LL32(grHOSTDATA[0], pulXlate[p[0] >> 4] |
(pulXlate[p[0] & 0x0F] << 16));
p++;
}
// Now, write any remaining pixel.
if (i)
{
REQUIRE(1);
LL32(grHOSTDATA[0], pulXlate[p[0] >> 4]);
}
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[0], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
/* -----------------------------------------------------------------------
Test for 8-bpp source.
*/
else if (psoSrc->iBitmapFormat == BMF_8BPP)
{
//
// Attempt to load the translation table into the chip.
// After this call:
// pulXlate == NULL if there is no color translation is required.
// pulXlate == translation table if color translation is required.
// UseHWxlate == FALSE if the hardware will do the xlate for us.
// UseHWxlate == TRUE if we must do the translation in software.
//
#if COLOR_TRANSLATE
ULONG UseHWxlate = bCacheXlateTable(ppdev, &pulXlate, psoTrg, psoSrc,
pxlo, (BYTE)(ulDRAWBLTDEF&0xCC));
#else
if ( (pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL) )
{
pulXlate = NULL;
}
else if (pxlo->flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
#endif
//
// NVH: 5465 Color XLATE bug!!!
// Color translation is broken on the 5465 in 16, 24 and 32 bpp.
//
#if COLOR_TRANSLATE
if (UseHWxlate)
{
DWORD phase = ( ((DWORD)(pBits + ptlSrc.x)) & 3);
if (XLATE_IS_BROKEN(sizl.cx, 2, phase))
UseHWxlate = FALSE; // force SW translation.
}
if (UseHWxlate)
{
// Use Hardware color translation.
DISPDBG((COPYBITS_DBG_LEVEL, "Host16ToDevice: "
"Attempting HW color translation on 8bpp Host to 16bpp Screen.\n"));
// Calculate the source parameters. We are going to DWORD adjust the
// source, so we also set the source phase.
pBits += ptlSrc.x; // Start of source data on the host.
lLeadIn = (DWORD)pBits & 3; // Source phase.
pBits -= lLeadIn; // Backup to DWORD boundry.
n = (sizl.cx + lLeadIn + 3) >> 2;// Number of HOSTDATA per scanline.
// Start the blit.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT_XLATE(8, sizl.cx, sizl.cy); // HW xlate.
while (sizl.cy--)
{
// Copy all data in 32-bit. We don't have to worry about
// crossing any boundaries, since within NT everything is DWORD
// aligned.
WRITE_STRING(pBits, n);
pBits += lDelta;
}
}
else
#endif
{
//
// Use SW color translation.
//
DISPDBG((COPYBITS_DBG_LEVEL, "Host16ToDevice: "
"Attempting SW color translation on 8bpp Host to 16bpp Screen.\n"));
// To do 8bpp host to 16bpp screen we must have a translation table.
ASSERTMSG(pulXlate,
"Host16ToDevice: No translation table for color translation.\n");
#if !DRIVER_5465
// Get the number of extra DWORDS per line for the HOSTDATA hardware
// bug.
if (ppdev->dwLgDevID == CL_GD5462)
{
if (MAKE_HD_INDEX(sizl.cx * 2, 0, ptlDest.x * 2) == 3788)
{
// We have a problem with the HOSTDATA TABLE.
// Punt till we can figure it out.
return FALSE;
}
lExtra = ExtraDwordTable[
MAKE_HD_INDEX(sizl.cx * 2, 0, ptlDest.x * 2)];
}
else
{
lExtra = 0;
}
#endif
// Calculate the source parameters.
pBits += ptlSrc.x; // Start of source data on the host.
// Start the blit.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
LL_OP1_MONO(0, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
while (sizl.cy--)
{
BYTE *p = pBits;
// We need to copy 2 pixels at a time to create a 32-bit value
// for the HOSTDATA register.
for (i = sizl.cx; i >= 2; i -= 2)
{
REQUIRE(1);
LL32(grHOSTDATA[0], pulXlate[p[0]] |
(pulXlate[p[1]] << 16));
p += 2;
}
// Write any remainig pixels.
if (i)
{
REQUIRE(1);
LL32(grHOSTDATA[0], pulXlate[p[0]]);
}
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[0], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
}
/* -----------------------------------------------------------------------
Source is in same color depth as screen.
*/
else
{
// Get the pointer to the translation table.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if (flXlate & XO_TRIVIAL)
{
pulXlate = NULL;
}
else if (flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
// If we have a translation table, punt it.
#if _WIN32_WINNT >= 0x0500
if ( pulXlate || (flXlate & 0x0200) )
#else
if ( pulXlate || (flXlate & 0x0010) )
#endif
{
return(FALSE);
}
// Calculate the source parameters. We are going to DWORD adjust the
// source, so we also set the source phase.
pBits += ptlSrc.x * 2;
lLeadIn = (DWORD)pBits & 3;
pBits -= lLeadIn;
n = ((sizl.cx * 2) + lLeadIn + 3) >> 2;
#if !DRIVER_5465
// Get the number of extra DWORDS per line for the HOSTDATA hardware
// bug.
if (ppdev->dwLgDevID == CL_GD5462)
{
if (MAKE_HD_INDEX(sizl.cx * 2, lLeadIn, ptlDest.x * 2) == 3788)
{
// We have a problem with the HOSTDATA TABLE.
// Punt till we can figure it out.
return FALSE;
}
lExtra = ExtraDwordTable[MAKE_HD_INDEX(sizl.cx * 2, lLeadIn, ptlDest.x * 2)];
}
else
lExtra = 0;
#endif
// Setup the Laguna registers.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
// Start the blit.
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
// Copy all data in 32-bit. We don't have to worry about crossing any
// boundaries, since within NT everything is DWORD aligned.
while (sizl.cy--)
{
WRITE_STRING(pBits, n);
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[i], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
return(TRUE);
}
/*****************************************************************************\
* DoDeviceToHost16
*
* This routine performs a DeviceToHost for either monochrome or 16-bpp
* destinations.
*
* On entry: psoTrg Pointer to target surface object.
* psoSrc Pointer to source surface object.
* pxlo Pointer to translation object.
* prclTrg Destination rectangle.
* pptlSrc Source offset.
* ulDRAWBLTDEF Value for grDRAWBLTDEF register. This value has
* the ROP and the brush flags.
\*****************************************************************************/
BOOL DoDeviceToHost16(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF
)
{
POINTL ptlSrc;
PPDEV ppdev;
SIZEL sizl;
PBYTE pBits;
#if !S2H_USE_ENGINE
PBYTE pjScreen;
#endif
LONG lDelta;
ULONG i, n;
// Determine the source type and calculate the offset.
if (psoSrc->iType == STYPE_DEVBITMAP)
{
PDSURF pdsurf = (PDSURF)psoSrc->dhsurf;
ppdev = pdsurf->ppdev;
ptlSrc.x = pptlSrc->x + pdsurf->ptl.x;
ptlSrc.y = pptlSrc->y + pdsurf->ptl.y;
}
else
{
ppdev = (PPDEV)psoSrc->dhpdev;
ptlSrc.x = pptlSrc->x;
ptlSrc.y = pptlSrc->y;
}
// Calculate the size of the blit.
sizl.cx = prclTrg->right - prclTrg->left;
sizl.cy = prclTrg->bottom - prclTrg->top;
// Calculate the destination variables.
lDelta = psoTrg->lDelta;
pBits = (PBYTE)psoTrg->pvScan0 + (prclTrg->top * lDelta);
#if S2H_USE_ENGINE
// Setup the Laguna registers.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x20100000, 0);
LL_OP0(0, 0);
#else
// Calculate the screen address.
pjScreen = ppdev->pjScreen + ptlSrc.x * 2 + ptlSrc.y * ppdev->lDeltaScreen;
// Wait for the hardware to become idle.
while (LLDR_SZ(grSTATUS) != 0) ;
#endif
// Test for monochrome destination.
if (psoTrg->iBitmapFormat == BMF_1BPP)
{
BYTE data, leftMask, rightMask;
WORD fgColor;
DWORD *pulXlate;
LONG leftCount, rightCount, leftSkip;
#if S2H_USE_ENGINE
BYTE pixels[4];
#endif
// Calculate the monochrome masks.
pBits += prclTrg->left >> 3;
leftSkip = prclTrg->left & 7;
leftCount = (8 - leftSkip) & 7;
leftMask = 0xFF >> leftSkip;
rightCount = prclTrg->right & 7;
rightMask = 0xFF << (8 - rightCount);
// If we only have pixels in one byte, we combine rightMask with
// leftMask and set the routines to skip everything but the rightMask.
if (leftCount > sizl.cx)
{
rightMask &= leftMask;
leftMask = 0xFF;
n = 0;
}
else
{
n = (sizl.cx - leftCount) >> 3;
}
// Get the the foreground color from the translation table.
pulXlate = XLATEOBJ_piVector(pxlo);
fgColor = pulXlate ? (WORD) *pulXlate : 0;
#if S2H_USE_ENGINE
// Start the blit.
LL_OP1(ptlSrc.x - leftSkip, ptlSrc.y);
LL_BLTEXT(sizl.cx + leftSkip, sizl.cy);
#else
pjScreen -= leftSkip * 2;
#endif
while (sizl.cy--)
{
PBYTE pDest = pBits;
#if !S2H_USE_ENGINE
PWORD pSrc = (WORD *)pjScreen;
#endif
// If we have a left mask specified, we get the pixels and store
// them with the destination.
if (leftMask != 0xFF)
{
data = 0;
#if S2H_USE_ENGINE
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x80;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x40;
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x20;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x10;
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x08;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x04;
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x02;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x01;
#else
if (pSrc[0] == fgColor) data |= 0x80;
if (pSrc[1] == fgColor) data |= 0x40;
if (pSrc[2] == fgColor) data |= 0x20;
if (pSrc[3] == fgColor) data |= 0x10;
if (pSrc[4] == fgColor) data |= 0x08;
if (pSrc[5] == fgColor) data |= 0x04;
if (pSrc[6] == fgColor) data |= 0x02;
if (pSrc[7] == fgColor) data |= 0x01;
pSrc += 8;
#endif
*pDest++ = (*pDest & ~leftMask) | (data & leftMask);
}
// Translate all pixels that don't require masking.
for (i = 0; i < n; i++)
{
data = 0;
#if S2H_USE_ENGINE
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x80;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x40;
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x20;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x10;
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x08;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x04;
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x02;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x01;
#else
if (pSrc[0] == fgColor) data |= 0x80;
if (pSrc[1] == fgColor) data |= 0x40;
if (pSrc[2] == fgColor) data |= 0x20;
if (pSrc[3] == fgColor) data |= 0x10;
if (pSrc[4] == fgColor) data |= 0x08;
if (pSrc[5] == fgColor) data |= 0x04;
if (pSrc[6] == fgColor) data |= 0x02;
if (pSrc[7] == fgColor) data |= 0x01;
pSrc += 8;
#endif
*pDest++ = data;
}
// If we have a right mask specified, we get the pixels and store
// them with the destination.
if (rightMask != 0x00)
{
data = 0;
#if S2H_USE_ENGINE
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x80;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x40;
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x20;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x10;
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x08;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x04;
*(DWORD *)pixels = LLDR_SZ(grHOSTDATA[0]);
if (*(WORD *)&pixels[0] == fgColor) data |= 0x02;
if (*(WORD *)&pixels[1] == fgColor) data |= 0x01;
#else
if (pSrc[0] == fgColor) data |= 0x80;
if (pSrc[1] == fgColor) data |= 0x40;
if (pSrc[2] == fgColor) data |= 0x20;
if (pSrc[3] == fgColor) data |= 0x10;
if (pSrc[4] == fgColor) data |= 0x08;
if (pSrc[5] == fgColor) data |= 0x04;
if (pSrc[6] == fgColor) data |= 0x02;
if (pSrc[7] == fgColor) data |= 0x01;
#endif
*pDest = (*pDest & ~rightMask) | (data & rightMask);
}
// Next line.
#if !S2H_USE_ENGINE
pjScreen += ppdev->lDeltaScreen;
#endif
pBits += lDelta;
}
}
// We only support destination bitmaps with the same color depth and we
// do not support any color translation.
else if ( (psoTrg->iBitmapFormat != BMF_16BPP) ||
(pxlo && !(pxlo->flXlate & XO_TRIVIAL)) )
{
return(FALSE);
}
/*
If the GetPixel routine is being called, we get here with both cx and
cy set to 1 and the ROP to 0xCC (source copy). In this special case we
read the pixel directly from memory. Of course, we must be sure the
blit engine is finished working since it may still update the very
pixel we are going to read! We could use the hardware for this, but it
seems there is a HARDWARE BUG that doesn't seem to like the 1-pixel
ScreenToHost very much.
*/
#if S2H_USE_ENGINE
else if ( (sizl.cx == 1) && (sizl.cy == 1) && (ulDRAWBLTDEF == 0x000000CC) )
{
// Wait for the hardware to become idle.
while (LLDR_SZ(grSTATUS) != 0) ;
// Get the pixel from screen.
*(WORD *)pBits[prclTrg->left] = *(WORD *)
&ppdev->pjScreen[ptlSrc.x * 2 + ptlSrc.y * ppdev->lDeltaScreen];
}
#endif
else
{
#if S2H_USE_ENGINE
// The hardware requires us to get QWORDS.
BOOL fExtra = ((sizl.cx * 2 + 3) >> 2) & 1;
#endif
pBits += prclTrg->left * 2;
#if S2H_USE_ENGINE
// Start the blit.
LL_OP1(ptlSrc.x, ptlSrc.y);
LL_BLTEXT(sizl.cx, sizl.cy);
#endif
while (sizl.cy--)
{
#if S2H_USE_ENGINE
DWORD *p = (DWORD *)pBits;
// First, we get pixels in chunks of 2 so the 32-bit HOSTDATA is
// happy.
for (i = sizl.cx; i >= 2; i -= 2)
{
*p++ = LLDR_SZ(grHOSTDATA[0]);
}
// Then, we have to do the remainig pixel.
if (i)
{
*(WORD *)p = (WORD)LLDR_SZ(grHOSTDATA[0]);
}
// Get the extra pixel required for QWORD alignment.
if (fExtra)
{
LLDR_SZ(grHOSTDATA[0]);
}
#else
// Copy all pixels from screen to memory.
memcpy(pBits, pjScreen, sizl.cx * 2);
// Next line.
pjScreen += ppdev->lDeltaScreen;
#endif
pBits += lDelta;
}
}
return(TRUE);
}
/*****************************************************************************\
* *
* 2 4 - B P P *
* *
\*****************************************************************************/
/*****************************************************************************\
* DoHost24ToDevice
*
* This routine performs a HostToScreen or HostToDevice blit. The host data
* can be either monochrome, 4-bpp, or 24-bpp. Color translation is only
* supported for monochrome and 4-bpp modes.
*
* On entry: psoTrg Pointer to target surface object.
* psoSrc Pointer to source surface object.
* pxlo Pointer to translation object.
* prclTrg Destination rectangle.
* pptlSrc Source offset.
* ulDRAWBLTDEF Value for grDRAWBLTDEF register. This value has
* the ROP and the brush flags.
\*****************************************************************************/
BOOL DoHost24ToDevice(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF
)
{
POINTL ptlDest, ptlSrc;
SIZEL sizl;
PPDEV ppdev;
PBYTE pBits;
LONG lDelta, i, n, lLeadIn, lExtra, i1;
ULONG *pulXlate;
FLONG flXlate;
// Calculate te source offset.
ptlSrc.x = pptlSrc->x;
ptlSrc.y = pptlSrc->y;
// Determine the destination type and calculate the destination offset.
if (psoTrg->iType == STYPE_DEVBITMAP)
{
PDSURF pdsurf = (PDSURF) psoTrg->dhsurf;
ptlDest.x = prclTrg->left + pdsurf->ptl.x;
ptlDest.y = prclTrg->top + pdsurf->ptl.y;
ppdev = pdsurf->ppdev;
}
else
{
ptlDest.x = prclTrg->left;
ptlDest.y = prclTrg->top;
ppdev = (PPDEV) psoTrg->dhpdev;
}
// Calculate the size of the blit.
sizl.cx = prclTrg->right - prclTrg->left;
sizl.cy = prclTrg->bottom - prclTrg->top;
// Get the source variables and ofsfet into source bits.
lDelta = psoSrc->lDelta;
pBits = (PBYTE)psoSrc->pvScan0 + (ptlSrc.y * lDelta);
/* -----------------------------------------------------------------------
Test for monochrome source.
*/
if (psoSrc->iBitmapFormat == BMF_1BPP)
{
ULONG bgColor, fgColor;
#if SWAT7
SIZEL sizlTotal;
#endif
// Get the pointer to the translation table.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if (flXlate & XO_TRIVIAL)
{
pulXlate = NULL;
}
else if (flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
// Set background and foreground colors.
if (pulXlate == NULL)
{
bgColor = 0x00000000;
fgColor = 0x00FFFFFF;
}
else
{
bgColor = pulXlate[0] & 0x00FFFFFF;
fgColor = pulXlate[1] & 0x00FFFFFF;
}
//
// Special case: when we are expanding monochrome sources and we
// already have a colored brush, we must make sure the monochrome color
// translation can be achived by setting the saturation bit (expanding
// 0's to 0 and 1's to 1). If the monochrome source also requires color
// translation, we simply punt this blit back to GDI.
//
if (ulDRAWBLTDEF & 0x00040000)
{
if ( (bgColor == 0x00000000) && (fgColor == 0x00FFFFFF) )
{
// Enable saturation for source (OP1).
ulDRAWBLTDEF |= 0x00008000;
}
#if SOLID_CACHE
else if ( ((ulDRAWBLTDEF & 0x000F0000) == 0x00070000) &&
ppdev->Bcache )
{
CacheSolid(ppdev);
ulDRAWBLTDEF ^= (0x00070000 ^ 0x00090000);
REQUIRE(4);
LL_BGCOLOR(bgColor, 2);
LL_FGCOLOR(fgColor, 2);
}
#endif
else
{
// Punt this call to the GDI.
return(FALSE);
}
}
else
{
REQUIRE(4);
LL_BGCOLOR(bgColor, 2);
LL_FGCOLOR(fgColor, 2);
}
REQUIRE(9);
#if SWAT7
// Setup the Laguna registers for the blit. We also set the bit swizzle
// bit in the grCONTROL register.
ppdev->grCONTROL |= SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10600000, 2);
sizlTotal = sizl;
while (sizlTotal.cx)
{
sizl.cx = min(sizlTotal.cx, 864);
sizl.cy = sizlTotal.cy;
#endif
// Calculate the source parameters. We are going to BYTE
// adjust the source, so we must setup the source phase.
lLeadIn = ptlSrc.x & 7;
pBits += ptlSrc.x >> 3;
n = (sizl.cx + lLeadIn + 7) >> 3;
#if !SWAT7
//
// Chip bug. Laguna locks with more than 15 dwords HOSTDATA
//
if (n > 120) // 15 qwords = 120 bytes
{
return FALSE;
}
// Setup the Laguna registers for the blit. We also set the bit swizzle
// bit in the grCONTROL register.
ppdev->grCONTROL |= SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10600000, 2);
#endif
// Start the blit.
// added REQUIRE above
// REQUIRE(7);
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
// Copy all the bits to the screen, 32-bits at a time. We don't have to
// worry about crossing any boundary since NT is always DWORD aligned.
while (sizl.cy--)
{
BYTE *p = pBits;
BYTE pixels[4];
// First, we draw 32-pixels at a time to keep HOSTDATA happy.
for (i = n; i >= 4; i -= 4)
{
REQUIRE(1);
LL32(grHOSTDATA[0], *(DWORD *)p);
p += 4;
}
// Draw any remainig pixls.
switch (i)
{
case 1:
REQUIRE(1);
LL32(grHOSTDATA[0], *p);
break;
case 2:
REQUIRE(1);
LL32(grHOSTDATA[0], *(WORD *)p);
break;
case 3:
pixels[0] = p[0];
pixels[1] = p[1];
pixels[2] = p[2];
REQUIRE(1);
LL32(grHOSTDATA[0], *(DWORD *)pixels);
break;
}
// Next line.
pBits += lDelta;
}
#if SWAT7
sizlTotal.cx -= sizl.cx;
ptlSrc.x += sizl.cx;
ptlDest.x += sizl.cx;
#if 1 // SWAT: 08/08/97
// Reload pBits.
pBits = (PBYTE) psoSrc->pvScan0 + (ptlSrc.y * lDelta);
#endif
}
#endif
// Disable the swizzle bit in the grCONTROL register.
ppdev->grCONTROL = ppdev->grCONTROL & ~SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
}
/* -----------------------------------------------------------------------
Test for 4-bpp source.
*/
else if (psoSrc->iBitmapFormat == BMF_4BPP)
{
// Get the pointer to the translation table.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if (flXlate & XO_TRIVIAL)
{
pulXlate = NULL;
}
else if (flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
// Calculate the source parameters. We are going to BYTE adjust the
// source, so we also set the source phase.
lLeadIn = (ptlSrc.x & 1) * 3;
pBits += ptlSrc.x >> 1;
n = sizl.cx + (ptlSrc.x & 1);
#if !DRIVER_5465
// Get the number of extra DWORDS per line for the HOSTDATA hardware
// bug.
if (ppdev->dwLgDevID == CL_GD5462)
{
if (MAKE_HD_INDEX(sizl.cx * 3, lLeadIn, ptlDest.x * 3) == 3788)
{
// We have a problem with the HOSTDATA TABLE.
// Punt till we can figure it out.
return FALSE;
}
lExtra = ExtraDwordTable[MAKE_HD_INDEX(sizl.cx * 3, lLeadIn, ptlDest.x * 3)];
}
else
lExtra = 0;
#endif
// Start the blit.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
// If there is no translation table, use the default translation table.
if (pulXlate == NULL)
{
pulXlate = ulXlate;
}
// Now we are ready to copy all the pixels to the hardware.
while (sizl.cy--)
{
BYTE *p = pBits;
ULONG pixels[4];
// First, we convert 4 pixels at a time to create three 32-bit
// values to write to the hardware.
for (i = n; i >= 4; i -= 4)
{
pixels[0] = pulXlate[p[0] >> 4];
pixels[1] = pulXlate[p[0] & 0x0F];
pixels[2] = pulXlate[p[1] >> 4];
pixels[3] = pulXlate[p[1] & 0x0F];
// 1000
REQUIRE(3);
LL32(grHOSTDATA[0], pixels[0] | (pixels[1] << 24));
// 2211
LL32(grHOSTDATA[1], (pixels[1] >> 8) | (pixels[2] << 16));
// 3332
LL32(grHOSTDATA[2], (pixels[2] >> 16) | (pixels[3] << 8));
p += 2;
}
// Now, write any remaining pixels.
switch (i)
{
case 1:
// x000
REQUIRE(1);
LL32(grHOSTDATA[0], pulXlate[p[0] >> 4]);
break;
case 2:
pixels[0] = pulXlate[p[0] >> 4];
pixels[1] = pulXlate[p[0] & 0x0F];
// 1000
REQUIRE(2);
LL32(grHOSTDATA[0], pixels[0] | (pixels[1] << 24));
// xx11
LL32(grHOSTDATA[1], pixels[1] >> 8);
break;
case 3:
pixels[0] = pulXlate[p[0] >> 4];
pixels[1] = pulXlate[p[0] & 0x0F];
pixels[2] = pulXlate[p[1] >> 4];
// 1000
REQUIRE(3);
LL32(grHOSTDATA[0], pixels[0] | (pixels[1] << 24));
// 2211
LL32(grHOSTDATA[1], (pixels[1] >> 8) | (pixels[2] << 16));
// xxx2
LL32(grHOSTDATA[2], pixels[2] >> 16);
break;
}
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[0], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
/* -----------------------------------------------------------------------
Test for 8-bpp source.
*/
else if (psoSrc->iBitmapFormat == BMF_8BPP)
{
//
// Attempt to load the translation table into the chip.
// After this call:
// pulXlate == NULL if there is no color translation is required.
// pulXlate == translation table if color translation is required.
// UseHWxlate == FALSE if the hardware will do the xlate for us.
// UseHWxlate == TRUE if we must do the translation in software.
//
#if COLOR_TRANSLATE
ULONG UseHWxlate = bCacheXlateTable(ppdev, &pulXlate, psoTrg, psoSrc,
pxlo, (BYTE)(ulDRAWBLTDEF&0xCC));
#else
if ( (pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL) )
{
pulXlate = NULL;
}
else if (pxlo->flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
#endif
// A translation table is required.
// "Well, DUH!" you might say, but I've seen it missing before...
if (!pulXlate)
{
DISPDBG((0, "\n\nHost24ToDevice: !!! WARNING !!! 8BPP source "
"bitmap does not have a translation table. Punting!\n\n"));
return FALSE;
}
#if COLOR_TRANSLATE
//
// NVH: 5465 Color XLATE bug!!!
// Color translation is broken on the 5465 in 16, 24 and 32 bpp.
//
if (UseHWxlate)
{
DWORD phase = ( ((DWORD)(pBits + ptlSrc.x)) & 3);
if (XLATE_IS_BROKEN(sizl.cx, 3, phase))
UseHWxlate = FALSE; // force SW translation.
}
if (UseHWxlate)
{
// Use Hardware color translation.
DISPDBG((COPYBITS_DBG_LEVEL, "Host24ToDevice: "
"Attempting HW color translation on 8bpp Host to 24bpp Screen.\n"));
// Calculate the source parameters. We are going to DWORD adjust the
// source, so we also set the source phase.
pBits += ptlSrc.x; // Start of source data on the host.
lLeadIn = (DWORD)pBits & 3; // Source phase.
pBits -= lLeadIn; // Backup to DWORD boundry.
n = (sizl.cx + lLeadIn + 3) >> 2;// Number of HOSTDATA per scanline.
// Start the blit.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT_XLATE(8, sizl.cx, sizl.cy); // HW xlate.
while (sizl.cy--)
{
// Copy all data in 32-bit. We don't have to worry about
// crossing any boundaries, since within NT everything is DWORD
// aligned.
WRITE_STRING(pBits, n);
pBits += lDelta;
}
}
else
#endif
{
//
// Use SW color translation.
//
// Calculate the source parameters.
pBits += ptlSrc.x;
#if !DRIVER_5465
// Get the number of extra DWORDS per line for the HOSTDATA hardware
// bug.
if (ppdev->dwLgDevID == CL_GD5462)
{
if (MAKE_HD_INDEX(sizl.cx * 3, 0, ptlDest.x * 3) == 3788)
{
// We have a problem with the HOSTDATA TABLE.
// Punt till we can figure it out.
return FALSE;
}
lExtra = ExtraDwordTable[MAKE_HD_INDEX(sizl.cx * 3, 0, ptlDest.x * 3)];
}
else
{
lExtra = 0;
}
#endif
// Setup the Laguna registers.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
// Start the blit.
LL_OP1_MONO(0, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
while (sizl.cy--)
{
BYTE *p = pBits;
// We need to copy 4 pixels at a time to create three 32-bit values
// for the HOSTDATA register and stay in sync.
for (i = sizl.cx; i >= 4; i -= 4)
{
REQUIRE(3);
LL32(grHOSTDATA[0],
pulXlate[p[0]] | (pulXlate[p[1]] << 24));
LL32(grHOSTDATA[1],
(pulXlate[p[1]] >> 8) | (pulXlate[p[2]] << 16));
LL32(grHOSTDATA[2],
(pulXlate[p[2]] >> 16) | (pulXlate[p[3]] << 8));
p += 4;
}
// Write any remainig pixels.
switch (i)
{
case 1:
REQUIRE(1);
LL32(grHOSTDATA[0], pulXlate[p[0]]);
break;
case 2:
REQUIRE(2);
LL32(grHOSTDATA[0],
pulXlate[p[0]] | (pulXlate[p[1]] << 24));
LL32(grHOSTDATA[1], pulXlate[p[1]] >> 8);
break;
case 3:
REQUIRE(3);
LL32(grHOSTDATA[0],
pulXlate[p[0]] | (pulXlate[p[1]] << 24));
LL32(grHOSTDATA[1],
(pulXlate[p[1]] >> 8) | (pulXlate[p[2]] << 16));
LL32(grHOSTDATA[2], pulXlate[p[2]] >> 16);
break;
}
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[0], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
}
/* -----------------------------------------------------------------------
Source is in same color depth as screen.
*/
else
{
// Get the pointer to the translation table.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if (flXlate & XO_TRIVIAL)
{
pulXlate = NULL;
}
else if (flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
// If we have a translation table, punt it.
if ( pulXlate || (flXlate & 0x10) )
{
return(FALSE);
}
// Calculate the source parameters. We are going to DWORD adjust the
// source, so we also set the source phase.
pBits += ptlSrc.x * 3;
lLeadIn = (DWORD)pBits & 3;
pBits -= lLeadIn;
n = (sizl.cx * 3 + lLeadIn + 3) >> 2;
#if !DRIVER_5465
// Get the number of extra DWORDS per line for the HOSTDATA hardware
// bug.
if (ppdev->dwLgDevID == CL_GD5462)
{
if (MAKE_HD_INDEX(sizl.cx * 3, lLeadIn, ptlDest.x * 3) == 3788)
{
// We have a problem with the HOSTDATA TABLE.
// Punt till we can figure it out.
return FALSE;
}
lExtra = ExtraDwordTable[MAKE_HD_INDEX(sizl.cx * 3, lLeadIn, ptlDest.x * 3)];
}
else
lExtra = 0;
#endif
// Setup the Laguna registers.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
// Start the blit.
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
// Copy all data in 32-bit. We don't have to worry about crossing any
// boundaries, since within NT everything is DWORD aligned.
while (sizl.cy--)
{
WRITE_STRING(pBits, n);
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[0], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
return(TRUE);
}
/*****************************************************************************\
* DoDeviceToHost24
*
* This routine performs a DeviceToHost for either monochrome or 24-bpp
* destinations.
*
* On entry: psoTrg Pointer to target surface object.
* psoSrc Pointer to source surface object.
* pxlo Pointer to translation object.
* prclTrg Destination rectangle.
* pptlSrc Source offset.
* ulDRAWBLTDEF Value for grDRAWBLTDEF register. This value has
* the ROP and the brush flags.
\*****************************************************************************/
BOOL DoDeviceToHost24(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF
)
{
POINTL ptlSrc;
PPDEV ppdev;
SIZEL sizl;
PBYTE pBits;
#if !S2H_USE_ENGINE
PBYTE pjScreen;
#endif
LONG lDelta;
ULONG i, n;
// Determine the source type and calculate the offset.
if (psoSrc->iType == STYPE_DEVBITMAP)
{
PDSURF pdsurf = (PDSURF)psoSrc->dhsurf;
ppdev = pdsurf->ppdev;
ptlSrc.x = pptlSrc->x + pdsurf->ptl.x;
ptlSrc.y = pptlSrc->y + pdsurf->ptl.y;
}
else
{
ppdev = (PPDEV)psoSrc->dhpdev;
ptlSrc.x = pptlSrc->x;
ptlSrc.y = pptlSrc->y;
}
// Calculate the size of the blit.
sizl.cx = prclTrg->right - prclTrg->left;
sizl.cy = prclTrg->bottom - prclTrg->top;
// Calculate the destination variables.
lDelta = psoTrg->lDelta;
pBits = (PBYTE)psoTrg->pvScan0 + (prclTrg->top * lDelta);
#if S2H_USE_ENGINE
// Setup the Laguna registers.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x20100000, 0);
LL_OP0(0, 0);
#else
// Calculate the screen address.
pjScreen = ppdev->pjScreen + ptlSrc.x * 3 + ptlSrc.y * ppdev->lDeltaScreen;
// Wait for the hardware to become idle.
while (LLDR_SZ(grSTATUS) != 0) ;
#endif
// Test for a monochrome destination.
if (psoTrg->iBitmapFormat == BMF_1BPP)
{
BYTE data, leftMask, rightMask;
ULONG fgColor;
DWORD *pulXlate;
LONG leftCount, rightCount, leftSkip;
BYTE pixels[12];
// Calculate the monochrome masks.
pBits += prclTrg->left >> 3;
leftSkip = prclTrg->left & 7;
leftCount = (8 - leftSkip) & 7;
leftMask = 0xFF >> leftSkip;
rightCount = prclTrg->right & 7;
rightMask = 0xFF << (8 - rightCount);
// If we only have pixels in one byte, we combine rightMask with
// leftMask and set the routine to skip everything but the rightMask.
if (leftCount > sizl.cx)
{
rightMask &= leftMask;
leftMask = 0xFF;
n = 0;
}
else
{
n = (sizl.cx - leftCount) >> 3;
}
// Get the foreground color from the translation table.
pulXlate = XLATEOBJ_piVector(pxlo);
fgColor = pulXlate ? *pulXlate : 0;
#if S2H_USE_ENGINE
// Start the blit.
LL_OP1(ptlSrc.x - leftSkip, ptlSrc.y);
LL_BLTEXT(sizl.cx + leftSkip, sizl.cy);
#else
pjScreen -= leftSkip * 3;
#endif
while (sizl.cy--)
{
PBYTE pDest = pBits;
#if !S2H_USE_ENGINE
DWORD *pSrc = (DWORD *)pjScreen;
#endif
// If we have a leftMask specified, we get the pixels and store
// them in the destination.
if (leftMask != 0xFF)
{
data = 0;
#if S2H_USE_ENGINE
*(DWORD *)&pixels[0] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[4] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[8] = LLDR_SZ(grHOSTDATA[0]);
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x80;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x40;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x20;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x10;
*(DWORD *)&pixels[0] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[4] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[8] = LLDR_SZ(grHOSTDATA[0]);
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x08;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x04;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x02;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x01;
#else
*(DWORD *)&pixels[0] = pSrc[0];
*(DWORD *)&pixels[4] = pSrc[1];
*(DWORD *)&pixels[8] = pSrc[2];
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x80;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x40;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x20;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x10;
*(DWORD *)&pixels[0] = pSrc[3];
*(DWORD *)&pixels[4] = pSrc[4];
*(DWORD *)&pixels[8] = pSrc[5];
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x08;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x04;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x02;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x01;
pSrc += 6;
#endif
*pDest++ = (*pDest & ~leftMask) | (data & leftMask);
}
// Translate all pixels that don't require masking.
for (i = 0; i < n; i++)
{
data = 0;
#if S2H_USE_ENGINE
*(DWORD *)&pixels[0] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[4] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[8] = LLDR_SZ(grHOSTDATA[0]);
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x80;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x40;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x20;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x10;
*(DWORD *)&pixels[0] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[4] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[8] = LLDR_SZ(grHOSTDATA[0]);
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x08;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x04;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x02;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x01;
#else
*(DWORD *)&pixels[0] = pSrc[0];
*(DWORD *)&pixels[4] = pSrc[1];
*(DWORD *)&pixels[8] = pSrc[2];
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x80;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x40;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x20;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x10;
*(DWORD *)&pixels[0] = pSrc[3];
*(DWORD *)&pixels[4] = pSrc[4];
*(DWORD *)&pixels[8] = pSrc[5];
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x08;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x04;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x02;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x01;
pSrc += 6;
#endif
*pDest++ = data;
}
// If we have a rightMask specified, we get the pixels and store
// them in the destination.
if (rightMask != 0x00)
{
data = 0;
#if S2H_USE_ENGINE
*(DWORD *)&pixels[0] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[4] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[8] = LLDR_SZ(grHOSTDATA[0]);
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x80;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x40;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x20;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x10;
*(DWORD *)&pixels[0] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[4] = LLDR_SZ(grHOSTDATA[0]);
*(DWORD *)&pixels[8] = LLDR_SZ(grHOSTDATA[0]);
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x08;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x04;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x02;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x01;
#else
*(DWORD *)&pixels[0] = pSrc[0];
*(DWORD *)&pixels[4] = pSrc[1];
*(DWORD *)&pixels[8] = pSrc[2];
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x80;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x40;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x20;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x10;
*(DWORD *)&pixels[0] = pSrc[3];
*(DWORD *)&pixels[4] = pSrc[4];
*(DWORD *)&pixels[8] = pSrc[5];
if ( (*(DWORD *)&pixels[0] & 0x00FFFFFF) == fgColor )
data |= 0x08;
if ( (*(DWORD *)&pixels[3] & 0x00FFFFFF) == fgColor )
data |= 0x04;
if ( (*(DWORD *)&pixels[6] & 0x00FFFFFF) == fgColor )
data |= 0x02;
if ( (*(DWORD *)&pixels[9] & 0x00FFFFFF) == fgColor )
data |= 0x01;
#endif
*pDest = (*pDest & ~rightMask) | (data & rightMask);
}
// Next line.
#if !S2H_USE_ENGINE
pjScreen += ppdev->lDeltaScreen;
#endif
pBits += lDelta;
}
}
// We only support destination bitmaps with the same color depth and we
// do not support any color translation.
else if ( (psoTrg->iBitmapFormat != BMF_24BPP) ||
(pxlo && !(pxlo->flXlate & XO_TRIVIAL)) )
{
return(FALSE);
}
/*
If the GetPixel routine is being called, we get here with both cx and
cy set to 1 and the ROP to 0xCC (source copy). In this special case we
read the pixel directly from memory. Of course, we must be sure the
blit engine is finished working since it may still update the very
pixel we are going to read! We could use the hardware for this, but it
seems there is a HARDWARE BUG that doesn't seem like the 1-pixel
ScreenToHost very much.
*/
#if S2H_USE_ENGINE
else if ( (sizl.cx == 1) && (sizl.cy == 1) && (ulDRAWBLTDEF == 0x000000CC) )
{
DWORD data;
// Wait for the hardware to become idle.
while (LLDR_SZ(grSTATUS) != 0) ;
// Get the pixel from screen.
pBits += prclTrg->left * 3;
data = *(DWORD *)
&ppdev->pjScreen[ptlSrc.x * 3 + ptlSrc.y * ppdev->lDeltaScreen];
*(WORD *)&pBits[0] = (WORD)data;
*(BYTE *)&pBits[2] = (BYTE)(data >> 16);
}
#endif
else
{
#if S2H_USE_ENGINE
// The hardware requires us to get QWORDS.
BOOL fExtra = ((sizl.cx * 3 + 3) >> 2) & 1;
#endif
pBits += prclTrg->left * 3;
#if S2H_USE_ENGINE
// Start the blit.
LL_OP1(ptlSrc.x, ptlSrc.y);
LL_BLTEXT(sizl.cx, sizl.cy);
#endif
while (sizl.cy--)
{
#if S2H_USE_ENGINE
DWORD *p = (DWORD *)pBits;
// First, we get pixels in chunks of 4 so the 32-bit HOSTDATA is
// happy and we are still in phase.
for (i = sizl.cx; i >= 4; i -= 4)
{
*p++ = LLDR_SZ(grHOSTDATA[0]);
*p++ = LLDR_SZ(grHOSTDATA[0]);
*p++ = LLDR_SZ(grHOSTDATA[0]);
}
// Then, we have to do the remaining pixel(s).
switch (i)
{
case 1:
i = LLDR_SZ(grHOSTDATA[0]);
((WORD *)p)[0] = (WORD)i;
((BYTE *)p)[2] = (BYTE)(i >> 16);
break;
case 2:
*p++ = LLDR_SZ(grHOSTDATA[0]);
*(WORD *)p = (WORD)LLDR_SZ(grHOSTDATA[0]);
break;
case 3:
*p++ = LLDR_SZ(grHOSTDATA[0]);
*p++ = LLDR_SZ(grHOSTDATA[0]);
*(BYTE *)p = (BYTE)LLDR_SZ(grHOSTDATA[0]);
break;
}
// Get the extra pixel required for QWORD alignment.
if (fExtra)
{
LLDR_SZ(grHOSTDATA[0]);
}
#else
// Copy all pixels from screen to memory.
memcpy(pBits, pjScreen, sizl.cx * 3);
// Next line.
pjScreen += ppdev->lDeltaScreen;
#endif
pBits += lDelta;
}
}
return(TRUE);
}
/*****************************************************************************\
* *
* 3 2 - B P P *
* *
\*****************************************************************************/
/*****************************************************************************\
* DoHost32ToDevice
*
* This routine performs a HostToScreen or HostToDevice blit. The host data
* can be either monochrome, 4-bpp, or 32-bpp. Color translation is only
* supported for monochrome and 4-bpp modes.
*
* On entry: psoTrg Pointer to target surface object.
* psoSrc Pointer to source surface object.
* pxlo Pointer to translation object.
* prclTrg Destination rectangle.
* pptlSrc Source offset.
* ulDRAWBLTDEF Value for grDRAWBLTDEF register. This value has
* the ROP and the brush flags.
\*****************************************************************************/
BOOL DoHost32ToDevice(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF
)
{
POINTL ptlDest, ptlSrc;
SIZEL sizl;
PPDEV ppdev;
PBYTE pBits;
LONG lDelta, i, n, lLeadIn, lExtra, i1;
ULONG *pulXlate;
FLONG flXlate;
// Calculate te source offset.
ptlSrc.x = pptlSrc->x;
ptlSrc.y = pptlSrc->y;
// Determine the destination type and calculate the destination offset.
if (psoTrg->iType == STYPE_DEVBITMAP)
{
PDSURF pdsurf = (PDSURF) psoTrg->dhsurf;
ptlDest.x = prclTrg->left + pdsurf->ptl.x;
ptlDest.y = prclTrg->top + pdsurf->ptl.y;
ppdev = pdsurf->ppdev;
}
else
{
ptlDest.x = prclTrg->left;
ptlDest.y = prclTrg->top;
ppdev = (PPDEV) psoTrg->dhpdev;
}
// Calculate the size of the blit.
sizl.cx = prclTrg->right - prclTrg->left;
sizl.cy = prclTrg->bottom - prclTrg->top;
// Get the source variables and ofFset into source bits.
lDelta = psoSrc->lDelta;
pBits = (PBYTE)psoSrc->pvScan0 + (ptlSrc.y * lDelta);
/* -----------------------------------------------------------------------
Test for monochrome source.
*/
if (psoSrc->iBitmapFormat == BMF_1BPP)
{
ULONG bgColor, fgColor;
#if SWAT7
SIZEL sizlTotal;
#endif
// Get the pointer to the translation table.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if (flXlate & XO_TRIVIAL)
{
pulXlate = NULL;
}
else if (flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
// Set background and foreground colors.
if (pulXlate == NULL)
{
bgColor = 0x00000000;
fgColor = 0xFFFFFFFF;
}
else
{
bgColor = pulXlate[0];
fgColor = pulXlate[1];
}
//
// Special case: when we are expanding monochrome sources and we
// already have a colored brush, we must make sure the monochrome color
// translation can be achived by setting the saturation bit (expanding
// 0's to 0 and 1's to 1). If the monochrome source also requires color
// translation, we simply punt this blit back to GDI.
//
if (ulDRAWBLTDEF & 0x00040000)
{
if ( (bgColor == 0x00000000) &&
((fgColor & 0x00FFFFFF) == 0x00FFFFFF) )
{
// Enable saturation for source (OP1).
ulDRAWBLTDEF |= 0x00008000;
}
#if SOLID_CACHE
else if ( ((ulDRAWBLTDEF & 0x000F0000) == 0x00070000) &&
ppdev->Bcache )
{
CacheSolid(ppdev);
ulDRAWBLTDEF ^= (0x00070000 ^ 0x00090000);
REQUIRE(4);
LL_BGCOLOR(bgColor, 2);
LL_FGCOLOR(fgColor, 2);
}
#endif
else
{
// Punt this call to the GDI.
return(FALSE);
}
}
else
{
REQUIRE(4);
LL_BGCOLOR(bgColor, 2);
LL_FGCOLOR(fgColor, 2);
}
REQUIRE(9);
#if SWAT7
// Setup the Laguna registers for the blit. We also set the bit swizzle
// bit in the grCONTROL register.
ppdev->grCONTROL |= SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10600000, 2);
sizlTotal = sizl;
while (sizlTotal.cx)
{
sizl.cx = min(sizlTotal.cx, 864);
sizl.cy = sizlTotal.cy;
#endif
// Calculate the source parameters. We are going to DWORD adjust the
// source, so we must setup the source phase.
lLeadIn = ptlSrc.x & 31;
pBits += (ptlSrc.x >> 3) & ~3;
n = (sizl.cx + lLeadIn + 31) >> 5;
#if !SWAT7
//
// Chip bug. Laguna locks with more than 14 dwords HOSTDATA
//
if (n > 28) // 14 qwords = 28 dwords
{
return FALSE;
}
// Setup the Laguna registers for the blit. We also set the bit swizzle
// bit in the grCONTROL register.
ppdev->grCONTROL |= SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10600000, 2);
#endif
// Start the blit.
// added REQUIRE above
// REQUIRE(7);
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
// Copy all the bits to the screen, 32-bits at a time. We don't have to
// worry about crossing any boundary since NT is always DWORD aligned.
while (sizl.cy--)
{
WRITE_STRING(pBits, n);
pBits += lDelta;
}
#if SWAT7
sizlTotal.cx -= sizl.cx;
ptlSrc.x += sizl.cx;
ptlDest.x += sizl.cx;
// Reload pBits.
pBits = (PBYTE) psoSrc->pvScan0 + (ptlSrc.y * lDelta);
}
#endif
// Disable the swizzle bit in the grCONTROL register.
ppdev->grCONTROL = ppdev->grCONTROL & ~SWIZ_CNTL;
LL16(grCONTROL, ppdev->grCONTROL);
}
/* -----------------------------------------------------------------------
Test for 4-bpp source.
*/
else if (psoSrc->iBitmapFormat == BMF_4BPP)
{
// Get the pointer to the translation table.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if (flXlate & XO_TRIVIAL)
{
pulXlate = NULL;
}
else if (flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
// Calculate the source parameters.
pBits += ptlSrc.x >> 1;
#if !DRIVER_5465
// Get the number of extra DWORDS per line for the HOSTDATA hardware
// bug.
if (ppdev->dwLgDevID == CL_GD5462)
{
if (MAKE_HD_INDEX(sizl.cx * 4, 0, ptlDest.x * 4) == 3788)
{
// We have a problem with the HOSTDATA TABLE.
// Punt till we can figure it out.
return FALSE;
}
lExtra = ExtraDwordTable[MAKE_HD_INDEX(sizl.cx * 4, 0, ptlDest.x * 4)];
}
else
lExtra = 0;
#endif
// Start the blit.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
LL_OP1_MONO(0, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
// If there is no translation table, use the default translation table.
if (pulXlate == NULL)
{
pulXlate = ulXlate;
}
// Now we are ready to copy all the pixels to the hardware.
while (sizl.cy--)
{
BYTE *p = pBits;
// First, we must align the source to a BYTE boundary.
if (ptlSrc.x & 1)
{
// We convert 2 pixels at a time to create two 32-bit values
// to write to the hardware.
for (i = sizl.cx; i >= 2; i -= 2)
{
REQUIRE(2);
LL32(grHOSTDATA[0], pulXlate[p[0] & 0x0F]);
LL32(grHOSTDATA[1], pulXlate[p[1] >> 4]);
p++;
}
// Now, write any remaining pixel.
if (i)
{
REQUIRE(1);
LL32(grHOSTDATA[0], pulXlate[*p & 0x0F]);
}
}
else
{
// We convert 2 pixels at a time to create two 32-bit values
// to write to the hardware.
for (i = sizl.cx; i >= 2; i -= 2)
{
REQUIRE(2);
LL32(grHOSTDATA[0], pulXlate[p[0] >> 4]);
LL32(grHOSTDATA[1], pulXlate[p[0] & 0x0F]);
p++;
}
// Now, write any remaining pixel.
if (i)
{
REQUIRE(1);
LL32(grHOSTDATA[0], pulXlate[*p >> 4]);
}
}
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[0], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
/* -----------------------------------------------------------------------
Test for 8-bpp source.
*/
else if (psoSrc->iBitmapFormat == BMF_8BPP)
{
//
// Attempt to load the translation table into the chip.
// After this call:
// pulXlate == NULL if there is no color translation is required.
// pulXlate == translation table if color translation is required.
// UseHWxlate == FALSE if the hardware will do the xlate for us.
// UseHWxlate == TRUE if we must do the translation in software.
//
#if COLOR_TRANSLATE
ULONG UseHWxlate = bCacheXlateTable(ppdev, &pulXlate, psoTrg, psoSrc,
pxlo, (BYTE)(ulDRAWBLTDEF&0xCC));
#else
if ( (pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL) )
{
pulXlate = NULL;
}
else if (pxlo->flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
#endif
// A translation table is required.
// "Well, DUH!" you might say, but I've seen it missing before...
if (!pulXlate)
{
DISPDBG((0, "\n\nHost32ToDevice: !!! WARNING !!! 8BPP source "
"bitmap does not have a translation table. Punting!\n\n"));
return FALSE;
}
#if COLOR_TRANSLATE
//
// NVH: 5465 Color XLATE bug!!!
// Color translation is broken on the 5465 in 16, 24 and 32 bpp.
//
if (UseHWxlate)
{
DWORD phase = ( ((DWORD)(pBits + ptlSrc.x)) & 3);
if (XLATE_IS_BROKEN(sizl.cx, 4, phase))
UseHWxlate = FALSE; // force SW translation.
}
if (UseHWxlate)
{
// Use Hardware color translation.
DISPDBG((COPYBITS_DBG_LEVEL, "Host32ToDevice: "
"Attempting HW color translation on 8bpp Host to 32bpp Screen.\n"));
// Calculate the source parameters. We are going to DWORD adjust the
// source, so we also set the source phase.
pBits += ptlSrc.x; // Start of source data on the host.
lLeadIn = (DWORD)pBits & 3; // Source phase.
pBits -= lLeadIn; // Backup to DWORD boundry.
n = (sizl.cx + lLeadIn + 3) >> 2;// Number of HOSTDATA per scanline.
// Start the blit.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT_XLATE(8, sizl.cx, sizl.cy); // HW xlate.
while (sizl.cy--)
{
// Copy all data in 32-bit. We don't have to worry about
// crossing any boundaries, since within NT everything is DWORD
// aligned.
WRITE_STRING(pBits, n);
pBits += lDelta;
}
}
else
#endif
{
//
// Use SW color translation.
//
DISPDBG((COPYBITS_DBG_LEVEL, "Host32ToDevice: "
"Attempting SW color translation on 8bpp Host to 32bpp Screen.\n"));
// To do 8bpp host to 32bpp screen we must have a translation table.
ASSERTMSG(pulXlate,
"Host32ToDevice: No translation table for color translation.\n");
// Calculate the source parameters.
pBits += ptlSrc.x; // Start of source data on the host.
#if !DRIVER_5465
// Get the number of extra DWORDS per line for the HOSTDATA hardware
// bug.
if (ppdev->dwLgDevID == CL_GD5462)
{
if (MAKE_HD_INDEX(sizl.cx * 4, 0, ptlDest.x * 4) == 3788)
{
// We have a problem with the HOSTDATA TABLE.
// Punt till we can figure it out.
return FALSE;
}
lExtra = ExtraDwordTable[MAKE_HD_INDEX(sizl.cx * 4, 0, ptlDest.x * 4)];
}
else
{
lExtra = 0;
}
#endif
// Setup the Laguna registers.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
// Start the blit.
LL_OP1_MONO(0, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
while (sizl.cy--)
{
BYTE *p = pBits;
// Copy the pixels.
for (i = sizl.cx; i > 0; i--)
{
REQUIRE(1);
LL32(grHOSTDATA[0], pulXlate[*p]);
p++;
}
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[0], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
}
/* -----------------------------------------------------------------------
Source is in same color depth as screen.
*/
else
{
// Get the pointer to the translation table.
flXlate = pxlo ? pxlo->flXlate : XO_TRIVIAL;
if (flXlate & XO_TRIVIAL)
{
pulXlate = NULL;
}
else if (flXlate & XO_TABLE)
{
pulXlate = pxlo->pulXlate;
}
else if (pxlo->iSrcType == PAL_INDEXED)
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
else
{
// Some kind of translation we don't handle
return FALSE;
}
// If we have a translation table, punt it.
if ( pulXlate || (flXlate & 0x10) )
{
return(FALSE);
}
// Calculate the source parameters.
pBits += ptlSrc.x * 4;
#if !DRIVER_5465
// Get the number of extra DWORDS per line for the HOSTDATA hardware
// bug.
if (ppdev->dwLgDevID == CL_GD5462)
{
if (MAKE_HD_INDEX(sizl.cx * 4, 0, ptlDest.x * 4) == 3788)
{
// We have a problem with the HOSTDATA TABLE.
// Punt till we can figure it out.
return FALSE;
}
lExtra = ExtraDwordTable[MAKE_HD_INDEX(sizl.cx * 4, 0, ptlDest.x * 4)];
}
else
lExtra = 0;
#endif
// Setup the Laguna registers.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
// Start the blit.
LL_OP1_MONO(0, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
while (sizl.cy--)
{
WRITE_STRING(pBits, sizl.cx);
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[0], 0);
}
#endif
// Next line.
pBits += lDelta;
}
}
return(TRUE);
}
/*****************************************************************************\
* DoDeviceToHost32
*
* This routine performs a DeviceToHost for either monochrome or 32-bpp
* destinations.
*
* On entry: psoTrg Pointer to target surface object.
* psoSrc Pointer to source surface object.
* pxlo Pointer to translation object.
* prclTrg Destination rectangle.
* pptlSrc Source offset.
* ulDRAWBLTDEF Value for grDRAWBLTDEF register. This value has
* the ROP and the brush flags.
\*****************************************************************************/
BOOL DoDeviceToHost32(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF
)
{
POINTL ptlSrc;
PPDEV ppdev;
SIZEL sizl;
PBYTE pBits;
#if !S2H_USE_ENGINE
PBYTE pjScreen;
#endif
LONG lDelta;
ULONG i, n;
// Determine the source type and calculate the offset.
if (psoSrc->iType == STYPE_DEVBITMAP)
{
PDSURF pdsurf = (PDSURF)psoSrc->dhsurf;
ppdev = pdsurf->ppdev;
ptlSrc.x = pptlSrc->x + pdsurf->ptl.x;
ptlSrc.y = pptlSrc->y + pdsurf->ptl.y;
}
else
{
ppdev = (PPDEV)psoSrc->dhpdev;
ptlSrc.x = pptlSrc->x;
ptlSrc.y = pptlSrc->y;
}
// Calculate the size of the blit.
sizl.cx = prclTrg->right - prclTrg->left;
sizl.cy = prclTrg->bottom - prclTrg->top;
// Calculate the destination variables.
lDelta = psoTrg->lDelta;
pBits = (PBYTE)psoTrg->pvScan0 + (prclTrg->top * lDelta);
#if S2H_USE_ENGINE
// Setup the Laguna registers.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x20100000, 0);
LL_OP0(0, 0);
#else
// Calculate the screen address.
pjScreen = ppdev->pjScreen + ptlSrc.x * 4 + ptlSrc.y * ppdev->lDeltaScreen;
// Wait for the hardware to become idle.
while (LLDR_SZ(grSTATUS) != 0) ;
#endif
// Test for a monochrome destination.
if (psoTrg->iBitmapFormat == BMF_1BPP)
{
BYTE data, leftMask, rightMask;
ULONG fgColor;
DWORD *pulXlate;
LONG leftCount, rightCount, leftSkip;
// Calculate the monochrome masks.
pBits += prclTrg->left >> 3;
leftSkip = prclTrg->left & 7;
leftCount = (8 - leftSkip) & 7;
leftMask = 0xFF >> leftSkip;
rightCount = prclTrg->right & 7;
rightMask = 0xFF << (8 - rightCount);
// If we only have pixels in one byte, we combine rightMask with
// leftMask and set the routine to skip everything but the rightMask.
if (leftCount > sizl.cx)
{
rightMask &= leftMask;
leftMask = 0xFF;
n = 0;
}
else
{
n = (sizl.cx - leftCount) >> 3;
}
// Get the foreground color from the translation table.
pulXlate = XLATEOBJ_piVector(pxlo);
fgColor = pulXlate ? *pulXlate : 0;
#if S2H_USE_ENGINE
// Start the blit.
LL_OP1(ptlSrc.x - leftSkip, ptlSrc.y);
LL_BLTEXT(sizl.cx + leftSkip, sizl.cy);
#else
pjScreen -= leftSkip * 4;
#endif
while (sizl.cy--)
{
PBYTE pDest = pBits;
#if !S2H_USE_ENGINE
DWORD *pSrc = (DWORD *)pjScreen;
#endif
// If we have a left mask specified, we get the pixels and store
// them in the destination.
if (leftMask != 0xFF)
{
data = 0;
#if S2H_USE_ENGINE
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x80;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x40;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x20;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x10;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x08;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x04;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x02;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x01;
#else
if (pSrc[0] == fgColor) data |= 0x80;
if (pSrc[1] == fgColor) data |= 0x40;
if (pSrc[2] == fgColor) data |= 0x20;
if (pSrc[3] == fgColor) data |= 0x10;
if (pSrc[4] == fgColor) data |= 0x08;
if (pSrc[5] == fgColor) data |= 0x04;
if (pSrc[6] == fgColor) data |= 0x02;
if (pSrc[7] == fgColor) data |= 0x01;
pSrc += 8;
#endif
*pDest++ = (*pDest & ~leftMask) | (data & leftMask);
}
// Translate all pixels that don't require masking.
for (i = 0; i < n; i++)
{
data = 0;
#if S2H_USE_ENGINE
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x80;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x40;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x20;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x10;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x08;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x04;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x02;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x01;
#else
if (pSrc[0] == fgColor) data |= 0x80;
if (pSrc[1] == fgColor) data |= 0x40;
if (pSrc[2] == fgColor) data |= 0x20;
if (pSrc[3] == fgColor) data |= 0x10;
if (pSrc[4] == fgColor) data |= 0x08;
if (pSrc[5] == fgColor) data |= 0x04;
if (pSrc[6] == fgColor) data |= 0x02;
if (pSrc[7] == fgColor) data |= 0x01;
pSrc += 8;
#endif
*pDest++ = data;
}
// If we have a right mask specified, we get the pixels and store
// them in the destination.
if (rightMask != 0x00)
{
data = 0;
#if S2H_USE_ENGINE
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x80;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x40;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x20;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x10;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x08;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x04;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x02;
if (LLDR_SZ(grHOSTDATA[0]) == fgColor) data |= 0x01;
#else
if (pSrc[0] == fgColor) data |= 0x80;
if (pSrc[1] == fgColor) data |= 0x40;
if (pSrc[2] == fgColor) data |= 0x20;
if (pSrc[3] == fgColor) data |= 0x10;
if (pSrc[4] == fgColor) data |= 0x08;
if (pSrc[5] == fgColor) data |= 0x04;
if (pSrc[6] == fgColor) data |= 0x02;
if (pSrc[7] == fgColor) data |= 0x01;
#endif
*pDest = (*pDest & ~rightMask) | (data & rightMask);
}
// Next line.
#if !S2H_USE_ENGINE
pjScreen += ppdev->lDeltaScreen;
#endif
pBits += lDelta;
}
}
// We only support destination bitmaps with the same color depth and we
// do not support any color translation.
else if ( (psoTrg->iBitmapFormat != BMF_32BPP) ||
(pxlo && !(pxlo->flXlate & XO_TRIVIAL)) )
{
return(FALSE);
}
/*
If the GetPixel routine is being called, we get here with both cx and
cy set to 1 and the ROP to 0xCC (source copy). In this special case we
read the pixel directly from memory. Of course, we must be sure the
blit engine is finished working since it may still update the very
pixel we are going to read! We could use the hardware for this, but it
seems there is a HARDWARE BUG that doesn't seem to like the 1-pixel
ScreenToHost very much.
*/
#if S2H_USE_ENGINE
else if ( (sizl.cx == 1) && (sizl.cy == 1) && (ulDRAWBLTDEF == 0x000000CC) )
{
// Wait for the hardware to become idle.
while (LLDR_SZ(grSTATUS) != 0) ;
// Get the pixel from screen.
*(DWORD *)pBits[prclTrg->left] = *(DWORD *)
&ppdev->pjScreen[ptlSrc.x * 4 + ptlSrc.y * ppdev->lDeltaScreen];
}
#endif
else
{
#if S2H_USE_ENGINE
// The hardware requires us to get QWORDS.
BOOL fExtra = sizl.cx & 1;
#endif
pBits += prclTrg->left * 4;
#if S2H_USE_ENGINE
// Start the bit.
LL_OP1(ptlSrc.x, ptlSrc.y);
LL_BLTEXT(sizl.cx, sizl.cy);
#endif
while (sizl.cy--)
{
#if S2H_USE_ENGINE
DWORD *p = (DWORD *)pBits;
// Copy all pixels from screen to memory.
for (i = sizl.cx; i >= 1; i -= 1)
{
*p++ = LLDR_SZ(grHOSTDATA[0]);
}
// Get the extra pixel required for QWORD alignment.
if (fExtra)
{
LLDR_SZ(grHOSTDATA[0]);
}
#else
// Copy all pixels from screen to memory.
memcpy(pBits, pjScreen, sizl.cx * 4);
// Next line.
pjScreen += ppdev->lDeltaScreen;
#endif
pBits += lDelta;
}
}
return(TRUE);
}