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.
1452 lines
46 KiB
1452 lines
46 KiB
/******************************Module*Header***********************************\
|
|
*
|
|
* *******************
|
|
* * GDI SAMPLE CODE *
|
|
* *******************
|
|
*
|
|
* Module Name: solidfil.c
|
|
*
|
|
* Contains grab bag collection of hardware acceleration entry points.
|
|
*
|
|
* Note, we will be moving several of the routines in this file to there
|
|
* modle leaving only the solid fill related entry points.
|
|
*
|
|
* Copyright (c) 1994-1998 3Dlabs Inc. Ltd. All rights reserved.
|
|
* Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
|
|
\******************************************************************************/
|
|
#include "precomp.h"
|
|
#include "gdi.h"
|
|
#include "directx.h"
|
|
|
|
// The shift equations are a nuisance. We want x<<32 to be
|
|
// zero but some processors only use the bottom 5 bits
|
|
// of the shift value. So if we want to shift by n bits
|
|
// where we know that (32 >= n > 0), we do it in two parts.
|
|
// In some places the algorithm guarantees n < 32 so we can
|
|
// use a single shift.
|
|
#define SHIFT_LEFT(src, n) (((src) << ((n)-1)) << 1)
|
|
|
|
VOID
|
|
vMonoBitsDownload(PPDev ppdev,
|
|
BYTE* pSrcBase, // ptr to word containing first bit we want to download
|
|
LONG lSrcDelta, // offset in bytes from one scanline to the next
|
|
LONG xOffset, // offset of first bit to download in pSrcBase
|
|
LONG widthInBits, // number of bits to download on each scanline
|
|
LONG nScanLines) // number of scanlines to download
|
|
|
|
{
|
|
ULONG bitWord;
|
|
ULONG bitMask;
|
|
ULONG bits;
|
|
LONG unused;
|
|
LONG nStart;
|
|
LONG nRemainder;
|
|
LONG nBits;
|
|
ULONG *pSrc;
|
|
|
|
ULONG* pBuffer;
|
|
ULONG* pReservationEnd;
|
|
ULONG* pBufferEnd;
|
|
|
|
InputBufferStart(ppdev, MAX_INPUT_BUFFER_RESERVATION,
|
|
&pBuffer, &pBufferEnd, &pReservationEnd);
|
|
|
|
DBG_GDI((6, "vDoMonoBitsDownload called"));
|
|
ASSERTDD(((INT_PTR)pSrcBase & 3) == 0,
|
|
"vDoMonoBitsDownload: non-dword aligned source");
|
|
|
|
//
|
|
// Special case where the source width is a multiple of 32 bits.
|
|
// This is true for many small resources such as icons.
|
|
//
|
|
if ( (xOffset | (widthInBits & 31)) == 0 )
|
|
{
|
|
|
|
//
|
|
// Simplest case: one 32 bit word per scanline
|
|
//
|
|
if ( widthInBits == 32 )
|
|
{
|
|
|
|
*pBuffer++ = ((nScanLines - 1) << 16)
|
|
| __Permedia2TagBitMaskPattern;
|
|
|
|
do
|
|
{
|
|
LSWAP_BYTES(bits, pSrcBase);
|
|
*pBuffer++ = bits;
|
|
if(pBuffer == pReservationEnd)
|
|
{
|
|
InputBufferContinue(ppdev, MAX_INPUT_BUFFER_RESERVATION,
|
|
&pBuffer, &pBufferEnd, &pReservationEnd);
|
|
}
|
|
pSrcBase += lSrcDelta;
|
|
} while ( --nScanLines > 0 );
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Multiple 32 bit words per scanline. convert the delta to the
|
|
// delta as we need it at the end of each line by subtracting the
|
|
// width in bytes of the data we're downloading. Note, pSrcBase
|
|
// is always 1 LONG short of the end of the line because we break
|
|
// before adding on the last ULONG. Thus, we subtract sizeof(ULONG)
|
|
// from the original adjustment.
|
|
//
|
|
|
|
LONG widthInLongs = widthInBits >> 5;
|
|
|
|
do {
|
|
|
|
LONG lLongs = widthInLongs;
|
|
ULONG* src = (ULONG *) pSrcBase;
|
|
|
|
*pBuffer++ = ((lLongs - 1) << 16)
|
|
| __Permedia2TagBitMaskPattern;
|
|
|
|
if(pBuffer == pReservationEnd)
|
|
{
|
|
InputBufferContinue(ppdev, MAX_INPUT_BUFFER_RESERVATION,
|
|
&pBuffer, &pBufferEnd, &pReservationEnd);
|
|
}
|
|
|
|
do
|
|
{
|
|
LSWAP_BYTES(bits, src);
|
|
*pBuffer++ = bits;
|
|
if(pBuffer == pReservationEnd)
|
|
{
|
|
InputBufferContinue(ppdev, MAX_INPUT_BUFFER_RESERVATION,
|
|
&pBuffer, &pBufferEnd, &pReservationEnd);
|
|
}
|
|
src++;
|
|
} while( --lLongs > 0);
|
|
|
|
pSrcBase += lSrcDelta;
|
|
|
|
} while(--nScanLines > 0);
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
//
|
|
// Some common values at the start of each scanline:
|
|
// bitWord: collect bits in this ulong and write out when full
|
|
// unused: number of bits left to fill in bitWord
|
|
// nStart = number of valid bits in the first longword
|
|
// nRemainder = number of bits on scanline minus nStart
|
|
//
|
|
bitWord = 0;
|
|
unused = 32;
|
|
nStart = 32 - xOffset;
|
|
nRemainder = widthInBits - nStart;
|
|
|
|
//
|
|
// We special case where the complete set of bits on a scanline
|
|
// is contained in the first ulong.
|
|
//
|
|
//@@BEGIN_DDKSPLIT
|
|
//TODO: We should be able to clean this up a little. It would be
|
|
// nice to be able to calculate the number of bit masks we
|
|
// will be sending enabling us to use the dma hold method
|
|
// for all cases.
|
|
//@@END_DDKSPLIT
|
|
|
|
if ( nRemainder <= 0 )
|
|
{
|
|
nBits = -nRemainder; // number of invalid bits on right
|
|
bitMask = (1 << widthInBits) - 1; // widthInBits == 32 is handled above
|
|
pSrc = (ULONG *)pSrcBase;
|
|
|
|
while ( TRUE )
|
|
{
|
|
LSWAP_BYTES(bits, pSrc);
|
|
bits = (bits >> nBits) & bitMask;
|
|
unused -= widthInBits;
|
|
if ( unused > 0 )
|
|
{
|
|
bitWord |= bits << unused;
|
|
}
|
|
else
|
|
{
|
|
bitWord |= bits >> -unused;
|
|
|
|
InputBufferContinue(ppdev, 2, &pBuffer, &pBufferEnd, &pReservationEnd);
|
|
pBuffer[0] = __Permedia2TagBitMaskPattern;
|
|
pBuffer[1] = bitWord;
|
|
pBuffer += 2;
|
|
|
|
unused += 32;
|
|
bitWord = SHIFT_LEFT(bits, unused);
|
|
}
|
|
|
|
//
|
|
// Break will generate an extra jump
|
|
//
|
|
if ( --nScanLines == 0 )
|
|
{
|
|
goto completeDownload;
|
|
}
|
|
|
|
pSrc = (ULONG *) (((UCHAR *)pSrc) + lSrcDelta);
|
|
}
|
|
}// if ( nRemainder <= 0 )
|
|
else
|
|
{
|
|
//
|
|
// Use bitMask to zero left edge bits in first long
|
|
//
|
|
bitMask = SHIFT_LEFT(1, nStart) - 1;
|
|
while ( TRUE )
|
|
{
|
|
//
|
|
// Read the first word from this scanline of the bitmap
|
|
// and mask out the lefthand offset bits if any.
|
|
//
|
|
nBits = nRemainder;
|
|
pSrc = (ULONG *)pSrcBase;
|
|
|
|
LSWAP_BYTES(bits, pSrc);
|
|
bits &= bitMask;
|
|
|
|
//
|
|
// Handle the left hand edge
|
|
//
|
|
unused -= nStart;
|
|
if ( unused > 0 )
|
|
{
|
|
bitWord |= bits << unused;
|
|
}
|
|
else
|
|
{
|
|
bitWord |= bits >> -unused;
|
|
|
|
InputBufferContinue(ppdev, 2, &pBuffer, &pBufferEnd, &pReservationEnd);
|
|
pBuffer[0] = __Permedia2TagBitMaskPattern;
|
|
pBuffer[1] = bitWord;
|
|
pBuffer += 2;
|
|
|
|
unused += 32;
|
|
bitWord = SHIFT_LEFT(bits, unused);
|
|
}
|
|
|
|
//
|
|
// Handle all the full longs in the middle, if any
|
|
//
|
|
while ( nBits >= 32 )
|
|
{
|
|
++pSrc;
|
|
LSWAP_BYTES(bits, pSrc);
|
|
bitWord |= bits >> (32 - unused);
|
|
|
|
InputBufferContinue(ppdev, 2, &pBuffer, &pBufferEnd, &pReservationEnd);
|
|
pBuffer[0] = __Permedia2TagBitMaskPattern;
|
|
pBuffer[1] = bitWord;
|
|
pBuffer += 2;
|
|
|
|
bitWord = SHIFT_LEFT(bits, unused);
|
|
nBits -= 32;
|
|
}
|
|
|
|
//
|
|
// Handle the right hand edge, if any
|
|
//
|
|
if ( nBits > 0 )
|
|
{
|
|
++pSrc;
|
|
LSWAP_BYTES(bits, pSrc);
|
|
bits >>= (32 - nBits);
|
|
unused -= nBits;
|
|
if ( unused > 0 )
|
|
{
|
|
bitWord |= bits << unused;
|
|
}
|
|
else
|
|
{
|
|
bitWord |= bits >> -unused;
|
|
|
|
InputBufferContinue(ppdev, 2, &pBuffer, &pBufferEnd, &pReservationEnd);
|
|
pBuffer[0] = __Permedia2TagBitMaskPattern;
|
|
pBuffer[1] = bitWord;
|
|
pBuffer += 2;
|
|
|
|
unused += 32;
|
|
bitWord = SHIFT_LEFT(bits, unused);
|
|
}
|
|
}
|
|
|
|
if ( --nScanLines == 0 )
|
|
{
|
|
goto completeDownload;
|
|
}
|
|
|
|
//
|
|
// go onto next scanline
|
|
//
|
|
pSrcBase += lSrcDelta;
|
|
}
|
|
}
|
|
|
|
completeDownload:
|
|
|
|
//
|
|
// Write out final, partial bitWord if any
|
|
//
|
|
if ( unused < 32 )
|
|
{
|
|
InputBufferContinue(ppdev, 2, &pBuffer, &pBufferEnd, &pReservationEnd);
|
|
pBuffer[0] = __Permedia2TagBitMaskPattern;
|
|
pBuffer[1] = bitWord;
|
|
pBuffer += 2;
|
|
}
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
}// vDoMonoBitsDownload()
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// void vMonoDownload(GFNPB * ppb)
|
|
//
|
|
// Dowload the monochrome source from system memory to video memory using
|
|
// provided source to destination rop2.
|
|
//
|
|
// Argumentes needed from function block (GFNPB)
|
|
//
|
|
// ppdev-------PPDev
|
|
// psoSrc------Source SURFOBJ
|
|
// psurfDst----Destination Surf
|
|
// lNumRects---Number of rectangles to fill
|
|
// pptlSrc-----Source point
|
|
// prclDst-----Points to a RECTL structure that defines the rectangular area
|
|
// to be modified
|
|
// pRects------Pointer to a list of rectangles information which needed to be
|
|
// filled
|
|
// pxlo--------XLATEOBJ
|
|
// usRop4------Rop to be performed
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
|
|
VOID
|
|
vMonoDownload(GFNPB * ppb)
|
|
{
|
|
PDev* ppdev = ppb->ppdev;
|
|
RECTL* prcl = ppb->pRects;
|
|
LONG count = ppb->lNumRects;
|
|
SURFOBJ* psoSrc = ppb->psoSrc;
|
|
POINTL* pptlSrc = ppb->pptlSrc;
|
|
RECTL* prclDst = ppb->prclDst;
|
|
XLATEOBJ * pxlo = ppb->pxlo;
|
|
ULONG logicop = ulRop2ToLogicop((unsigned char)(ppb->ulRop4 & 0xf));
|
|
DWORD dwBitMask;
|
|
|
|
PERMEDIA_DECL_VARS;
|
|
PERMEDIA_DECL_INIT;
|
|
|
|
ASSERTDD(count > 0, "Can't handle zero rectangles");
|
|
|
|
if ( ppb->ulRop4 == 0xB8B8 )
|
|
{
|
|
dwBitMask = permediaInfo->RasterizerMode
|
|
| INVERT_BITMASK_BITS;
|
|
logicop = K_LOGICOP_COPY;
|
|
}
|
|
else if ( ppb->ulRop4 == 0xE2E2 )
|
|
{
|
|
dwBitMask = permediaInfo->RasterizerMode;
|
|
logicop = K_LOGICOP_COPY;
|
|
}
|
|
else
|
|
{
|
|
dwBitMask = permediaInfo->RasterizerMode | FORCE_BACKGROUND_COLOR;
|
|
}
|
|
|
|
ULONG* pBuffer;
|
|
|
|
InputBufferReserve(ppdev, 14, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagFBReadMode;
|
|
pBuffer[1] = PM_FBREADMODE_PARTIAL(ppb->psurfDst->ulPackedPP)
|
|
| LogicopReadDest[logicop];
|
|
pBuffer[2] = __Permedia2TagLogicalOpMode;
|
|
pBuffer[3] = P2_ENABLED_LOGICALOP(logicop);
|
|
pBuffer[4] = __Permedia2TagColorDDAMode;
|
|
pBuffer[5] = __COLOR_DDA_FLAT_SHADE;
|
|
pBuffer[6] = __Permedia2TagConstantColor;
|
|
pBuffer[7] = pxlo->pulXlate[1];
|
|
pBuffer[8] = __Permedia2TagTexel0;
|
|
pBuffer[9] = pxlo->pulXlate[0];
|
|
pBuffer[10] = __Permedia2TagFBWindowBase;
|
|
pBuffer[11] = ppb->psurfDst->ulPixOffset;
|
|
pBuffer[12] = __Permedia2TagRasterizerMode;
|
|
pBuffer[13] = dwBitMask;
|
|
|
|
pBuffer += 14;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
while (count--) {
|
|
LONG xOffset;
|
|
BYTE* pjSrc;
|
|
|
|
// calc x pixel offset from origin
|
|
xOffset = pptlSrc->x + (prcl->left - prclDst->left);
|
|
|
|
// pjSrc is first dword containing a bit to download
|
|
pjSrc = (BYTE*)((INT_PTR)((PUCHAR) psoSrc->pvScan0
|
|
+ ((pptlSrc->y + (prcl->top - prclDst->top)) * psoSrc->lDelta)
|
|
+ ((xOffset >> 3) & ~3)));
|
|
|
|
// pjSrc gets us to the first DWORD. Convert xOffset to be the offset
|
|
// to the first pixel in the first DWORD
|
|
xOffset &= 0x1f;
|
|
|
|
InputBufferReserve(ppdev, 10, &pBuffer);
|
|
|
|
// set up the destination rectangle
|
|
pBuffer[0] = __Permedia2TagStartXDom;
|
|
pBuffer[1] = INTtoFIXED(prcl->left);
|
|
pBuffer[2] = __Permedia2TagStartXSub;
|
|
pBuffer[3] = INTtoFIXED(prcl->right);
|
|
pBuffer[4] = __Permedia2TagStartY;
|
|
pBuffer[5] = INTtoFIXED(prcl->top);
|
|
pBuffer[6] = __Permedia2TagCount;
|
|
pBuffer[7] = prcl->bottom - prcl->top;
|
|
pBuffer[8] = __Permedia2TagRender;
|
|
pBuffer[9] = __RENDER_TRAPEZOID_PRIMITIVE
|
|
| __RENDER_SYNC_ON_BIT_MASK;
|
|
|
|
pBuffer += 10;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
vMonoBitsDownload(
|
|
ppdev, pjSrc, psoSrc->lDelta, xOffset,
|
|
prcl->right - prcl->left, prcl->bottom - prcl->top);
|
|
|
|
prcl++;
|
|
|
|
}
|
|
|
|
InputBufferReserve(ppdev, 4, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagColorDDAMode;
|
|
pBuffer[1] = __PERMEDIA_DISABLE;
|
|
pBuffer[2] = __Permedia2TagRasterizerMode;
|
|
pBuffer[3] = permediaInfo->RasterizerMode;
|
|
|
|
pBuffer += 4;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// void vGradientFillRect(GFNPB * ppb)
|
|
//
|
|
// Shades the specified primitives.
|
|
//
|
|
// Argumentes needed from function block (GFNPB)
|
|
//
|
|
// ppdev-------PPDev
|
|
// psurfDst----Destination surface
|
|
// lNumRects---Number of rectangles to fill
|
|
// pRects------Pointer to a list of rectangles information which needed to be
|
|
// filled
|
|
// ulMode------Specifies the current drawing mode and how to interpret the
|
|
// array to which pMesh points
|
|
// ptvrt-------Points to an array of TRIVERTEX structures, with each entry
|
|
// containing position and color information.
|
|
// ulNumTvrt---Specifies the number of TRIVERTEX structures in the array to
|
|
// which pVertex points
|
|
// pvMesh------Points to an array of structures that define the connectivity
|
|
// of the TRIVERTEX elements to which ptvrt points
|
|
// ulNumMesh---Specifies the number of elements in the array to which pvMesh
|
|
// points
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
VOID
|
|
vGradientFillRect(GFNPB * ppb)
|
|
{
|
|
Surf * psurfDst = ppb->psurfDst;
|
|
RECTL* prcl = ppb->pRects;
|
|
LONG c = ppb->lNumRects;
|
|
PPDev ppdev = psurfDst->ppdev;
|
|
DWORD windowBase = psurfDst->ulPixOffset;
|
|
TRIVERTEX *ptvrt = ppb->ptvrt;
|
|
GRADIENT_RECT *pgr;
|
|
GRADIENT_RECT *pgrSentinel = ((GRADIENT_RECT *) ppb->pvMesh)
|
|
+ ppb->ulNumMesh;
|
|
LONG xShift;
|
|
LONG yShift;
|
|
ULONG* pBuffer;
|
|
|
|
DBG_GDI((10, "vGradientFillRect"));
|
|
|
|
|
|
// setup loop invariant state
|
|
|
|
InputBufferReserve(ppdev, 14, &pBuffer);
|
|
|
|
|
|
pBuffer[0] = __Permedia2TagLogicalOpMode;
|
|
pBuffer[1] = __PERMEDIA_DISABLE;
|
|
pBuffer[2] = __Permedia2TagDitherMode;
|
|
pBuffer[3] = (COLOR_MODE << PM_DITHERMODE_COLORORDER) |
|
|
(ppdev->ulPermFormat << PM_DITHERMODE_COLORFORMAT) |
|
|
(ppdev->ulPermFormatEx << PM_DITHERMODE_COLORFORMATEXTENSION) |
|
|
(1 << PM_DITHERMODE_ENABLE) |
|
|
(1 << PM_DITHERMODE_DITHERENABLE);
|
|
pBuffer[4] = __Permedia2TagFBReadMode;
|
|
pBuffer[5] = PM_FBREADMODE_PARTIAL(ppb->psurfDst->ulPackedPP) |
|
|
PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE);
|
|
pBuffer[6] = __Permedia2TagFBWindowBase;
|
|
pBuffer[7] = windowBase;
|
|
pBuffer[8] = __Permedia2TagLogicalOpMode;
|
|
pBuffer[9] = __PERMEDIA_DISABLE;
|
|
pBuffer[10] = __Permedia2TagColorDDAMode;
|
|
pBuffer[11] = 3;
|
|
pBuffer[12] = __Permedia2TagdY;
|
|
pBuffer[13] = 1 << 16;
|
|
|
|
pBuffer += 14;
|
|
//@@BEGIN_DDKSPLIT
|
|
// TODO: This code can be cleaned up a little
|
|
// 1. the delta values should not change with each rectangle
|
|
// 2. we can use the render rectangle primitive
|
|
//@@END_DDKSPLIT
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
while(c--)
|
|
{
|
|
|
|
pgr = (GRADIENT_RECT *) ppb->pvMesh;
|
|
|
|
while(pgr < pgrSentinel)
|
|
{
|
|
TRIVERTEX *ptrvtLr = ptvrt + pgr->LowerRight;
|
|
TRIVERTEX *ptrvtUl = ptvrt + pgr->UpperLeft;
|
|
LONG rd;
|
|
LONG gd;
|
|
LONG bd;
|
|
LONG dx;
|
|
LONG dy;
|
|
RECTL rect;
|
|
LONG rdx;
|
|
LONG rdy;
|
|
LONG gdx;
|
|
LONG gdy;
|
|
LONG bdx;
|
|
LONG bdy;
|
|
LONG rs;
|
|
LONG gs;
|
|
LONG bs;
|
|
LONG lTemp;
|
|
BOOL bReverseH = FALSE;
|
|
BOOL bReverseV = FALSE;
|
|
|
|
rect.left = ptrvtUl->x;
|
|
rect.right = ptrvtLr->x;
|
|
rect.top = ptrvtUl->y;
|
|
rect.bottom = ptrvtLr->y;
|
|
|
|
if ( rect.left > rect.right )
|
|
{
|
|
//
|
|
// The fill is from right to left. So we need to swap
|
|
// the rectangle coordinates
|
|
//
|
|
lTemp = rect.left;
|
|
rect.left = rect.right;
|
|
rect.right = lTemp;
|
|
|
|
bReverseH = TRUE;
|
|
}
|
|
|
|
if ( rect.top > rect.bottom )
|
|
{
|
|
//
|
|
// The coordinate is from bottom to top. So we need to swap
|
|
// the rectangle coordinates
|
|
//
|
|
lTemp = rect.top;
|
|
rect.top = rect.bottom;
|
|
rect.bottom = lTemp;
|
|
|
|
bReverseV = TRUE;
|
|
}
|
|
|
|
//
|
|
// We need to set start color and color delta according to the
|
|
// rectangle drawing direction
|
|
//
|
|
if( (ppb->ulMode == GRADIENT_FILL_RECT_H) && (bReverseH == TRUE)
|
|
||(ppb->ulMode == GRADIENT_FILL_RECT_V) && (bReverseV == TRUE) )
|
|
{
|
|
rd = (ptrvtUl->Red - ptrvtLr->Red) << 7;
|
|
gd = (ptrvtUl->Green - ptrvtLr->Green) << 7;
|
|
bd = (ptrvtUl->Blue - ptrvtLr->Blue) << 7;
|
|
|
|
rs = ptrvtLr->Red << 7;
|
|
gs = ptrvtLr->Green << 7;
|
|
bs = ptrvtLr->Blue << 7;
|
|
}
|
|
else
|
|
{
|
|
rd = (ptrvtLr->Red - ptrvtUl->Red) << 7;
|
|
gd = (ptrvtLr->Green - ptrvtUl->Green) << 7;
|
|
bd = (ptrvtLr->Blue - ptrvtUl->Blue) << 7;
|
|
|
|
rs = ptrvtUl->Red << 7;
|
|
gs = ptrvtUl->Green << 7;
|
|
bs = ptrvtUl->Blue << 7;
|
|
}
|
|
|
|
// quick clipping reject
|
|
if(prcl->left >= rect.right ||
|
|
prcl->right <= rect.left ||
|
|
prcl->top >= rect.bottom ||
|
|
prcl->bottom <= rect.top)
|
|
goto nextPgr;
|
|
|
|
dx = rect.right - rect.left;
|
|
dy = rect.bottom - rect.top;
|
|
|
|
if(ppb->ulMode == GRADIENT_FILL_RECT_H)
|
|
{
|
|
rdx = rd / dx;
|
|
gdx = gd / dx;
|
|
bdx = bd / dx;
|
|
|
|
rdy = 0;
|
|
gdy = 0;
|
|
bdy = 0;
|
|
}
|
|
else
|
|
{
|
|
rdy = rd / dy;
|
|
gdy = gd / dy;
|
|
bdy = bd / dy;
|
|
|
|
rdx = 0;
|
|
gdx = 0;
|
|
bdx = 0;
|
|
}
|
|
|
|
//
|
|
// Convert from 9.15 to 9.11 format. The Permedia2
|
|
// dRdx, dGdx etc. registers using 9.11 fixed format. The bottom 4
|
|
// bits are not used.
|
|
//
|
|
rdx &= ~0xf;
|
|
gdx &= ~0xf;
|
|
bdx &= ~0xf;
|
|
rdy &= ~0xf;
|
|
gdy &= ~0xf;
|
|
bdy &= ~0xf;
|
|
|
|
// now perform some clipping adjusting start values as necessary
|
|
xShift = prcl->left - rect.left;
|
|
if(xShift > 0)
|
|
{
|
|
rs = rs + (rdx * xShift);
|
|
gs = gs + (gdx * xShift);
|
|
bs = bs + (bdx * xShift);
|
|
rect.left = prcl->left;
|
|
}
|
|
|
|
yShift = prcl->top - rect.top;
|
|
if(yShift > 0)
|
|
{
|
|
rs = rs + (rdy * yShift);
|
|
gs = gs + (gdy * yShift);
|
|
bs = bs + (bdy * yShift);
|
|
rect.top = prcl->top;
|
|
}
|
|
|
|
// just move up the bottom right as necessary
|
|
if(prcl->right < rect.right)
|
|
rect.right = prcl->right;
|
|
|
|
if(prcl->bottom < rect.bottom)
|
|
rect.bottom = prcl->bottom;
|
|
|
|
InputBufferReserve(ppdev, 28, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagRStart;
|
|
pBuffer[1] = rs;
|
|
pBuffer[2] = __Permedia2TagGStart;
|
|
pBuffer[3] = gs;
|
|
pBuffer[4] = __Permedia2TagBStart;
|
|
pBuffer[5] = bs;
|
|
|
|
pBuffer[6] = __Permedia2TagdRdx;
|
|
pBuffer[7] = rdx;
|
|
pBuffer[8] = __Permedia2TagdRdyDom;
|
|
pBuffer[9] = rdy;
|
|
pBuffer[10] = __Permedia2TagdGdx;
|
|
pBuffer[11] = gdx;
|
|
pBuffer[12] = __Permedia2TagdGdyDom;
|
|
pBuffer[13] = gdy;
|
|
pBuffer[14] = __Permedia2TagdBdx;
|
|
pBuffer[15] = bdx;
|
|
pBuffer[16] = __Permedia2TagdBdyDom;
|
|
pBuffer[17] = bdy;
|
|
|
|
// NOTE: alpha is always constant
|
|
|
|
|
|
// Render the rectangle
|
|
|
|
pBuffer[18] = __Permedia2TagStartXDom;
|
|
pBuffer[19] = rect.left << 16;
|
|
pBuffer[20] = __Permedia2TagStartXSub;
|
|
pBuffer[21] = rect.right << 16;
|
|
pBuffer[22] = __Permedia2TagStartY;
|
|
pBuffer[23] = rect.top << 16;
|
|
pBuffer[24] = __Permedia2TagCount;
|
|
pBuffer[25] = rect.bottom - rect.top;
|
|
|
|
pBuffer[26] = __Permedia2TagRender;
|
|
pBuffer[27] = __RENDER_TRAPEZOID_PRIMITIVE;
|
|
|
|
|
|
pBuffer += 28;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
nextPgr:
|
|
|
|
pgr++;
|
|
|
|
}
|
|
|
|
prcl++;
|
|
|
|
}
|
|
|
|
InputBufferReserve(ppdev, 6, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagdY;
|
|
pBuffer[1] = INTtoFIXED(1);
|
|
pBuffer[2] = __Permedia2TagDitherMode;
|
|
pBuffer[3] = 0;
|
|
pBuffer[4] = __Permedia2TagColorDDAMode;
|
|
pBuffer[5] = 0;
|
|
|
|
pBuffer += 6;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
}// vGradientFillRect()
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// void vTransparentBlt(GFNPB * ppb)
|
|
//
|
|
// Provides bit-block transfer capabilities with transparency.
|
|
//
|
|
// Argumentes needed from function block (GFNPB)
|
|
//
|
|
// ppdev-------PPDev
|
|
// psurfSrc----Source surface
|
|
// psurfDst----Destination surface
|
|
// lNumRects---Number of rectangles to fill
|
|
// prclSrc-----Points to a RECTL structure that defines the rectangular area
|
|
// to be copied
|
|
// prclDst-----Points to a RECTL structure that defines the rectangular area
|
|
// to be modified
|
|
// colorKey----Specifies the transparent color in the source surface format.
|
|
// It is a color index value that has been translated to the
|
|
// source surface's palette.
|
|
// pRects------Pointer to a list of rectangles information which needed to be
|
|
// filled
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
VOID
|
|
vTransparentBlt(GFNPB * ppb)
|
|
{
|
|
Surf * psurfDst = ppb->psurfDst;
|
|
Surf * psurfSrc = ppb->psurfSrc;
|
|
RECTL* prcl = ppb->pRects;
|
|
LONG c = ppb->lNumRects;
|
|
RECTL* prclSrc = ppb->prclSrc;
|
|
RECTL* prclDst = ppb->prclDst;
|
|
DWORD colorKey = ppb->colorKey;
|
|
PPDev ppdev = psurfDst->ppdev;
|
|
DWORD windowBase = psurfDst->ulPixOffset;
|
|
LONG sourceOffset = psurfSrc->ulPixOffset;
|
|
DWORD dwRenderDirection;
|
|
DWORD format = ppdev->ulPermFormat;
|
|
DWORD extension = ppdev->ulPermFormatEx;
|
|
DWORD dwLowerBound;
|
|
DWORD dwUpperBound;
|
|
ULONG* pBuffer;
|
|
|
|
DBG_GDI((6, "vTransparentBlt"));
|
|
|
|
ASSERTDD(prclSrc->right - prclSrc->left == (prclDst->right - prclDst->left),
|
|
"vTransparentBlt: expect one-to-one blts only");
|
|
|
|
ASSERTDD(prclSrc->bottom - prclSrc->top == (prclDst->bottom - prclDst->top),
|
|
"vTransparentBlt: expect one-to-one blts only");
|
|
//@@BEGIN_DDKSPLIT
|
|
// TODO: should call utility function to format color key
|
|
//@@END_DDKSPLIT
|
|
if (format == PERMEDIA_8BIT_PALETTEINDEX)
|
|
{
|
|
colorKey = FORMAT_PALETTE_32BIT(colorKey);
|
|
dwLowerBound = CHROMA_LOWER_ALPHA(colorKey);
|
|
dwUpperBound = CHROMA_UPPER_ALPHA(colorKey);
|
|
}
|
|
else if(ppdev->ulPermFormat == PERMEDIA_565_RGB)
|
|
{
|
|
colorKey = FORMAT_565_32BIT_BGR(colorKey);
|
|
dwLowerBound = CHROMA_LOWER_ALPHA(colorKey);
|
|
dwUpperBound = CHROMA_UPPER_ALPHA(colorKey);
|
|
dwLowerBound = dwLowerBound & 0xF8F8FCF8;
|
|
dwUpperBound = dwUpperBound | 0x07070307;
|
|
}
|
|
else
|
|
{
|
|
colorKey = FORMAT_8888_32BIT_BGR(colorKey);
|
|
dwLowerBound = CHROMA_LOWER_ALPHA(colorKey);
|
|
dwUpperBound = CHROMA_UPPER_ALPHA(colorKey);
|
|
}
|
|
|
|
// setup loop invariant state
|
|
|
|
InputBufferReserve(ppdev, 24, &pBuffer);
|
|
|
|
// Reject range
|
|
pBuffer[0] = __Permedia2TagYUVMode;
|
|
pBuffer[1] = 0x2 << 1;
|
|
pBuffer[2] = __Permedia2TagFBWindowBase;
|
|
pBuffer[3] = windowBase;
|
|
|
|
// set no read of source.
|
|
// add read src/dest enable
|
|
pBuffer[4] = __Permedia2TagFBReadMode;
|
|
pBuffer[5] = psurfDst->ulPackedPP;
|
|
pBuffer[6] = __Permedia2TagLogicalOpMode;
|
|
pBuffer[7] = __PERMEDIA_DISABLE;
|
|
|
|
// set base of source
|
|
pBuffer[8] = __Permedia2TagTextureBaseAddress;
|
|
pBuffer[9] = sourceOffset;
|
|
pBuffer[10] = __Permedia2TagTextureAddressMode;
|
|
pBuffer[11] = 1 << PM_TEXADDRESSMODE_ENABLE;
|
|
//
|
|
// modulate & ramp??
|
|
pBuffer[12] = __Permedia2TagTextureColorMode;
|
|
pBuffer[13] = (1 << PM_TEXCOLORMODE_ENABLE) |
|
|
(_P2_TEXTURE_COPY << PM_TEXCOLORMODE_APPLICATION);
|
|
|
|
pBuffer[14] = __Permedia2TagTextureReadMode;
|
|
pBuffer[15] = PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) |
|
|
PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE) |
|
|
PM_TEXREADMODE_WIDTH(11) |
|
|
PM_TEXREADMODE_HEIGHT(11);
|
|
|
|
pBuffer[16] = __Permedia2TagTextureDataFormat;
|
|
pBuffer[17] = (format << PM_TEXDATAFORMAT_FORMAT) |
|
|
(extension << PM_TEXDATAFORMAT_FORMATEXTENSION) |
|
|
(COLOR_MODE << PM_TEXDATAFORMAT_COLORORDER);
|
|
|
|
pBuffer[18] = __Permedia2TagTextureMapFormat;
|
|
pBuffer[19] = (psurfSrc->ulPackedPP) |
|
|
(ppdev->cPelSize << PM_TEXMAPFORMAT_TEXELSIZE);
|
|
|
|
|
|
pBuffer[20] = __Permedia2TagChromaLowerBound;
|
|
pBuffer[21] = dwLowerBound;
|
|
pBuffer[22] = __Permedia2TagChromaUpperBound;
|
|
pBuffer[23] = dwUpperBound;
|
|
|
|
pBuffer += 24;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
if (format != PERMEDIA_8BIT_PALETTEINDEX)
|
|
{
|
|
|
|
InputBufferReserve(ppdev, 2, &pBuffer);
|
|
|
|
// Reject range
|
|
pBuffer[0] = __Permedia2TagDitherMode;
|
|
pBuffer[1] = (COLOR_MODE << PM_DITHERMODE_COLORORDER) |
|
|
(format << PM_DITHERMODE_COLORFORMAT) |
|
|
(extension << PM_DITHERMODE_COLORFORMATEXTENSION) |
|
|
(1 << PM_DITHERMODE_ENABLE);
|
|
|
|
pBuffer += 2;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
}
|
|
|
|
while(c--) {
|
|
|
|
RECTL rDest;
|
|
RECTL rSrc;
|
|
|
|
rDest = *prcl;
|
|
|
|
rSrc.left = prclSrc->left + (rDest.left - prclDst->left);
|
|
rSrc.top = prclSrc->top + (rDest.top - prclDst->top);
|
|
rSrc.right = rSrc.left + (rDest.right - rDest.left);
|
|
rSrc.bottom = rSrc.top + (rDest.bottom - rDest.top);
|
|
|
|
if (rSrc.top < 0) {
|
|
rDest.top -= rSrc.top;
|
|
rSrc.top = 0;
|
|
}
|
|
|
|
if (rSrc.left < 0) {
|
|
rDest.left -= rSrc.left;
|
|
rSrc.left = 0;
|
|
}
|
|
|
|
if ((psurfSrc->ulPixOffset) != (psurfDst->ulPixOffset))
|
|
{
|
|
dwRenderDirection = 1;
|
|
}
|
|
else
|
|
{
|
|
if(rSrc.top < rDest.top)
|
|
{
|
|
dwRenderDirection = 0;
|
|
}
|
|
else if(rSrc.top > rDest.top)
|
|
{
|
|
dwRenderDirection = 1;
|
|
}
|
|
else if(rSrc.left < rDest.left)
|
|
{
|
|
dwRenderDirection = 0;
|
|
}
|
|
else dwRenderDirection = 1;
|
|
}
|
|
|
|
InputBufferReserve(ppdev, 24, &pBuffer);
|
|
|
|
|
|
// Left -> right, top->bottom
|
|
if (dwRenderDirection)
|
|
{
|
|
// set offset of source
|
|
pBuffer[0] = __Permedia2TagSStart;
|
|
pBuffer[1] = rSrc.left << 20;
|
|
pBuffer[2] = __Permedia2TagTStart;
|
|
pBuffer[3] = rSrc.top << 20;
|
|
pBuffer[4] = __Permedia2TagdSdx;
|
|
pBuffer[5] = 1 << 20;
|
|
pBuffer[6] = __Permedia2TagdSdyDom;
|
|
pBuffer[7] = 0;
|
|
pBuffer[8] = __Permedia2TagdTdx;
|
|
pBuffer[9] = 0;
|
|
pBuffer[10] = __Permedia2TagdTdyDom;
|
|
pBuffer[11] = 1 << 20;
|
|
|
|
pBuffer[12] = __Permedia2TagStartXDom;
|
|
pBuffer[13] = rDest.left << 16;
|
|
pBuffer[14] = __Permedia2TagStartXSub;
|
|
pBuffer[15] = rDest.right << 16;
|
|
pBuffer[16] = __Permedia2TagStartY;
|
|
pBuffer[17] = rDest.top << 16;
|
|
pBuffer[18] = __Permedia2TagdY;
|
|
pBuffer[19] = 1 << 16;
|
|
pBuffer[20] = __Permedia2TagCount;
|
|
pBuffer[21] = rDest.bottom - rDest.top;
|
|
pBuffer[22] = __Permedia2TagRender;
|
|
pBuffer[23] = __RENDER_TRAPEZOID_PRIMITIVE |
|
|
__RENDER_TEXTURED_PRIMITIVE;
|
|
}
|
|
else
|
|
// right->left, bottom->top
|
|
{
|
|
// set offset of source
|
|
pBuffer[0] = __Permedia2TagSStart;
|
|
pBuffer[1] = rSrc.right << 20;
|
|
pBuffer[2] = __Permedia2TagTStart;
|
|
pBuffer[3] = (rSrc.bottom - 1) << 20;
|
|
pBuffer[4] = __Permedia2TagdSdx;
|
|
pBuffer[5] = (DWORD) (-1 << 20);
|
|
pBuffer[6] = __Permedia2TagdSdyDom;
|
|
pBuffer[7] = 0;
|
|
pBuffer[8] = __Permedia2TagdTdx;
|
|
pBuffer[9] = 0;
|
|
pBuffer[10] = __Permedia2TagdTdyDom;
|
|
pBuffer[11] = (DWORD)(-1 << 20);
|
|
|
|
// Render right to left, bottom to top
|
|
pBuffer[12] = __Permedia2TagStartXDom;
|
|
pBuffer[13] = rDest.right << 16;
|
|
pBuffer[14] = __Permedia2TagStartXSub;
|
|
pBuffer[15] = rDest.left << 16;
|
|
pBuffer[16] = __Permedia2TagStartY;
|
|
pBuffer[17] = (rDest.bottom - 1) << 16;
|
|
pBuffer[18] = __Permedia2TagdY;
|
|
pBuffer[19] = (DWORD)(-1 << 16);
|
|
pBuffer[20] = __Permedia2TagCount;
|
|
pBuffer[21] = rDest.bottom - rDest.top;
|
|
pBuffer[22] = __Permedia2TagRender;
|
|
pBuffer[23] = __RENDER_TRAPEZOID_PRIMITIVE |
|
|
__RENDER_TEXTURED_PRIMITIVE;
|
|
}
|
|
|
|
pBuffer += 24;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
prcl++;
|
|
}
|
|
|
|
// restore default state
|
|
|
|
InputBufferReserve(ppdev, 12, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagdY;
|
|
pBuffer[1] = INTtoFIXED(1);
|
|
pBuffer[2] = __Permedia2TagDitherMode;
|
|
pBuffer[3] = 0;
|
|
pBuffer[4] = __Permedia2TagYUVMode;
|
|
pBuffer[5] = 0x0;
|
|
pBuffer[6] = __Permedia2TagTextureAddressMode;
|
|
pBuffer[7] = __PERMEDIA_DISABLE;
|
|
pBuffer[8] = __Permedia2TagTextureColorMode;
|
|
pBuffer[9] = __PERMEDIA_DISABLE;
|
|
pBuffer[10] = __Permedia2TagTextureReadMode;
|
|
pBuffer[11] = __PERMEDIA_DISABLE;
|
|
|
|
pBuffer += 12;
|
|
|
|
InputBufferCommit(ppdev,pBuffer);
|
|
|
|
}// vTransparentBlt()
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// void vSolidFill(GFNPB* ppb)
|
|
//
|
|
// Fill a set of rectangles with a solid color
|
|
//
|
|
// Argumentes needed from function block (GFNPB)
|
|
//
|
|
// ppdev-------PPDev
|
|
// psurfDst----Destination surface
|
|
// lNumRects---Number of rectangles to fill
|
|
// pRects------Pointer to a list of rectangles information which needed to be
|
|
// filled
|
|
// solidColor--Fill color
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
VOID
|
|
vSolidFill(GFNPB * ppb)
|
|
{
|
|
PPDev ppdev = ppb->ppdev;
|
|
ULONG color = ppb->solidColor;
|
|
RECTL * pRect = ppb->pRects;
|
|
LONG count = ppb->lNumRects;
|
|
Surf* psurf = ppb->psurfDst;
|
|
//@@BEGIN_DDKSPLIT
|
|
// TODO should call utility function to setup fill color
|
|
//@@END_DDKSPLIT
|
|
|
|
//
|
|
// Note: GDI guarantees that the unused bits are set to zero. We have
|
|
// an assert in DrvBitBlt to check the color value for unused high bits
|
|
// to make it sure that they are zero.
|
|
//
|
|
if (ppdev->cPelSize == 1)
|
|
{
|
|
color |= (color << 16);
|
|
}
|
|
else if (ppdev->cPelSize == 0)
|
|
{
|
|
color |= color << 8;
|
|
color |= color << 16;
|
|
}
|
|
|
|
//
|
|
// setup loop invariant state
|
|
//
|
|
ULONG* pBuffer;
|
|
ULONG* pReservationEnd;
|
|
ULONG* pBufferEnd;
|
|
|
|
InputBufferStart(ppdev, 8, &pBuffer, &pBufferEnd, &pReservationEnd);
|
|
|
|
pBuffer[0] = __Permedia2TagFBBlockColor;
|
|
pBuffer[1] = color;
|
|
pBuffer[2] = __Permedia2TagFBReadMode;
|
|
pBuffer[3] = PM_FBREADMODE_PARTIAL(psurf->ulPackedPP) |
|
|
PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE);
|
|
pBuffer[4] = __Permedia2TagLogicalOpMode;
|
|
pBuffer[5] = __PERMEDIA_CONSTANT_FB_WRITE;
|
|
pBuffer[6] = __Permedia2TagFBWindowBase;
|
|
pBuffer[7] = psurf->ulPixOffset;
|
|
|
|
while(count--)
|
|
{
|
|
|
|
// Render the rectangle
|
|
|
|
pBuffer = pReservationEnd;
|
|
|
|
InputBufferContinue(ppdev, 6, &pBuffer, &pBufferEnd, &pReservationEnd);
|
|
|
|
pBuffer[0] = __Permedia2TagRectangleOrigin;
|
|
pBuffer[1] = pRect->top << 16 | pRect->left;
|
|
pBuffer[2] = __Permedia2TagRectangleSize;
|
|
pBuffer[3] = ((pRect->bottom - pRect->top) << 16) |
|
|
(pRect->right - pRect->left);
|
|
pBuffer[4] = __Permedia2TagRender;
|
|
pBuffer[5] = __RENDER_FAST_FILL_ENABLE | __RENDER_RECTANGLE_PRIMITIVE |
|
|
__RENDER_INCREASE_X | __RENDER_INCREASE_Y;
|
|
|
|
pRect++;
|
|
|
|
}
|
|
|
|
pBuffer = pReservationEnd;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
}// vSolidFill()
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// VOID vInvert
|
|
//
|
|
// Fill a set of rectangles with a solid color
|
|
//
|
|
// Argumentes needed from function block (GFNPB)
|
|
//
|
|
// ppdev-------PPDev
|
|
// psurfDst----Pointer to device surface
|
|
// lNumRects---Number of clipping rectangles
|
|
// pRect-------Array of clipping rectangles
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
VOID
|
|
vInvert(GFNPB * ppb)
|
|
{
|
|
PPDev ppdev = ppb->ppdev;
|
|
RECTL * pRect = ppb->pRects;
|
|
LONG count = ppb->lNumRects;
|
|
Surf* psurf = ppb->psurfDst;
|
|
ULONG* pBuffer;
|
|
|
|
// setup loop invariant state
|
|
|
|
InputBufferReserve(ppdev, 6, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagFBWindowBase;
|
|
pBuffer[1] = psurf->ulPixOffset;
|
|
|
|
pBuffer[2] = __Permedia2TagFBReadMode;
|
|
pBuffer[3] = PM_FBREADMODE_PARTIAL(psurf->ulPackedPP) |
|
|
PM_FBREADMODE_READDEST(__PERMEDIA_ENABLE);
|
|
|
|
pBuffer[4] = __Permedia2TagLogicalOpMode;
|
|
pBuffer[5] = P2_ENABLED_LOGICALOP(K_LOGICOP_INVERT);
|
|
|
|
pBuffer += 6;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
while(count--)
|
|
{
|
|
|
|
// Render the rectangle
|
|
|
|
InputBufferReserve(ppdev, 6, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagRectangleOrigin;
|
|
pBuffer[1] = (pRect->top << 16) | pRect->left;
|
|
pBuffer[2] = __Permedia2TagRectangleSize;
|
|
pBuffer[3] = ((pRect->bottom - pRect->top) << 16)
|
|
| (pRect->right - pRect->left);
|
|
pBuffer[4] = __Permedia2TagRender;
|
|
pBuffer[5] = __RENDER_RECTANGLE_PRIMITIVE
|
|
| __RENDER_INCREASE_X
|
|
| __RENDER_INCREASE_Y;
|
|
|
|
pBuffer += 6;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
pRect++;
|
|
|
|
}
|
|
|
|
}// vInvert()
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// void vSolidFillWithRop(GFNPB* ppb)
|
|
//
|
|
// Fill a set of rectangles with a solid color based on the given lLogicOP.
|
|
//
|
|
// Argumentes needed from function block (GFNPB)
|
|
//
|
|
// ppdev-------PPDev
|
|
// psurfDst----Destination surface
|
|
// lNumRects---Number of rectangles to fill
|
|
// pRects------Pointer to a list of rectangles information which needed to be
|
|
// filled
|
|
// solidColor--Fill color
|
|
// ulRop4------Logic OP for the fill
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
//@@BEGIN_DDKSPLIT
|
|
// TODO: Some clean up: Why are we calculating lLeft andn lRight
|
|
// but use pRcl->left and pRcl->right below.
|
|
//@@END_DDKSPLIT
|
|
VOID
|
|
vSolidFillWithRop(GFNPB* ppb)
|
|
{
|
|
PPDev ppdev = ppb->ppdev;
|
|
Surf* psurfDst = ppb->psurfDst;
|
|
|
|
DWORD dwExtra = 0;
|
|
DWORD dwRenderBits;
|
|
DWORD dwShift = 0;
|
|
DWORD dwWindowBase = psurfDst->ulPixOffset;
|
|
|
|
LONG lLeft;
|
|
LONG lNumOfRects = ppb->lNumRects; // Number of rectangles
|
|
LONG lRight;
|
|
|
|
RECTL* pRcl = ppb->pRects;
|
|
ULONG ulColor = ppb->solidColor; // Brush solid fill color
|
|
ULONG ulLogicOP = ulRop3ToLogicop(ppb->ulRop4 & 0xFF);
|
|
// Hardware mix mode
|
|
// (foreground mix mode if
|
|
// the brush has a mask)
|
|
ULONG* pBuffer;
|
|
|
|
|
|
DBG_GDI((6,"vSolidFillWithRop: numRects = %ld Rop4 = 0x%x",
|
|
lNumOfRects, ppb->ulRop4));
|
|
|
|
//
|
|
// Setup logic OP invariant state
|
|
//
|
|
|
|
InputBufferReserve(ppdev, 2, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagFBWindowBase;
|
|
pBuffer[1] = dwWindowBase;
|
|
pBuffer += 2;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
switch ( ulLogicOP )
|
|
{
|
|
case K_LOGICOP_COPY:
|
|
DBG_GDI((6,"vSolidFillWithRop: COPY"));
|
|
|
|
//
|
|
// For SRC_COPY, we can use fastfill
|
|
//
|
|
dwRenderBits = __RENDER_FAST_FILL_ENABLE
|
|
| __RENDER_TRAPEZOID_PRIMITIVE
|
|
| __RENDER_INCREASE_Y
|
|
| __RENDER_INCREASE_X;
|
|
|
|
|
|
//
|
|
// Setup color data based on current color mode we are in
|
|
//
|
|
if ( ppdev->cPelSize == 1 )
|
|
{
|
|
//
|
|
// We are in 16 bit packed mode. So the color data must be
|
|
// repeated in both halves of the FBBlockColor register
|
|
//
|
|
ASSERTDD((ulColor & 0xFFFF0000) == 0,
|
|
"vSolidFillWithRop: upper bits not zero");
|
|
ulColor |= (ulColor << 16);
|
|
}
|
|
else if ( ppdev->cPelSize == 0 )
|
|
{
|
|
//
|
|
// We are in 8 bit packed mode. So the color data must be
|
|
// repeated in all 4 bytes of the FBBlockColor register
|
|
//
|
|
ASSERTDD((ulColor & 0xFFFFFF00) == 0,
|
|
"vSolidFillWithRop: upper bits not zero");
|
|
ulColor |= ulColor << 8;
|
|
ulColor |= ulColor << 16;
|
|
}
|
|
|
|
//
|
|
// Setup some loop invariant states
|
|
//
|
|
InputBufferReserve(ppdev, 6, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagLogicalOpMode;
|
|
pBuffer[1] = __PERMEDIA_CONSTANT_FB_WRITE;
|
|
pBuffer[2] = __Permedia2TagFBReadMode;
|
|
pBuffer[3] = PM_FBREADMODE_PARTIAL(psurfDst->ulPackedPP)
|
|
| PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE);
|
|
pBuffer[4] = __Permedia2TagFBBlockColor;
|
|
pBuffer[5] = ulColor;
|
|
pBuffer += 6;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
break;
|
|
|
|
case K_LOGICOP_INVERT:
|
|
DBG_GDI((6,"vSolidFillWithRop: INVERT"));
|
|
|
|
dwRenderBits = __RENDER_TRAPEZOID_PRIMITIVE
|
|
| __RENDER_INCREASE_Y
|
|
| __RENDER_INCREASE_X;
|
|
|
|
//
|
|
// When using packed operations we have to convert the left and
|
|
// right X coordinates into 32-bit-based quantities, we do this by
|
|
// shifting. We also have to round up the right X co-ord if the
|
|
// pixels don't fill a DWORD. Not a problem for 32BPP.
|
|
//
|
|
dwShift = 2 - (ppdev->cPelSize);
|
|
|
|
if ( dwShift )
|
|
{
|
|
dwExtra = (dwShift << 1) - 1;
|
|
}
|
|
else
|
|
{
|
|
dwExtra = 0;
|
|
}
|
|
|
|
//
|
|
// setup some loop invariant states
|
|
//
|
|
|
|
InputBufferReserve(ppdev, 6, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagLogicalOpMode;
|
|
pBuffer[1] = __PERMEDIA_DISABLE;
|
|
pBuffer[2] = __Permedia2TagFBReadMode;
|
|
pBuffer[3] = PM_FBREADMODE_PARTIAL(psurfDst->ulPackedPP)
|
|
| PM_FBREADMODE_PACKEDDATA(__PERMEDIA_DISABLE);
|
|
pBuffer[4] = __Permedia2TagConfig;
|
|
pBuffer[5] = __PERMEDIA_CONFIG_LOGICOP(ulLogicOP)
|
|
| __PERMEDIA_CONFIG_FBWRITE
|
|
| __PERMEDIA_CONFIG_PACKED_DATA
|
|
| ConfigReadDest[ulLogicOP];
|
|
pBuffer += 6;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DBG_GDI((6,"vSolidFillWithRop: numRects %ld, Rop4=0x%x color=0x%lx",
|
|
lNumOfRects, ppb->ulRop4, ulColor));
|
|
|
|
dwRenderBits = __RENDER_TRAPEZOID_PRIMITIVE
|
|
| __RENDER_INCREASE_Y
|
|
| __RENDER_INCREASE_X;
|
|
|
|
InputBufferReserve(ppdev, 8, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagLogicalOpMode;
|
|
pBuffer[1] = __PERMEDIA_DISABLE;
|
|
pBuffer[2] = __Permedia2TagFBReadMode;
|
|
pBuffer[3] = PM_FBREADMODE_PARTIAL(psurfDst->ulPackedPP);
|
|
pBuffer[4] = __Permedia2TagConstantColor;
|
|
pBuffer[5] = ulColor;
|
|
pBuffer[6] = __Permedia2TagConfig;
|
|
pBuffer[7] = __PERMEDIA_CONFIG_LOGICOP(ulLogicOP)
|
|
| __PERMEDIA_CONFIG_FBWRITE
|
|
| __PERMEDIA_CONFIG_COLOR_DDA
|
|
| ConfigReadDest[ulLogicOP];
|
|
pBuffer += 8;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
break;
|
|
}// switch( ulLogicOP )
|
|
|
|
//
|
|
// Loop through all the rectangles and fill them
|
|
//
|
|
for(;;)
|
|
{
|
|
|
|
//
|
|
// Calculate the left and right pixels from the rectangle.
|
|
//
|
|
lLeft = pRcl->left;
|
|
lRight = pRcl->right;
|
|
|
|
InputBufferReserve(ppdev, 12, &pBuffer);
|
|
|
|
//
|
|
// If we need to set up the packed data limits then do it, also convert
|
|
// the left and right X coordinates to DWORD-based numbers, with a bit
|
|
// of rounding
|
|
//
|
|
if ( ulLogicOP == K_LOGICOP_INVERT )
|
|
{
|
|
pBuffer[0] = __Permedia2TagPackedDataLimits;
|
|
pBuffer[1] = (lLeft << 16) | lRight;
|
|
|
|
pBuffer += 2;
|
|
|
|
lLeft >>= dwShift;
|
|
lRight = (lRight + dwExtra) >> dwShift;
|
|
}
|
|
|
|
pBuffer[0] = __Permedia2TagStartXDom;
|
|
pBuffer[1] = pRcl->left << 16;
|
|
pBuffer[2] = __Permedia2TagStartXSub;
|
|
pBuffer[3] = pRcl->right << 16;
|
|
pBuffer[4] = __Permedia2TagStartY;
|
|
pBuffer[5] = pRcl->top << 16;
|
|
pBuffer[6] = __Permedia2TagCount;
|
|
pBuffer[7] = pRcl->bottom - pRcl->top;
|
|
pBuffer[8] = __Permedia2TagRender;
|
|
pBuffer[9] = dwRenderBits;
|
|
|
|
pBuffer += 10;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
if ( --lNumOfRects == 0 )
|
|
{
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Move onto the next rectangle
|
|
//
|
|
++pRcl;
|
|
} // for()
|
|
|
|
//
|
|
// Restore the DDA mode
|
|
//
|
|
InputBufferReserve(ppdev, 2, &pBuffer);
|
|
|
|
pBuffer[0] = __Permedia2TagColorDDAMode;
|
|
pBuffer[1] = __PERMEDIA_DISABLE;
|
|
pBuffer += 2;
|
|
|
|
InputBufferCommit(ppdev, pBuffer);
|
|
|
|
}// vSolidFillWithRop()
|
|
|