windows-nt/Source/XPSP1/NT/drivers/video/matrox/mga/disp/mcdutil.h
2020-09-26 16:20:57 +08:00

479 lines
15 KiB
C

/******************************Module*Header*******************************\
* Module Name: mcdutil.h
*
* Include file which indirects all of the hardware-dependent functionality
* in the MCD driver code.
*
* Copyright (c) 1996 Microsoft Corporation
\**************************************************************************/
#ifndef _MCDUTIL_H
#define _MCDUTIL_H
// Function prorotypes:
VOID PickRenderingFuncs(DEVRC *pRc);
#if DBG
UCHAR *MCDDbgAlloc(UINT);
VOID MCDDbgFree(UCHAR *);
#define MCDAlloc MCDDbgAlloc
#define MCDFree MCDDbgFree
VOID MCDrvDebugPrint(char *, ...);
#define MCDBG_PRINT MCDrvDebugPrint
#else
UCHAR *MCDAlloc(UINT);
VOID MCDFree(UCHAR *);
#define MCDBG_PRINT
#endif
#define INTERSECTRECT(RectInter, pRect, Rect)\
{\
RectInter.left = max(pRect->left, Rect.left);\
RectInter.right = min(pRect->right, Rect.right);\
RectInter.top = max(pRect->top, Rect.top);\
RectInter.bottom = min(pRect->bottom, Rect.bottom);\
}
#define MCD_CHECK_RC(pRc)\
if (pRc == NULL) {\
MCDBG_PRINT("NULL device RC");\
return FALSE;\
}
#define MCD_CHECK_DEVWND(pMCDSurface, pDevWnd, resChangedRet)\
{\
if (!pDevWnd) {\
MCDBG_PRINT("MCD_CHECK_DEVWND: NULL DEVWND");\
return FALSE;\
}\
\
if (pDevWnd->dispUnique != GetDisplayUniqueness((PDEV *)pMCDSurface->pso->dhpdev)) {\
MCDBG_PRINT("MCD_CHECK_DEVWND: resolution changed but not updated");\
return resChangedRet;\
}\
}
#define MCD_CHECK_BUFFERS_VALID(pMCDSurface, pRc, resChangedRet)\
{\
DEVWND *pDevWnd = (DEVWND *)pMCDSurface->pWnd->pvUser;\
\
MCD_CHECK_DEVWND(pMCDSurface, pDevWnd, resChangedRet);\
\
if (((pRc)->backBufEnabled) &&\
(!pDevWnd->bValidBackBuffer)) {\
MCDBG_PRINT("HW_CHECK_BUFFERS_VALID: back buffer invalid");\
return FALSE;\
}\
\
if (((pRc)->zBufEnabled) &&\
(!pDevWnd->bValidZBuffer)) {\
MCDBG_PRINT("HW_CHECK_BUFFERS_VALID: z buffer invalid");\
return FALSE;\
}\
\
}
#define MCD_INIT_BUFFER_PARAMS(pMCDSurface, pMCDWnd, pDevWnd, pRc)\
{\
pRc->hwYOrgBias = pMCDWnd->clipBoundsRect.top;\
\
if ((pRc)->MCDState.drawBuffer == GL_FRONT) {\
(pRc)->hwBufferYBias = 0;\
} else if ((pRc)->MCDState.drawBuffer == GL_BACK) {\
if (ppdev->pohBackBuffer == pDevWnd->pohBackBuffer) {\
pRc->hwBufferYBias = pDevWnd->backBufferY;\
} else {\
pRc->hwBufferYBias = pDevWnd->backBufferY - \
pMCDWnd->clipBoundsRect.top;\
}\
}\
}
__inline ULONG HW_GET_VCOUNT(BYTE *pjBase)
{
CP_EIEIO();
return(CP_READ_REGISTER((pjBase) + HST_VCOUNT));
}
__inline void HW_WAIT_DRAWING_DONE(DEVRC *pRc)
{
BYTE *pjBase = pRc->ppdev->pjBase;
ULONG *pScreen;
volatile ULONG read;
while ((GET_FIFO_SPACE(pjBase) < FIFOSIZE) || IS_BUSY(pjBase))
;
pScreen = (ULONG *)pRc->ppdev->pjScreen;
read = *pScreen;
read |= *(pScreen+32);
}
__inline void HW_INIT_DRAWING_STATE(MCDSURFACE *pMCDSurface, MCDWINDOW *pMCDWnd,
DEVRC *pRc)
{
DEVWND *pDevWnd = (DEVWND *)pMCDWnd->pvUser;
PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
BYTE *pjBase = ppdev->pjBase;
ULONG ulAccess;
LONG yOrg;
CHECK_FIFO_SPACE(pjBase, 4);
ulAccess = ppdev->ulAccess;
if (!(pRc->MCDState.enables & MCD_DITHER_ENABLE))
ulAccess |= dither_DISABLE;
pRc->ulAccess = ulAccess;
CP_WRITE(pjBase, DWG_MACCESS, ulAccess);
// Stash the upper-left y away in the context:
pRc->hwYOrgBias = pMCDWnd->clipBoundsRect.top;
// Note: zBufferOffset is maintained in MCDrvTrackWindow
if (pRc->MCDState.drawBuffer == GL_FRONT) {
if (pDevWnd->pohZBuffer) {
LONG zDiff;
if (ppdev->pohZBuffer == pDevWnd->pohZBuffer)
zDiff = pDevWnd->zBufferOffset;
else
zDiff = pDevWnd->zBufferOffset -
(pMCDWnd->clipBoundsRect.top * pDevWnd->zPitch);
if (zDiff < 0)
zDiff = 0x800000 + zDiff;
ASSERTDD((zDiff & 0x1ff) == 0,
"Front and Z buffers are not a multiple of 512 apart.");
CP_WRITE(pjBase, DWG_ZORG, zDiff);
}
pRc->hwBufferYBias = 0;
yOrg = pMCDWnd->clipBoundsRect.top;
} else if (pRc->MCDState.drawBuffer == GL_BACK) {
if (pDevWnd->pohZBuffer) {
LONG zDiff;
zDiff = pDevWnd->zBufferOffset -
(pDevWnd->backBufferY * pDevWnd->zPitch);
ASSERTDD((zDiff & 0x1ff) == 0,
"Back and Z buffers are not a multiple of 512 apart.");
if (zDiff < 0)
zDiff = 0x800000 + zDiff;
CP_WRITE(pjBase, DWG_ZORG, zDiff);
}
if (ppdev->pohBackBuffer == pDevWnd->pohBackBuffer) {
yOrg = pMCDWnd->clipBoundsRect.top + pDevWnd->backBufferY;
pRc->hwBufferYBias = pDevWnd->backBufferY;
} else {
yOrg = pDevWnd->backBufferY;
pRc->hwBufferYBias = pDevWnd->backBufferY -
pMCDWnd->clipBoundsRect.top;
}
}
// We have to adjust the stipple pattern on each batch since the window
// may have moved, and the HW stipple pattern is screen-relative whereas
// OpenGL's is window-relative. We can't do the update in the tracking
// function since we don't have an RC. Note that we only deal with simple
// (101010) checkerboard stipples which are the most common.
if (pRc->hwStipple) {
LONG ofsAdj = (pMCDSurface->pWnd->clientRect.bottom & 0x1) ^
(pMCDSurface->pWnd->clientRect.left & 0x1);
pRc->hwTrapFunc &= ~((ULONG)trans_15);
if (ofsAdj)
pRc->hwTrapFunc |= (pRc->hwStipple ^ (trans_1 | trans_2));
else
pRc->hwTrapFunc |= pRc->hwStipple;
}
CP_WRITE(pjBase, DWG_YDSTORG, (yOrg * ppdev->cxMemory) + ppdev->ulYDstOrg);
CP_WRITE(pjBase, DWG_PLNWT, pRc->hwPlaneMask);
}
__inline void HW_INIT_PRIMITIVE_STATE(MCDSURFACE *pMCDSurface, DEVRC *pRc)
{
PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
BYTE *pjBase = ppdev->pjBase;
if (!(pRc->privateEnables & __MCDENABLE_SMOOTH)) {
// We will be using the interpolation mode of the hardware, but we'll
// only be interpolation Z, so set the color deltas to 0.
CHECK_FIFO_SPACE(pjBase, 6);
CP_WRITE(pjBase, DWG_DR6, 0);
CP_WRITE(pjBase, DWG_DR7, 0);
CP_WRITE(pjBase, DWG_DR10, 0);
CP_WRITE(pjBase, DWG_DR11, 0);
CP_WRITE(pjBase, DWG_DR14, 0);
CP_WRITE(pjBase, DWG_DR15, 0);
}
CHECK_FIFO_SPACE(pjBase, FIFOSIZE);
pRc->cFifo = 32;
}
__inline void HW_DEFAULT_STATE(MCDSURFACE *pMCDSurface)
{
PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
BYTE *pjBase = ppdev->pjBase;
CHECK_FIFO_SPACE(pjBase, 7);
// restore default clipping, sign register, plane mask, pitch
CP_WRITE(pjBase, DWG_MACCESS, ppdev->ulAccess);
CP_WRITE(pjBase, DWG_SGN, 0);
CP_WRITE(pjBase, DWG_PITCH, ppdev->cxMemory | ylin_LINEARIZE);
CP_WRITE(pjBase, DWG_PLNWT, ppdev->ulPlnWt);
CP_WRITE(pjBase, DWG_YDSTORG, ppdev->ulYDstOrg);
vResetClipping(ppdev);
ppdev->HopeFlags = 0; // brute-force this
}
__inline void HW_GET_PLANE_MASK(DEVRC *pRc)
{
if (pRc->MCDState.colorWritemask[0] &&
pRc->MCDState.colorWritemask[1] &&
pRc->MCDState.colorWritemask[2] &&
pRc->MCDState.colorWritemask[3])
pRc->hwPlaneMask = ~((ULONG)0);
else {
ULONG mask = 0;
if (pRc->MCDState.colorWritemask[0])
mask |= ((1 << pRc->pixelFormat.rBits) - 1) <<
pRc->pixelFormat.rShift;
if (pRc->MCDState.colorWritemask[1])
mask |= ((1 << pRc->pixelFormat.gBits) - 1) <<
pRc->pixelFormat.gShift;
if (pRc->MCDState.colorWritemask[2])
mask |= ((1 << pRc->pixelFormat.bBits) - 1) <<
pRc->pixelFormat.bShift;
switch (pRc->pixelFormat.cColorBits) {
case 8:
pRc->hwPlaneMask = mask | (mask << 8) | (mask << 16) | (mask << 24);
break;
case 15:
case 16:
pRc->hwPlaneMask = mask | (mask << 16);
break;
default:
pRc->hwPlaneMask = mask;
break;
}
}
}
__inline void HW_START_FILL_RECT(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc,
DEVRC *pRc, ULONG buffers)
{
PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
BYTE *pjBase = ppdev->pjBase;
DEVWND *pDevWnd = (DEVWND *)pMCDSurface->pWnd->pvUser;
ULONG hwOp;
BOOL bFillC = (buffers & GL_COLOR_BUFFER_BIT) != 0;
BOOL bFillZ = (buffers & GL_DEPTH_BUFFER_BIT) &&
pRc->MCDState.depthWritemask;
RGBACOLOR color;
ULONG zFillValue;
ULONG sumColor;
//MCDBG_PRINT("HW_START_FILL_RECT: bFillC = %d, bFillZ = %d", bFillC, bFillZ);
// This is a little slimy, but we don't know whether or not the plane
// mask has changed since the last drawing batch:
if (pRc->pickNeeded)
HW_GET_PLANE_MASK(pRc);
if (!bFillZ && (pRc->MCDState.colorClearValue.r == (MCDFLOAT)0.0) &&
(pRc->MCDState.colorClearValue.g == (MCDFLOAT)0.0) &&
(pRc->MCDState.colorClearValue.b == (MCDFLOAT)0.0)) {
CHECK_FIFO_SPACE(pjBase, 3);
CP_WRITE(pjBase, DWG_DWGCTL, opcode_TRAP | atype_RPL | bop_SRCCOPY |
zdrwen_NO_DEPTH | blockm_ON | solid_SOLID | arzero_ZERO |
sgnzero_ZERO);
CP_WRITE(pjBase, DWG_FCOL, 0);
CP_WRITE(pjBase, DWG_PLNWT, pRc->hwPlaneMask);
} else {
CHECK_FIFO_SPACE(pjBase, 16);
MCDFIXEDRGB(color, pRc->MCDState.colorClearValue);
// This logic is needed to pass conformance, since dithering
// with pure white will cause problems on the Millenium.
sumColor = (color.r | color.g | color.b) & ~(0x7fff);
if ((sumColor == 0x7f8000) || (sumColor == 0)) {
CP_WRITE(pjBase, DWG_MACCESS, pRc->ulAccess | dither_DISABLE);
}
//MCDBG_PRINT("fixcolor = %x, %x, %x, %x", color.r, color.g, color.b, color.a);
//color.b = 0x3f0000;
//!!MCDBG_PRINT("realcolor = %f, %f, %f, %f", pRc->MCDState.colorClearValue.r,
//!! pRc->MCDState.colorClearValue.g,
//!! pRc->MCDState.colorClearValue.b,
//!! pRc->MCDState.colorClearValue.a);
// NOTE: For Storm, assuming it's fixed so that the z-buffer isn't
// always written, regardless of the 'zdrwen' bit, we will
// have to clear the z-buffer using a 2-d blt (don't forget
// to reset clipping!). But with the Athena, we get this
// functionality by default.
zFillValue = (ULONG)(pRc->MCDState.depthClearValue);
//MCDBG_PRINT("zFillValue = %x", zFillValue);
if (bFillZ) {
//MCDBG_PRINT("Fill Rect with Color+Z");
CP_WRITE(pjBase, DWG_DWGCTL, opcode_TRAP | atype_ZI | bop_SRCCOPY |
solid_SOLID | arzero_ZERO | sgnzero_ZERO);
CP_WRITE(pjBase, DWG_DR0, zFillValue << 15);
} else {
//MCDBG_PRINT("Fill Rect with Color");
CP_WRITE(pjBase, DWG_DWGCTL, opcode_TRAP | atype_I | bop_SRCCOPY |
solid_SOLID | arzero_ZERO | sgnzero_ZERO);
}
// If we're filling the z-buffer only, zero the plane mask:
if (bFillZ && !bFillC)
CP_WRITE(pjBase, DWG_PLNWT, 0);
else
CP_WRITE(pjBase, DWG_PLNWT, pRc->hwPlaneMask);
CP_WRITE(pjBase, DWG_DR4, color.r);
CP_WRITE(pjBase, DWG_DR8, color.g);
CP_WRITE(pjBase, DWG_DR12, color.b);
// Set all deltas to 0
CP_WRITE(pjBase, DWG_DR2, 0);
CP_WRITE(pjBase, DWG_DR3, 0);
CP_WRITE(pjBase, DWG_DR6, 0);
CP_WRITE(pjBase, DWG_DR7, 0);
CP_WRITE(pjBase, DWG_DR10, 0);
CP_WRITE(pjBase, DWG_DR11, 0);
CP_WRITE(pjBase, DWG_DR14, 0);
CP_WRITE(pjBase, DWG_DR15, 0);
}
CHECK_FIFO_SPACE(pjBase, 4);
CP_WRITE(pjBase, DWG_CYTOP,
((pMCDSurface->pWnd->clipBoundsRect.top + pRc->hwBufferYBias) * ppdev->cxMemory) +
ppdev->ulYDstOrg);
CP_WRITE(pjBase, DWG_CXLEFT, pMCDSurface->pWnd->clipBoundsRect.left);
CP_WRITE(pjBase, DWG_CXRIGHT, pMCDSurface->pWnd->clipBoundsRect.right - 1);
CP_WRITE(pjBase, DWG_CYBOT,
((pMCDSurface->pWnd->clipBoundsRect.bottom + pRc->hwBufferYBias - 1) * ppdev->cxMemory) +
ppdev->ulYDstOrg);
}
__inline void HW_FILL_RECT(MCDSURFACE *pMCDSurface, DEVRC *pRc, RECTL *pRecl)
{
PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
BYTE *pjBase = ppdev->pjBase;
//MCDBG_PRINT("fill rect = %d, %d, %d, %d", pRecl->left,
// pRecl->top,
// pRecl->right,
// pRecl->bottom);
CHECK_FIFO_SPACE(pjBase, 5);
CP_WRITE(pjBase, DWG_YDST, pRecl->top - pRc->hwYOrgBias);
CP_WRITE(pjBase, DWG_YDST, pRecl->top - pRc->hwYOrgBias);
CP_WRITE(pjBase, DWG_FXLEFT, pRecl->left);
CP_WRITE(pjBase, DWG_LEN, pRecl->bottom - pRecl->top);
CP_START(pjBase, DWG_FXRIGHT, pRecl->right);
}
__inline void HW_START_SWAP_BUFFERS(MCDSURFACE *pMCDSurface,
LONG *hwBufferYBias,
ULONG flags)
{
PDEV *ppdev = (PDEV *)pMCDSurface->pso->dhpdev;
BYTE *pjBase = ppdev->pjBase;
DEVWND *pDevWnd = (DEVWND *)(pMCDSurface->pWnd->pvUser);
CHECK_FIFO_SPACE(pjBase, 4);
CP_WRITE(pjBase, DWG_DWGCTL, opcode_BITBLT + atype_RPL + blockm_OFF +
bltmod_BFCOL + pattern_OFF + transc_BG_OPAQUE +
bop_SRCCOPY);
CP_WRITE(pjBase, DWG_SHIFT, 0);
CP_WRITE(pjBase, DWG_SGN, 0);
CP_WRITE(pjBase, DWG_AR5, ppdev->cxMemory);
if (ppdev->pohBackBuffer == pDevWnd->pohBackBuffer) {
*hwBufferYBias = pDevWnd->backBufferY;
} else {
*hwBufferYBias = pDevWnd->backBufferY -
pMCDSurface->pWnd->clipBoundsRect.top;
}
}
void SETUPTRIANGLEDRAWING(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc);
void DrawTriangle(MCDSURFACE *pMCDSurface, MCDRC *pMCDRc,
MCDVERTEX *pMCDVertex);
// External declarations
void FASTCALL __HWDrawTrap(DEVRC *pRc, MCDFLOAT dxLeft, MCDFLOAT dxRight,
LONG y, LONG dy);
VOID FASTCALL __HWSetupDeltas(DEVRC *pRc);
BOOL HWAllocResources(MCDWINDOW *pMCDWnd, SURFOBJ *pso, BOOL zEnabled,
BOOL backBufferEnabled);
VOID HWUpdateBufferPos(MCDWINDOW *pMCDWnd, SURFOBJ *pso, BOOL bForce);
VOID HWFreeResources(MCDWINDOW *pMCDWnd, SURFOBJ *pso);
VOID vMilCopyBlt3D(PDEV* ppdev, POINTL* pptlSrc, RECTL* prclDst);
#endif /* _MCDUTIL_H */