Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

410 lines
15 KiB

/******************************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)
{
}