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.
 
 
 
 
 
 

674 lines
18 KiB

/******************************Module*Header*******************************\
* Module Name: DEV2DEV.c
*
* Author: Noel VanHook
*
* Purpose: Handle device to device BLTs.
*
* Copyright (c) 1997 Cirrus Logic, Inc.
*
* $Log: X:/log/laguna/nt35/displays/cl546x/dev2dev.c $
*
* Rev 1.11 Mar 04 1998 15:13:52 frido
* Added new shadow macros.
*
* Rev 1.10 Jan 22 1998 16:20:10 frido
* Added 16-bit striping code.
*
* Rev 1.9 Jan 21 1998 13:46:52 frido
* Fixed the striping code since this is really the first time we check it.
*
* Rev 1.8 Jan 20 1998 11:43:26 frido
* Guess what? Striping was not turned on!
*
* Rev 1.7 Dec 10 1997 13:32:12 frido
* Merged from 1.62 branch.
*
* Rev 1.6.1.2 Dec 05 1997 13:34:26 frido
* PDR#11043. When using a brush, striping should use pixels instead of
* bytes, so now there is an intelligent switcher in place.
*
* Rev 1.6.1.1 Nov 18 1997 15:14:56 frido
* Added striping for 24-bpp.
*
* Rev 1.6.1.0 Nov 10 1997 13:39:26 frido
* PDR#10893: Inside DoDeviceToDeviceWithXlate the source pointer
* was not updated after each access.
*
* Rev 1.6 Nov 04 1997 13:40:56 frido
* I removed a little too much code in DoDeviceToDevice. The result was
* a very slow screen-to-screen blits since everything was punted back to
* GDI.
*
* Rev 1.5 Nov 04 1997 09:49:18 frido
* Added COLOR_TRANSLATE switches around hardware color translation code.
*
* Rev 1.4 Nov 03 1997 15:20:06 frido
* Added REQUIRE macros.
*
* Rev 1.3 15 Oct 1997 12:03:00 noelv
* Pass rop code to CacheXlateTable().
*
* Rev 1.2 02 Oct 1997 09:48:22 noelv
*
* Hardwre color translation only works with CC rop code.
*
* Rev 1.1 19 Feb 1997 13:14:22 noelv
*
* Fixed LL_BLTEXT_XLATE()
*
* Rev 1.0 06 Feb 1997 10:35:48 noelv
* Initial revision.
*
\**************************************************************************/
#include "precomp.h"
#define DEV2DEV_DBG_LEVEL 0
//
// Set to 1 to stripe screen to screen operations along tile boundries.
// Set to 0 to do screen to screen operations in a few BLTs as possible.
//
// on the 62, 64 and 65 striping is faster than not striping.
//
#define STRIPE_SCR2SCR 1
//
// internal prototypes.
//
BOOL DoDeviceToDeviceWithXlate(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
ULONG *pulXlate,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF
);
/*****************************************************************************\
* DoDeviceToDevice
*
* This routine performs a ScreenToScreen, DeviceToScreen or ScreenToDevice
* blit. If there is a color translation table, we will attempt to use
* the hardware color translator. If we can't (or don't have one) we will
* pass the call to DoDeviceToDeviceWithXlate, which will do the color
* translation is software.
*
* 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 DoDeviceToDevice(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
XLATEOBJ *pxlo,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF
)
{
POINTL ptlSrc, ptlDest;
SIZEL sizl;
PPDEV ppdev;
LONG tileSize, maxStripeWidth;
ULONG* pulXlate;
BOOL fStripePixels;
BOOL fFirst = TRUE;
//
// Determine the source type and adjust the source offset.
//
if (psoSrc->iType == STYPE_DEVBITMAP)
{
// Source is a device bitmap.
PDSURF pdsurf = (PDSURF) psoSrc->dhsurf;
ptlSrc.x = pptlSrc->x + pdsurf->ptl.x;
ptlSrc.y = pptlSrc->y + pdsurf->ptl.y;
ppdev = pdsurf->ppdev;
}
else
{
// Source is the screen.
ptlSrc.x = pptlSrc->x;
ptlSrc.y = pptlSrc->y;
ppdev = (PPDEV) psoSrc->dhpdev;
}
//
// Determine the destination type and adjust 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;
}
else
{
ptlDest.x = prclTrg->left;
ptlDest.y = prclTrg->top;
}
//
// Is there a translation table?
// If so, we will attempt to load it into the chip. This also
// points pulXlate at the color translation table, if there is one.
//
#if COLOR_TRANSLATE
if (! 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
{
pulXlate = XLATEOBJ_piVector(pxlo);
}
if (pulXlate != NULL)
#endif
{
// We must do software color translation.
return DoDeviceToDeviceWithXlate(psoTrg, psoSrc, pulXlate, prclTrg,
pptlSrc, ulDRAWBLTDEF);
}
//
// if pulXlate == NULL, there is no color translation required.
// if pulXlate != NULL, we will do hardware translation.
//
//
// We only do screen to screen color translation in 8 bpp.
//
ASSERTMSG( ((pulXlate == NULL) || (ppdev->iBitmapFormat == BMF_8BPP)),
"DoDeviceToDevice: Xlate with non-8bpp.\n");
if ((pulXlate) && (ppdev->iBitmapFormat != BMF_8BPP))
{
return FALSE;
}
// Calculate the size of the blit.
sizl.cx = prclTrg->right - prclTrg->left;
sizl.cy = prclTrg->bottom - prclTrg->top;
fStripePixels = (ulDRAWBLTDEF & 0x000F0000) | (pulXlate != NULL);
if (fStripePixels)
{
// Calculate the number of pixels per tile and per SRAM line.
switch (ppdev->iBitmapFormat)
{
case BMF_8BPP:
tileSize = ppdev->lTileSize;
maxStripeWidth = 120;
break;
case BMF_16BPP:
tileSize = ppdev->lTileSize / 2;
maxStripeWidth = 120 / 2;
break;
case BMF_24BPP:
tileSize = ppdev->cxScreen;
maxStripeWidth = max(ptlDest.x - ptlSrc.x, 120 / 3);
break;
case BMF_32BPP:
tileSize = ppdev->lTileSize / 4;
maxStripeWidth = 120 / 4;
break;
}
}
else
{
// Convert everything to bytes.
ptlSrc.x *= ppdev->iBytesPerPixel;
ptlDest.x *= ppdev->iBytesPerPixel;
sizl.cx *= ppdev->iBytesPerPixel;
tileSize = ppdev->lTileSize;
maxStripeWidth = 120;
}
// Test vertical direction of blitting and set grDRAWBLTDEF register
// accordingly.
if (ptlSrc.y < ptlDest.y)
{
ptlSrc.y += sizl.cy - 1;
ptlDest.y += sizl.cy - 1;
ulDRAWBLTDEF |= 0x90100000;
}
else
{
ulDRAWBLTDEF |= 0x10100000;
}
// Test horizontal direction of blitting.
if ( (ptlSrc.x >= ptlDest.x) || (ptlSrc.y != ptlDest.y) )
{
if (ptlSrc.x >= ptlDest.x)
{
// Blit to left.
while (sizl.cx > 0)
{
// Calculate the width of this blit.
LONG cx = sizl.cx;
// Calculate how many pixels it is to the next source tile
// boundary. Use lesser value.
cx = min(cx, tileSize - (ptlSrc.x % tileSize));
// Calculate how many pixels it is to the next destination tile
// boundary. Use lesser value.
cx = min(cx, tileSize - (ptlDest.x % tileSize));
// Perform the blit.
if (fFirst)
{
fFirst = FALSE;
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF, 0);
if (fStripePixels)
{
LL_OP1(ptlSrc.x, ptlSrc.y);
LL_OP0(ptlDest.x, ptlDest.y);
if (pulXlate) // launch a color xlate BLT
LL_BLTEXT_XLATE(8, cx, sizl.cy);
else // Launch a regular BLT
LL_BLTEXT(cx, sizl.cy);
}
else
{
LL_OP1_MONO(ptlSrc.x, ptlSrc.y);
LL_OP0_MONO(ptlDest.x, ptlDest.y);
LL_MBLTEXT(cx, sizl.cy);
}
}
else if (pulXlate)
{
REQUIRE(7);
LL_OP1(ptlSrc.x, ptlSrc.y);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT_XLATE(8, cx, sizl.cy);
}
else
{
REQUIRE(4);
if (fStripePixels)
{
LL16(grOP1_opRDRAM.PT.X, ptlSrc.x);
LL16(grOP0_opRDRAM.PT.X, ptlDest.x);
LL16(grBLTEXT_XEX.PT.X, cx);
}
else
{
LL16(grOP1_opMRDRAM.PT.X, ptlSrc.x);
LL16(grOP0_opMRDRAM.PT.X, ptlDest.x);
LL16(grMBLTEXT_XEX.PT.X, cx);
}
}
// Adjust the coordinates.
ptlSrc.x += cx;
ptlDest.x += cx;
sizl.cx -= cx;
}
}
else
{
// Blit to right.
ptlSrc.x += sizl.cx;
ptlDest.x += sizl.cx;
while (sizl.cx > 0)
{
// Calculate the width of this blit.
LONG cx = sizl.cx;
// Calculate how many pixels it is to the next source tile
// boundary. Use lesser value.
if ((ptlSrc.x % tileSize) == 0)
{
cx = min(cx, tileSize);
}
else
{
cx = min(cx, ptlSrc.x % tileSize);
}
// Calculate how many pixels it is to the next destination tile
// boundary. Use lesser value.
if ((ptlDest.x % tileSize) == 0)
{
cx = min(cx, tileSize);
}
else
{
cx = min(cx, ptlDest.x % tileSize);
}
// Perform the blit.
if (fFirst)
{
fFirst = FALSE;
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF, 0);
if (fStripePixels)
{
LL_OP1(ptlSrc.x - cx, ptlSrc.y);
LL_OP0(ptlDest.x - cx, ptlDest.y);
if (pulXlate) // launch a color xlate BLT
LL_BLTEXT_XLATE(8, cx, sizl.cy);
else // Launch a regular BLT
LL_BLTEXT(cx, sizl.cy);
}
else
{
LL_OP1_MONO(ptlSrc.x - cx, ptlSrc.y);
LL_OP0_MONO(ptlDest.x - cx, ptlDest.y);
LL_MBLTEXT(cx, sizl.cy);
}
}
else if (pulXlate)
{
REQUIRE(7);
LL_OP1(ptlSrc.x - cx, ptlSrc.y);
LL_OP0(ptlDest.x - cx, ptlDest.y);
LL_BLTEXT_XLATE(8, cx, sizl.cy);
}
else
{
REQUIRE(4);
if (fStripePixels)
{
LL16(grOP1_opRDRAM.PT.X, ptlSrc.x - cx);
LL16(grOP0_opRDRAM.PT.X, ptlDest.x - cx);
LL16(grBLTEXT_XEX.PT.X, cx);
}
else
{
LL16(grOP1_opMRDRAM.PT.X, ptlSrc.x - cx);
LL16(grOP0_opMRDRAM.PT.X, ptlDest.x - cx);
LL16(grMBLTEXT_XEX.PT.X, cx);
}
}
// Adjust the coordinates.
ptlSrc.x -= cx;
ptlDest.x -= cx;
sizl.cx -= cx;
}
}
}
else
{
// Blit using SRAM.
ptlSrc.x += sizl.cx;
ptlDest.x += sizl.cx;
while (sizl.cx > 0)
{
// Calculate the width of this blit. We must never overrun a single
// SRAM cache line.
LONG cx = min(sizl.cx, maxStripeWidth);
// Calculate how many pixels it is to the next source tile
// boundary. Use lesser value.
cx = min(cx, ((ptlSrc.x - 1) % tileSize) + 1);
// Calculate how many pixels it is to the next destination tile
// boundary. Use lesser value.
cx = min(cx, ((ptlDest.x - 1) % tileSize) + 1);
// Do the blit.
if (fFirst)
{
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF, 0);
if (fStripePixels)
{
LL_OP1(ptlSrc.x - cx, ptlSrc.y);
LL_OP0(ptlDest.x - cx, ptlDest.y);
if (pulXlate) // Launch a color xlate BLT
LL_BLTEXT_XLATE(8, cx, sizl.cy);
else // Launch a regular BLT
LL_BLTEXT(cx, sizl.cy);
}
else
{
LL_OP1_MONO(ptlSrc.x - cx, ptlSrc.y);
LL_OP0_MONO(ptlDest.x - cx, ptlDest.y);
LL_MBLTEXT(cx, sizl.cy);
}
}
else if (pulXlate)
{
REQUIRE(7);
LL_OP1(ptlSrc.x - cx, ptlSrc.y);
LL_OP0(ptlDest.x - cx, ptlDest.y);
LL_BLTEXT_XLATE(8, cx, sizl.cy);
}
else
{
REQUIRE(4);
if (fStripePixels)
{
LL16(grOP1_opRDRAM.PT.X, ptlSrc.x - cx);
LL16(grOP0_opRDRAM.PT.X, ptlDest.x - cx);
LL16(grBLTEXT_XEX.PT.X, cx);
}
else
{
LL16(grOP1_opMRDRAM.PT.X, ptlSrc.x - cx);
LL16(grOP0_opMRDRAM.PT.X, ptlDest.x - cx);
LL16(grMBLTEXT_XEX.PT.X, cx);
}
}
// Adjust the coordinates.
ptlSrc.x -= cx;
ptlDest.x -= cx;
sizl.cx -= cx;
}
}
return(TRUE);
}
/*****************************************************************************\
* DoDeviceToDeviceWithXlate
*
* This routine performs a ScreenToScreen, DeviceToScreen or ScreenToDevice
* blit when there is a color translation table.
* Color translation is done in software.
*
*
* On entry: psoTrg Pointer to target surface object.
* psoSrc Pointer to source surface object.
* pulXlate Translation table.
* prclTrg Destination rectangle.
* pptlSrc Source offset.
* ulDRAWBLTDEF Value for grDRAWBLTDEF register. This value has
* the ROP and the brush flags.
\*****************************************************************************/
BOOL DoDeviceToDeviceWithXlate(
SURFOBJ *psoTrg,
SURFOBJ *psoSrc,
ULONG *pulXlate,
RECTL *prclTrg,
POINTL *pptlSrc,
ULONG ulDRAWBLTDEF
)
{
POINTL ptlSrc, ptlDest;
SIZEL sizl;
PPDEV ppdev;
BYTE* pjSrc;
DWORD* pjHostData;
LONG lDelta, lExtra, lLeadIn, i, n, tileSize, maxStripeWidth;
// Determine the source type and adjust the source offset.
if (psoSrc->iType == STYPE_DEVBITMAP)
{
// Source is a device bitmap.
PDSURF pdsurf = (PDSURF) psoSrc->dhsurf;
ptlSrc.x = pptlSrc->x + pdsurf->ptl.x;
ptlSrc.y = pptlSrc->y + pdsurf->ptl.y;
ppdev = pdsurf->ppdev;
}
else
{
// Source is the screen.
ptlSrc.x = pptlSrc->x;
ptlSrc.y = pptlSrc->y;
ppdev = (PPDEV) psoSrc->dhpdev;
}
// Determine the destination type and adjust 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;
}
else
{
ptlDest.x = prclTrg->left;
ptlDest.y = prclTrg->top;
}
// We only support color translations in 8-bpp.
if (ppdev->iBitmapFormat != BMF_8BPP)
{
return FALSE;
}
// Calculate the size of the blit.
sizl.cx = prclTrg->right - prclTrg->left;
sizl.cy = prclTrg->bottom - prclTrg->top;
// Calculate the screen address.
pjSrc = ppdev->pjScreen + ptlSrc.x + ptlSrc.y * ppdev->lDeltaScreen;
lDelta = ppdev->lDeltaScreen;
pjHostData = (DWORD*) ppdev->pLgREGS->grHOSTDATA;
// Wait for the hardware to become idle.
while (LLDR_SZ(grSTATUS) != 0) ;
// DWORD align the source.
lLeadIn = (DWORD)pjSrc & 3;
pjSrc -= lLeadIn;
n = (sizl.cx + lLeadIn + 3) >> 2;
// Test for overlapping.
if (ptlSrc.y < ptlDest.y)
{
// Negative direction.
pjSrc += (sizl.cy - 1) * lDelta;
ptlDest.y += sizl.cy - 1;
lDelta = -lDelta;
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x90200000, 0);
}
else if (ptlSrc.y > ptlDest.y)
{
// Positive direction.
REQUIRE(9);
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
}
else
{
// Maybe horizontal overlap, punt call to GDI anyway.
return(FALSE);
}
#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.
LL_OP1_MONO(lLeadIn, 0);
LL_OP0(ptlDest.x, ptlDest.y);
LL_BLTEXT(sizl.cx, sizl.cy);
while (sizl.cy--)
{
BYTE *p = pjSrc;
BYTE pixel[4];
for (i = 0; i < n; i++)
{
pixel[0] = (BYTE) pulXlate[p[0]];
pixel[1] = (BYTE) pulXlate[p[1]];
pixel[2] = (BYTE) pulXlate[p[2]];
pixel[3] = (BYTE) pulXlate[p[3]];
p += 4;
REQUIRE(1);
*pjHostData = *(DWORD*) pixel;
}
#if !DRIVER_5465
// Now, write the extra DWORDS.
REQUIRE(lExtra);
for (i = 0; i < lExtra; i++)
{
LL32(grHOSTDATA[i], 0);
}
#endif
// Next line.
pjSrc += lDelta;
}
// Return okay.
return(TRUE);
}