/******************************Module*Header*******************************\ * Module Name: ddraw64.c * * Implements all the common DirectDraw components for the * ATI MACH 64/32/32 Memory mapped driver. * * Copyright (c) 1995-1996 Microsoft Corporation \**************************************************************************/ #include "precomp.h" extern BOOL DrvGetDirectDrawInfo32I( DHPDEV dhpdev,DD_HALINFO* pHalInfo,DWORD* pdwNumHeaps,VIDEOMEMORY* pvmList, DWORD* pdwNumFourCC,DWORD* pdwFourCC); extern BOOL DrvGetDirectDrawInfo32M( DHPDEV dhpdev,DD_HALINFO* pHalInfo,DWORD* pdwNumHeaps,VIDEOMEMORY* pvmList, DWORD* pdwNumFourCC,DWORD* pdwFourCC); extern BOOL DrvGetDirectDrawInfo64( DHPDEV dhpdev,DD_HALINFO* pHalInfo,DWORD* pdwNumHeaps,VIDEOMEMORY* pvmList, DWORD* pdwNumFourCC,DWORD* pdwFourCC); extern VOID vGetDisplayDuration32I(PDEV* ppdev); extern DWORD DdBlt32I(PDD_BLTDATA lpBlt); extern DWORD DdFlip32I(PDD_FLIPDATA lpFlip); extern DWORD DdLock32I(PDD_LOCKDATA lpLock); extern DWORD DdGetBltStatus32I(PDD_GETBLTSTATUSDATA lpGetBltStatus); extern DWORD DdGetFlipStatus32I(PDD_GETFLIPSTATUSDATA lpGetFlipStatus); extern DWORD DdWaitForVerticalBlank32I(PDD_WAITFORVERTICALBLANKDATA lpWaitForVerticalBlank); extern DWORD DdGetScanLine32I(PDD_GETSCANLINEDATA lpGetScanLine); extern VOID vGetDisplayDuration32M(PDEV* ppdev); extern DWORD DdBlt32M(PDD_BLTDATA lpBlt); extern DWORD DdFlip32M(PDD_FLIPDATA lpFlip); extern DWORD DdLock32M(PDD_LOCKDATA lpLock); extern DWORD DdGetBltStatus32M(PDD_GETBLTSTATUSDATA lpGetBltStatus); extern DWORD DdGetFlipStatus32M(PDD_GETFLIPSTATUSDATA lpGetFlipStatus); extern DWORD DdWaitForVerticalBlank32M(PDD_WAITFORVERTICALBLANKDATA lpWaitForVerticalBlank); extern DWORD DdGetScanLine32M(PDD_GETSCANLINEDATA lpGetScanLine); extern VOID vGetDisplayDuration64(PDEV* ppdev); extern DWORD DdBlt64(PDD_BLTDATA lpBlt); extern DWORD DdFlip64(PDD_FLIPDATA lpFlip); extern DWORD DdLock64(PDD_LOCKDATA lpLock); extern DWORD DdGetBltStatus64(PDD_GETBLTSTATUSDATA lpGetBltStatus); extern DWORD DdGetFlipStatus64(PDD_GETFLIPSTATUSDATA lpGetFlipStatus); extern DWORD DdWaitForVerticalBlank64(PDD_WAITFORVERTICALBLANKDATA lpWaitForVerticalBlank); extern DWORD DdGetScanLine64(PDD_GETSCANLINEDATA lpGetScanLine); /******************************Public*Routine******************************\ * DWORD DdMapMemory * * This is a new DDI call specific to Windows NT that is used to map * or unmap all the application modifiable portions of the frame buffer * into the specified process's address space. * \**************************************************************************/ DWORD DdMapMemory( PDD_MAPMEMORYDATA lpMapMemory) { PDEV* ppdev; VIDEO_SHARE_MEMORY ShareMemory; VIDEO_SHARE_MEMORY_INFORMATION ShareMemoryInformation; DWORD ReturnedDataLength; ppdev = (PDEV*) lpMapMemory->lpDD->dhpdev; if (lpMapMemory->bMap) { ShareMemory.ProcessHandle = lpMapMemory->hProcess; // 'RequestedVirtualAddress' isn't actually used for the SHARE IOCTL: ShareMemory.RequestedVirtualAddress = 0; // We map in starting at the top of the frame buffer: ShareMemory.ViewOffset = 0; // We map down to the end of the frame buffer. // // Note: There is a 64k granularity on the mapping (meaning that // we have to round up to 64k). // // Note: If there is any portion of the frame buffer that must // not be modified by an application, that portion of memory // MUST NOT be mapped in by this call. This would include // any data that, if modified by a malicious application, // would cause the driver to crash. This could include, for // example, any DSP code that is kept in off-screen memory. ShareMemory.ViewSize = ROUND_UP_TO_64K(ppdev->cyMemory * ppdev->lDelta); DISPDBG((10, "Share memory size %x %d",ShareMemory.ViewSize,ShareMemory.ViewSize)); if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_SHARE_VIDEO_MEMORY, &ShareMemory, sizeof(VIDEO_SHARE_MEMORY), &ShareMemoryInformation, sizeof(VIDEO_SHARE_MEMORY_INFORMATION), &ReturnedDataLength)) { DISPDBG((10, "Failed IOCTL_VIDEO_SHARE_MEMORY")); lpMapMemory->ddRVal = DDERR_GENERIC; return(DDHAL_DRIVER_HANDLED); } lpMapMemory->fpProcess =(FLATPTR)ShareMemoryInformation.VirtualAddress; } else { ShareMemory.ProcessHandle = lpMapMemory->hProcess; ShareMemory.ViewOffset = 0; ShareMemory.ViewSize = 0; ShareMemory.RequestedVirtualAddress = (VOID*) lpMapMemory->fpProcess; if (EngDeviceIoControl(ppdev->hDriver, IOCTL_VIDEO_UNSHARE_VIDEO_MEMORY, &ShareMemory, sizeof(VIDEO_SHARE_MEMORY), NULL, 0, &ReturnedDataLength)) { RIP("Failed IOCTL_VIDEO_UNSHARE_MEMORY"); } } lpMapMemory->ddRVal = DD_OK; return(DDHAL_DRIVER_HANDLED); } /******************************Public*Routine******************************\ * BOOL DrvGetDirectDrawInfo * * Will be called before DrvEnableDirectDraw is called. * \**************************************************************************/ BOOL DrvGetDirectDrawInfo( DHPDEV dhpdev, DD_HALINFO* pHalInfo, DWORD* pdwNumHeaps, VIDEOMEMORY* pvmList, // Will be NULL on first call DWORD* pdwNumFourCC, DWORD* pdwFourCC) // Will be NULL on first call { PDEV* ppdev; ppdev = (PDEV*) dhpdev; // if no APERATURE then we are a MACH8 and have no DDraw support if (ppdev->iAperture == APERTURE_NONE) { return FALSE; } // we can't use DirectDraw on a banked device because of a conflict // over who owns the bank registers between VideoPortMapBankedMemory // and the display driver if (!(ppdev->flCaps & CAPS_LINEAR_FRAMEBUFFER)) { return FALSE; } if (ppdev->iMachType == MACH_MM_32) { // Can do memory-mapped IO: return(DrvGetDirectDrawInfo32M(dhpdev,pHalInfo,pdwNumHeaps,pvmList,pdwNumFourCC,pdwFourCC)); } else if (ppdev->iMachType == MACH_IO_32) { return(DrvGetDirectDrawInfo32I(dhpdev,pHalInfo,pdwNumHeaps,pvmList,pdwNumFourCC,pdwFourCC)); } else { // MACH 64 return(DrvGetDirectDrawInfo64(dhpdev,pHalInfo,pdwNumHeaps,pvmList,pdwNumFourCC,pdwFourCC)); } } /******************************Public*Routine******************************\ * BOOL DrvEnableDirectDraw * * This function is called by GDI to enable DirectDraw when a DirectDraw * program is started and DirectDraw is not already active. * \**************************************************************************/ BOOL DrvEnableDirectDraw( DHPDEV dhpdev, DD_CALLBACKS* pCallBacks, DD_SURFACECALLBACKS* pSurfaceCallBacks, DD_PALETTECALLBACKS* pPaletteCallBacks) { PDEV* ppdev; ppdev = (PDEV*) dhpdev; if (ppdev->iMachType == MACH_MM_32) { pSurfaceCallBacks->Blt = DdBlt32M; pSurfaceCallBacks->Flip = DdFlip32M; pSurfaceCallBacks->Lock = DdLock32M; pSurfaceCallBacks->GetBltStatus = DdGetBltStatus32M; pSurfaceCallBacks->GetFlipStatus = DdGetFlipStatus32M; if (ppdev->iBitmapFormat >= BMF_24BPP) { pSurfaceCallBacks->dwFlags = DDHAL_SURFCB32_LOCK; } else { pSurfaceCallBacks->dwFlags = DDHAL_SURFCB32_BLT | DDHAL_SURFCB32_FLIP | DDHAL_SURFCB32_LOCK | DDHAL_SURFCB32_GETBLTSTATUS | DDHAL_SURFCB32_GETFLIPSTATUS; } pCallBacks->WaitForVerticalBlank = DdWaitForVerticalBlank32M; pCallBacks->GetScanLine = DdGetScanLine32M; pCallBacks->MapMemory = DdMapMemory; pCallBacks->dwFlags = DDHAL_CB32_WAITFORVERTICALBLANK | DDHAL_CB32_GETSCANLINE | DDHAL_CB32_MAPMEMORY; } else if (ppdev->iMachType == MACH_IO_32 ) { pSurfaceCallBacks->Blt = DdBlt32I; pSurfaceCallBacks->Flip = DdFlip32I; pSurfaceCallBacks->Lock = DdLock32I; pSurfaceCallBacks->GetBltStatus = DdGetBltStatus32I; pSurfaceCallBacks->GetFlipStatus = DdGetFlipStatus32I; if (ppdev->iBitmapFormat >= BMF_24BPP) { pSurfaceCallBacks->dwFlags = DDHAL_SURFCB32_LOCK; } else { pSurfaceCallBacks->dwFlags = DDHAL_SURFCB32_BLT | DDHAL_SURFCB32_FLIP | DDHAL_SURFCB32_LOCK | DDHAL_SURFCB32_GETBLTSTATUS | DDHAL_SURFCB32_GETFLIPSTATUS; } pCallBacks->WaitForVerticalBlank = DdWaitForVerticalBlank32I; pCallBacks->GetScanLine = DdGetScanLine32I; pCallBacks->MapMemory = DdMapMemory; pCallBacks->dwFlags = DDHAL_CB32_WAITFORVERTICALBLANK | DDHAL_CB32_GETSCANLINE | DDHAL_CB32_MAPMEMORY; } else { // MACH 64 pSurfaceCallBacks->Blt = DdBlt64; pSurfaceCallBacks->Flip = DdFlip64; pSurfaceCallBacks->Lock = DdLock64; pSurfaceCallBacks->GetBltStatus = DdGetBltStatus64; pSurfaceCallBacks->GetFlipStatus = DdGetFlipStatus64; if (ppdev->iBitmapFormat >= BMF_24BPP) { pSurfaceCallBacks->dwFlags = DDHAL_SURFCB32_LOCK; } else { pSurfaceCallBacks->dwFlags = DDHAL_SURFCB32_BLT | DDHAL_SURFCB32_FLIP | DDHAL_SURFCB32_LOCK | DDHAL_SURFCB32_GETBLTSTATUS | DDHAL_SURFCB32_GETFLIPSTATUS; } pCallBacks->WaitForVerticalBlank = DdWaitForVerticalBlank64; pCallBacks->GetScanLine = DdGetScanLine64; pCallBacks->MapMemory = DdMapMemory; pCallBacks->dwFlags = DDHAL_CB32_WAITFORVERTICALBLANK | DDHAL_CB32_GETSCANLINE | DDHAL_CB32_MAPMEMORY; } // Note that we don't call 'vGetDisplayDuration' here, for a couple of // reasons: // // o Because the system is already running, it would be disconcerting // to pause the graphics for a good portion of a second just to read // the refresh rate; // o More importantly, we may not be in graphics mode right now. // // For both reasons, we always measure the refresh rate when we switch // to a new mode. return(TRUE); } /******************************Public*Routine******************************\ * BOOL DrvDisableDirectDraw * * This function is called by GDI when the last active DirectDraw program * is quit and DirectDraw will no longer be active. * \**************************************************************************/ VOID DrvDisableDirectDraw( DHPDEV dhpdev) { PDEV* ppdev; ppdev = (PDEV*) dhpdev; // DirectDraw is done with the display, so we can go back to using // all of off-screen memory ourselves: pohFree(ppdev, ppdev->pohDirectDraw); ppdev->pohDirectDraw = NULL; } /******************************Public*Routine******************************\ * VOID vAssertModeDirectDraw * * This function is called by enable.c when entering or leaving the * DOS full-screen character mode. * \**************************************************************************/ VOID vAssertModeDirectDraw( PDEV* ppdev, BOOL bEnabled) { } /******************************Public*Routine******************************\ * BOOL bEnableDirectDraw * * This function is called by enable.c when the mode is first initialized, * right after the miniport does the mode-set. * \**************************************************************************/ BOOL bEnableDirectDraw( PDEV* ppdev) { // if no APERATURE then we are a MACH8 and have no DDraw support if (ppdev->iAperture != APERTURE_NONE) { // Accurately measure the refresh rate for later: ppdev->bPassVBlank=TRUE; if (ppdev->iMachType == MACH_MM_32) { // Can do memory-mapped IO: vGetDisplayDuration32M(ppdev); } else if (ppdev->iMachType == MACH_IO_32 ) { vGetDisplayDuration32I(ppdev); } else { // MACH 64 // we have a problem with VBLANK on high speed multiprocessors machines on GX-F // so right now will test the VBlank routine; if OK report FLIP capabilities, otherwise no. int j; LONGLONG Counter[2], Freq; EngQueryPerformanceFrequency(&Freq); for (j = 0; j < 10; j++) { EngQueryPerformanceCounter(&Counter[0]); while (IN_VBLANK_64( ppdev->pjMmBase)) { EngQueryPerformanceCounter(&Counter[1]); if( (ULONG)(Counter[1]-Counter[0]) >= (ULONG)Freq ) // if we are here more than 1 sec { // we are stuck inside the VBlank routine ppdev->bPassVBlank=FALSE; goto ExitVBlankTest; } } EngQueryPerformanceCounter(&Counter[0]); while (!(IN_VBLANK_64( ppdev->pjMmBase))) { EngQueryPerformanceCounter(&Counter[1]); if( (ULONG)(Counter[1]-Counter[0]) >= (ULONG)Freq) // if we are here more than 1 sec { // we are stuck inside the VBlank routine ppdev->bPassVBlank=FALSE; goto ExitVBlankTest; } } } ExitVBlankTest: vGetDisplayDuration64(ppdev); } } return(TRUE); } /******************************Public*Routine******************************\ * VOID vDisableDirectDraw * * This function is called by enable.c when the driver is shutting down. * \**************************************************************************/ VOID vDisableDirectDraw( PDEV* ppdev) { }