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.
842 lines
23 KiB
842 lines
23 KiB
/*========================================================================== *
|
|
*
|
|
* Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: ddalias.c
|
|
* Content: DirectDraw support for allocating and mapping linear virtual
|
|
* memory aliased for video memory.
|
|
* History:
|
|
* Date By Reason
|
|
* ==== == ======
|
|
* 05-jul-96 colinmc initial implementation
|
|
* 10-oct-96 colinmc Refinements of the Win16 locking stuff
|
|
* 12-oct-96 colinmc Improvements to Win16 locking code to reduce virtual
|
|
* memory usage
|
|
* 25-jan-97 colinmc AGP work
|
|
* 01-jun-97 colinmc Bug xxxx: Defensive video memory checking to catch
|
|
* based video memory pointers passed by drivers
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "ddrawpr.h"
|
|
|
|
#ifdef USE_ALIAS
|
|
|
|
#ifdef WINNT
|
|
#include "ddrawgdi.h"
|
|
#endif
|
|
|
|
#pragma optimize("gle", off)
|
|
#define Not_VxD
|
|
#include <vmm.h>
|
|
#include <configmg.h>
|
|
#pragma optimize("", on)
|
|
|
|
/*
|
|
* We define the page lock IOCTLs here so that we don't have to include ddvxd.h.
|
|
* These must match the corresponding entries in ddvxd.h
|
|
*/
|
|
#define DDVXD_IOCTL_MEMRESERVEALIAS 23
|
|
#define DDVXD_IOCTL_MEMCOMMITALIAS 24
|
|
#define DDVXD_IOCTL_MEMREDIRECTALIAS 25
|
|
#define DDVXD_IOCTL_MEMDECOMMITALIAS 26
|
|
#define DDVXD_IOCTL_MEMFREEALIAS 27
|
|
#define DDVXD_IOCTL_MEMCOMMITPHYSALIAS 55
|
|
#define DDVXD_IOCTL_MEMREDIRECTPHYSALIAS 56
|
|
#define DDVXD_IOCTL_LINTOPHYS 69
|
|
#define GET_PIXELFORMAT( pdrv, psurf_lcl ) \
|
|
( ( ( psurf_lcl )->dwFlags & DDRAWISURF_HASPIXELFORMAT ) ? \
|
|
&( ( psurf_lcl )->lpGbl->ddpfSurface ) : \
|
|
&( ( pdrv )->vmiData.ddpfDisplay ) )
|
|
|
|
#define WIDTH_TO_BYTES( bpp, w ) ( ( ( ( w ) * ( bpp ) ) + 7 ) >> 3 )
|
|
|
|
BOOL UnmapHeapAliases( HANDLE hvxd, LPHEAPALIASINFO phaiInfo );
|
|
|
|
/*
|
|
* Are the heaps mapped at all?
|
|
*/
|
|
#define HEAPALIASINFO_MAPPED ( HEAPALIASINFO_MAPPEDREAL | HEAPALIASINFO_MAPPEDDUMMY )
|
|
|
|
#define MAP_HEAP_ALIAS_TO_VID_MEM( hvxd, lpHeapAlias ) \
|
|
vxdMapVMAliasToVidMem( (hvxd), \
|
|
(lpHeapAlias)->lpAlias, \
|
|
(lpHeapAlias)->dwAliasSize, \
|
|
(LPVOID)(lpHeapAlias)->fpVidMem )
|
|
|
|
#define MAP_HEAP_ALIAS_TO_DUMMY_MEM( hvxd, lpHeapAlias ) \
|
|
vxdMapVMAliasToDummyMem( (hvxd), \
|
|
(lpHeapAlias)->lpAlias, \
|
|
(lpHeapAlias)->dwAliasSize )
|
|
|
|
#define UNMAP_HEAP_ALIAS( hvxd, lpHeapAlias ) \
|
|
vxdUnmapVMAlias( (hvxd), \
|
|
(lpHeapAlias)->lpAlias, \
|
|
(lpHeapAlias)->dwAliasSize )
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "vxdAllocVMAlias"
|
|
|
|
/*
|
|
* vxdAllocVMAlias
|
|
*
|
|
* Allocate a virtual memory alias for a portion of video memory
|
|
* starting with the given start address and size.
|
|
*/
|
|
static BOOL vxdAllocVMAlias( HANDLE hvxd, LPVOID lpVidMem, DWORD dwSize, LPVOID *lplpAlias )
|
|
{
|
|
LPVOID lpAlias;
|
|
DWORD cbReturned;
|
|
BOOL rc;
|
|
struct RAInput
|
|
{
|
|
LPBYTE lpVidMem;
|
|
DWORD dwSize;
|
|
} raInput;
|
|
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
DDASSERT( NULL != lpVidMem );
|
|
DDASSERT( 0UL != dwSize );
|
|
DDASSERT( NULL != lplpAlias );
|
|
|
|
raInput.lpVidMem = (LPBYTE) lpVidMem;
|
|
raInput.dwSize = dwSize;
|
|
|
|
DPF( 5, "Trying to allocate alias starting at 0x%08x of size 0x%04x", lpVidMem, dwSize );
|
|
|
|
rc = DeviceIoControl( hvxd,
|
|
DDVXD_IOCTL_MEMRESERVEALIAS,
|
|
&raInput,
|
|
sizeof( raInput ),
|
|
&lpAlias,
|
|
sizeof( lpAlias ),
|
|
&cbReturned,
|
|
NULL);
|
|
|
|
if( rc )
|
|
{
|
|
DDASSERT( cbReturned == sizeof(lpAlias) );
|
|
|
|
*lplpAlias = lpAlias;
|
|
}
|
|
else
|
|
{
|
|
DPF( 0, "Could not allocate an alias for video memory starting at 0x%08x", lpVidMem );
|
|
|
|
*lplpAlias = NULL;
|
|
}
|
|
|
|
return rc;
|
|
} /* vxdAllocVMAlias */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "vxdFreeVMAlias"
|
|
|
|
/*
|
|
* vxdFreeVMAlias
|
|
*
|
|
* Free the virtual memory alias with the given start address and size.
|
|
*/
|
|
static BOOL vxdFreeVMAlias( HANDLE hvxd, LPVOID lpAlias, DWORD dwSize )
|
|
{
|
|
BOOL rc;
|
|
BOOL fSuccess;
|
|
DWORD cbReturned;
|
|
struct FAInput
|
|
{
|
|
LPBYTE pAlias;
|
|
DWORD cbBuffer;
|
|
} faInput;
|
|
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
DDASSERT( NULL != lpAlias);
|
|
DDASSERT( 0UL != dwSize );
|
|
|
|
faInput.pAlias = (LPBYTE) lpAlias;
|
|
faInput.cbBuffer = dwSize;
|
|
|
|
DPF( 5, "Trying to free an alias starting at 0x%08x of size 0x%04x", lpAlias, dwSize );
|
|
|
|
rc = DeviceIoControl( hvxd,
|
|
DDVXD_IOCTL_MEMFREEALIAS,
|
|
&faInput,
|
|
sizeof( faInput ),
|
|
&fSuccess,
|
|
sizeof( fSuccess ),
|
|
&cbReturned,
|
|
NULL);
|
|
|
|
if( !rc || !fSuccess )
|
|
{
|
|
DPF( 0, "Could not free an alias starting at 0x%08x (rc = %d fSuccess = %d)", lpAlias, rc, fSuccess );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
} /* vxdFreeVMAlias */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "vxdMapVMAliasToVidMem"
|
|
|
|
/*
|
|
* vxdMapVMAliasToVidMem
|
|
*
|
|
* Map the the virtual memory alias with the given start address and size
|
|
* to the porition of video memory with the given start address.
|
|
*/
|
|
static BOOL vxdMapVMAliasToVidMem( HANDLE hvxd, LPVOID lpAlias, DWORD dwSize, LPVOID lpVidMem )
|
|
{
|
|
BOOL rc;
|
|
BOOL fSuccess;
|
|
DWORD cbReturned;
|
|
struct CAInput
|
|
{
|
|
LPBYTE pAlias;
|
|
LPBYTE pVidMem;
|
|
DWORD cbBuffer;
|
|
} caInput;
|
|
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
DDASSERT( NULL != lpAlias );
|
|
DDASSERT( 0UL != dwSize );
|
|
DDASSERT( NULL != lpVidMem );
|
|
|
|
caInput.pAlias = (LPBYTE) lpAlias;
|
|
caInput.pVidMem = (LPBYTE) lpVidMem;
|
|
caInput.cbBuffer = dwSize;
|
|
|
|
DPF( 5, "Trying to map an alias starting at 0x%08x of size 0x%04x to video memory starting at 0x%08x", lpAlias, dwSize, lpVidMem );
|
|
|
|
rc = DeviceIoControl( hvxd,
|
|
DDVXD_IOCTL_MEMCOMMITPHYSALIAS,
|
|
&caInput,
|
|
sizeof( caInput ),
|
|
&fSuccess,
|
|
sizeof( fSuccess ),
|
|
&cbReturned,
|
|
NULL);
|
|
|
|
if( !rc || !fSuccess )
|
|
{
|
|
DPF( 0, "Could not map an alias starting at 0x%08x (rc = %d fSuccess = %d)", lpAlias, rc, fSuccess );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
} /* vxdMapVMAliasToVidMem */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "vxdMapVMAliasToDummyMem"
|
|
|
|
/*
|
|
* vxdMapVMAliasToDummyMem
|
|
*
|
|
* Map the the virtual memory alias with the given start address and size
|
|
* to a read / write dummy page.
|
|
*/
|
|
static BOOL vxdMapVMAliasToDummyMem( HANDLE hvxd, LPVOID lpAlias, DWORD dwSize )
|
|
{
|
|
BOOL rc;
|
|
BOOL fSuccess;
|
|
DWORD cbReturned;
|
|
struct RAInput
|
|
{
|
|
LPBYTE pAlias;
|
|
DWORD cbBuffer;
|
|
} raInput;
|
|
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
DDASSERT( NULL != lpAlias);
|
|
DDASSERT( 0UL != dwSize );
|
|
|
|
raInput.pAlias = (LPBYTE) lpAlias;
|
|
raInput.cbBuffer = dwSize;
|
|
|
|
DPF( 5, "Trying to map an alias starting at 0x%08x of size 0x%04x to dummy memory" , lpAlias, dwSize );
|
|
|
|
rc = DeviceIoControl( hvxd,
|
|
DDVXD_IOCTL_MEMREDIRECTPHYSALIAS,
|
|
&raInput,
|
|
sizeof( raInput ),
|
|
&fSuccess,
|
|
sizeof( fSuccess ),
|
|
&cbReturned,
|
|
NULL);
|
|
|
|
if( !rc || !fSuccess )
|
|
{
|
|
DPF( 0, "Could not map an alias starting at 0x%08x to dummy memory (rc = %d fSuccess = %d)", lpAlias, rc, fSuccess );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
} /* vxdMapVMAliasToDummyMem */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "vxdUnmapVMAlias"
|
|
|
|
/*
|
|
* vxdUnmapVMAlias
|
|
*
|
|
* Unmap the the virtual memory alias with the given start address and size.
|
|
*/
|
|
static BOOL vxdUnmapVMAlias( HANDLE hvxd, LPVOID lpAlias, DWORD dwSize )
|
|
{
|
|
BOOL rc;
|
|
BOOL fSuccess;
|
|
DWORD cbReturned;
|
|
struct DAInput
|
|
{
|
|
LPBYTE pAlias;
|
|
DWORD cbBuffer;
|
|
} daInput;
|
|
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
DDASSERT( NULL != lpAlias);
|
|
DDASSERT( 0UL != dwSize );
|
|
|
|
daInput.pAlias = (LPBYTE) lpAlias;
|
|
daInput.cbBuffer = dwSize;
|
|
|
|
DPF( 5, "Trying to unmap an alias starting at 0x%08x of size 0x%04x", lpAlias, dwSize );
|
|
|
|
rc = DeviceIoControl( hvxd,
|
|
DDVXD_IOCTL_MEMDECOMMITALIAS,
|
|
&daInput,
|
|
sizeof( daInput ),
|
|
&fSuccess,
|
|
sizeof( fSuccess ),
|
|
&cbReturned,
|
|
NULL );
|
|
|
|
if( !rc || !fSuccess )
|
|
{
|
|
DPF( 0, "Could not unmap an alias starting at 0x%08x (rc = %d fSuccess = %d)", lpAlias, rc, fSuccess );
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
} /* vxdUnmapVMAlias */
|
|
|
|
static BOOL vxdLinToPhys( HANDLE hvxd, LPVOID lpLin, DWORD dwSize, LPVOID* lplpPhys )
|
|
{
|
|
BOOL rc;
|
|
LPBYTE lpPhys;
|
|
DWORD cbReturned;
|
|
struct DAInput
|
|
{
|
|
LPBYTE pLin;
|
|
DWORD cbBuffer;
|
|
} daInput;
|
|
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
DDASSERT( NULL != lpLin);
|
|
// There really is a bug here: 27001. But since it's MOSTLY inoccuous, I'll turn the spew off.
|
|
// DDASSERT( 0UL != dwSize );
|
|
|
|
daInput.pLin = (LPBYTE) lpLin;
|
|
daInput.cbBuffer = dwSize;
|
|
|
|
DPF( 5, "Trying to map an linear address at 0x%08x of size 0x%04x to physical address", lpLin, dwSize );
|
|
|
|
rc = DeviceIoControl( hvxd,
|
|
DDVXD_IOCTL_LINTOPHYS,
|
|
&daInput,
|
|
sizeof( daInput ),
|
|
&lpPhys,
|
|
sizeof( lpPhys ),
|
|
&cbReturned,
|
|
NULL );
|
|
|
|
if( rc )
|
|
{
|
|
DDASSERT( cbReturned == sizeof(lpPhys) );
|
|
|
|
*lplpPhys = lpPhys;
|
|
}
|
|
else
|
|
{
|
|
DPF( 0, "Could not map linear address at 0x%08x to physical address", lpLin );
|
|
|
|
*lplpPhys = NULL;
|
|
}
|
|
|
|
return rc;
|
|
} /* vxdUnmapVMAlias */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "AllocHeapAlias"
|
|
|
|
/*
|
|
* AllocHeapAlias
|
|
*
|
|
* Allocate a virtual memory alias for the given heap
|
|
*/
|
|
static BOOL AllocHeapAlias( HANDLE hvxd, FLATPTR fpStart, DWORD dwSize, LPHEAPALIAS lpHeapAlias )
|
|
{
|
|
LPVOID lpAlias;
|
|
BOOL fSuccess;
|
|
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
DDASSERT( 0UL != fpStart ); /* This is a physical address pointer */
|
|
DDASSERT( 0UL != dwSize );
|
|
DDASSERT( NULL != lpHeapAlias );
|
|
|
|
/*
|
|
* Attempt to allocate an alias for this heap.
|
|
*/
|
|
fSuccess = vxdAllocVMAlias( hvxd, (LPVOID) fpStart, dwSize, &lpAlias );
|
|
if( fSuccess )
|
|
{
|
|
lpHeapAlias->fpVidMem = fpStart;
|
|
lpHeapAlias->lpAlias = lpAlias;
|
|
lpHeapAlias->dwAliasSize = dwSize;
|
|
}
|
|
else
|
|
{
|
|
lpHeapAlias->fpVidMem = 0UL;
|
|
lpHeapAlias->lpAlias = NULL;
|
|
lpHeapAlias->dwAliasSize = 0UL;
|
|
}
|
|
|
|
return fSuccess;
|
|
} /* AllocHeapAlias */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "FreeHeapAlias"
|
|
|
|
/*
|
|
* FreeHeapAlias
|
|
*
|
|
* Free the given virtual memory heap alias
|
|
*/
|
|
static BOOL FreeHeapAlias( HANDLE hvxd, LPHEAPALIAS lpHeapAlias )
|
|
{
|
|
BOOL fSuccess;
|
|
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
DDASSERT( NULL != lpHeapAlias );
|
|
|
|
if( NULL != lpHeapAlias->lpAlias )
|
|
{
|
|
fSuccess = vxdFreeVMAlias( hvxd, lpHeapAlias->lpAlias, lpHeapAlias->dwAliasSize );
|
|
lpHeapAlias->fpVidMem = 0UL;
|
|
lpHeapAlias->lpAlias = NULL;
|
|
lpHeapAlias->dwAliasSize = 0UL;
|
|
}
|
|
|
|
return fSuccess;
|
|
} /* FreeHeapAliases */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "CreateHeapAliases"
|
|
|
|
/*
|
|
* CreateHeapAliases
|
|
*
|
|
* Create a new set of virtual memory heap aliases for the given global
|
|
* object
|
|
*/
|
|
HRESULT CreateHeapAliases( HANDLE hvxd, LPDDRAWI_DIRECTDRAW_GBL pdrv )
|
|
{
|
|
LPHEAPALIASINFO phaiInfo;
|
|
DWORD dwNumHeaps;
|
|
DWORD dwSize;
|
|
DWORD dwHeapNo;
|
|
int i;
|
|
int n;
|
|
HRESULT hres;
|
|
CMCONFIG config;
|
|
LPVIDMEM pvm;
|
|
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
DDASSERT( NULL != pdrv );
|
|
DDASSERT( NULL == pdrv->phaiHeapAliases );
|
|
|
|
DDASSERT( !( pdrv->dwFlags & DDRAWI_NOHARDWARE ) );
|
|
DDASSERT( !( pdrv->dwFlags & DDRAWI_MODEX ) );
|
|
DDASSERT( 0UL != pdrv->vmiData.fpPrimary );
|
|
|
|
if (DD16_GetDeviceConfig(pdrv->cDriverName, &config, sizeof(config)) == 0)
|
|
{
|
|
DPF_ERR("Could not get display devices's address space ranges");
|
|
return DDERR_GENERIC;
|
|
}
|
|
// First we count the cards local vid mem windows in the config space
|
|
dwNumHeaps = config.wNumMemWindows;
|
|
DPF(5, "Config Space windows = %d", dwNumHeaps);
|
|
// Then we cycle through the AGP heaps that we need to alias
|
|
for( i = 0; i < (int)pdrv->vmiData.dwNumHeaps; i++ )
|
|
{
|
|
if( ( pdrv->vmiData.pvmList[i].dwFlags & VIDMEM_ISNONLOCAL ) )
|
|
{
|
|
// Found AGP heap
|
|
++dwNumHeaps;
|
|
}
|
|
}
|
|
DPF(5, "dwNumHeaps = %d", dwNumHeaps);
|
|
|
|
/*
|
|
* Allocate the heap alias info.
|
|
*/
|
|
phaiInfo = MemAlloc( sizeof( HEAPALIASINFO ) );
|
|
if( NULL == phaiInfo )
|
|
{
|
|
DPF_ERR( "Insufficient memory to map the heap alias info" );
|
|
return DDERR_OUTOFMEMORY;
|
|
}
|
|
|
|
/*
|
|
* Heaps are not yet mapped.
|
|
*/
|
|
phaiInfo->dwFlags &= ~HEAPALIASINFO_MAPPED;
|
|
|
|
/*
|
|
* Allocate the array of heap aliases.
|
|
*/
|
|
phaiInfo->lpAliases = MemAlloc( dwNumHeaps * sizeof( HEAPALIAS ) );
|
|
if( NULL == phaiInfo->lpAliases )
|
|
{
|
|
DPF_ERR( "Insufficient memory to allocate heap alias array" );
|
|
MemFree( phaiInfo );
|
|
return DDERR_OUTOFMEMORY;
|
|
}
|
|
phaiInfo->dwNumHeaps = dwNumHeaps;
|
|
|
|
/*
|
|
* Allocate the aliases for each vid mem config space window.
|
|
*/
|
|
for( i = 0; i < (int) config.wNumMemWindows; i++ )
|
|
{
|
|
DPF(5, "Window %d: wMemAttrib = %d", i, config.wMemAttrib[i]);
|
|
DPF(5, "Window %d: dMemBase = 0x%08x", i, config.dMemBase[i]);
|
|
DPF(5, "Window %d: dMemLength = 0x%08x", i, config.dMemLength[i]);
|
|
if ((config.wMemAttrib[i] & fMD_MemoryType) == fMD_ROM)
|
|
{
|
|
DPF(5, "fMD_MemoryType == fMD_ROM, skipping...");
|
|
continue;
|
|
}
|
|
if( !AllocHeapAlias( hvxd, config.dMemBase[i], config.dMemLength[i], &phaiInfo->lpAliases[i] ) )
|
|
{
|
|
DPF_ERR( "Insufficient memory to allocate virtual memory alias" );
|
|
/*
|
|
* Discard any aliases already allocated.
|
|
*/
|
|
for( n = 0; n < i; n++)
|
|
FreeHeapAlias( hvxd, &phaiInfo->lpAliases[n] );
|
|
MemFree( phaiInfo->lpAliases );
|
|
MemFree( phaiInfo );
|
|
return DDERR_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Allocate the aliases for each AGP heap.
|
|
*/
|
|
dwHeapNo = config.wNumMemWindows;
|
|
for( i = 0; i < (int)pdrv->vmiData.dwNumHeaps; i++ )
|
|
{
|
|
pvm = &(pdrv->vmiData.pvmList[i]);
|
|
if( ( pvm->dwFlags & VIDMEM_ISNONLOCAL ) )
|
|
{
|
|
DPF(5, "AGP Heap %d: fpGARTLin = 0x%08x", i, pvm->lpHeap->fpGARTLin);
|
|
DPF(5, "AGP Heap %d: fpGARTDev = 0x%08x", i, pvm->lpHeap->fpGARTDev);
|
|
DPF(5, "AGP Heap %d: dwTotalSize = 0x%08x", i, pvm->lpHeap->dwTotalSize);
|
|
if( !AllocHeapAlias( hvxd, pvm->lpHeap->fpGARTDev, pvm->lpHeap->dwTotalSize, &phaiInfo->lpAliases[dwHeapNo] ) )
|
|
{
|
|
DPF_ERR( "Insufficient memory to allocate virtual memory alias" );
|
|
/*
|
|
* Discard any aliases already allocated.
|
|
*/
|
|
for( n = 0; n < (int)dwHeapNo; n++)
|
|
FreeHeapAlias( hvxd, &phaiInfo->lpAliases[n] );
|
|
MemFree( phaiInfo->lpAliases );
|
|
MemFree( phaiInfo );
|
|
return DDERR_OUTOFMEMORY;
|
|
}
|
|
dwHeapNo++;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Now map all the aliases to video memory.
|
|
*/
|
|
hres = MapHeapAliasesToVidMem( hvxd, phaiInfo );
|
|
if( FAILED( hres ) )
|
|
{
|
|
for( i = 0; i < (int) dwNumHeaps; i++)
|
|
FreeHeapAlias( hvxd, &phaiInfo->lpAliases[i] );
|
|
MemFree( phaiInfo->lpAliases );
|
|
MemFree( phaiInfo );
|
|
return hres;
|
|
}
|
|
|
|
/*
|
|
* The global object holds a single reference to the aliases
|
|
*/
|
|
phaiInfo->dwRefCnt = 1UL;
|
|
pdrv->phaiHeapAliases = phaiInfo;
|
|
|
|
return DD_OK;
|
|
} /* CreateHeapAliases */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "ReleaseHeapAliases"
|
|
|
|
/*
|
|
* ReleaseHeapAliases
|
|
*
|
|
* Release the given heap aliases.
|
|
*/
|
|
BOOL ReleaseHeapAliases( HANDLE hvxd, LPHEAPALIASINFO phaiInfo )
|
|
{
|
|
int i;
|
|
|
|
DDASSERT( NULL != phaiInfo );
|
|
DDASSERT( 0UL != phaiInfo->dwRefCnt );
|
|
|
|
phaiInfo->dwRefCnt--;
|
|
if( 0UL == phaiInfo->dwRefCnt )
|
|
{
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
|
|
DPF( 4, "Heap aliases reference count is zero: discarding aliases" );
|
|
|
|
/*
|
|
* If the heaps are currently mapped then unmap them before
|
|
* freeing them.
|
|
*/
|
|
DDASSERT( phaiInfo->dwFlags & HEAPALIASINFO_MAPPED );
|
|
UnmapHeapAliases( hvxd, phaiInfo );
|
|
|
|
/*
|
|
* Release all the virtual memory aliases.
|
|
*/
|
|
for( i = 0; i < (int) phaiInfo->dwNumHeaps; i++ )
|
|
{
|
|
if( NULL != phaiInfo->lpAliases[i].lpAlias )
|
|
FreeHeapAlias( hvxd, &phaiInfo->lpAliases[i] );
|
|
}
|
|
|
|
MemFree( phaiInfo->lpAliases );
|
|
MemFree( phaiInfo );
|
|
}
|
|
|
|
return TRUE;
|
|
} /* ReleaseHeapAliases */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "MapHeapAliasesToVidMem"
|
|
|
|
/*
|
|
* MapHeapAliasesToVidMem
|
|
*
|
|
* Map all the heap aliases to video memory.
|
|
*/
|
|
HRESULT MapHeapAliasesToVidMem( HANDLE hvxd, LPHEAPALIASINFO phaiInfo )
|
|
{
|
|
int i;
|
|
|
|
DDASSERT( NULL != phaiInfo );
|
|
|
|
if( phaiInfo->dwFlags & HEAPALIASINFO_MAPPEDREAL )
|
|
{
|
|
DPF( 4, "Heap aliases already mapped to real video memory" );
|
|
return DD_OK;
|
|
}
|
|
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
|
|
for( i = 0; i < (int) phaiInfo->dwNumHeaps; i++ )
|
|
{
|
|
/*
|
|
* NOTE: If any of the maps fail then we just discard the
|
|
* alias and continue. Memory allocated out of the failed
|
|
* heap will need the Win16 lock taken.
|
|
*/
|
|
if( NULL != phaiInfo->lpAliases[i].lpAlias )
|
|
{
|
|
if( !MAP_HEAP_ALIAS_TO_VID_MEM( hvxd, &phaiInfo->lpAliases[i] ) )
|
|
{
|
|
DPF( 0, "Heap %d failed to map. Discarding that alias", i );
|
|
FreeHeapAlias( hvxd, &phaiInfo->lpAliases[i] );
|
|
}
|
|
}
|
|
}
|
|
|
|
phaiInfo->dwFlags = ((phaiInfo->dwFlags & ~HEAPALIASINFO_MAPPEDDUMMY) | HEAPALIASINFO_MAPPEDREAL);
|
|
|
|
return DD_OK;
|
|
} /* MapHeapAliasesToVidMem */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "MapHeapAliasesToDummyMem"
|
|
|
|
/*
|
|
* MapHeapAliasesToDummyMem
|
|
*
|
|
* Map all the heap aliases to the dummy read / write page.
|
|
*
|
|
* NOTE: The heap aliases must be mapped to real video memory before
|
|
* calling this function.
|
|
*/
|
|
HRESULT MapHeapAliasesToDummyMem( HANDLE hvxd, LPHEAPALIASINFO phaiInfo )
|
|
{
|
|
int i;
|
|
HRESULT hres;
|
|
|
|
DDASSERT( NULL != phaiInfo );
|
|
|
|
if( phaiInfo->dwFlags & HEAPALIASINFO_MAPPEDDUMMY )
|
|
{
|
|
DPF( 4, "Heap aliases already mapped to dummy memory" );
|
|
return DD_OK;
|
|
}
|
|
|
|
DDASSERT( phaiInfo->dwFlags & HEAPALIASINFO_MAPPEDREAL );
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
|
|
hres = DD_OK;
|
|
for( i = 0; i < (int) phaiInfo->dwNumHeaps; i++ )
|
|
{
|
|
if( NULL != phaiInfo->lpAliases[i].lpAlias )
|
|
{
|
|
if( !MAP_HEAP_ALIAS_TO_DUMMY_MEM( hvxd, &phaiInfo->lpAliases[i] ) )
|
|
{
|
|
/*
|
|
* Keep going but flag the failure.
|
|
*/
|
|
DPF( 0, "Could not map the heap alias to dummy memory" );
|
|
hres = DDERR_GENERIC;
|
|
}
|
|
}
|
|
}
|
|
|
|
phaiInfo->dwFlags = ((phaiInfo->dwFlags & ~HEAPALIASINFO_MAPPEDREAL) | HEAPALIASINFO_MAPPEDDUMMY);
|
|
|
|
return hres;
|
|
} /* MapHeapAliasesToDummyMem */
|
|
|
|
#undef DPF_MODNAME
|
|
#define DPF_MODNAME "UnmapHeapAliases"
|
|
|
|
/*
|
|
* UnmapHeapAliases
|
|
*
|
|
* Unmap all the heap aliases.
|
|
*/
|
|
BOOL UnmapHeapAliases( HANDLE hvxd, LPHEAPALIASINFO phaiInfo )
|
|
{
|
|
int i;
|
|
|
|
DDASSERT( NULL != phaiInfo );
|
|
|
|
if( 0UL == ( phaiInfo->dwFlags & HEAPALIASINFO_MAPPED ) )
|
|
{
|
|
DPF( 4, "Heap aliases already unmapped" );
|
|
return TRUE;
|
|
}
|
|
|
|
DDASSERT( INVALID_HANDLE_VALUE != hvxd );
|
|
|
|
for( i = 0; i < (int) phaiInfo->dwNumHeaps; i++ )
|
|
{
|
|
if( NULL != phaiInfo->lpAliases[i].lpAlias )
|
|
{
|
|
/*
|
|
* Nothing we can do if the unmap fails.
|
|
*/
|
|
UNMAP_HEAP_ALIAS( hvxd, &phaiInfo->lpAliases[i] );
|
|
}
|
|
}
|
|
|
|
phaiInfo->dwFlags &= ~HEAPALIASINFO_MAPPED;
|
|
|
|
return TRUE;
|
|
} /* UnmapHeapAliases */
|
|
|
|
/*
|
|
* GetAliasedVidMem
|
|
*
|
|
* Get an alias for the given surface with the given video
|
|
* memory pointer.
|
|
*/
|
|
FLATPTR GetAliasedVidMem( LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl,
|
|
LPDDRAWI_DDRAWSURFACE_LCL surf_lcl,
|
|
FLATPTR fpVidMem )
|
|
{
|
|
LPDDRAWI_DDRAWSURFACE_GBL surf;
|
|
LPDDRAWI_DIRECTDRAW_GBL pdrv;
|
|
LPDDPIXELFORMAT lpddpf;
|
|
DWORD dwVidMemSize;
|
|
int n;
|
|
LPHEAPALIAS phaAlias;
|
|
DWORD dwHeapOffset;
|
|
FLATPTR fpAliasedVidMem;
|
|
FLATPTR fpPhysVidMem;
|
|
BOOL fSuccess;
|
|
|
|
DDASSERT( NULL != pdrv_lcl );
|
|
DDASSERT( NULL != surf_lcl );
|
|
DDASSERT( 0UL != fpVidMem );
|
|
|
|
surf = surf_lcl->lpGbl;
|
|
pdrv = pdrv_lcl->lpGbl;
|
|
|
|
/*
|
|
* If there are not heap aliases we can't really return one.
|
|
*/
|
|
if( NULL == pdrv->phaiHeapAliases )
|
|
{
|
|
DPF( 3, "Driver has no heap aliases. Returning a NULL alias pointer" );
|
|
return (FLATPTR)NULL;
|
|
}
|
|
|
|
/*
|
|
* Compute the (inclusive) last byte in the surface. We need this
|
|
* to ensure that a surface pointers lies exactly in an aliased
|
|
* heap.
|
|
*/
|
|
if (surf_lcl->ddsCaps.dwCaps & DDSCAPS_EXECUTEBUFFER)
|
|
dwVidMemSize = surf->dwLinearSize;
|
|
else
|
|
{
|
|
GET_PIXEL_FORMAT( surf_lcl, surf, lpddpf );
|
|
dwVidMemSize = ( ( ( surf->wHeight - 1 ) * labs( surf->lPitch ) ) +
|
|
WIDTH_TO_BYTES( lpddpf->dwRGBBitCount, surf->wWidth ) );
|
|
}
|
|
DPF(5, "dwVidMemSize = 0x%08x", dwVidMemSize);
|
|
fpAliasedVidMem = 0UL;
|
|
fSuccess = vxdLinToPhys((HANDLE) pdrv_lcl->hDDVxd, (LPVOID)fpVidMem, dwVidMemSize, (LPVOID*)&fpPhysVidMem);
|
|
if (fSuccess && (fpPhysVidMem != 0))
|
|
{
|
|
phaAlias = &pdrv->phaiHeapAliases->lpAliases[0];
|
|
n = (int) pdrv->phaiHeapAliases->dwNumHeaps;
|
|
while( n-- )
|
|
{
|
|
DPF( 5, "Checking heap %d Heap start = 0x%08x Heap size = 0x%08x VidMem = 0x%08x",
|
|
n, phaAlias->fpVidMem, phaAlias->dwAliasSize , fpPhysVidMem );
|
|
|
|
if( ( NULL != phaAlias->lpAlias ) &&
|
|
( fpPhysVidMem >= phaAlias->fpVidMem ) &&
|
|
( fpPhysVidMem + dwVidMemSize <= ( phaAlias->fpVidMem + phaAlias->dwAliasSize ) ) )
|
|
{
|
|
/*
|
|
* Compute the aliased pointer we are going to return.
|
|
*/
|
|
dwHeapOffset = (DWORD) fpPhysVidMem - phaAlias->fpVidMem;
|
|
fpAliasedVidMem = (FLATPTR) ( ( (LPBYTE) phaAlias->lpAlias ) + dwHeapOffset );
|
|
|
|
DPF( 5, "Aliased pointer: 0x%08x - Offset: 0x%08x - Aliased heap: 0x%08x - VidMem heap: 0x%08x",
|
|
fpAliasedVidMem, dwHeapOffset, phaAlias->lpAlias, phaAlias->fpVidMem );
|
|
break;
|
|
}
|
|
phaAlias++;
|
|
}
|
|
}
|
|
else
|
|
DPF(4, "Could not find contiguous physical memory for linear mem pointer.");
|
|
return fpAliasedVidMem;
|
|
}
|
|
|
|
#endif /* USE_ALIAS */
|