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