/******************************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()