|
|
/******************************Module*Header**********************************\
* * ******************* * * GDI SAMPLE CODE * * ******************* * * Module Name: draw.c * * Contains the DrvFillPath routine. Permedia P2 optimised functions * * 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"
//-----------------------------------------------------------------------------
//
// void vAlphaBlendDownload(GFNPB * ppb)
//
// Doing an alpha blend on a source surface which is in a pre-multiplied alpha
// 32bpp "BGRA" format; that is, the surface type is BMF_32BPP and the palette
// type is BI_RGB.
//
// Argumentes needed from function block (GFNPB)
// ppdev-------PPDev
// psoSrc------Pointer to source SURFOBJ
// psurfDst----Destination surface
// pRects------Pointer to a list of rectangles information which needed to be
// filled
// lNumRects---Number of rectangles to fill
// prclDst-----Points to a RECTL structure that defines the rectangular area
// to be modified
// prclSrc-----Points to a RECTL structure that defines the rectangular area
// to be copied
// ucAlpha-----Alpha value
//
//-----------------------------------------------------------------------------
VOID vAlphaBlendDownload(GFNPB * ppb) { PDev* ppdev = ppb->ppdev; Surf* psurfDst = ppb->psurfDst; RECTL* prcl = ppb->pRects; LONG c = ppb->lNumRects; RECTL* prclDst = ppb->prclDst; RECTL* prclSrc = ppb->prclSrc; DWORD dwRenderDirection; UCHAR ucAlpha = ppb->ucAlpha; SURFOBJ* psoSrc = ppb->psoSrc; ULONG* pBuffer;
DBG_GDI((6, "vAlphaBlendDownload called"));
ASSERTDD(ppdev->cPelSize != 0, "vAlphaBlend: expect not to be in 8bpp mode");
ASSERTDD(psoSrc->iBitmapFormat == BMF_32BPP, "vAlphaBlend: expect source bitmap format to be 32bpp");
InputBufferReserve(ppdev, 20, &pBuffer);
pBuffer[0] = __Permedia2TagDitherMode; pBuffer[1] = (COLOR_MODE << PM_DITHERMODE_COLORORDER) | (ppdev->ulPermFormat << PM_DITHERMODE_COLORFORMAT) | (ppdev->ulPermFormatEx << PM_DITHERMODE_COLORFORMATEXTENSION) | (1 << PM_DITHERMODE_ENABLE); pBuffer[2] = __Permedia2TagAlphaBlendMode; pBuffer[3] = (1 << PM_ALPHABLENDMODE_BLENDTYPE) | // ramp
(1 << PM_ALPHABLENDMODE_COLORORDER) | // RGB
(1 << PM_ALPHABLENDMODE_ENABLE) | (81 << PM_ALPHABLENDMODE_OPERATION) | // PreMult
(ppdev->ulPermFormat << PM_ALPHABLENDMODE_COLORFORMAT) | (ppdev->ulPermFormatEx << PM_ALPHABLENDMODE_COLORFORMATEXTENSION); // Reject range
pBuffer[4] = __Permedia2TagFBWindowBase; pBuffer[5] = psurfDst->ulPixOffset; // set no read of source.
pBuffer[6] = __Permedia2TagFBReadMode; pBuffer[7] = 0x400 | psurfDst->ulPackedPP;
pBuffer[8] = __Permedia2TagLogicalOpMode; pBuffer[9] = __PERMEDIA_DISABLE; pBuffer[10] = __Permedia2TagTextureColorMode; pBuffer[11] = (1 << PM_TEXCOLORMODE_ENABLE) | (0 << 4) | // RGB
(0 << 1) ; // Modulate
pBuffer[12] = __Permedia2TagTextureDataFormat; pBuffer[13] = (ppdev->ulPermFormat << PM_TEXDATAFORMAT_FORMAT) | (ppdev->ulPermFormatEx << PM_TEXDATAFORMAT_FORMATEXTENSION) | (COLOR_MODE << PM_TEXDATAFORMAT_COLORORDER); pBuffer[14] = __Permedia2TagColorDDAMode; pBuffer[15] = 1;
pBuffer[16] = __Permedia2TagConstantColor; pBuffer[17] = ucAlpha << 24 | ucAlpha << 16 | ucAlpha << 8 | ucAlpha;
pBuffer[18] = __Permedia2TagTextureReadMode; pBuffer[19] = PM_TEXREADMODE_ENABLE(__PERMEDIA_DISABLE);
pBuffer += 20; InputBufferCommit(ppdev, pBuffer); while(c--) { InputBufferReserve(ppdev, 12, &pBuffer); 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] = __Permedia2TagdY; pBuffer[7] = 1 << 16; pBuffer[8] = __Permedia2TagCount; pBuffer[9] = prcl->bottom - prcl->top; pBuffer[10] = __Permedia2TagRender; pBuffer[11] = __RENDER_TRAPEZOID_PRIMITIVE | __RENDER_TEXTURED_PRIMITIVE | __RENDER_SYNC_ON_HOST_DATA;
pBuffer += 12; InputBufferCommit(ppdev, pBuffer);
// download data
{ LONG xOffset = prclSrc->left + (prcl->left - prclDst->left); LONG yOffset = prclSrc->top + (prcl->top - prclDst->top); ULONG * pulTexel = (ULONG *) psoSrc->pvScan0; ULONG ulWidth = prcl->right - prcl->left; ULONG ulHeight = prcl->bottom - prcl->top; LONG ulPixDelta = psoSrc->lDelta >> 2; LONG ulScanSkip = ulPixDelta - ulWidth; ULONG* pulSentinel;
ASSERTDD(psoSrc->pvScan0 != NULL, "pvScan0 is null"); ASSERTDD((psoSrc->lDelta & 3) == 0, "lDelta not multiple of four"); ASSERTDD(xOffset >= 0, "xOffset is negative"); ASSERTDD(yOffset >= 0, "yOffset is negative"); ASSERTDD(ulWidth < MAX_INPUT_BUFFER_RESERVATION, "vAlphaBlendDownload: width is too large");
pulTexel += xOffset; pulTexel += ulPixDelta * yOffset;
while(ulHeight--) { pulSentinel = pulTexel + ulWidth;
InputBufferReserve(ppdev, ulWidth + 1, &pBuffer);
*pBuffer++ = __Permedia2TagTexel0 | ((ulWidth - 1) << 16);
while(pulTexel < pulSentinel) { ULONG texel = *pulTexel++;
*pBuffer++ = SWAP_BR(texel); }
InputBufferCommit(ppdev, pBuffer);
pulTexel += ulScanSkip; } }
prcl++;
}
//
// Always restore default state
//
InputBufferReserve(ppdev, 16, &pBuffer); pBuffer[0] = __Permedia2TagdY; pBuffer[1] = INTtoFIXED(1); pBuffer[2] = __Permedia2TagDitherMode; pBuffer[3] = 0; pBuffer[4] = __Permedia2TagYUVMode; pBuffer[5] = 0; pBuffer[6] = __Permedia2TagTextureAddressMode; pBuffer[7] = __PERMEDIA_DISABLE; pBuffer[8] = __Permedia2TagTextureColorMode; pBuffer[9] = __PERMEDIA_DISABLE; pBuffer[10] = __Permedia2TagTextureReadMode; pBuffer[11] = __PERMEDIA_DISABLE; pBuffer[12] = __Permedia2TagAlphaBlendMode; pBuffer[13] = __PERMEDIA_DISABLE; pBuffer[14] = __Permedia2TagColorDDAMode; pBuffer[15] = __PERMEDIA_DISABLE;
pBuffer += 16;
InputBufferCommit(ppdev, pBuffer);
}// vAlphaBlend()
//-----------------------------------------------------------------------------
//
// void vConstantAlphaBlend(GFNPB * ppb)
//
// Using constant blend factor to apply to the entire source surface
//
// Argumentes needed from function block (GFNPB)
// ppdev-------PPDev
// psurfSrc----Source surface
// psurfDst----Destination surface
// pRects------Pointer to a list of rectangles information which needed to be
// filled
// lNumRects---Number of rectangles to fill
// prclDst-----Points to a RECTL structure that defines the rectangular area
// to be modified
// prclSrc-----Points to a RECTL structure that defines the rectangular area
// to be copied
// ucAlpha-----Alpha value
//
//-----------------------------------------------------------------------------
VOID vConstantAlphaBlend(GFNPB * ppb) { PDev* ppdev = ppb->ppdev; Surf* psurfSrc = ppb->psurfSrc; Surf* psurfDst = ppb->psurfDst; RECTL* prcl = ppb->pRects; LONG c = ppb->lNumRects; RECTL* prclDst = ppb->prclDst; RECTL* prclSrc = ppb->prclSrc; DWORD dwRenderDirection; UCHAR alpha = ppb->ucAlpha; ULONG* pBuffer;
DBG_GDI((6,"vConstantAlphaBlend called"));
ASSERTDD(ppdev->cPelSize != 0, "vAlphaBlend: expect not to be in 8bpp mode");
// setup loop invariant state
InputBufferReserve(ppdev, 26, &pBuffer); pBuffer[0] = __Permedia2TagDitherMode; pBuffer[1] = (COLOR_MODE << PM_DITHERMODE_COLORORDER) | (ppdev->ulPermFormat << PM_DITHERMODE_COLORFORMAT) | (ppdev->ulPermFormatEx << PM_DITHERMODE_COLORFORMATEXTENSION) | (1 << PM_DITHERMODE_ENABLE); pBuffer[2] = __Permedia2TagAlphaBlendMode; pBuffer[3] = ppdev->ulPermFormat << 8 | ppdev->ulPermFormatEx << 16 | ( 1 << 0 ) | // enable blending
( 1 << 13) | // color order: BGR=0, RGB=1
( 1 << 14) | // BlendType: RGB=0, Ramp=1
(84 << 1); // Operation: Blend=84, PreMult=81
// Reject range
pBuffer[4] = __Permedia2TagFBWindowBase; pBuffer[5] = psurfDst->ulPixOffset; // set no read of source.
pBuffer[6] = __Permedia2TagFBReadMode; pBuffer[7] = 0x400 // read destination enable
| psurfDst->ulPackedPP; pBuffer[8] = __Permedia2TagLogicalOpMode; pBuffer[9] = __PERMEDIA_DISABLE; // set base of source
pBuffer[10] = __Permedia2TagTextureBaseAddress; pBuffer[11] = psurfSrc->ulPixOffset; pBuffer[12] = __Permedia2TagTextureAddressMode; pBuffer[13] = (1 << PM_TEXADDRESSMODE_ENABLE); pBuffer[14] = __Permedia2TagTextureColorMode; pBuffer[15] = (1 << PM_TEXCOLORMODE_ENABLE) | (0 << 4) | // RGB
(0 << 1); // Modulate
pBuffer[16] = __Permedia2TagTextureReadMode; pBuffer[17] = PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) | PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE) | PM_TEXREADMODE_WIDTH(11) | PM_TEXREADMODE_HEIGHT(11); pBuffer[18] = __Permedia2TagTextureDataFormat; pBuffer[19] = (ppdev->ulPermFormat << PM_TEXDATAFORMAT_FORMAT) | (ppdev->ulPermFormatEx << PM_TEXDATAFORMAT_FORMATEXTENSION) | (COLOR_MODE << PM_TEXDATAFORMAT_COLORORDER) | (1 << 4); // no alpha
pBuffer[20] = __Permedia2TagTextureMapFormat; pBuffer[21] = (psurfSrc->ulPackedPP) | (ppdev->cPelSize << PM_TEXMAPFORMAT_TEXELSIZE);
pBuffer[22] = __Permedia2TagColorDDAMode; pBuffer[23] = 1; pBuffer[24] = __Permedia2TagConstantColor; pBuffer[25] = alpha << 24 | 0xffffff ;
pBuffer += 26;
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; } //@@BEGIN_DDKSPLIT
// TODO: remove some of the magic values
//@@END_DDKSPLIT
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++;
}
InputBufferReserve(ppdev, 20, &pBuffer);
pBuffer[0] = __Permedia2TagdY; pBuffer[1] = INTtoFIXED(1); pBuffer[2] = __Permedia2TagDitherMode; pBuffer[3] = 0; pBuffer[4] = __Permedia2TagYUVMode; pBuffer[5] = 0; pBuffer[6] = __Permedia2TagTextureAddressMode; pBuffer[7] = __PERMEDIA_DISABLE; pBuffer[8] = __Permedia2TagTextureColorMode; pBuffer[9] = __PERMEDIA_DISABLE; pBuffer[10] = __Permedia2TagTextureReadMode; pBuffer[11] = __PERMEDIA_DISABLE; pBuffer[12] = __Permedia2TagAlphaBlendMode; pBuffer[13] = __PERMEDIA_DISABLE; pBuffer[14] = __Permedia2TagColorDDAMode; pBuffer[15] = __PERMEDIA_DISABLE; pBuffer[16] = __Permedia2TagTextureDataFormat; pBuffer[17] = __PERMEDIA_DISABLE; pBuffer[18] = __Permedia2TagTextureMapFormat; pBuffer[19] = __PERMEDIA_DISABLE;
pBuffer += 20;
InputBufferCommit(ppdev, pBuffer);
}// vConstantAlphaBlend()
//-----------------------------------------------------------------------------
//
// void vAlphaBlend(GFNPB * ppb)
//
// Doing an alpha blend on a source surface which is in a pre-multiplied alpha
// 32bpp "BGRA" format; that is, the surface type is BMF_32BPP and the palette
// type is BI_RGB.
//
// Argumentes needed from function block (GFNPB)
// ppdev-------PPDev
// psurfSrc----Source surface
// psurfDst----Destination surface
// pRects------Pointer to a list of rectangles information which needed to be
// filled
// lNumRects---Number of rectangles to fill
// prclDst-----Points to a RECTL structure that defines the rectangular area
// to be modified
// prclSrc-----Points to a RECTL structure that defines the rectangular area
// to be copied
// ucAlpha-----Alpha value
//
//-----------------------------------------------------------------------------
VOID vAlphaBlend(GFNPB * ppb) { PDev* ppdev = ppb->ppdev; Surf* psurfSrc = ppb->psurfSrc; Surf* psurfDst = ppb->psurfDst; RECTL* prcl = ppb->pRects; LONG c = ppb->lNumRects; RECTL* prclDst = ppb->prclDst; RECTL* prclSrc = ppb->prclSrc; DWORD dwRenderDirection; UCHAR ucAlpha = ppb->ucAlpha; ULONG* pBuffer;
DBG_GDI((6, "vAlphaBlend called")); DBG_GDI((7,"vAlphaBlend"));
ASSERTDD(ppdev->cPelSize != 0, "vAlphaBlend: expect not to be in 8bpp mode");
InputBufferReserve(ppdev, 26, &pBuffer);
pBuffer[0] = __Permedia2TagDitherMode; pBuffer[1] = (COLOR_MODE << PM_DITHERMODE_COLORORDER) | (ppdev->ulPermFormat << PM_DITHERMODE_COLORFORMAT) | (ppdev->ulPermFormatEx << PM_DITHERMODE_COLORFORMATEXTENSION) | (1 << PM_DITHERMODE_ENABLE); pBuffer[2] = __Permedia2TagAlphaBlendMode; pBuffer[3] = (1 << PM_ALPHABLENDMODE_BLENDTYPE) | // ramp
(1 << PM_ALPHABLENDMODE_COLORORDER) | // RGB
(1 << PM_ALPHABLENDMODE_ENABLE) | (81 << PM_ALPHABLENDMODE_OPERATION) | // PreMult
(ppdev->ulPermFormat << PM_ALPHABLENDMODE_COLORFORMAT) | (ppdev->ulPermFormatEx << PM_ALPHABLENDMODE_COLORFORMATEXTENSION); // Reject range
pBuffer[4] = __Permedia2TagFBWindowBase; pBuffer[5] = psurfDst->ulPixOffset; // set no read of source.
pBuffer[6] = __Permedia2TagFBReadMode; pBuffer[7] = 0x400 | psurfDst->ulPackedPP; pBuffer[8] = __Permedia2TagLogicalOpMode; pBuffer[9] = __PERMEDIA_DISABLE; // set base of source
pBuffer[10] = __Permedia2TagTextureBaseAddress; pBuffer[11] = psurfSrc->ulPixOffset; pBuffer[12] = __Permedia2TagTextureAddressMode; pBuffer[13] = (1 << PM_TEXADDRESSMODE_ENABLE); pBuffer[14] = __Permedia2TagTextureColorMode; pBuffer[15] = (1 << PM_TEXCOLORMODE_ENABLE) | (0 << 4) | // RGB
(0 << 1); // Modulate
pBuffer[16] = __Permedia2TagTextureReadMode; pBuffer[17] = PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) | PM_TEXREADMODE_FILTER(__PERMEDIA_DISABLE) | PM_TEXREADMODE_WIDTH(11) | PM_TEXREADMODE_HEIGHT(11); pBuffer[18] = __Permedia2TagTextureDataFormat; pBuffer[19] = (ppdev->ulPermFormat << PM_TEXDATAFORMAT_FORMAT) | (ppdev->ulPermFormatEx << PM_TEXDATAFORMAT_FORMATEXTENSION) | (COLOR_MODE << PM_TEXDATAFORMAT_COLORORDER); pBuffer[20] = __Permedia2TagTextureMapFormat; pBuffer[21] = (psurfSrc->ulPackedPP) | (ppdev->cPelSize << PM_TEXMAPFORMAT_TEXELSIZE); pBuffer[22] = __Permedia2TagColorDDAMode; pBuffer[23] = 1;
pBuffer[24] = __Permedia2TagConstantColor; pBuffer[25] = ucAlpha << 24 | ucAlpha << 16 | ucAlpha << 8 | ucAlpha;
pBuffer += 26;
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; } //@@BEGIN_DDKSPLIT
// TODO: use continuation to save permedia writes
// TODO: remove some of the magic values
//@@END_DDKSPLIT
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; } /*
* Render the rectangle */ 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++;
}
//
// Always restore default state
//
InputBufferReserve(ppdev, 16, &pBuffer);
pBuffer[0] = __Permedia2TagdY; pBuffer[1] = INTtoFIXED(1); pBuffer[2] = __Permedia2TagDitherMode; pBuffer[3] = 0; pBuffer[4] = __Permedia2TagYUVMode; pBuffer[5] = 0; pBuffer[6] = __Permedia2TagTextureAddressMode; pBuffer[7] = __PERMEDIA_DISABLE; pBuffer[8] = __Permedia2TagTextureColorMode; pBuffer[9] = __PERMEDIA_DISABLE; pBuffer[10] = __Permedia2TagTextureReadMode; pBuffer[11] = __PERMEDIA_DISABLE; pBuffer[12] = __Permedia2TagAlphaBlendMode; pBuffer[13] = __PERMEDIA_DISABLE; pBuffer[14] = __Permedia2TagColorDDAMode; pBuffer[15] = __PERMEDIA_DISABLE;
pBuffer += 16;
InputBufferCommit(ppdev, pBuffer);
}// vAlphaBlend()
//-----------------------------------------------------------------------------
//
// VOID vCopyBlt(GFNPB* ppb)
//
// Does a screen-to-screen copy blt of a list of rectangles.
//
// Argumentes needed from function block (GFNPB)
// ppdev-------PPDev
// psurfSrc----Source surface
// psurfDst----Destination surface
// pRects------Pointer to a list of rectangles information which needed to be
// filled
// lNumRects---Number of rectangles to fill
// prclDst-----Points to a RECTL structure that defines the rectangular area
// to be modified
// pptlSrc-----Original unclipped source point
//
//-----------------------------------------------------------------------------
VOID vCopyBlt(GFNPB* ppb) { PDev* ppdev = ppb->ppdev; Surf* psurfSrc = ppb->psurfSrc; Surf* psurfDst = ppb->psurfDst; RECTL* prcl = ppb->pRects; LONG c = ppb->lNumRects; RECTL* prclDst = ppb->prclDst; POINTL* pptlSrc = ppb->pptlSrc; DWORD renderBits = __RENDER_TRAPEZOID_PRIMITIVE; DWORD offset; LONG sourceOffset; DWORD windowBase; LONG windowOffset; ULONG DestPitch = psurfDst->ulPixDelta; ULONG SourcePitch = psurfSrc->ulPixDelta; BOOL bEnablePacked = TRUE; ULONG ulLogicOP = ulRop2ToLogicop(ppb->ulRop4 & 0xf);
DBG_GDI((6, "vCopyBlt called"));
windowBase = psurfDst->ulPixOffset; windowOffset = (LONG) (psurfSrc->ulPixOffset - psurfDst->ulPixOffset);
// BUGFIX: Permedia hardware bug
// We can not enable if we have an overlapping blt with not vertical shift
// and a horizontal shift less or equal to ppdev->dwBppMask
if (psurfSrc == psurfDst && prclDst->top == pptlSrc->y) { LONG xShift = prclDst->left - pptlSrc->x;
if(xShift >= 0 && xShift <= (LONG) ppdev->dwBppMask) bEnablePacked = FALSE; }
// BUGFIX: Permedia hardware bug???
// We have intermittent failures of the copy operation
// when going from the screen to offscreen where the first
// four bytes (when in 8bpp) of every row are not copied.
// For now, I'm disabling until we can talk with the permedia folks.
bEnablePacked = FALSE;
// setup loop invariant state
ULONG* pBuffer;
InputBufferReserve(ppdev, 4, &pBuffer);
pBuffer[0] = __Permedia2TagLogicalOpMode; pBuffer[1] = P2_ENABLED_LOGICALOP(ulLogicOP); pBuffer[2] = __Permedia2TagFBWindowBase; pBuffer[3] = windowBase;
pBuffer += 4;
InputBufferCommit(ppdev, pBuffer);
while(c--) {
RECTL rDest; RECTL rSrc;
rDest = *prcl;
rSrc.left = pptlSrc->x + (rDest.left - prclDst->left); rSrc.top = pptlSrc->y + (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(bEnablePacked) { offset = (((rDest.left & ppdev->dwBppMask) - (rSrc.left & ppdev->dwBppMask)) & 7); sourceOffset = windowOffset + ((rSrc.top * SourcePitch) + (rSrc.left & ~(ppdev->dwBppMask))) - ((rDest.top * DestPitch) + (rDest.left & ~(ppdev->dwBppMask))) + ((DestPitch - SourcePitch) * rDest.top); } else { offset = 0; sourceOffset = windowOffset + ((rSrc.top * SourcePitch) + rSrc.left) - ((rDest.top * DestPitch) + rDest.left) + ((DestPitch - SourcePitch) * rDest.top); } // P2_DEFAULT_FB_DEPTH;
ULONG readMode = PM_FBREADMODE_PARTIAL(psurfSrc->ulPackedPP) | PM_FBREADMODE_READSOURCE(__PERMEDIA_ENABLE) | PM_FBREADMODE_RELATIVEOFFSET(offset) | LogicopReadDest[ulLogicOP];
ULONG writeConfig = PM_FBREADMODE_PARTIAL(psurfDst->ulPackedPP) | PM_FBREADMODE_READSOURCE(__PERMEDIA_ENABLE) | PM_FBREADMODE_RELATIVEOFFSET(offset) | LogicopReadDest[ulLogicOP];
if(bEnablePacked) { readMode |= PM_FBREADMODE_PACKEDDATA(__PERMEDIA_ENABLE); writeConfig |= PM_FBREADMODE_PACKEDDATA(__PERMEDIA_ENABLE); } // Render the rectangle
ULONG startXDom; ULONG startXSub; ULONG packedDataLimits; ULONG startY; ULONG dy; if (sourceOffset >= 0) { // Use left to right and top to bottom
if(bEnablePacked) { startXDom = (rDest.left >> ppdev->bBppShift) << 16; startXSub = ((rDest.right >> ppdev->bBppShift) + ppdev->dwBppMask) << 16; packedDataLimits = PM_PACKEDDATALIMITS_OFFSET(offset) | PM_PACKEDDATALIMITS_XSTART(rDest.left) | PM_PACKEDDATALIMITS_XEND(rDest.right); } else { startXDom = rDest.left << 16; startXSub = rDest.right << 16; }
startY = rDest.top << 16; dy = 1 << 16; } else { // Use right to left and bottom to top
if(bEnablePacked) { startXDom = (((rDest.right) >> ppdev->bBppShift) + ppdev->dwBppMask) << 16; startXSub = (rDest.left >> ppdev->bBppShift) << 16; packedDataLimits = PM_PACKEDDATALIMITS_OFFSET(offset) | PM_PACKEDDATALIMITS_XSTART(rDest.right) | PM_PACKEDDATALIMITS_XEND(rDest.left); } else { startXDom = rDest.right << 16; startXSub = rDest.left << 16; } startY = (rDest.bottom - 1) << 16; dy = (DWORD)((-1) << 16); } ULONG count = rDest.bottom - rDest.top; InputBufferReserve(ppdev, 18, &pBuffer);
pBuffer[0] = __Permedia2TagFBSourceOffset; pBuffer[1] = sourceOffset; pBuffer[2] = __Permedia2TagFBReadMode; pBuffer[3] = readMode; pBuffer[4] = __Permedia2TagFBWriteConfig; pBuffer[5] = writeConfig; pBuffer[6] = __Permedia2TagStartXDom; pBuffer[7] = startXDom; pBuffer[8] = __Permedia2TagStartXSub; pBuffer[9] = startXSub; #if 0
if(bEnablePacked) { pBuffer[0] = __Permedia2TagPackedDataLimits; pBuffer[1] = packedDataLimits; } #endif
pBuffer[10] = __Permedia2TagStartY; pBuffer[11] = startY; pBuffer[12] = __Permedia2TagdY; pBuffer[13] = dy; pBuffer[14] = __Permedia2TagCount; pBuffer[15] = count; pBuffer[16] = __Permedia2TagRender; pBuffer[17] = renderBits;
pBuffer += 18;
InputBufferCommit(ppdev, pBuffer);
prcl++; }
InputBufferReserve(ppdev, 2, &pBuffer);
pBuffer[0] = __Permedia2TagdY; pBuffer[1] = INTtoFIXED(1);
pBuffer += 2; InputBufferCommit(ppdev, pBuffer);
}// vCopyBlt()
//-----------------------------------------------------------------------------
//
// VOID vCopyBltNative(GFNPB* ppb)
//
// Does a screen-to-screen copy blt of a list of rectangles.
//
// Note: The difference between this function and vCopyBlt() is that this
// function will be called only when the source and dest has the same pitch
// size. The reason is that we are using the Permedia2 packed data feature to
// do a 32 bits copy. Unfortunately when the source and dest has the different
// pitch, the hardware has some problems to implement it right. So in
// vCopyBlt(), we have to disable PackedData copy which slows down a lot
//
// Argumentes needed from function block (GFNPB)
// ppdev-------PPDev
// psurfSrc----Source surface
// psurfDst----Destination surface
// pRects------Pointer to a list of rectangles information which needed to be
// filled
// lNumRects---Number of rectangles to fill
// prclDst-----Points to a RECTL structure that defines the rectangular area
// to be modified
// pptlSrc-----Original unclipped source point
//
//-----------------------------------------------------------------------------
VOID vCopyBltNative(GFNPB* ppb) { PDev* ppdev = ppb->ppdev; Surf* psurfDst = ppb->psurfDst; Surf* psurfSrc = ppb->psurfSrc; RECTL* prcl = ppb->pRects; RECTL* prclDst = ppb->prclDst; POINTL* pptlSrc = ppb->pptlSrc; LONG lNumRects = ppb->lNumRects; LONG lSourceOffset; LONG lWindowOffset; DWORD dwOffset; ULONG ulLogicOP = ulRop2ToLogicop(ppb->ulRop4 & 0xf); ULONG ulPitch = psurfDst->ulPixDelta;
DBG_GDI((6, "vCopyBltNative called, ulPitch=%d", ulPitch));
lWindowOffset = (LONG)(psurfSrc->ulPixOffset - psurfDst->ulPixOffset);
//
// Setup loop invariant state
//
ULONG* pBuffer;
InputBufferReserve(ppdev, 4, &pBuffer);
pBuffer[0] = __Permedia2TagLogicalOpMode; pBuffer[1] = P2_ENABLED_LOGICALOP(ulLogicOP); pBuffer[2] = __Permedia2TagFBWindowBase; pBuffer[3] = psurfDst->ulPixOffset;
pBuffer += 4;
InputBufferCommit(ppdev, pBuffer);
while( lNumRects-- ) { RECTL rDest; RECTL rSrc;
rDest = *prcl; rSrc.left = pptlSrc->x + (rDest.left - prclDst->left); rSrc.top = pptlSrc->y + (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; }
dwOffset = (((rDest.left & ppdev->dwBppMask) - (rSrc.left & ppdev->dwBppMask)) & 7); lSourceOffset = lWindowOffset + ( (rSrc.top - rDest.top) * ulPitch ) + ( rSrc.left & ~(ppdev->dwBppMask) ) - ( rDest.left & ~(ppdev->dwBppMask) );
//
// Render the rectangle
//
ULONG ulStartXDom; ULONG ulStartXSub; ULONG ulPackedDataLimits; ULONG ulStartY; ULONG ulDY;
DBG_GDI((6, "lSourceOffset=%d", lSourceOffset));
if ( lSourceOffset >= 0 ) { //
// Use left to right and top to bottom
//
ulStartXDom = (rDest.left >> ppdev->bBppShift) << 16; ulStartXSub = ((rDest.right >> ppdev->bBppShift) + ppdev->dwBppMask) << 16;
ulPackedDataLimits = PM_PACKEDDATALIMITS_OFFSET(dwOffset) | (rDest.left << 16) | (rDest.right);
ulStartY = rDest.top << 16; ulDY = 1 << 16; }// if ( lSourceOffset >= 0 )
else { //
// Use right to left and bottom to top
//
ulStartXDom = (((rDest.right) >> ppdev->bBppShift) + ppdev->dwBppMask) << 16; ulStartXSub = (rDest.left >> ppdev->bBppShift) << 16; ulPackedDataLimits = PM_PACKEDDATALIMITS_OFFSET(dwOffset) | (rDest.right << 16) | (rDest.left);
ulStartY = (rDest.bottom - 1) << 16; ulDY = (DWORD)((-1) << 16); }// if ( lSourceOffset < 0 )
InputBufferReserve(ppdev, 18, &pBuffer);
pBuffer[0] = __Permedia2TagFBSourceOffset; pBuffer[1] = lSourceOffset; pBuffer[2] = __Permedia2TagFBReadMode; pBuffer[3] = PM_FBREADMODE_PARTIAL(psurfSrc->ulPackedPP) | PM_FBREADMODE_READSOURCE(__PERMEDIA_ENABLE) | PM_FBREADMODE_RELATIVEOFFSET(dwOffset) | PM_FBREADMODE_PACKEDDATA(__PERMEDIA_ENABLE) | LogicopReadDest[ulLogicOP]; pBuffer[4] = __Permedia2TagPackedDataLimits; pBuffer[5] = ulPackedDataLimits; pBuffer[6] = __Permedia2TagStartXDom; pBuffer[7] = ulStartXDom; pBuffer[8] = __Permedia2TagStartXSub; pBuffer[9] = ulStartXSub; pBuffer[10] = __Permedia2TagStartY; pBuffer[11] = ulStartY; pBuffer[12] = __Permedia2TagdY; pBuffer[13] = ulDY; pBuffer[14] = __Permedia2TagCount; pBuffer[15] = rDest.bottom - rDest.top; pBuffer[16] = __Permedia2TagRender; pBuffer[17] = __RENDER_TRAPEZOID_PRIMITIVE;
pBuffer += 18;
InputBufferCommit(ppdev, pBuffer);
prcl++; }// while( lNumRects-- )
//
// Restore dY register value
//
InputBufferReserve(ppdev, 2, &pBuffer);
pBuffer[0] = __Permedia2TagdY; pBuffer[1] = INTtoFIXED(1);
pBuffer += 2;
InputBufferCommit(ppdev, pBuffer); }// vCopyBltNative()
//-----------------------------------------------------------------------------
//
// VOID vRop2Blt
//
// Does a screen-to-screen blt of a list of rectangles.
//
// Argumentes needed from function block (GFNPB)
// ppdev-------PPDev
// psurfSrc----Source surface
// psurfDst----Destination surface
// pRects------Pointer to a list of rectangles information which needed to be
// filled
// lNumRects---Number of rectangles to fill
// prclDst-----Points to a RECTL structure that defines the rectangular area
// to be modified
// pptlSrc-----Original unclipped source point
// usRop4------Rop4
//
//-----------------------------------------------------------------------------
VOID vRop2Blt(GFNPB * ppb) { PDev* ppdev = ppb->ppdev; Surf* psurfSrc = ppb->psurfSrc; Surf* psurfDst = ppb->psurfDst; RECTL* prcl = ppb->pRects; LONG c = ppb->lNumRects; RECTL* prclDst = ppb->prclDst; POINTL* pptlSrc = ppb->pptlSrc; ULONG ulLogicOP = ulRop2ToLogicop(ppb->ulRop4 & 0xf); ULONG* pBuffer; // PERMEDIA_DECL_VARS;
// PERMEDIA_DECL_INIT;
ASSERTDD(psurfSrc != psurfDst, "vRop2Blt: unexpected psurfSrc == psurfDst");
InputBufferReserve(ppdev, 32, &pBuffer); pBuffer[0] = __Permedia2TagFBWindowBase; pBuffer[1] = psurfDst->ulPixOffset; pBuffer[2] = __Permedia2TagLogicalOpMode; pBuffer[3] = P2_ENABLED_LOGICALOP(ulLogicOP); pBuffer[4] = __Permedia2TagFBReadMode; pBuffer[5] = PM_FBREADMODE_PARTIAL(psurfDst->ulPackedPP) | LogicopReadDest[ulLogicOP]; pBuffer[6] = __Permedia2TagFBWriteConfig; pBuffer[7] = PM_FBREADMODE_PARTIAL(psurfDst->ulPackedPP) | LogicopReadDest[ulLogicOP]; pBuffer[8] = __Permedia2TagDitherMode; pBuffer[9] = (COLOR_MODE << PM_DITHERMODE_COLORORDER) | (ppdev->ulPermFormat << PM_DITHERMODE_COLORFORMAT) | (ppdev->ulPermFormatEx << PM_DITHERMODE_COLORFORMATEXTENSION) | (1 << PM_DITHERMODE_ENABLE); pBuffer[10] = __Permedia2TagTextureAddressMode; pBuffer[11] = (1 << PM_TEXADDRESSMODE_ENABLE); pBuffer[12] = __Permedia2TagTextureColorMode; pBuffer[13] = (1 << PM_TEXCOLORMODE_ENABLE) | (0 << 4) | // RGB
(3 << 1); // Copy
pBuffer[14] = __Permedia2TagTextureReadMode; pBuffer[15] = PM_TEXREADMODE_ENABLE(__PERMEDIA_ENABLE) | PM_TEXREADMODE_WIDTH(11) | PM_TEXREADMODE_HEIGHT(11); pBuffer[16] = __Permedia2TagTextureDataFormat; pBuffer[17] = (ppdev->ulPermFormat << PM_TEXDATAFORMAT_FORMAT) | (ppdev->ulPermFormatEx << PM_TEXDATAFORMAT_FORMATEXTENSION) | (COLOR_MODE << PM_TEXDATAFORMAT_COLORORDER); pBuffer[18] = __Permedia2TagTextureMapFormat; pBuffer[19] = (psurfSrc->ulPackedPP) | (ppdev->cPelSize << PM_TEXMAPFORMAT_TEXELSIZE); pBuffer[20] = __Permedia2TagSStart; pBuffer[21] = 0; pBuffer[22] = __Permedia2TagTStart; pBuffer[23] = 0; pBuffer[24] = __Permedia2TagdSdx; pBuffer[25] = 1 << 20; pBuffer[26] = __Permedia2TagdSdyDom; pBuffer[27] = 0; pBuffer[28] = __Permedia2TagdTdx; pBuffer[29] = 0; pBuffer[30] = __Permedia2TagdTdyDom; pBuffer[31] = 1 << 20;
pBuffer += 32;
InputBufferCommit(ppdev, pBuffer); while(c--) {
// Render the rectangle
ULONG ulSrcOffset = psurfSrc->ulPixOffset + pptlSrc->x + (prcl->left - prclDst->left) + (pptlSrc->y + (prcl->top - prclDst->top)) * psurfSrc->ulPixDelta;
InputBufferReserve(ppdev, 12, &pBuffer);
pBuffer[0] = __Permedia2TagTextureBaseAddress; pBuffer[1] = ulSrcOffset; pBuffer[2] = __Permedia2TagStartXDom; pBuffer[3] = prcl->left << 16; pBuffer[4] = __Permedia2TagStartXSub; pBuffer[5] = prcl->right << 16; pBuffer[6] = __Permedia2TagStartY; pBuffer[7] = prcl->top << 16; pBuffer[8] = __Permedia2TagCount; pBuffer[9] = prcl->bottom - prcl->top; pBuffer[10] = __Permedia2TagRender; pBuffer[11] = __RENDER_TRAPEZOID_PRIMITIVE | __RENDER_TEXTURED_PRIMITIVE;
pBuffer += 12; InputBufferCommit(ppdev, pBuffer); prcl++; }
// Restore default state
InputBufferReserve(ppdev, 8, &pBuffer); pBuffer[0] = __Permedia2TagDitherMode; pBuffer[1] = 0; pBuffer[2] = __Permedia2TagTextureAddressMode; pBuffer[3] = __PERMEDIA_DISABLE; pBuffer[4] = __Permedia2TagTextureColorMode; pBuffer[5] = __PERMEDIA_DISABLE; pBuffer[6] = __Permedia2TagTextureReadMode; pBuffer[7] = __PERMEDIA_DISABLE;
pBuffer += 8;
InputBufferCommit(ppdev, pBuffer);
}
|