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.
2035 lines
64 KiB
2035 lines
64 KiB
/*============================ Module Header ==========================*\
|
|
*
|
|
* Module Name: HOST2SCN.c
|
|
* Author: Noel VanHook
|
|
* Date: Oct. 10, 1995
|
|
* Purpose: Handles HOST to SCREEN BLTs
|
|
*
|
|
* Copyright (c) 1995 Cirrus Logic, Inc.
|
|
*
|
|
* $Log: X:/log/laguna/nt35/displays/cl546x/HOST2SCN.C $
|
|
*
|
|
* Rev 1.7 Mar 04 1998 15:27:16 frido
|
|
* Added new shadow macros.
|
|
*
|
|
* Rev 1.6 Nov 03 1997 15:43:52 frido
|
|
* Added REQUIRE and WRITE_STRING macros.
|
|
*
|
|
\*=====================================================================*/
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
#if BUS_MASTER
|
|
|
|
extern ULONG ulXlate[16]; // See COPYBITS.C
|
|
|
|
|
|
/*****************************************************************************\
|
|
* *
|
|
* 8 - B P P *
|
|
* *
|
|
\*****************************************************************************/
|
|
|
|
/*****************************************************************************\
|
|
* BusMasterBufferedHost8ToDevice
|
|
*
|
|
* This routine performs a HostToScreen or HostToDevice blit. The host data
|
|
* can be either monochrome, 4-bpp, or 8-bpp. Color translation is supported.
|
|
*
|
|
* Host data is read from the host bitmap and stored in a common buffer.
|
|
* The HOSTXY unit on the chip is used to transfer the data from the common
|
|
* buffer to the screen.
|
|
*
|
|
* 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 BusMasterBufferedHost8ToDevice(
|
|
SURFOBJ *psoTrg,
|
|
SURFOBJ *psoSrc,
|
|
XLATEOBJ *pxlo,
|
|
RECTL *prclTrg,
|
|
POINTL *pptlSrc,
|
|
ULONG ulDRAWBLTDEF
|
|
)
|
|
{
|
|
POINTL ptlDest, ptlSrc;
|
|
SIZEL sizl;
|
|
PPDEV ppdev;
|
|
PBYTE pBits;
|
|
LONG lDelta, i, j, n, lLeadIn, lExtra;
|
|
ULONG *pulXlate;
|
|
FLONG flXlate;
|
|
ULONG CurrentBuffer,
|
|
BufPhysAddr;
|
|
long ScanLinesPerBuffer,
|
|
ScanLinesThisBuffer;
|
|
PDWORD pHostData;
|
|
|
|
// Calculate the source offset.
|
|
ptlSrc.x = pptlSrc->x;
|
|
ptlSrc.y = pptlSrc->y;
|
|
|
|
//
|
|
// If the destination is a device bitmap, then our destination coordinates
|
|
// are relative the the upper left corner of the bitmap. The chip expects
|
|
// destination coordinates relative to to screen(0,0).
|
|
//
|
|
// 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.
|
|
// point pBits at the first scan line in the source.
|
|
//
|
|
lDelta = psoSrc->lDelta;
|
|
pBits = (PBYTE)psoSrc->pvScan0 + (ptlSrc.y * lDelta);
|
|
|
|
// 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;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
//
|
|
// Test for monochrome source.
|
|
//
|
|
// ------------------------------------------------------------------------
|
|
if (psoSrc->iBitmapFormat == BMF_1BPP)
|
|
{
|
|
ULONG bgColor, fgColor;
|
|
PDWORD pHostData = (PDWORD) ppdev->pLgREGS->grHOSTDATA;
|
|
|
|
// 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);
|
|
}
|
|
|
|
// 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;
|
|
|
|
// Setup the Laguna registers for the blit. We also set the bit swizzle
|
|
// bit in the grCONTROL register.
|
|
ppdev->grCONTROL |= SWIZ_CNTL;
|
|
REQUIRE(10);
|
|
LL16(grCONTROL, ppdev->grCONTROL);
|
|
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10600000, 0);
|
|
|
|
// Start the blit.
|
|
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;
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
// 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);
|
|
|
|
// Get the number of extra DWORDS per line for the HOSTDATA hardware
|
|
// bug.
|
|
lExtra = ExtraDwordTable[MAKE_HD_INDEX(sizl.cx, lLeadIn, ptlDest.x)];
|
|
|
|
// 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;
|
|
}
|
|
|
|
// Now, write the extra DWORDS.
|
|
REQUIRE(lExtra);
|
|
for (i = 0; i < lExtra; i++)
|
|
{
|
|
LL32(grHOSTDATA[0], 0);
|
|
}
|
|
|
|
// Next line.
|
|
pBits += lDelta;
|
|
}
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------
|
|
//
|
|
// Source is in same color depth as screen (8 bpp).
|
|
//
|
|
// -----------------------------------------------------------------------
|
|
else
|
|
{
|
|
DISPDBG((1, " * * * * Doing bus mastered SRCCPY. * * * * \n"));
|
|
|
|
// If we have invalid translation flags, punt the blit.
|
|
if (flXlate & 0x10)
|
|
return(FALSE);
|
|
|
|
|
|
//
|
|
// pBits points to the first host bitmap scan line that will
|
|
// be part of the BLT.
|
|
// This function relies on the fact that in NT land, scanlines always
|
|
// begin on a DWORD boundry in system memory.
|
|
//
|
|
ASSERTMSG( ((((ULONG)pBits) % 4) == 0),
|
|
"Scanline doesn't begin on a DWORD boundry.\n");
|
|
|
|
// Now point pBits at the first host bitmap pixel to be
|
|
// transferred to the screen.
|
|
pBits += ptlSrc.x; // pBits = First pixel of source bitmap.
|
|
|
|
//
|
|
// The Intel CPU doesn't like to transfer unaligned DWORDs.
|
|
//
|
|
// Just because the first pixel in a host bitmap scan line
|
|
// is DWORD aligned, doesn't mean that the first source pixel
|
|
// in this BLT is DWORD alinged. We may be starting with
|
|
// pixel 3 or something.
|
|
// If our first pixel is in the middle of a DWORD, we need to know
|
|
// where in the DWORD it lives.
|
|
// For example:
|
|
// If our first pixel is 0, then it lives at the start of a DWORD.
|
|
// If our first pixel is 3, then it lives at byte 3 in the DWORD.
|
|
// If our first pixel is 6, then it lives at byte 2 in the DWORD.
|
|
//
|
|
lLeadIn = (DWORD)pBits & 3;
|
|
|
|
|
|
// If the first pixel of the source data doesn't fall on a
|
|
// DWORD boundry, adjust it to the left until it does.
|
|
// We can do this because of the ASSERT we made above.
|
|
// We will instruct the chip to ignore the 'lead in' pixels
|
|
// at the start of each scan line.
|
|
pBits -= lLeadIn;
|
|
|
|
|
|
// Now figure out how many dwords there are in each scan line.
|
|
n = (sizl.cx + lLeadIn + 3) >> 2;
|
|
|
|
|
|
//
|
|
// We will split the BLT into pieces that can fit into our common
|
|
// buffer. We are guarenteed by the miniport that each buffer is big
|
|
// enough to fit at least one scan line.
|
|
//
|
|
// One optimization is if bitmap pitch = blt width, glue the
|
|
// scan lines together.
|
|
//
|
|
ScanLinesPerBuffer = ppdev->BufLength / (n*4);
|
|
CurrentBuffer = 1;
|
|
|
|
//
|
|
// Now BLT the bitmap one buffer at a time.
|
|
//
|
|
|
|
// Enable the HOST XY unit.
|
|
LL32(grHXY_HOST_CRTL_3D, 1);
|
|
LL32(grHXY_BASE1_OFFSET1_3D, 0);
|
|
|
|
// Setup the Laguna registers.
|
|
REQUIRE(4);
|
|
LL_DRAWBLTDEF(ulDRAWBLTDEF | 0x10200000, 0);
|
|
LL_OP1_MONO(lLeadIn, 0);
|
|
|
|
while (1) // Each loop transfers one buffer.
|
|
{
|
|
DISPDBG((1, " Filling buffer.\n"));
|
|
|
|
//
|
|
// Select the buffer we will use for this BLT.
|
|
//
|
|
if (CurrentBuffer)
|
|
{
|
|
pHostData = (PDWORD) ppdev->Buf1VirtAddr;
|
|
BufPhysAddr = (ULONG) ppdev->Buf1PhysAddr;
|
|
}
|
|
else
|
|
{
|
|
pHostData = (PDWORD) ppdev->Buf2VirtAddr;
|
|
BufPhysAddr = (ULONG) ppdev->Buf2PhysAddr;
|
|
}
|
|
|
|
|
|
// Is there enough bitmap left to fill an entire buffer?
|
|
if (ScanLinesPerBuffer > sizl.cy)
|
|
ScanLinesThisBuffer = sizl.cy; // No.
|
|
else
|
|
ScanLinesThisBuffer = ScanLinesPerBuffer;
|
|
|
|
|
|
//
|
|
// Now fill the buffer with bitmap data.
|
|
//
|
|
j = ScanLinesThisBuffer; // Counter for scan lines.
|
|
|
|
|
|
// Test for color translation.
|
|
if (pulXlate == NULL)
|
|
{
|
|
while (j--) // Loop for each scan line.
|
|
{
|
|
// Copy all data in 32-bit. We don't have to worry about
|
|
// crossing any boundaries, since within NT everything is
|
|
// DWORD aligned.
|
|
#if defined(i386) && INLINE_ASM
|
|
_asm
|
|
{
|
|
mov edi, pHostData
|
|
mov esi, pBits
|
|
mov ecx, n
|
|
rep movsd
|
|
}
|
|
#else
|
|
for (i = 0; i < n; i++)
|
|
pHostData[i] = pBits[i];
|
|
#endif
|
|
|
|
// Next line in source.
|
|
pBits += lDelta;
|
|
|
|
// Next line in buffer.
|
|
pHostData += n;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DWORD *p;
|
|
while (j--) // Loop for each scan line.
|
|
{
|
|
// p = pointer to source scan line
|
|
p = (DWORD *)pBits;
|
|
|
|
// Copy the scan line one DWORD at a time.
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
|
|
// We copy 4 pixels to fill an entire 32-bit DWORD.
|
|
union
|
|
{
|
|
BYTE byte[4];
|
|
DWORD dw;
|
|
} hostdata;
|
|
|
|
// Read a DWORD from the source.
|
|
hostdata.dw = *p++;
|
|
|
|
// Color convert it.
|
|
hostdata.byte[0] = (BYTE) pulXlate[hostdata.byte[0]];
|
|
hostdata.byte[1] = (BYTE) pulXlate[hostdata.byte[1]];
|
|
hostdata.byte[2] = (BYTE) pulXlate[hostdata.byte[2]];
|
|
hostdata.byte[3] = (BYTE) pulXlate[hostdata.byte[3]];
|
|
|
|
// Write it to the buffer.
|
|
*pHostData++ = hostdata.dw;
|
|
}
|
|
|
|
// Move to next line in source.
|
|
pBits += lDelta;
|
|
}
|
|
}
|
|
|
|
//
|
|
// The common buffer is full, now BLT it.
|
|
//
|
|
|
|
//
|
|
// Wait until HOST XY unit goes idle.
|
|
//
|
|
DISPDBG((1, " Waiting for HOSTXY idle.\n"));
|
|
do {
|
|
i = LLDR_SZ (grPF_STATUS_3D);
|
|
} while (i & 0x80);
|
|
|
|
//
|
|
// Wait until 2D unit goes idle.
|
|
//
|
|
DISPDBG((1, " Waiting for 2D idle.\n"));
|
|
do {
|
|
i = LLDR_SZ (grSTATUS);
|
|
} while (i);
|
|
|
|
|
|
//
|
|
// Program 2D Blitter.
|
|
//
|
|
DISPDBG((1, " Blitting buffer.\n"));
|
|
|
|
// Start the blit.
|
|
REQUIRE(5);
|
|
LL_OP0(ptlDest.x, ptlDest.y);
|
|
LL_BLTEXT(sizl.cx, ScanLinesThisBuffer);
|
|
|
|
|
|
//
|
|
// Program HostXY unit.
|
|
//
|
|
|
|
// Write host address page.
|
|
LL32(grHXY_BASE1_ADDRESS_PTR_3D, (BufPhysAddr&0xFFFFF000));
|
|
|
|
// Write host address offset.
|
|
LL32(grHXY_BASE1_OFFSET0_3D, (BufPhysAddr&0x00000FFF));
|
|
|
|
|
|
if (0)
|
|
{
|
|
// Write the length of the host data (in bytes)
|
|
// This starts the Host XY unit.
|
|
LL32(grHXY_BASE1_LENGTH_3D, (n*ScanLinesThisBuffer*4));
|
|
}
|
|
else
|
|
{
|
|
int i;
|
|
PDWORD BufVirtAddr;
|
|
|
|
if (CurrentBuffer)
|
|
BufVirtAddr = (PDWORD) ppdev->Buf1VirtAddr;
|
|
else
|
|
BufVirtAddr = (PDWORD) ppdev->Buf2VirtAddr;
|
|
|
|
WRITE_STRING(BufVirtAddr, n * ScanLinesThisBuffer);
|
|
}
|
|
|
|
//
|
|
// Get ready to do the next buffer.
|
|
//
|
|
|
|
//
|
|
// Wait until HOST XY unit goes idle.
|
|
//
|
|
DISPDBG((1, " Waiting for HOSTXY idle.\n"));
|
|
do {
|
|
i = LLDR_SZ (grPF_STATUS_3D);
|
|
} while (i & 0x80);
|
|
|
|
//
|
|
// Wait until 2D unit goes idle.
|
|
//
|
|
DISPDBG((1, " Waiting for 2D idle.\n"));
|
|
do {
|
|
i = LLDR_SZ (grSTATUS);
|
|
} while (i);
|
|
|
|
//
|
|
// Subtract the amount we're doing in this buffer from the
|
|
// total amount we have to do.
|
|
//
|
|
sizl.cy -= ScanLinesThisBuffer;
|
|
ptlDest.y += ScanLinesThisBuffer;
|
|
|
|
//
|
|
// Have we done the entire host bitmap?
|
|
//
|
|
if (sizl.cy == 0)
|
|
break;
|
|
|
|
DISPDBG((1, " Swapping buffers.\n"));
|
|
|
|
// Swap buffers.
|
|
// CurrentBuffer = !(CurrentBuffer);
|
|
if (CurrentBuffer)
|
|
CurrentBuffer = 0;
|
|
else
|
|
CurrentBuffer = 1;
|
|
|
|
|
|
} // End loop. Do next buffer.
|
|
|
|
//
|
|
// Wait until HOST XY unit goes idle.
|
|
//
|
|
DISPDBG((1, " Waiting for final idle.\n"));
|
|
do {
|
|
i = LLDR_SZ (grPF_STATUS_3D);
|
|
} while (i & 0x80);
|
|
|
|
DISPDBG((1, " Done.\n"));
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
#define H2S_DBG_LEVEL 1
|
|
|
|
//
|
|
// In an attempt to trace the problems with the FIFO, we supply a few
|
|
// macros that will allow us to easily try different FIFO stratagies.
|
|
//
|
|
|
|
//
|
|
// Certian parts of our driver are optimized for the i386.
|
|
// They have slower counterparts for non i386 machines.
|
|
//
|
|
#if defined(i386)
|
|
#define USE_DWORD_CAST 1 // i386 can address a DWORD anywhere.
|
|
#define USE_REP_MOVSD 0 // We could use a bit of in-line assembler.
|
|
#else
|
|
#define USE_DWORD_CAST 0
|
|
#define USE_REP_MOVSD 0
|
|
#endif
|
|
|
|
//
|
|
// All the BLT functions take the same parameters.
|
|
//
|
|
typedef BOOL BLTFN(
|
|
PPDEV ppdev,
|
|
RECTL* DestRect,
|
|
SURFOBJ* psoSrc,
|
|
POINTL* pptlSrc,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ULONG fg_rop,
|
|
XLATEOBJ* pxlo,
|
|
CLIPOBJ* pco);
|
|
|
|
|
|
//
|
|
// Top level BLT functions.
|
|
//
|
|
BLTFN MonoHostToScreen;
|
|
BLTFN Color8HostToScreen, Color16HostToScreen,
|
|
Color24HostToScreen, Color32HostToScreen;
|
|
|
|
//
|
|
// Clipping stuff
|
|
//
|
|
VOID BltClip(
|
|
PPDEV ppdev,
|
|
CLIPOBJ* pco,
|
|
RECTL* DestRect,
|
|
SURFOBJ* psoSrc,
|
|
POINTL* pptlSrc,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ULONG fg_rop,
|
|
XLATEOBJ* pxlo,
|
|
BLTFN* pDoBlt);
|
|
|
|
//
|
|
// Bottom level BLT functions.
|
|
//
|
|
BLTFN HW1HostToScreen, HW8HostToScreen, HW16HostToScreen, HW32HostToScreen;
|
|
|
|
//
|
|
// 8 bpp HostToScreen helper functions.
|
|
//
|
|
VOID DoAlignedH2SBlt(
|
|
PPDEV ppdev,
|
|
ULONG ulDstX, ULONG ulDstY,
|
|
ULONG ulExtX, ULONG ulExtY,
|
|
UCHAR *pucData, ULONG deltaX);
|
|
|
|
VOID DoNarrowH2SBlt(
|
|
PPDEV ppdev,
|
|
ULONG ulDstX, ULONG ulDstY,
|
|
ULONG ulExtX, ULONG ulExtY,
|
|
UCHAR *pucImageD, ULONG deltaX);
|
|
|
|
//
|
|
// Driver profiling stuff.
|
|
// Gets compiled out in a free bulid.
|
|
// Declaring puntcode as a global violates display driver rules, but the
|
|
// emulator was chock full of globals anyway, and besides we won't ever
|
|
// release a version with this enabled.
|
|
//
|
|
#if PROFILE_DRIVER
|
|
void DumpInfo(int acc, PPDEV ppdev, SURFOBJ* psoSrc, SURFOBJ* psoDest,
|
|
ULONG fg_rop, ULONG bg_rop, CLIPOBJ* pco, BRUSHOBJ* pbo, XLATEOBJ* pxlo);
|
|
extern int puntcode;
|
|
#define PUNTCODE(x) puntcode = x;
|
|
#else
|
|
#define DumpInfo(acc,ppdev,psoSrc,psoDest,fg_rop,bg_rop,pco,pbo,pxlo)
|
|
#define PUNTCODE(x)
|
|
#endif
|
|
|
|
// *************************************************************************
|
|
//
|
|
// MonoHostToScreen()
|
|
//
|
|
// Handles Monochrome Host to screen blts.
|
|
// Called by op1BLT() and op1op2BLT
|
|
// op1BLT() calls this routine with pbo = NULL.
|
|
// op1op2BLT calls it with pbo = current brush.
|
|
//
|
|
// This is the top level function. This function verifies parameters,
|
|
// and decides if we should punt or not.
|
|
//
|
|
// The BLT is then handed off to the clipping function. The clipping
|
|
// function is also given a pointer to the lower level BLT function
|
|
// HW1HostToScreen(), which will complete the clipped BLT.
|
|
//
|
|
// This function is the last chance to decide to punt. The clipping
|
|
// functions and the lower level HW1HostToScreen() function aren't
|
|
// allowed to punt.
|
|
//
|
|
// Return TRUE if we can do the BLT,
|
|
// Return FALSE to punt it back to GDI.
|
|
//
|
|
// *************************************************************************
|
|
BOOL MonoHostToScreen(
|
|
PPDEV ppdev,
|
|
RECTL* prclDest,
|
|
SURFOBJ* psoSrc,
|
|
POINTL* pptlSrc,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ULONG fg_rop,
|
|
XLATEOBJ* pxlo,
|
|
CLIPOBJ* pco)
|
|
{
|
|
PULONG pulXlate;
|
|
ULONG fg, bg, bltdef = 0x1160;
|
|
|
|
DISPDBG(( H2S_DBG_LEVEL,"DrvBitBlt: MonoHostToScreen Entry.\n"));
|
|
|
|
//
|
|
// Make sure source is a standard top-down bitmap.
|
|
//
|
|
if ( (psoSrc->iType != STYPE_BITMAP) ||
|
|
(!(psoSrc->fjBitmap & BMF_TOPDOWN)) )
|
|
{ PUNTCODE(4); return FALSE; }
|
|
|
|
//
|
|
// We don't do brushes with mono src.
|
|
//
|
|
if (pbo)
|
|
{ PUNTCODE(7); return FALSE; }
|
|
|
|
|
|
//
|
|
// Handle color translation.
|
|
//
|
|
if (pxlo == NULL) // Mono source requires translation.
|
|
{
|
|
PUNTCODE(6);
|
|
return FALSE;
|
|
}
|
|
else if (pxlo->flXlate & XO_TRIVIAL)
|
|
{
|
|
// For trivial translation we don't need a Xlate table.
|
|
fg = 1;
|
|
bg = 0;
|
|
}
|
|
else
|
|
{
|
|
// Get the Xlate table.
|
|
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;
|
|
}
|
|
|
|
// Translate the colors.
|
|
fg = ExpandColor(pulXlate[1],ppdev->ulBitCount);
|
|
bg = ExpandColor(pulXlate[0],ppdev->ulBitCount);
|
|
}
|
|
REQUIRE(4);
|
|
LL_FGCOLOR(fg, 2);
|
|
LL_BGCOLOR(bg, 2);
|
|
|
|
//
|
|
// Turn swizzle on.
|
|
//
|
|
ppdev->grCONTROL |= SWIZ_CNTL;
|
|
LL16(grCONTROL, ppdev->grCONTROL);
|
|
|
|
//
|
|
// Set function and ROP code.
|
|
//
|
|
LL_DRAWBLTDEF(((DWORD)bltdef << 16) | fg_rop, 2);
|
|
|
|
//
|
|
// Clip the BLT.
|
|
// The clipping function will call HW1HostToScreen() to finish the BLT.
|
|
//
|
|
if ((pco == 0) || (pco->iDComplexity==DC_TRIVIAL))
|
|
HW1HostToScreen(ppdev, prclDest, psoSrc, pptlSrc,
|
|
pbo, pptlBrush, fg_rop, pxlo, pco);
|
|
else
|
|
BltClip(ppdev, pco, prclDest, psoSrc, pptlSrc,
|
|
pbo, pptlBrush, fg_rop, pxlo, &HW1HostToScreen);
|
|
|
|
//
|
|
// Turn swizzle off
|
|
//
|
|
ppdev->grCONTROL = ppdev->grCONTROL & ~SWIZ_CNTL;
|
|
LL16(grCONTROL, ppdev->grCONTROL);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|
|
// ************************************************************************* //
|
|
// //
|
|
// HW1HostToScreen() //
|
|
// //
|
|
// This function is responsible for actually talking to the chip. //
|
|
// At this point we are required to handle the BLT, so we must return TRUE. //
|
|
// All decisions as to whether to punt or not must be made in the top level //
|
|
// function MonoHostToScreen(). //
|
|
// //
|
|
// This function is called from BltClip() through a pointer set by //
|
|
// MonoHostToScreen(). //
|
|
// //
|
|
// ************************************************************************* //
|
|
BOOL HW1HostToScreen(
|
|
PPDEV ppdev,
|
|
RECTL* prclDest,
|
|
SURFOBJ* psoSrc,
|
|
POINTL* pptlSrc,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ULONG fg_rop,
|
|
XLATEOBJ* pxlo,
|
|
CLIPOBJ* pco)
|
|
{
|
|
INT x, y, i;
|
|
INT bltWidth, bltHeight, phase;
|
|
PBYTE psrc;
|
|
DWORD hostdata;
|
|
char *phd = (char *)&hostdata;
|
|
|
|
DISPDBG(( H2S_DBG_LEVEL,"DrvBitBlt: HW1HostToScreen Entry.\n"));
|
|
|
|
|
|
// Calculate BLT size in pixels.
|
|
bltWidth = (prclDest->right - prclDest->left);
|
|
bltHeight = (prclDest->bottom - prclDest->top);
|
|
|
|
|
|
//
|
|
// Phase
|
|
// For 1bpp sources, we must be concerned with phase.
|
|
// Phase is the number of pixels to skip in the first dword
|
|
// of a scan line. For instance, if our BLT has a Src_X of 10,
|
|
// we take our first dword starting at second byte in the src
|
|
// scan line, and set our phase to 2 to indicate that we skip
|
|
// the first two pixels.
|
|
//
|
|
phase = pptlSrc->x % 8;
|
|
REQUIRE(7);
|
|
LL_OP1_MONO(phase,0);
|
|
|
|
//
|
|
// Calculate blt width in BYTESs.
|
|
// When calculating the number of BYTES per line, we need to
|
|
// include the unused pixels at the start of the first BYTE
|
|
//
|
|
bltWidth += phase;
|
|
|
|
// Divide bltWidth by 8 pixels per BYTE.
|
|
// Account for extra partial BYTE if bltWidth isn't evenly
|
|
// divisible by 8.
|
|
bltWidth = (bltWidth+7) / 8;
|
|
|
|
//
|
|
// Set psrc to point to first pixel in source.
|
|
//
|
|
psrc = psoSrc->pvScan0; // Start of surface.
|
|
psrc += (psoSrc->lDelta * pptlSrc->y); // Start of scanline.
|
|
psrc += (pptlSrc->x / 8); // Starting pixel in scanline.
|
|
|
|
// Set up the chip.
|
|
LL_OP0 (prclDest->left, prclDest->top);
|
|
LL_BLTEXT ((prclDest->right - prclDest->left), bltHeight);
|
|
|
|
|
|
// For each scan line in the source rectangle.
|
|
for (y=0; y<bltHeight; ++y)
|
|
{
|
|
//
|
|
// Supply the HOSTDATA for this scan line.
|
|
// We do this by reading it one byte at a time, and packing it into a
|
|
// DWORD, which we write to the chip when it gets full.
|
|
// It sound's inefficent, but a general purpose solution that
|
|
// does only aligned DWORD accesses on both the host and the chip would
|
|
// require lots of special casing around the first and last DWORD.
|
|
// Combine that with the fact that most Mono-to-Color BLTS are
|
|
// less than 2 dwords wide, and this simpler solution becomes
|
|
// more attractive.
|
|
//
|
|
#if 1
|
|
WRITE_STRING(psrc, (bltWidth + 3) / 4);
|
|
#else
|
|
i=0; // counter to tell us when our DWORD is full.
|
|
hostdata=0; // The DWORD we will be filling with hostdata.
|
|
// pdh is a char pointer that points to the start
|
|
// of the dword we are filling up.
|
|
|
|
for (x=0; x<bltWidth; ) // For each byte in the scan line...
|
|
{
|
|
#if (USE_DWORD_CAST)
|
|
if ( (x + 4) <= bltWidth)
|
|
{
|
|
|
|
REQUIRE(1);
|
|
LL32 (grHOSTDATA[0], *(DWORD*)(&psrc[x]));
|
|
x += 4;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
phd[i++] = psrc[x]; // Store this byte.
|
|
|
|
if (i == 4) // We have a full DWORD of data, write it to the chip.
|
|
{
|
|
REQUIRE(1);
|
|
LL32 (grHOSTDATA[0], hostdata);
|
|
i=0;
|
|
hostdata=0;
|
|
}
|
|
++x;
|
|
}
|
|
}
|
|
|
|
// Write the last partial DWORD.
|
|
if (i != 0)
|
|
REQUIRE(1);
|
|
LL32 (grHOSTDATA[0], hostdata);
|
|
#endif
|
|
|
|
// Move down one scanline in source.
|
|
psrc += psoSrc->lDelta;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
// ************************************************************************* //
|
|
// //
|
|
// Color8HostToScreen() //
|
|
// //
|
|
// Handles 8 bpp Host to screen blts. //
|
|
// //
|
|
// Called by op1BLT() and op1op2BLT //
|
|
// op1BLT() calls this routine with pbo = NULL. //
|
|
// op1op2BLT calls it with pbo = current brush. //
|
|
// //
|
|
// This is the top level function. This function verifies parameters, //
|
|
// and decides if we should punt or not. //
|
|
// //
|
|
// The BLT is then handed off to the clipping function. The clipping //
|
|
// function is also given a pointer to the lower level BLT function //
|
|
// HW8HostToScreen(), which will complete the clipped BLT. //
|
|
// //
|
|
// This function is the last chance to decide to punt. The clipping //
|
|
// functions and the lower level HW8HostToScreen() function aren't //
|
|
// allowed to punt. //
|
|
// //
|
|
// Return TRUE if we can do the BLT, //
|
|
// Return FALSE to punt it back to GDI. //
|
|
// //
|
|
// //
|
|
// ************************************************************************* //
|
|
BOOL Color8HostToScreen(
|
|
PPDEV ppdev,
|
|
RECTL* prclDest,
|
|
SURFOBJ* psoSrc,
|
|
POINTL* pptlSrc,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ULONG fg_rop,
|
|
XLATEOBJ* pxlo,
|
|
CLIPOBJ* pco)
|
|
{
|
|
ULONG bltdef = 0x1120; // RES=fb, OP0=fb OP1=host
|
|
|
|
DISPDBG(( H2S_DBG_LEVEL, "DrvBitBlt: Color8HostToScreen Entry.\n"));
|
|
|
|
//
|
|
// We don't handle src with a different color depth than the screen
|
|
//
|
|
if (psoSrc->iBitmapFormat != ppdev->iBitmapFormat)
|
|
{
|
|
PUNTCODE(13);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Translation type must be nothing or trivial.
|
|
// We don't handle Xlates for color source.
|
|
//
|
|
if (!((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
|
|
{
|
|
PUNTCODE(5);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Make sure source is a standard top-down bitmap.
|
|
//
|
|
if ( (psoSrc->iType != STYPE_BITMAP) ||
|
|
(!(psoSrc->fjBitmap & BMF_TOPDOWN)) )
|
|
{
|
|
PUNTCODE(4);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Set up the brush if there is one.
|
|
//
|
|
if (pbo)
|
|
{
|
|
if (SetBrush(ppdev, &bltdef, pbo, pptlBrush) == FALSE)
|
|
{
|
|
PUNTCODE(8);
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Function and ROP code.
|
|
//
|
|
REQUIRE(1);
|
|
LL_DRAWBLTDEF((bltdef << 16) | fg_rop, 2);
|
|
|
|
//
|
|
// Turn swizzle off.
|
|
//
|
|
ppdev->grCONTROL = ppdev->grCONTROL & ~SWIZ_CNTL;
|
|
LL16(grCONTROL, ppdev->grCONTROL);
|
|
|
|
//
|
|
// Clip the BLT.
|
|
// The clipping function will call HW8HostToScreen() to finish the BLT.
|
|
//
|
|
if ((pco == 0) || (pco->iDComplexity==DC_TRIVIAL))
|
|
HW8HostToScreen(ppdev, prclDest, psoSrc, pptlSrc,
|
|
pbo, pptlBrush, fg_rop, pxlo, pco);
|
|
else
|
|
BltClip(ppdev, pco, prclDest, psoSrc, pptlSrc,
|
|
pbo, pptlBrush, fg_rop, pxlo, &HW8HostToScreen);
|
|
|
|
return (TRUE);
|
|
}
|
|
|
|
|
|
// *************************************************************************
|
|
//
|
|
// HW8HostToScreen()
|
|
//
|
|
// This function is responsible for actually talking to the chip.
|
|
// At this point we are required to handle the BLT, so we must return TRUE.
|
|
// All decisions as to whether to punt or not must be made in the top level
|
|
// function Color8HostToScreen().
|
|
//
|
|
// This function is called from BltClip() through a pointer set by
|
|
// Color8HostToScreen().
|
|
//
|
|
/*
|
|
|
|
This routine does host to screen BLTs using DWORD aligned
|
|
reads on the host whenever possible.
|
|
|
|
The general plan is to split the BLT into up to three stripes.
|
|
|
|
The first stripe is used if the BLT doesn't begin on a DWORD
|
|
boundry.
|
|
This stripe is < 1 DWORD wide and uses CHAR accesses on
|
|
the host, and a single DWORD write to the screen, with the
|
|
source phase set to indicated which bytes are valid.
|
|
|
|
The second stripe is a middle stripe that both starts and ends
|
|
on DWORD boundries. This stripe will make up the bulk of large BLTs,
|
|
but for narrow BLTs, it may not be used at all.
|
|
|
|
The third stripe is used if the BLT doesn't end on a DWORD boundry.
|
|
It is implimented much the way the first stripe is.
|
|
|
|
One thing to consider is the scan line length of the bitmap on
|
|
the host. We can ignore bitmaps with an odd scan line length
|
|
since Windows requires that all bitmaps have an even scan line
|
|
length. That leaves two interesting cases:
|
|
|
|
1) Bitmaps with a scan line length that is DWORD divisable.
|
|
(even WORD length)
|
|
|
|
2) Bitmaps with a scan line lenght that is *not* DWORD divisable.
|
|
(odd WORD length)
|
|
|
|
For case one, the above plan works nicely. It handles the host data
|
|
one byte at a time until it reaches the first DWORD boundry, then
|
|
it handles the data one DWORD at a time, until there is less than
|
|
one DWORD of data left, and then handles the last couple of bytes
|
|
one byte at a time.
|
|
|
|
For case two, however, the plan only works for odd scan lines.
|
|
When BLTing the large "aligned" block in the middle of the BLT,
|
|
the odd scan lines will all align nicely on DWORD boundries,
|
|
but the even scan lines will be "off" by one word. While this
|
|
is not optimal, it "almost" optimal, and is easier than an
|
|
optimal solution, and will work even on a Power PC.
|
|
|
|
The code looks something like this:
|
|
|
|
if (BLT is 4 bytes wide or less)
|
|
{
|
|
Read host one byte at a time, pack it into DWORDS, and
|
|
write it to the chip.
|
|
}
|
|
else
|
|
{
|
|
if (left edge of the source doesn't align to a DWORD address)
|
|
{
|
|
Split the BLT at the first DWORD boundry on the source.
|
|
|
|
BLT the left part like it was an under-4-byte-wide BLT.
|
|
(see above)
|
|
|
|
Adjust BLT source, destination and extents to exclude
|
|
the stripe just done.
|
|
}
|
|
|
|
//
|
|
// Now we know that the left edge of source aligns to a
|
|
// DWORD boundry on the host.
|
|
//
|
|
|
|
if (right edge of source doesn't align to a DWORD address)
|
|
{
|
|
Split off a stripe to the right of the last DWORD
|
|
boundry, and use an under-4-byte-wide BLT on it.
|
|
|
|
Adjust BLT extent to exclude the stripe just done.
|
|
}
|
|
|
|
|
|
//
|
|
// Anything left over will always DWORD aligned on both edges.
|
|
//
|
|
|
|
if (there is any part of the BLT left over)
|
|
{
|
|
do an ALINGED BLT.
|
|
}
|
|
|
|
}
|
|
|
|
All Done!
|
|
|
|
*/
|
|
//
|
|
// *************************************************************************
|
|
|
|
BOOL HW8HostToScreen(
|
|
PPDEV ppdev,
|
|
RECTL* prclDest,
|
|
SURFOBJ* psoSrc,
|
|
POINTL* pptlSrc,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ULONG fg_rop,
|
|
XLATEOBJ* pxlo,
|
|
CLIPOBJ* pco)
|
|
{
|
|
PBYTE psrc;
|
|
DWORD *pdsrc;
|
|
UCHAR *pucData;
|
|
ULONG temp, x, y,
|
|
ulExtX, ulExtY,
|
|
ulDstX, ulDstY;
|
|
|
|
|
|
DISPDBG(( H2S_DBG_LEVEL, "DrvBitBlt: HW8HostToScreen Entry.\n"));
|
|
|
|
//
|
|
// Calculate BLT size in pixels.
|
|
//
|
|
ulDstX = prclDest->left;
|
|
ulDstY = prclDest->top;
|
|
ulExtX = (prclDest->right - prclDest->left);
|
|
ulExtY = (prclDest->bottom - prclDest->top);
|
|
|
|
|
|
//
|
|
// Get the address of the upper left source pixel.
|
|
//
|
|
pucData = psoSrc->pvScan0; // Start of surface.
|
|
pucData += (psoSrc->lDelta * pptlSrc->y); // Start of scanline.
|
|
pucData += (pptlSrc->x * ppdev->iBytesPerPixel); // Starting pixel.
|
|
|
|
|
|
|
|
//
|
|
// if the BLT is 4 or less bytes wide, just do it.
|
|
//
|
|
if (ulExtX <= 4)
|
|
{
|
|
// Do the BLT and exit.
|
|
DoNarrowH2SBlt( ppdev,
|
|
ulDstX, ulDstY,
|
|
ulExtX, ulExtY,
|
|
pucData, psoSrc->lDelta);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
// Is the left edge DWORD aligned?
|
|
//
|
|
temp = ((ULONG)pucData) % 4;
|
|
if ( temp != 0) // No.
|
|
{
|
|
ULONG ulLeftStripeExtX;
|
|
|
|
//
|
|
// Blt the unaligned left edge.
|
|
//
|
|
ulLeftStripeExtX = (4 - temp);
|
|
DoNarrowH2SBlt( ppdev,
|
|
ulDstX, ulDstY,
|
|
ulLeftStripeExtX, ulExtY,
|
|
pucData, psoSrc->lDelta);
|
|
|
|
//
|
|
// Adjust BLT parameters to exclude the part we just did.
|
|
//
|
|
ulDstX = ulDstX + ulLeftStripeExtX;
|
|
ulExtX = ulExtX - ulLeftStripeExtX;
|
|
pucData = pucData + ulLeftStripeExtX;
|
|
|
|
}
|
|
|
|
|
|
//
|
|
// Is the right edge DWORD aligned?
|
|
//
|
|
temp = ((ULONG)(pucData + ulExtX)) % 4;
|
|
if (temp != 0) // No.
|
|
{
|
|
ULONG ulMiddleStripeExtX,
|
|
ulRightStripeExtX,
|
|
ulRightStripeDstX;
|
|
UCHAR * pucRightStripeData;
|
|
|
|
|
|
//
|
|
// Break the BLT into a middle (aligned) stripe and a
|
|
// right (unaligned) stripe.
|
|
// The middle stripe could be 0 width.
|
|
//
|
|
ulRightStripeExtX = temp;
|
|
ulMiddleStripeExtX = ulExtX - ulRightStripeExtX;
|
|
ulRightStripeDstX = ulDstX + ulMiddleStripeExtX;
|
|
pucRightStripeData = pucData + ulMiddleStripeExtX;
|
|
|
|
//
|
|
// BLT the right (unaligned) stripe.
|
|
//
|
|
DoNarrowH2SBlt( ppdev,
|
|
ulRightStripeDstX, ulDstY,
|
|
ulRightStripeExtX, ulExtY,
|
|
pucRightStripeData, psoSrc->lDelta);
|
|
|
|
//
|
|
// Adjust BLT parameters to exclude the right stripe we just did.
|
|
//
|
|
ulExtX = ulMiddleStripeExtX;
|
|
}
|
|
|
|
//
|
|
// If anything remains, it is aligned to a DWORD boundry
|
|
// on the HOST and is an multiple of 4 wide.
|
|
//
|
|
|
|
if (ulExtX != 0)
|
|
{
|
|
DoAlignedH2SBlt
|
|
(ppdev, ulDstX, ulDstY, ulExtX, ulExtY, pucData, psoSrc->lDelta);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
//
|
|
// DoNarrowBlt() -- Does an 8bpp BLT that is no more than 4 pixels wide
|
|
//
|
|
//****************************************************************************
|
|
VOID DoNarrowH2SBlt(
|
|
PPDEV ppdev,
|
|
ULONG ulDstX,
|
|
ULONG ulDstY,
|
|
ULONG ulExtX,
|
|
ULONG ulExtY,
|
|
UCHAR *pucImageD,
|
|
ULONG deltaX)
|
|
{
|
|
ULONG usDataIncrement = deltaX,
|
|
usSrcPhase = 0,
|
|
ulY;
|
|
UCHAR *pucData = pucImageD;
|
|
union
|
|
{
|
|
ULONG ul;
|
|
struct
|
|
{
|
|
unsigned char c0;
|
|
unsigned char c1;
|
|
unsigned char c2;
|
|
unsigned char c3;
|
|
} b;
|
|
} hostdata;
|
|
|
|
DISPDBG(( (H2S_DBG_LEVEL), "DrvBitBlt: Entry to DoNarrowH2SBlt.\n"));
|
|
|
|
REQUIRE(7);
|
|
LL_OP1(usSrcPhase,0);
|
|
LL_OP0 (ulDstX, ulDstY);
|
|
LL_BLTEXT (ulExtX, ulExtY);
|
|
|
|
//
|
|
// Since there are only 4 possible x extents,
|
|
// we will handle each seperatly for maximum speed.
|
|
//
|
|
switch (ulExtX)
|
|
{
|
|
case 1:
|
|
for (ulY = 0; ulY < ulExtY; ulY++)
|
|
{
|
|
#if USE_DWORD_CAST // Intel x86 can do DWORD access anywhere.
|
|
REQUIRE(1);
|
|
LL32 (grHOSTDATA[0], ((ULONG)pucData[0]) );
|
|
#else
|
|
hostdata.ul = 0;
|
|
hostdata.b.c0 = pucData[0];
|
|
REQUIRE(1);
|
|
LL32 (grHOSTDATA[0], hostdata.ul );
|
|
#endif
|
|
|
|
pucData += usDataIncrement; // Move to next scan line.
|
|
} // End for each scan line.
|
|
break;
|
|
|
|
case 2:
|
|
for (ulY = 0; ulY < ulExtY; ulY++)
|
|
{
|
|
#if USE_DWORD_CAST // Intel x86 can do DWORD access anywhere.
|
|
REQUIRE(1);
|
|
LL32 (grHOSTDATA[0], (ULONG)(*((unsigned short *) pucData)) );
|
|
#else
|
|
hostdata.ul = 0;
|
|
hostdata.b.c1 = pucData[1];
|
|
hostdata.b.c0 = pucData[0];
|
|
REQUIRE(1);
|
|
LL32 (grHOSTDATA[0], hostdata.ul );
|
|
#endif
|
|
|
|
pucData += usDataIncrement; // Move to next scan line.
|
|
} // End for each scan line.
|
|
break;
|
|
|
|
case 3:
|
|
for (ulY = 0; ulY < ulExtY; ulY++)
|
|
{
|
|
hostdata.ul = 0;
|
|
hostdata.b.c2 = pucData[2];
|
|
hostdata.b.c1 = pucData[1];
|
|
hostdata.b.c0 = pucData[0];
|
|
REQUIRE(1);
|
|
LL32 (grHOSTDATA[0], hostdata.ul );
|
|
|
|
pucData += usDataIncrement; // Move to next scan line.
|
|
} // End for each scan line.
|
|
break;
|
|
|
|
case 4:
|
|
for (ulY = 0; ulY < ulExtY; ulY++)
|
|
{
|
|
#if USE_DWORD_CAST // Intel x86 can do DWORD access anywhere.
|
|
REQUIRE(1);
|
|
LL32 (grHOSTDATA[0], (*((unsigned long *) pucData)) );
|
|
#else
|
|
hostdata.b.c3 = pucData[3];
|
|
hostdata.b.c2 = pucData[2];
|
|
hostdata.b.c1 = pucData[1];
|
|
hostdata.b.c0 = pucData[0];
|
|
REQUIRE(1);
|
|
LL32 (grHOSTDATA[0], hostdata.ul );
|
|
#endif
|
|
|
|
pucData += usDataIncrement; // Move to next scan line.
|
|
} // End for each scan line.
|
|
break;
|
|
} // End switch.
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//****************************************************************************
|
|
//
|
|
// DoAlignedH2SBlt()
|
|
//
|
|
// Does an aligned 8bpp BLT.
|
|
// On entry Source will always be aligned to a DWORD boundry and
|
|
// X extent will always be a DWORD multiple.
|
|
//
|
|
//****************************************************************************
|
|
|
|
VOID DoAlignedH2SBlt(
|
|
PPDEV ppdev,
|
|
ULONG ulDstX,
|
|
ULONG ulDstY,
|
|
ULONG ulExtX,
|
|
ULONG ulExtY,
|
|
UCHAR *pucData,
|
|
ULONG deltaX)
|
|
|
|
{
|
|
ULONG ulX, ulY, i, num_extra, ulNumDwords,
|
|
usDataIncrement, usSrcPhase;
|
|
void *pdst = (void *)ppdev->pLgREGS->grHOSTDATA;
|
|
|
|
DISPDBG(( (H2S_DBG_LEVEL), "DrvBitBlt: Entry to DoAlignedH2SBlt.\n"));
|
|
|
|
ulNumDwords = ulExtX / 4;
|
|
usDataIncrement = deltaX;
|
|
usSrcPhase = 0;
|
|
|
|
|
|
//
|
|
// We have a bug in the chip that causes it to require extra data under
|
|
// certian conditions. We use a look-up table to see how much extra
|
|
// data this BLT will require for each scanline.
|
|
//
|
|
i = MAKE_HD_INDEX(ulExtX, usSrcPhase, ulDstX);
|
|
num_extra = ExtraDwordTable [i];
|
|
|
|
|
|
//
|
|
// Set up the chip.
|
|
//
|
|
REQUIRE(7);
|
|
LL_OP1 (usSrcPhase,0);
|
|
LL_OP0 (ulDstX, ulDstY);
|
|
LL_BLTEXT (ulExtX, ulExtY);
|
|
|
|
|
|
//
|
|
// Supply the HOSTDATA.
|
|
// We keep the decision about whether we have to work
|
|
// around the HOSTDATA bug *outside* of the loop, even though
|
|
// that means keeping two copies of it.
|
|
//
|
|
|
|
if (num_extra) // Do we have to deal with the HostData bug?
|
|
{
|
|
//
|
|
// Yes, append extra DWORDs to the end of each scan line.
|
|
//
|
|
|
|
for (ulY = 0; ulY < ulExtY; ulY++) // for each scan line.
|
|
{
|
|
// Write the data for this scan line.
|
|
WRITE_STRING(pucData, ulNumDwords);
|
|
|
|
// Write extra data to get around chip bug.
|
|
REQUIRE(num_extra);
|
|
for (i=0; i<num_extra; ++i)
|
|
LL32 (grHOSTDATA[0], 0);
|
|
|
|
// Move to next scan line.
|
|
pucData += usDataIncrement;
|
|
|
|
} // End for each scan line.
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// No need to worry about the HOSTDATA bug,
|
|
// Just blast the data out there.
|
|
//
|
|
|
|
for (ulY = 0; ulY < ulExtY; ulY++) // for each scan line.
|
|
{
|
|
// Write the data for this scan line.
|
|
WRITE_STRING(pucData, ulNumDwords);
|
|
|
|
// Move to next scan line.
|
|
pucData += usDataIncrement;
|
|
|
|
} // End for each scan line.
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
//
|
|
// Color16HostToScreen
|
|
//
|
|
// Handles 16 bpp Host to screen blts.
|
|
//
|
|
// Called by op1BLT() and op1op2BLT
|
|
// op1BLT() calls this routine with pbo = NULL.
|
|
// op1op2BLT calls it with pbo = current brush.
|
|
//
|
|
// This is the top level function. This function verifies parameters,
|
|
// and decides if we should punt or not.
|
|
//
|
|
// The BLT is then handed off to the clipping function. The clipping
|
|
// function is also given a pointer to the lower level BLT function
|
|
// HW16HostToScreen(), which will complete the clipped BLT.
|
|
//
|
|
// This function is the last chance to decide to punt. The clipping
|
|
// functions and the lower level HW16HostToScreen() function aren't
|
|
// allowed to punt.
|
|
//
|
|
// Return TRUE if we can do the BLT,
|
|
// Return FALSE to punt it back to GDI.
|
|
//
|
|
// ===========================================================================
|
|
BOOL Color16HostToScreen(
|
|
PPDEV ppdev,
|
|
RECTL* prclDest,
|
|
SURFOBJ* psoSrc,
|
|
POINTL* pptlSrc,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ULONG fg_rop,
|
|
XLATEOBJ* pxlo,
|
|
CLIPOBJ* pco)
|
|
{
|
|
PULONG pulXlate;
|
|
ULONG bltdef = 0x1120; // RES=fb, OP0=fb OP1=host
|
|
|
|
DISPDBG(( H2S_DBG_LEVEL, "DrvBitBlt: Color16HostToScreen Entry.\n"));
|
|
|
|
//
|
|
// We don't handle src with a different color depth than the screen
|
|
//
|
|
if (psoSrc->iBitmapFormat != ppdev->iBitmapFormat)
|
|
{
|
|
PUNTCODE(13);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the source translation type.
|
|
// We don't handle Xlates for color source.
|
|
//
|
|
if (!((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
|
|
{
|
|
PUNTCODE(5);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Make sure source is a standard top-down bitmap.
|
|
//
|
|
if ( (psoSrc->iType != STYPE_BITMAP) ||
|
|
(!(psoSrc->fjBitmap & BMF_TOPDOWN)) )
|
|
{
|
|
PUNTCODE(4);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Set up the brush if there is one.
|
|
//
|
|
if (pbo)
|
|
if (SetBrush(ppdev, &bltdef, pbo, pptlBrush) == FALSE)
|
|
{
|
|
PUNTCODE(8);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
//
|
|
// Turn swizzle off.
|
|
//
|
|
ppdev->grCONTROL = ppdev->grCONTROL & ~SWIZ_CNTL;
|
|
LL16(grCONTROL, ppdev->grCONTROL);
|
|
|
|
//
|
|
// BLTDEF, and rop code.
|
|
//
|
|
REQUIRE(1);
|
|
LL_DRAWBLTDEF((bltdef << 16) | fg_rop, 2);
|
|
|
|
//
|
|
// Clip the BLT.
|
|
// The clipping function will call HW16HostToScreen() to finish the BLT.
|
|
//
|
|
if ((pco == 0) || (pco->iDComplexity==DC_TRIVIAL))
|
|
HW16HostToScreen(ppdev, prclDest, psoSrc, pptlSrc,
|
|
pbo, pptlBrush, fg_rop, pxlo, pco);
|
|
else
|
|
BltClip(ppdev, pco, prclDest, psoSrc, pptlSrc,
|
|
pbo, pptlBrush, fg_rop, pxlo, &HW16HostToScreen);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// ===========================================================================
|
|
//
|
|
// HW16HostToScreen
|
|
//
|
|
// This function is responsible for actually talking to the chip.
|
|
// At this point we are required to handle the BLT, so we must return TRUE.
|
|
// All decisions as to whether to punt or not must be made in the top level
|
|
// function Color16HostToScreen().
|
|
//
|
|
// This function is called from BltClip() through a pointer set by
|
|
// Color16HostToScreen(). //
|
|
//
|
|
// Since scan lines are WORD aligned by GDI, that means
|
|
// all pixels will be WORD aligned by GDI, so the only thing
|
|
// we need to be concerned about is if there are a even or an odd
|
|
// number of WORDS per scan line.
|
|
//
|
|
// ===========================================================================
|
|
BOOL HW16HostToScreen(
|
|
PPDEV ppdev,
|
|
RECTL* prclDest,
|
|
SURFOBJ* psoSrc,
|
|
POINTL* pptlSrc,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ULONG fg_rop,
|
|
XLATEOBJ* pxlo,
|
|
CLIPOBJ* pco)
|
|
{
|
|
ULONG bltWidth, bltHeight,
|
|
x, y, i, odd,
|
|
num_dwords, num_extra;
|
|
PBYTE psrc;
|
|
DWORD *pdsrc;
|
|
UCHAR *pucData;
|
|
ULONG SrcPhase = 0;
|
|
void *pHOSTDATA = (void *)ppdev->pLgREGS->grHOSTDATA;
|
|
|
|
|
|
DISPDBG(( H2S_DBG_LEVEL, "DrvBitBlt: HW16HostToScreen Entry.\n"));
|
|
|
|
//
|
|
// Set psrc to point to first pixel in source.
|
|
//
|
|
psrc = psoSrc->pvScan0; // Start of surface.
|
|
psrc += (psoSrc->lDelta * pptlSrc->y); // Start of scanline.
|
|
psrc += (pptlSrc->x * ppdev->iBytesPerPixel); // Starting pixel in scanline.
|
|
|
|
|
|
//
|
|
// Set source phase
|
|
//
|
|
REQUIRE(7);
|
|
LL_OP1 (SrcPhase,0);
|
|
|
|
|
|
//
|
|
// Set DEST x,y
|
|
//
|
|
LL_OP0 (prclDest->left, prclDest->top);
|
|
|
|
|
|
//
|
|
// Set the X and Y extents, and do the BLT.
|
|
// Calculate BLT size in pixels.
|
|
//
|
|
bltWidth = (prclDest->right - prclDest->left);
|
|
bltHeight = (prclDest->bottom - prclDest->top);
|
|
DISPDBG(( H2S_DBG_LEVEL, "DrvBitBlt: BLT width is %d pixels.\n",bltWidth));
|
|
LL_BLTEXT (bltWidth, bltHeight);
|
|
|
|
|
|
//
|
|
// The chip has a bug in it that causes us to have to write extra HOSTDATA
|
|
// under certian conditions.
|
|
//
|
|
i = MAKE_HD_INDEX((bltWidth*2), SrcPhase, (prclDest->left*2));
|
|
num_extra = ExtraDwordTable [i];
|
|
DISPDBG(( H2S_DBG_LEVEL, "DrvBitBlt: BLT requires %d extra HOSTDATA writes.\n",num_extra));
|
|
|
|
//
|
|
// Now we supply the HOSTDATA for each scan line.
|
|
//
|
|
|
|
for (y=0; y<bltHeight; ++y)
|
|
{
|
|
WRITE_STRING(psrc, ((bltWidth + 1) / 2);
|
|
|
|
//
|
|
// Add any extra hostdata we need to get around the hostdata bug.
|
|
//
|
|
REQUIRE(num_extra);
|
|
for (i=0; i<num_extra; ++i)
|
|
LL32 (grHOSTDATA[0], 0);
|
|
|
|
// Move down one scanline in source.
|
|
psrc += psoSrc->lDelta;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
//
|
|
// Color24HostToScreen
|
|
//
|
|
// Handles 24 bpp Host to screen blts.
|
|
//
|
|
// Called by op1BLT() and op1op2BLT
|
|
// op1BLT() calls this routine with pbo = NULL.
|
|
// op1op2BLT calls it with pbo = current brush.
|
|
//
|
|
// This is the top level function. This function verifies parameters,
|
|
// and decides if we should punt or not.
|
|
//
|
|
// The BLT is then handed off to the clipping function. The clipping
|
|
// function is also given a pointer to the lower level BLT function
|
|
// HW24HostToScreen(), which will complete the clipped BLT.
|
|
//
|
|
// This function is the last chance to decide to punt. The clipping
|
|
// functions and the lower level HW24HostToScreen() function aren't
|
|
// allowed to punt.
|
|
//
|
|
// Return TRUE if we can do the BLT,
|
|
// Return FALSE to punt it back to GDI.
|
|
//
|
|
// ===========================================================================
|
|
BOOL Color24HostToScreen(
|
|
PPDEV ppdev,
|
|
RECTL* prclDest,
|
|
SURFOBJ* psoSrc,
|
|
POINTL* pptlSrc,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ULONG fg_rop,
|
|
XLATEOBJ* pxlo,
|
|
CLIPOBJ* pco)
|
|
{
|
|
|
|
//
|
|
// I'm not even going to try this.
|
|
// I've got better things to do with my time.
|
|
//
|
|
|
|
DISPDBG(( H2S_DBG_LEVEL, "DrvBitBlt: Color24HostToScreen Entry.\n"));
|
|
PUNTCODE(17);
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// ===========================================================================
|
|
//
|
|
// Color32HostToScreen
|
|
//
|
|
// Handles 32 bpp Host to screen blts.
|
|
//
|
|
// Called by op1BLT() and op1op2BLT
|
|
// op1BLT() calls this routine with pbo = NULL.
|
|
// op1op2BLT calls it with pbo = current brush.
|
|
//
|
|
// This is the top level function. This function verifies parameters,
|
|
// and decides if we should punt or not.
|
|
//
|
|
// The BLT is then handed off to the clipping function. The clipping
|
|
// function is also given a pointer to the lower level BLT function
|
|
// HW24HostToScreen(), which will complete the clipped BLT.
|
|
//
|
|
// This function is the last chance to decide to punt. The clipping
|
|
// functions and the lower level HW24HostToScreen() function aren't
|
|
// allowed to punt.
|
|
//
|
|
// Return TRUE if we can do the BLT,
|
|
// Return FALSE to punt it back to GDI.
|
|
//
|
|
// ===========================================================================
|
|
BOOL Color32HostToScreen(
|
|
PPDEV ppdev,
|
|
RECTL* prclDest,
|
|
SURFOBJ* psoSrc,
|
|
POINTL* pptlSrc,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ULONG fg_rop,
|
|
XLATEOBJ* pxlo,
|
|
CLIPOBJ* pco)
|
|
{
|
|
PULONG pulXlate;
|
|
ULONG bltdef = 0x1120; // RES=fb, OP0=fb OP1=host
|
|
|
|
return FALSE; // There are some unresolved issues here.
|
|
|
|
DISPDBG(( H2S_DBG_LEVEL, "DrvBitBlt: Color32HostToScreen Entry.\n"));
|
|
|
|
//
|
|
// We don't handle src with a different color depth than the screen
|
|
//
|
|
if (psoSrc->iBitmapFormat != ppdev->iBitmapFormat)
|
|
{
|
|
PUNTCODE(13); return FALSE;
|
|
}
|
|
|
|
//
|
|
// Get the source translation type.
|
|
// We don't handle Xlates for color source.
|
|
//
|
|
if (!((pxlo == NULL) || (pxlo->flXlate & XO_TRIVIAL)))
|
|
{
|
|
PUNTCODE(5); return FALSE;
|
|
}
|
|
|
|
//
|
|
// Make sure source is a standard top-down bitmap.
|
|
//
|
|
if ( (psoSrc->iType != STYPE_BITMAP) ||
|
|
(!(psoSrc->fjBitmap & BMF_TOPDOWN)) )
|
|
{
|
|
PUNTCODE(4); return FALSE;
|
|
}
|
|
|
|
//
|
|
// Set up the brush if there is one.
|
|
//
|
|
if (pbo)
|
|
if (SetBrush(ppdev, &bltdef, pbo, pptlBrush) == FALSE)
|
|
{
|
|
PUNTCODE(8);
|
|
return FALSE;
|
|
}
|
|
|
|
//
|
|
// Source phase.
|
|
//
|
|
//LL16 (grOP1_opRDRAM.pt.X, (WORD)0);
|
|
REQUIRE(4);
|
|
LL_OP1(0,0);
|
|
|
|
//
|
|
// Turn swizzle off.
|
|
//
|
|
ppdev->grCONTROL = ppdev->grCONTROL & ~SWIZ_CNTL;
|
|
LL16(grCONTROL, ppdev->grCONTROL);
|
|
|
|
//
|
|
// BLTDEF, and rop code.
|
|
//
|
|
LL_DRAWBLTDEF((bltdef << 16) | fg_rop, 2);
|
|
|
|
//
|
|
// Clip the BLT.
|
|
// The clipping function will call HW16HostToScreen() to finish the BLT.
|
|
//
|
|
if ((pco == 0) || (pco->iDComplexity==DC_TRIVIAL))
|
|
HW32HostToScreen(ppdev, prclDest, psoSrc, pptlSrc,
|
|
pbo, pptlBrush, fg_rop, pxlo, pco);
|
|
else
|
|
BltClip(ppdev, pco, prclDest, psoSrc, pptlSrc,
|
|
pbo, pptlBrush, fg_rop, pxlo, &HW32HostToScreen);
|
|
|
|
return TRUE;
|
|
}// ===========================================================================
|
|
//
|
|
// HW32HostToScreen
|
|
//
|
|
// This function is responsible for actually talking to the chip.
|
|
// At this point we are required to handle the BLT, so we must return TRUE.
|
|
// All decisions as to whether to punt or not must be made in the top level
|
|
// function Color32HostToScreen().
|
|
//
|
|
// This function is called from BltClip() through a pointer set by
|
|
// Color326HostToScreen().
|
|
//
|
|
// ===========================================================================
|
|
BOOL HW32HostToScreen(
|
|
PPDEV ppdev,
|
|
RECTL* prclDest,
|
|
SURFOBJ* psoSrc,
|
|
POINTL* pptlSrc,
|
|
BRUSHOBJ* pbo,
|
|
POINTL* pptlBrush,
|
|
ULONG fg_rop,
|
|
XLATEOBJ* pxlo,
|
|
CLIPOBJ* pco)
|
|
{
|
|
ULONG x, y, i,
|
|
bltWidth, bltHeight,
|
|
num_dwords, num_extra;
|
|
PBYTE psrc;
|
|
DWORD *pdsrc;
|
|
UCHAR *pucData;
|
|
ULONG SrcPhase = 0;
|
|
void *pHOSTDATA = (void *)ppdev->pLgREGS->grHOSTDATA;
|
|
|
|
|
|
DISPDBG(( H2S_DBG_LEVEL, "DrvBitBlt: HW32HostToScreen Entry.\n"));
|
|
|
|
//
|
|
// Set psrc to point to first pixel in source.
|
|
//
|
|
psrc = psoSrc->pvScan0; // Start of surface.
|
|
psrc += (psoSrc->lDelta * pptlSrc->y); // Start of scanline.
|
|
psrc += (pptlSrc->x * ppdev->iBytesPerPixel); // Starting pixel in scanline.
|
|
|
|
|
|
//
|
|
// Set DEST x,y
|
|
//
|
|
REQUIRE(5);
|
|
LL_OP0 (prclDest->left, prclDest->top);
|
|
|
|
|
|
//
|
|
// Set the X and Y extents, and do the BLT.
|
|
// Calculate BLT size in pixels.
|
|
//
|
|
bltWidth = (prclDest->right - prclDest->left);
|
|
bltHeight = (prclDest->bottom - prclDest->top);
|
|
LL_BLTEXT (bltWidth, bltHeight);
|
|
|
|
|
|
//
|
|
// Now we supply the HOSTDATA.
|
|
// 1 pixel per DWORD. This is easy.
|
|
//
|
|
|
|
//
|
|
// The chip has a bug in it that causes us to have to write extra HOSTDATA
|
|
// under certian conditions.
|
|
//
|
|
i = MAKE_HD_INDEX((bltWidth*4), SrcPhase, (prclDest->left*4));
|
|
num_extra = ExtraDwordTable [i];
|
|
DISPDBG(( H2S_DBG_LEVEL, "DrvBitBlt: BLT requires %d extra HOSTDATA writes.\n",num_extra));
|
|
|
|
|
|
// Supply HOSTDATA for each scan line.
|
|
for (y=0; y<bltHeight; ++y)
|
|
{
|
|
WRITE_STRING(psrc, bltWidth);
|
|
|
|
|
|
//
|
|
// Add any extra hostdata we need to get around the hostdata bug.
|
|
//
|
|
REQUIRE(num_extra);
|
|
for (i=0; i<num_extra; ++i)
|
|
LL32 (grHOSTDATA[0], 0);
|
|
|
|
|
|
// Move down one scanline in source.
|
|
psrc += psoSrc->lDelta;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
#endif // 0
|
|
#endif // BUS_MASTER
|