Leaked source code of windows server 2003
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.
 
 
 
 
 
 

8262 lines
262 KiB

/*==========================================================================
*
* Copyright (C) 1994-1995 Microsoft Corporation. All Rights Reserved.
*
* File: ddcreate.c
* Content: DirectDraw create object.
* History:
* Date By Reason
* ==== == ======
* 31-dec-94 craige initial implementation
* 13-jan-95 craige re-worked to updated spec + ongoing work
* 21-jan-95 craige made 32-bit + ongoing work
* 13-feb-94 craige allow 32-bit callbacks
* 21-feb-95 craige disconnect anyone who forgot to do it themselves
* 27-feb-95 craige new sync. macros
* 06-mar-95 craige HEL integration
* 08-mar-95 craige new APIs
* 11-mar-95 craige palette stuff
* 15-mar-95 craige more HEL integration
* 19-mar-95 craige use HRESULTs, process termination cleanup fixes
* 27-mar-95 craige linear or rectangular vidmem
* 28-mar-95 craige removed Get/SetColorKey, added FlipToGDISurface
* 29-mar-95 craige reorg to only call driver once per creation, and
* to allow driver to load us first
* 01-apr-95 craige happy fun joy updated header file
* 06-apr-95 craige fill in free video memory
* 09-apr-95 craige fixed deadlock situation with a process having a lock
* on the primary surface while another process starts
* 12-apr-95 craige bug when driver object freed (extra leave csect)
* 13-apr-95 craige EricEng's little contribution to our being late
* 15-apr-95 craige fail load if no DD components present
* 06-may-95 craige use driver-level csects only
* 09-may-95 craige escape call to get 32-bit DLL
* 12-may-95 craige added DirectDrawEnumerate; use GUIDs in DirectDrawCreate
* 14-may-95 craige call DoneExclusiveMode during CurrentProcessCleanup
* 15-may-95 craige restore display mode on a per-process basis
* 19-may-95 craige memory leak on mode change
* 23-may-95 craige added Flush, GetBatchLimit, SetBatchLimit
* 24-may-95 craige plugged another memory leak; allow fourcc codes &
* number of vmem heaps to change
* 26-may-95 craige some idiot freed the vmem heaps and then tried to
* free the surfaces!
* 28-may-95 craige unicode support; make sure blt means at least srccopy
* 05-jun-95 craige removed GetVersion, FreeAllSurfaces, DefWindowProc;
* change GarbageCollect to Compact
* 06-jun-95 craige call RestoreDisplayMode
* 07-jun-95 craige removed DCLIST
* 12-jun-95 craige new process list stuff
* 16-jun-95 craige new surface structure
* 18-jun-95 craige specify pitch for rectangular memory; deadlock
* with MemAlloc16 if we don't take the DLL lock
* 25-jun-95 craige one ddraw mutex
* 26-jun-95 craige reorganized surface structure
* 27-jun-95 craige replaced batch limit/flush stuff with BltBatch
* 28-jun-95 craige ENTER_DDRAW at very start of fns
* 02-jul-95 craige new registry format
* 03-jul-95 craige YEEHAW: new driver struct; SEH
* 06-jul-95 craige RemoveFromDriverList was screwing up links
* 07-jul-95 craige added pdevice stuff
* 08-jul-95 craige call InvalidateAllSurfaces
* 10-jul-95 craige support SetOverlayPosition
* 11-jul-95 craige validate pdevice is from a dibeng mini driver;
* fail aggregation calls; one ddraw object/process
* 13-jul-95 craige ENTER_DDRAW is now the win16 lock; need to
* leave Win16 lock while doing ExtEscape calls
* 14-jul-95 craige allow driver to specify heap is already allocated
* 15-jul-95 craige invalid HDC set in emulation only
* 18-jul-95 craige need to initialize dwPreferredMode
* 20-jul-95 craige internal reorg to prevent thunking during modeset
* 20-jul-95 toddla zero DDHALINFO before thunking in case nobody home.
* 22-jul-95 craige emulation only needs to initialize correctly
* 29-jul-95 toddla added DEBUG code to clear driver caps
* 31-jul-95 toddla added DD_HAL_VERSION
* 31-jul-95 craige set DDCAPS_BANKSWITCHED
* 01-aug-95 toddla added dwPDevice to DDRAWI_DIRECTDRAW_GBL
* 10-aug-95 craige validate alignment fields
* 13-aug-95 craige check DD_HAL_VERSION & set DDCAPS2_CERTIFIED
* 21-aug-95 craige mode X support
* 27-aug-95 craige bug 738: use GUID instead of IID
* 05-sep-95 craige bug 814
* 08-sep-95 craige bug 845: reset driver callbacks every time
* 09-sep-95 craige bug 949: don't allow ddraw to run in 4bpp
* bug 951: NULL out fn tables at reset
* 10-sep-95 toddla dont allow DirectDrawCreate to work for < 8bpp mode.
* 10-sep-95 toddla added Message box when DirectDrawCreate fails
* 20-sep-95 craige made primary display desc. a string resource
* 21-sep-95 craige bug 1215: let ddraw16 know about certified for modex
* 21-nov-95 colinmc made Direct3D a queryable interface off DirectDraw
* 27-nov-95 colinmc new member to return available vram of a given type
* (defined by DDSCAPS)
* 05-dec-95 colinmc changed DDSCAPS_TEXTUREMAP => DDSCAPS_TEXTURE for
* consitency with Direct3D
* 09-dec-95 colinmc execute buffer support
* 15-dec-95 colinmc fixed bug setting HAL up for execute buffers
* 25-dec-95 craige added InternalDirectDrawCreate for ClassFactory work
* 31-dec-95 craige more ClassFactory work
* 04-jan-96 kylej add driver interface structures
* 22-jan-96 jeffno NT driver conversation in createSurface.
* Since vidmem ptrs can legally be 0 for kernel, added
* DDRAWISURFACEGBL_ISGDISURFACE and use that to find gdi
* 02-feb-96 kylej Move HAL function pointers to local object
* 28-feb-96 kylej Change DDHALINFO structure
* 02-mar-96 colinmc Repulsive hack to support interim drivers
* 06-mar-96 kylej init HEL even with non-display drivers
* 13-mar-96 craige Bug 7528: hw that doesn't have modex
* 13-mar-96 jeffno Dynamic mode switch support for NT
* Register process IDs with NT kernel stuff
* 16-mar-96 colinmc Callback tables now initialized in dllmain
* 18-mar-96 colinmc Bug 13545: Independent clippers cleanup
* 22-mar-96 colinmc Bug 13316: uninitialized interfaces
* 23-mar-96 colinmc Bug 12252: Direct3D not cleaned up properly on crash
* 14-apr-96 colinmc Bug 17736: No driver notification of flip to GDI
* 16-apr-96 colinmc Bug 17921: Remove interim driver support
* 19-apr-96 colinmc Bug 18059: New caps bit to indicate that driver
* can't interleave 2D and 3D operations during scene
* rendering
* 11-may-96 colinmc Bug 22293: Now validate GUID passed to DirectDraw
* Create in retail as well as debug
* 16-may-96 colinmc Bug 23215: Not checking for a mode index of -1
* on driver initialization
* 27-may-96 kylej Bug 24595: Set Certified bit after call to
* FakeDDCreateDriverObject.
* 26-jun-96 colinmc Bug 2041: DirectDraw needs time bomb
* 22-jul-96 colinmc Work Item: Minimal stackable driver support
* 23-aug-96 craige registry entries for sw only and modex only
* 31-aug-96 colinmc Removed erroneous time bomb
* 03-sep-96 craige App compatibilty stuff
* 01-oct-96 ketand added GetAvailVidMem entrypoint for driver callbacks
* 05-sep-96 colinmc Work Item: Removing the restriction on taking Win16
* lock on VRAM surfaces (not including the primary)
* 10-oct-96 colinmc Refinements of the Win16 locking stuff
* 12-oct-96 colinmc Improvements to Win16 locking code to reduce virtual
* memory usage
* 15-oct-96 toddla support multimonitor
* 09-nov-96 colinmc Fixed problem with old and new drivers not working
* with DirectDraw
* 17-nov-96 colinmc Added ability to use PrintScrn key to snapshot
* DirectDraw applications.
* 08-dec-96 colinmc Initial AGP support
* 21-jan-97 ketand Added a rectMonitor to lpDD_gbl to allow for correct clipping
* on multi-monitor systems.
* 25-jan-97 nwilt Instance GUID in GetDriverInfo struct
* Query for D3DCallbacks2 w/no deps on D3D
* 27-jan-97 colinmc Fixed problem with multi-mon on emulated displays
* 27-jan-97 ketand Multi-mon. Remove bad globals; pass them explicitly. Fix ATTENTIONs.
* 29-jan-97 smac Removed old ring 0 code
* 30-jan-97 colinmc Work item 4125: Add time bomb for beta
* 30-jan-97 jeffno Allow surfaces wider than the primary
* 30-jan-97 ketand Only enumerate secondaries for multi-mon systems.
* 01-feb-97 colinmc Bug 5457: Fixed Win16 lock problem causing hang
* with mutliple AMovie instances on old cards
* 07-feb-97 ketand Zero DisplayDevice struct between calls to EnumDisplayDevices.
* Fix memory leak w.r.t. GetAndValidateNewHalInfo
* 24-feb-97 ketand Update Rects whenever a display change occurs.
* 24-feb-97 ketand Add a dwContext to GetDriverInfoData
* 03-mar-97 smac Added kernel mode interface
* 03-mar-97 jeffno Work item: Extended surface memory alignment
* 08-mar-97 colinmc Added support for DMA style AGP usage
* 11-mar-97 jeffno Asynchronous DMA support
* 11-mar-97 nwilt Fail driver create if driver exports some DrawPrimitive
* exports without exporting all of them.
* 13-mar-97 colinmc Bug 6533: Pass uncached flag to VMM correctly
* 20-mar-97 nwilt #6625 and D3D extended caps
* 24-mar-97 jeffno Optimized Surfaces
* 13-may-97 colinmc AGP support on OSR 2.1 systems
* 26-may-97 nwilt Fail driver create if driver sets D3DDEVCAPS_DRAWPRIMTLVERTEX
* without exporting the callbacks.
* 31-jul-97 jvanaken Bug 7093: Ensure unique HDC for each process/driver pair
* in a multimonitor system.
* 16-sep-97 jeffno DirectDrawEnumerateEx
* 30-sep-97 jeffno IDirectDraw4
* 31-oct-97 johnstep Persistent-content surfaces for Windows 9x
* 05-nov-97 jvanaken Support for master sprite list in SetSpriteDisplayList
* 24-may-00 RichGr IA64: Remove casts from pointer assignment, effectively
* changing assignment from DWORD(32-bit only) to
* ULONG_PTR(32/64-bit). Change debug output to use %p
* format specifier instead of %x for 32/64-bit pointers.
*
***************************************************************************/
#include "ddrawpr.h"
#include "dx8priv.h"
#include "apphack.h"
#ifdef WINNT
#include <ddrawint.h>
#include "ddrawgdi.h"
#define BUILD_DDDDK
#include "d3dhal.h"
#endif
#ifdef WIN95
#include "d3dhal.h"
#endif
#ifdef DEBUG
#define static
#endif
#define RESPATH_D3D "Software\\Microsoft\\Direct3D"
#define DPF_MODNAME "DirectDrawObjectCreate"
#define DISPLAY_STR "display"
HMONITOR GetMonitorFromDeviceName(LPSTR szName);
#ifdef WINNT
DWORD GetNumberOfMonitorAttachedToDesktop(VOID);
DWORD APIENTRY GetDriverInfo2(LPDDRAWI_DIRECTDRAW_GBL lpGbl,DWORD* pdwDrvRet,DWORD dwType,DWORD dwSize,void* pBuffer);
#endif
char g_szPrimaryDisplay[MAX_DRIVER_NAME] = "";
void getPrimaryDisplayName(void);
void convertV1DDHALINFO( LPDDHALINFO lpDDHALInfo );
DWORD dwRegFlags; // registry flags
// ATTENTION: Does this work for Multi-Mon??
WORD dwFakeFlags = 0; // Magic flags for the PDevice??
#ifdef WIN95
/*
* DDHELP's handle for communicating with the DirectSound VXD. We need this
* when we are executing DDRAW code with one of DDHELP's threads.
*/
HANDLE hHelperDDVxd = INVALID_HANDLE_VALUE;
#define CLOSEVXD( hvxd ) CloseHandle( hvxd )
#else /* WIN95 */
#define CLOSEVXD( hvxd )
#endif /* WIN95 */
//#ifdef WIN95
/*
* initial HAL callbacks
*/
#ifndef WINNT //don't want these just yet
static DDHAL_DDCALLBACKS ddHALDD =
{
sizeof( DDHAL_DDCALLBACKS ),
0,
_DDHAL_DestroyDriver,
_DDHAL_CreateSurface,
NULL, // _DDHAL_DrvSetColorKey
_DDHAL_SetMode,
_DDHAL_WaitForVerticalBlank,
_DDHAL_CanCreateSurface,
_DDHAL_CreatePalette,
_DDHAL_GetScanLine,
_DDHAL_SetExclusiveMode,
_DDHAL_FlipToGDISurface
};
static DDHAL_DDSURFACECALLBACKS ddHALDDSurface =
{
sizeof( DDHAL_DDSURFACECALLBACKS ),
0,
_DDHAL_DestroySurface,
_DDHAL_Flip,
_DDHAL_SetClipList,
_DDHAL_Lock,
_DDHAL_Unlock,
_DDHAL_Blt,
_DDHAL_SetColorKey,
_DDHAL_AddAttachedSurface,
_DDHAL_GetBltStatus,
_DDHAL_GetFlipStatus,
_DDHAL_UpdateOverlay,
_DDHAL_SetOverlayPosition,
NULL,
_DDHAL_SetPalette
};
static DDHAL_DDPALETTECALLBACKS ddHALDDPalette =
{
sizeof( DDHAL_DDPALETTECALLBACKS ),
0,
_DDHAL_DestroyPalette,
_DDHAL_SetEntries
};
/*
* NOTE: Currently don't support thunking for these babies. If
* a driver does the execute buffer thing it must explicitly
* export 32-bit functions to handle these calls.
* !!! NOTE: Need to determine whether we will ever need to
* support thunking for this HAL.
*/
static DDHAL_DDEXEBUFCALLBACKS ddHALDDExeBuf =
{
sizeof( DDHAL_DDEXEBUFCALLBACKS ),
0,
NULL, /* CanCreateExecuteBuffer */
NULL, /* CreateExecuteBuffer */
NULL, /* DestroyExecuteBuffer */
NULL, /* LockExecuteBuffer */
NULL /* UnlockExecuteBuffer */
};
/*
* NOTE: Currently don't support thunking for these babies. If
* a driver does the video port thing it must explicitly
* export 32-bit functions to handle these calls.
* !!! NOTE: Need to determine whether we will ever need to
* support thunking for this HAL.
*/
static DDHAL_DDVIDEOPORTCALLBACKS ddHALDDVideoPort =
{
sizeof( DDHAL_DDVIDEOPORTCALLBACKS ),
0,
NULL, // CanCreateVideoPort
NULL, // CreateVideoPort
NULL, // FlipVideoPort
NULL, // GetVideoPortBandwidthInfo
NULL, // GetVideoPortInputFormats
NULL, // GetVideoPortOutputFormats
NULL, // GetCurrentAutoflipSurface
NULL, // GetVideoPortField
NULL, // GetVideoPortLine
NULL, // GetVideoPortConnectInfo
NULL, // DestroyVideoPort
NULL, // GetVideoPortFlipStatus
NULL, // UpdateVideoPort
NULL, // WaitForVideoPortSync
NULL, // GetVideoSignalStatus
NULL // ColorControl
};
/*
* NOTE: Currently don't support thunking for these babies. If
* a driver has a kernel mode interface it must explicitly
* export 32-bit functions to handle these calls.
*/
static DDHAL_DDKERNELCALLBACKS ddHALDDKernel =
{
sizeof( DDHAL_DDKERNELCALLBACKS ),
0,
NULL, // SyncSurfaceData
NULL // SyncVideoPortData
};
static DDHAL_DDCOLORCONTROLCALLBACKS ddHALDDColorControl =
{
sizeof( DDHAL_DDSURFACECALLBACKS ),
0,
_DDHAL_ColorControl
};
#endif //not defined winnt
//#endif //defined(WIN95)
#ifndef WIN16_SEPARATE
#ifdef WIN95
CRITICAL_SECTION ddcCS = {0};
#define ENTER_CSDDC() EnterCriticalSection( &ddcCS )
#define LEAVE_CSDDC() LeaveCriticalSection( &ddcCS )
#else
#define ENTER_CSDDC()
#define LEAVE_CSDDC()
#endif
#else
#define ENTER_CSDDC()
#define LEAVE_CSDDC()
#endif
// DisplayGUID - GUID used to enumerate secondary displays.
//
// {67685559-3106-11d0-B971-00AA00342F9F}
//
// we use this GUID and the next 32 for enumerating devices
// returned via EnumDisplayDevices
//
static const GUID DisplayGUID =
{0x67685559,0x3106,0x11d0,{0xb9,0x71,0x0,0xaa,0x0,0x34,0x2f,0x9f}};
/*
* DISPLAY_DEVICEA
*
* define a local copy of the structures and constants needed
* to call EnumDisplayDevices
*
*/
#ifndef DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP 0x00000001
#define DISPLAY_DEVICE_MULTI_DRIVER 0x00000002
#define DISPLAY_DEVICE_PRIMARY_DEVICE 0x00000004
#define DISPLAY_DEVICE_MIRRORING_DRIVER 0x00000008
#define DISPLAY_DEVICE_VGA 0x00000010
typedef struct {
DWORD cb;
CHAR DeviceName[MAX_DRIVER_NAME];
CHAR DeviceString[128];
DWORD StateFlags;
} DISPLAY_DEVICEA;
#endif
/*
* xxxEnumDisplayDevices
*
* wrapper around the new Win32 API EnumDisplayDevices
* uses GetProcAddress() so we run on Win95.
*
* this function exists in NT 4.0 and Win97 (Memphis) but not Win95
*
*/
BOOL xxxEnumDisplayDevicesA(LPVOID lpUnused, DWORD iDevice, DISPLAY_DEVICEA *pdd, DWORD dwFlags)
{
HANDLE h = GetModuleHandle("USER32");
BOOL (WINAPI *pfnEnumDisplayDevices)(LPVOID, DWORD, DISPLAY_DEVICEA *, DWORD);
(FARPROC)pfnEnumDisplayDevices = GetProcAddress(h,"EnumDisplayDevicesA");
//
// NT 4.0 had a EnumDisplayDevicesA but it does not have the same
// number of params, so ignore it unless a GetMonitorInfoA exists too.
//
if (GetProcAddress(h,"GetMonitorInfoA") == NULL)
pfnEnumDisplayDevices = NULL;
if (pfnEnumDisplayDevices)
{
return (*pfnEnumDisplayDevices)(lpUnused, iDevice, pdd, dwFlags);
}
return FALSE;
}
/*
* xxxChangeDisplaySettingsEx
*
* wrapper around the new Win32 API ChangeDisplaySettingsEx
* uses GetProcAddress() so we run on Win95.
*
* this function exists in NT 4.0 and Win97 (Memphis) but not Win95
*
*/
LONG xxxChangeDisplaySettingsExA(LPCSTR szDevice, LPDEVMODEA pdm, HWND hwnd, DWORD dwFlags,LPVOID lParam)
{
// We don't use ChangeDisplaySettingsEx on WIN95 because there is a magic
// bit in DDraw16 that needs to be set/unset for us to correctly distinguish
// between our own mode sets and external mode sets. (We need to know because
// of RestoreMode state.)
#ifdef WINNT
HANDLE h = GetModuleHandle("USER32");
LONG (WINAPI *pfnChangeDisplaySettingsExA)(LPCSTR,LPDEVMODEA,HWND,DWORD,LPVOID);
(FARPROC)pfnChangeDisplaySettingsExA = GetProcAddress(h,"ChangeDisplaySettingsExA");
if (pfnChangeDisplaySettingsExA)
{
LONG lRet;
NotifyDriverToDeferFrees();
lRet = (*pfnChangeDisplaySettingsExA)(szDevice, pdm, hwnd, dwFlags, lParam);
if (lRet != DISP_CHANGE_SUCCESSFUL)
{
NotifyDriverOfFreeAliasedLocks();
}
return lRet;
}
else
#endif
if (szDevice == NULL)
{
return DD16_ChangeDisplaySettings(pdm, dwFlags);
}
#ifdef WIN95
else
{
// This method works on Win95 for mode-setting other
// devices. We're not yet sure whether the equivalent would
// work for NT; so we'd rather call the 'approved' API (ChangeDisplaySettingsExA above.)
if (pdm != NULL)
{
lstrcpy(pdm->dmDeviceName,szDevice);
}
return DD16_ChangeDisplaySettings(pdm, dwFlags);
}
#else
else
{
return DISP_CHANGE_FAILED;
}
#endif
}
// Multi-monitor defines; these are wrong in the TRANGO tree;
// so I need to define them here explicitly. When we move to
// something that matches Memphis/NT5 then we can remove these
#undef SM_XVIRTUALSCREEN
#undef SM_YVIRTUALSCREEN
#undef SM_CXVIRTUALSCREEN
#undef SM_CYVIRTUALSCREEN
#undef SM_CMONITORS
#define SM_XVIRTUALSCREEN 76
#define SM_YVIRTUALSCREEN 77
#define SM_CXVIRTUALSCREEN 78
#define SM_CYVIRTUALSCREEN 79
#define SM_CMONITORS 80
#ifndef ENUM_CURRENT_SETTINGS
#define ENUM_CURRENT_SETTINGS ((DWORD)-1)
#endif
// This function walks through all GBLs and calls update rect on them
// This is called by DDHELP when it receives a message regarding WM_DISPLAYCHANGE
void UpdateAllDeviceRects( void )
{
LPDDRAWI_DIRECTDRAW_LCL tmp_lcl;
ENTER_DDRAW();
DPF( 1, W, "WM_DISPLAYCHANGE being processed by DDraw" );
tmp_lcl = lpDriverLocalList;
while( tmp_lcl )
{
// This interface may be "uninitialized" in which case
// it doesn't point to a global object yet.
if( tmp_lcl->lpGbl )
{
DPF( 4, W, "Updating rect for %s", tmp_lcl->lpGbl->cDriverName );
UpdateRectFromDevice( tmp_lcl->lpGbl );
}
tmp_lcl = tmp_lcl->lpLink;
}
LEAVE_DDRAW();
return;
}
#ifdef WINNT
// This function gets the device rect by calling GetMonitorInfo.
// On Win98, we got this by calling EnumDisplaySettings, but this
// doesn't work on NT5 and reading the documentation, it never
// indicates that it should work, so we'll just do it the documented
// way.
HRESULT GetNTDeviceRect( LPSTR pDriverName, LPRECT lpRect )
{
MONITORINFO MonInfo;
HMONITOR hMon;
MonInfo.cbSize = sizeof( MONITORINFO );
if( _stricmp( pDriverName, DISPLAY_STR ) == 0 )
{
hMon = GetMonitorFromDeviceName( g_szPrimaryDisplay );
}
else
{
hMon = GetMonitorFromDeviceName( pDriverName );
}
if( hMon != NULL )
{
if( GetMonitorInfo( hMon, &MonInfo ) != 0 )
{
CopyMemory( lpRect, &MonInfo.rcMonitor, sizeof(RECT) );
return DD_OK;
}
}
return DDERR_GENERIC;
}
#endif
// This function updates our GBL with topology information
// relevant to the device in question.
void UpdateRectFromDevice(
LPDDRAWI_DIRECTDRAW_GBL pdrv )
{
DEVMODE dm;
// Sanity Check
DDASSERT( pdrv );
pdrv->cMonitors = GetSystemMetrics( SM_CMONITORS );
if( pdrv->cMonitors > 1 )
{
#ifdef WIN95
/*
* First, get the device rectangle
*/
ZeroMemory( &dm, sizeof(dm) );
dm.dmSize = sizeof(dm);
// Get the DevMode for current settings
if( _stricmp( pdrv->cDriverName, DISPLAY_STR ) == 0 )
{
// Don't need g_szPrimaryDisplay here, just use NULL!!!
EnumDisplaySettings( g_szPrimaryDisplay, ENUM_CURRENT_SETTINGS, &dm );
}
else
{
EnumDisplaySettings( pdrv->cDriverName, ENUM_CURRENT_SETTINGS, &dm );
}
//
// the position of the device is in the dmPosition field
// which happens to be unioned with dmOrientation. dmPosition isn't defined
// in our current header
//
// BUG-BUG: After reading the definition of the DEVMODE struct in
// wingdi.h, I'm amazed that the entire dest rectangle should be
// stored at &dm.dmOrientation. But the code below obviously works,
// so I'm reluctant to change it until I know what's going on.
CopyMemory( &pdrv->rectDevice, &dm.dmOrientation, sizeof(RECT) );
#else
if( GetNTDeviceRect( pdrv->cDriverName, &pdrv->rectDevice ) != DD_OK )
{
pdrv->rectDevice.left = 0;
pdrv->rectDevice.top = 0;
pdrv->rectDevice.right = pdrv->vmiData.dwDisplayWidth;
pdrv->rectDevice.bottom = pdrv->vmiData.dwDisplayHeight;
}
#endif
}
if( ( pdrv->cMonitors <= 1 ) || IsRectEmpty( &pdrv->rectDevice ) )
{
pdrv->rectDevice.left = 0;
pdrv->rectDevice.top = 0;
pdrv->rectDevice.right = pdrv->vmiData.dwDisplayWidth;
pdrv->rectDevice.bottom = pdrv->vmiData.dwDisplayHeight;
}
DPF( 1, W, "Device's rect is %d, %d, %d, %d", pdrv->rectDevice.left, pdrv->rectDevice.top, pdrv->rectDevice.right, pdrv->rectDevice.bottom );
/*
* Now get the desktop rect. If we are in virtual desktop mode,
* we will get the whole dektop; otherwise, we will use the device
* rectangle.
*/
// BUG-BUG: The VIRTUALDESKTOP and ATTACHEDTODESKTOP flags referred to
// below are never set if we reach this point when we're creating a new
// surface. That means that in a multimon system, pdrv->rectDesktop
// gets set to pdrv->rectDevice instead of to the full desktop.
if( ( pdrv->dwFlags & DDRAWI_VIRTUALDESKTOP ) &&
( pdrv->dwFlags & DDRAWI_ATTACHEDTODESKTOP ) )
{
int x, y;
x = GetSystemMetrics( SM_XVIRTUALSCREEN ); // left
y = GetSystemMetrics( SM_YVIRTUALSCREEN ); // right
SetRect( &pdrv->rectDesktop,
x, // left
y, // top
x + GetSystemMetrics( SM_CXVIRTUALSCREEN ), // right
y + GetSystemMetrics( SM_CYVIRTUALSCREEN ) // bottom
);
}
else
{
memcpy( &pdrv->rectDesktop, &pdrv->rectDevice, sizeof( RECT ) );
}
DPF( 1, W, "Desktop's rect is %d, %d, %d, %d", pdrv->rectDesktop.left, pdrv->rectDesktop.top, pdrv->rectDesktop.right, pdrv->rectDesktop.bottom );
return;
}
/*
* IsVGADevice()
*
* determine if the passed device name is a VGA
*
*/
BOOL IsVGADevice(LPSTR szDevice)
{
//
// assume "DISPLAY" and "DISPLAY1" are VGA devices
//
if (_stricmp(szDevice, DISPLAY_STR) == 0)
return TRUE;
return FALSE;
}
/*
* number of callbacks in a CALLBACK struct
*/
#define NUM_CALLBACKS( ptr ) ((ptr->dwSize-2*sizeof( DWORD ))/ sizeof( LPVOID ))
#if defined( WIN95 )
/*
* loadSecondaryDriver
*
* Determine if a secondary DirectDraw driver key is present in the registry.
* If it is extract the DLL name and (optional) entry point to invoke. Load
* the DLL in DDHELP's address space, get the validation entry point and
* invoke it. If it returns TRUE and gives us back a GUID we have certified
* as a secondary driver, call its HAL patching function.
*
* If any of this stuff fails we simply ignore the error. No secondary driver
* - no problem.
*
* Returns TRUE if a secondary is successfully loaded.
*/
static BOOL loadSecondaryDriver( LPDDHALINFO lpDDHALInfo )
{
HKEY hKey;
DWORD dwType;
DWORD dwSize;
LPSECONDARY_VALIDATE fpValidate;
LPSECONDARY_PATCHHALINFO fpPatchHALInfo;
char szDriverName[MAX_SECONDARY_DRIVERNAME];
char szEntryPoint[MAX_SECONDARY_ENTRYPOINTNAME];
GUID guid;
BOOL bLoaded = FALSE;
/*
* Any secondary driver information in the registry at all?
*/
if( ERROR_SUCCESS == RegOpenKey( HKEY_LOCAL_MACHINE,
REGSTR_PATH_SECONDARY,
&hKey ) )
{
/*
* Extract the entry point of the secondary driver. If no entry
* point is specified we will use the default instead.
*/
dwSize = sizeof( szEntryPoint ) - 1;
if( ERROR_SUCCESS == RegQueryValueEx( hKey,
REGSTR_VALUE_SECONDARY_ENTRYPOINTNAME,
NULL,
&dwType,
szEntryPoint,
&dwSize ) )
{
if( REG_SZ != dwType )
{
/*
* Key is not a string. Bail.
*/
RegCloseKey( hKey );
return FALSE;
}
}
else
{
/*
* No entry point sepecified. Use the default.
*/
lstrcpy( szEntryPoint, DEFAULT_SECONDARY_ENTRYPOINTNAME );
}
/*
* Extract the name of the secondary driver's DLL.
*/
dwSize = sizeof( szDriverName ) - 1;
if( ERROR_SUCCESS == RegQueryValueEx( hKey,
REGSTR_VALUE_SECONDARY_DRIVERNAME,
NULL,
&dwType,
szDriverName,
&dwSize ) )
{
if( REG_SZ == dwType )
{
/*
* Now ask DDHELP to load this DLL and invoke the entry point specified.
* The value returned by DDHELP will be the address of the secondary
* driver's validation function if all went well.
*/
#if defined(WIN95)
LEAVE_WIN16LOCK();
#endif
fpValidate = (LPSECONDARY_VALIDATE)HelperLoadDLL( szDriverName, szEntryPoint, 0UL );
#if defined(WIN95)
ENTER_WIN16LOCK();
#endif
if( NULL != fpValidate )
{
/*
* Now we need to invoke the validate entry point to ensure that
* the secondary driver has been certified by us (and that it actually
* wants to run).
*/
fpPatchHALInfo = (fpValidate)( &guid );
if( NULL != fpPatchHALInfo )
{
/*
* Got returned a non-NULL HAL patching function so the secondary
* driver wishes to run. However, we need to verify that the driver
* is one we have certified as being OK to run. Check the guid.
*/
if( IsEqualIID( &guid, &guidCertifiedSecondaryDriver ) )
{
LPVOID pFlipRoutine = (LPVOID) lpDDHALInfo->lpDDSurfaceCallbacks->Flip;
/*
* Its a certified secondary driver so invoke its HAL patching
* function with the given HAL info and callback thunks.
* The rule is if this function failes the DDHALINFO must be
* unmodified so we can carry on regardless.
*/
(*fpPatchHALInfo)(lpDDHALInfo, &ddHALDD, &ddHALDDSurface, &ddHALDDPalette, &ddHALDDExeBuf);
//
// Only say we loaded it if the HALInfo was changed, specifically if the PVR took
// over the surface flip routine. This is an absolute must for the PVR.
// If the PVR is turned off via the control panel, then this fn pointer will be unchanged,
// and we can know later not to enumerate the PVR via GetDeviceIdentifier.
//
if (pFlipRoutine != (LPVOID) lpDDHALInfo->lpDDSurfaceCallbacks->Flip)
{
bLoaded = TRUE;
}
}
}
}
}
}
RegCloseKey( hKey );
}
return bLoaded;
}
#endif /* WIN95 */
/*
* mergeHELCaps
*
* merge HEL caps with default caps
*/
static void mergeHELCaps( LPDDRAWI_DIRECTDRAW_GBL pdrv )
{
int i;
if( pdrv->dwFlags & DDRAWI_EMULATIONINITIALIZED )
{
pdrv->ddBothCaps.dwCaps &= pdrv->ddHELCaps.dwCaps;
pdrv->ddBothCaps.dwCaps2 &= pdrv->ddHELCaps.dwCaps2;
pdrv->ddBothCaps.dwCKeyCaps &= pdrv->ddHELCaps.dwCKeyCaps;
pdrv->ddBothCaps.dwFXCaps &= pdrv->ddHELCaps.dwFXCaps;
pdrv->lpddBothMoreCaps->dwAlphaCaps &= pdrv->lpddHELMoreCaps->dwAlphaCaps;
pdrv->lpddBothMoreCaps->dwFilterCaps &= pdrv->lpddHELMoreCaps->dwFilterCaps;
#ifdef POSTPONED2
pdrv->lpddBothMoreCaps->dwTransformCaps &= pdrv->lpddHELMoreCaps->dwTransformCaps;
#endif //POSTPONED2
pdrv->ddBothCaps.dwSVBCaps &= pdrv->ddHELCaps.dwSVBCaps;
pdrv->ddBothCaps.dwSVBCKeyCaps &= pdrv->ddHELCaps.dwSVBCKeyCaps;
pdrv->ddBothCaps.dwSVBFXCaps &= pdrv->ddHELCaps.dwSVBFXCaps;
pdrv->lpddBothMoreCaps->dwSVBAlphaCaps &= pdrv->lpddHELMoreCaps->dwSVBAlphaCaps;
pdrv->lpddBothMoreCaps->dwSVBFilterCaps &= pdrv->lpddHELMoreCaps->dwSVBFilterCaps;
#ifdef POSTPONED2
pdrv->lpddBothMoreCaps->dwSVBTransformCaps &= pdrv->lpddHELMoreCaps->dwSVBTransformCaps;
#endif //POSTPONED2
pdrv->ddBothCaps.dwVSBCaps &= pdrv->ddHELCaps.dwVSBCaps;
pdrv->ddBothCaps.dwVSBCKeyCaps &= pdrv->ddHELCaps.dwVSBCKeyCaps;
pdrv->ddBothCaps.dwVSBFXCaps &= pdrv->ddHELCaps.dwVSBFXCaps;
pdrv->lpddBothMoreCaps->dwVSBAlphaCaps &= pdrv->lpddHELMoreCaps->dwVSBAlphaCaps;
pdrv->lpddBothMoreCaps->dwVSBFilterCaps &= pdrv->lpddHELMoreCaps->dwVSBFilterCaps;
#ifdef POSTPONED2
pdrv->lpddBothMoreCaps->dwVSBTransformCaps &= pdrv->lpddHELMoreCaps->dwVSBTransformCaps;
#endif //POSTPONED2
pdrv->ddBothCaps.dwSSBCaps &= pdrv->ddHELCaps.dwSSBCaps;
pdrv->ddBothCaps.dwSSBCKeyCaps &= pdrv->ddHELCaps.dwSSBCKeyCaps;
pdrv->ddBothCaps.dwSSBFXCaps &= pdrv->ddHELCaps.dwSSBFXCaps;
pdrv->lpddBothMoreCaps->dwSSBAlphaCaps &= pdrv->lpddHELMoreCaps->dwSSBAlphaCaps;
pdrv->lpddBothMoreCaps->dwSSBFilterCaps &= pdrv->lpddHELMoreCaps->dwSSBFilterCaps;
#ifdef POSTPONED2
pdrv->lpddBothMoreCaps->dwSSBTransformCaps &= pdrv->lpddHELMoreCaps->dwSSBTransformCaps;
#endif //POSTPONED2
for( i=0;i<DD_ROP_SPACE;i++ )
{
pdrv->ddBothCaps.dwRops[i] &= pdrv->ddHELCaps.dwRops[i];
pdrv->ddBothCaps.dwSVBRops[i] &= pdrv->ddHELCaps.dwSVBRops[i];
pdrv->ddBothCaps.dwVSBRops[i] &= pdrv->ddHELCaps.dwVSBRops[i];
pdrv->ddBothCaps.dwSSBRops[i] &= pdrv->ddHELCaps.dwSSBRops[i];
}
pdrv->ddBothCaps.ddsCaps.dwCaps &= pdrv->ddHELCaps.ddsCaps.dwCaps;
if( NULL != pdrv->lpddNLVBothCaps )
{
DDASSERT( NULL != pdrv->lpddNLVHELCaps );
pdrv->lpddNLVBothCaps->dwNLVBCaps &= pdrv->lpddNLVHELCaps->dwNLVBCaps;
pdrv->lpddNLVBothCaps->dwNLVBCaps2 &= pdrv->lpddNLVHELCaps->dwNLVBCaps2;
pdrv->lpddNLVBothCaps->dwNLVBCKeyCaps &= pdrv->lpddNLVHELCaps->dwNLVBCKeyCaps;
pdrv->lpddNLVBothCaps->dwNLVBFXCaps &= pdrv->lpddNLVHELCaps->dwNLVBFXCaps;
for( i = 0; i < DD_ROP_SPACE; i++ )
pdrv->lpddNLVBothCaps->dwNLVBRops[i] &= pdrv->lpddNLVHELCaps->dwNLVBRops[i];
}
if( pdrv->lpddBothMoreCaps != NULL )
{
DDASSERT( pdrv->lpddHELMoreCaps != NULL );
pdrv->lpddBothMoreCaps->dwAlphaCaps &= pdrv->lpddHELMoreCaps->dwAlphaCaps;
pdrv->lpddBothMoreCaps->dwSVBAlphaCaps &= pdrv->lpddHELMoreCaps->dwSVBAlphaCaps;
pdrv->lpddBothMoreCaps->dwVSBAlphaCaps &= pdrv->lpddHELMoreCaps->dwVSBAlphaCaps;
pdrv->lpddBothMoreCaps->dwSSBAlphaCaps &= pdrv->lpddHELMoreCaps->dwSSBAlphaCaps;
pdrv->lpddBothMoreCaps->dwFilterCaps &= pdrv->lpddHELMoreCaps->dwFilterCaps;
pdrv->lpddBothMoreCaps->dwSVBFilterCaps &= pdrv->lpddHELMoreCaps->dwSVBFilterCaps;
pdrv->lpddBothMoreCaps->dwVSBFilterCaps &= pdrv->lpddHELMoreCaps->dwVSBFilterCaps;
pdrv->lpddBothMoreCaps->dwSSBFilterCaps &= pdrv->lpddHELMoreCaps->dwSSBFilterCaps;
#ifdef POSTPONED2
pdrv->lpddBothMoreCaps->dwTransformCaps &= pdrv->lpddHELMoreCaps->dwTransformCaps;
pdrv->lpddBothMoreCaps->dwSVBTransformCaps &= pdrv->lpddHELMoreCaps->dwSVBTransformCaps;
pdrv->lpddBothMoreCaps->dwVSBTransformCaps &= pdrv->lpddHELMoreCaps->dwVSBTransformCaps;
pdrv->lpddBothMoreCaps->dwSSBTransformCaps &= pdrv->lpddHELMoreCaps->dwSSBTransformCaps;
#endif //POSTPONED2
}
}
} /* mergeHELCaps */
// This variable is a shared instance and has been moved to dllmain.c: BOOL bReloadReg;
/*
* capsInit
*
* initialize shared caps
*/
static void capsInit( LPDDRAWI_DIRECTDRAW_GBL pdrv )
{
#ifdef DEBUG
if( GetProfileInt("DirectDraw","nohwblt",0) )
{
pdrv->ddCaps.dwCaps &= ~DDCAPS_BLT;
DPF( 2, "Turning off blt <<<<<<<<<<<<<<<<<<<<<<<<<<" );
}
if( GetProfileInt("DirectDraw","nohwtrans",0) )
{
pdrv->ddCaps.dwCKeyCaps &= ~(DDCKEYCAPS_DESTBLT|DDCKEYCAPS_SRCBLT);
DPF( 2, "Turning off hardware transparency <<<<<<<<<<<<<<<<<<<<<<<<<<" );
}
if( GetProfileInt("DirectDraw","nohwfill",0) )
{
pdrv->ddCaps.dwCaps &= ~(DDCAPS_BLTCOLORFILL);
DPF( 2, "Turning off color fill <<<<<<<<<<<<<<<<<<<<<<<<<<" );
}
#endif
// initialize the BothCaps structure
pdrv->ddBothCaps = pdrv->ddCaps;
if( NULL != pdrv->lpddNLVCaps )
{
DDASSERT( NULL != pdrv->lpddNLVBothCaps );
memcpy( pdrv->lpddNLVBothCaps, pdrv->lpddNLVCaps, sizeof( DDNONLOCALVIDMEMCAPS ) );
}
else if ( pdrv->lpddNLVBothCaps != NULL)
{
ZeroMemory( pdrv->lpddNLVBothCaps, sizeof( DDNONLOCALVIDMEMCAPS ) );
pdrv->lpddNLVBothCaps->dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
}
if( pdrv->lpddBothMoreCaps != NULL )
{
DDASSERT( pdrv->lpddMoreCaps != NULL );
memcpy(pdrv->lpddBothMoreCaps, pdrv->lpddMoreCaps, sizeof(DDMORECAPS));
}
} /* capsInit */
#ifdef WINNT
//
// pdd_gbl may be null (if coming from the create code path) or non null (from the reset code path).
// We assert that if pdd_gbl==NULL, then we can't be in an emulated ModeX mode, because the
// only way to get there is to use a ddraw object to set such a mode. So we only have to check
// for fake modex mode if pdd_gbl is non-null.
//
BOOL GetCurrentMode(LPDDRAWI_DIRECTDRAW_GBL pdd_gbl, LPDDHALINFO lpHalInfo, char *szDrvName)
{
LPDDHALMODEINFO pmi;
DEVMODE dm;
HDC hdc;
LPCTSTR pszDevice;
pmi = MemAlloc(sizeof (DDHALMODEINFO));
if (pmi)
{
pszDevice = _stricmp(szDrvName, DISPLAY_STR) ? szDrvName : NULL;
ZeroMemory(&dm, sizeof dm);
dm.dmSize = sizeof dm;
if ( pdd_gbl && pdd_gbl->dwFlags & DDRAWI_MODEX )
{
// If the current mode is modex, then we could only have gotten here if
// it's the current mode.
pmi->dwWidth = pdd_gbl->dmiCurrent.wWidth;
pmi->dwHeight = pdd_gbl->dmiCurrent.wHeight;
pmi->dwBPP = pdd_gbl->dmiCurrent.wBPP;
pmi->wRefreshRate = pdd_gbl->dmiCurrent.wRefreshRate;
pmi->lPitch = pmi->dwWidth;
pmi->dwRBitMask = 0;
pmi->dwGBitMask = 0;
pmi->dwBBitMask = 0;
pmi->dwAlphaBitMask = 0;
}
else if (EnumDisplaySettings(pszDevice, ENUM_CURRENT_SETTINGS, &dm))
{
pmi->dwWidth = dm.dmPelsWidth;
pmi->dwHeight = dm.dmPelsHeight;
pmi->dwBPP = dm.dmBitsPerPel;
pmi->wRefreshRate = (WORD) dm.dmDisplayFrequency;
pmi->lPitch = (pmi->dwWidth * pmi->dwBPP) >> 3;
if (pmi->dwBPP > 8)
{
void FillBitMasks(LPDDPIXELFORMAT pddpf, HDC hdc);
DDPIXELFORMAT ddpf;
hdc = DD_CreateDC(szDrvName);
if (hdc)
{
FillBitMasks(&ddpf, hdc);
DD_DoneDC(hdc);
}
if (pmi->dwBPP == 15)
{
pmi->dwBPP = 16;
pmi->wFlags = DDMODEINFO_555MODE;
}
pmi->dwRBitMask = ddpf.dwRBitMask;
pmi->dwGBitMask = ddpf.dwGBitMask;
pmi->dwBBitMask = ddpf.dwBBitMask;
pmi->dwAlphaBitMask = ddpf.dwRGBAlphaBitMask;
}
else
{
pmi->wFlags = DDMODEINFO_PALETTIZED;
}
lpHalInfo->dwNumModes = 1;
lpHalInfo->dwMonitorFrequency = pmi->wRefreshRate;
}
else
{
MemFree(pmi);
pmi = NULL;
}
}
lpHalInfo->lpModeInfo = pmi;
return pmi != NULL;
}
#endif
static HRESULT
GetDriverInfo(LPDDHAL_GETDRIVERINFO lpGetDriverInfo,
LPDDHAL_GETDRIVERINFODATA lpGDInfo,
LPVOID lpDriverInfo,
DWORD dwSize,
const GUID *lpGUID,
LPDDRAWI_DIRECTDRAW_GBL lpDD,
BOOL bInOut) // Indicates whether the data passed is in/out or just out
{
int i;
// 1K temp buffer to pull driver info into
static DWORD dwDriverInfoBuffer[256];
if (bInOut)
{
DDASSERT((dwSize & 3) == 0);
// Copy over the data from our source
memcpy(dwDriverInfoBuffer, lpDriverInfo, dwSize);
// Only dead-beef the unused part of the buffer
i = dwSize>>2;
}
else
{
i = 0;
}
for (i; i < 256; i += 1)
dwDriverInfoBuffer[i] = 0xdeadbeef;
#ifdef DEBUG
if(dwSize>255*sizeof(DWORD)) { // 0xdeadbeef overwrite test wont work unless dwSize>>2 <= 255
DPF_ERR("****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Internal DDraw Error: GetDriverInfo() dwSize parameter > 1020");
return DDERR_NODIRECTDRAWSUPPORT;
}
#endif
memset(lpGDInfo, 0, sizeof(*lpGDInfo) );
lpGDInfo->dwSize = sizeof(*lpGDInfo);
lpGDInfo->dwFlags = 0;
memcpy(&lpGDInfo->guidInfo, lpGUID, sizeof(*lpGUID) );
lpGDInfo->dwExpectedSize = dwSize;
lpGDInfo->lpvData = dwDriverInfoBuffer;
lpGDInfo->ddRVal = DDERR_GENERIC;
// Pass a context variable so that the driver
// knows which instance of itself to use
// w.r.t. this function. These are different
// values on Win95 and NT.
#ifdef WIN95
lpGDInfo->dwContext = lpDD->dwReserved3;
#else
lpGDInfo->dwContext = lpDD->hDD;
#endif
if ( lpGetDriverInfo(lpGDInfo) == DDHAL_DRIVER_HANDLED && lpGDInfo->ddRVal == DD_OK )
{
// Fail if the driver wrote more bytes than the expected size
if (dwDriverInfoBuffer[dwSize>>2] != 0xdeadbeef)
{
return DDERR_NODIRECTDRAWSUPPORT;
}
memcpy(lpDriverInfo, dwDriverInfoBuffer, min(dwSize, lpGDInfo->dwActualSize));
}
return lpGDInfo->ddRVal;
}
static BOOL
ValidateCallbacks(LPVOID lpCallbacks)
{
int N = ((((DWORD FAR *) lpCallbacks)[0] >> 2) - 2) / (sizeof(DWORD_PTR) / sizeof(DWORD));
if (N > 0)
{
DWORD dwFlags = ((DWORD FAR *) lpCallbacks)[1];
DWORD bit = 1;
int i;
LPVOID *pcbrtn = (LPVOID *) &(((DWORD FAR *) lpCallbacks)[2]);
for (i = 0; i < N; i += 1)
{
LPVOID cbrtn;
cbrtn = *pcbrtn++;
// If a function is non-NULL and they failed to set the
// 32-bit flag, fail. We might support 16-bit callbacks
// in future but not for now.
if ( (cbrtn != NULL) && ( 0 == (dwFlags & bit) ) )
return FALSE;
if (dwFlags & bit)
{
#if defined(NT_FIX) || defined(WIN95) // check this some other way // If the bit is set, validate the callback.
if (! VALIDEX_CODE_PTR(cbrtn) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid 32-bit callback");
return FALSE;
}
#endif
}
bit <<= 1;
}
}
return TRUE;
}
/*
* Validate the core HAL information the driver passed to us.
*/
BOOL
ValidateCoreHALInfo( LPDDHALINFO lpDDHALInfo )
{
int i;
LPVIDMEM pvm;
int numcb;
LPDDHAL_DDCALLBACKS drvcb;
LPDDHAL_DDSURFACECALLBACKS surfcb;
LPDDHAL_DDPALETTECALLBACKS palcb;
LPDDHAL_DDEXEBUFCALLBACKS exebufcb;
DWORD bit;
LPVOID cbrtn;
TRY
{
/*
* Valid HAL info
*/
if( !VALIDEX_DDHALINFO_PTR( lpDDHALInfo ) )
{
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF(0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid DDHALINFO provided: 0x%p",lpDDHALInfo );
if( lpDDHALInfo != NULL )
{
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: size = was %d, expecting %d or %d", lpDDHALInfo->dwSize, sizeof( DDHALINFO ), sizeof( DDHALINFO_V1) );
}
return FALSE;
}
if( lpDDHALInfo->dwSize == sizeof( DDHALINFO_V1 ) )
{
/*
* The DDHALINFO structure returned by the driver is in the DDHALINFO_V1
* format. Convert it to the new DDHALINFO structure.
*/
convertV1DDHALINFO( lpDDHALInfo );
}
/*
* validate video memory heaps
*/
for( i=0;i<(int)lpDDHALInfo->vmiData.dwNumHeaps;i++ )
{
pvm = &lpDDHALInfo->vmiData.pvmList[i];
if( pvm->dwFlags & VIDMEM_ISNONLOCAL )
{
/*
* NOTE: It is entirely legal to pass a NULL fpStart for a non-local
* heap. The start address is meaningless for non-local heaps.
*/
/*
* If the heap is non-local then the driver must have specified
* the DDCAPS2_NONLOCALVIDMEM. If it hasn't we fail the initialization.
*/
if( !( lpDDHALInfo->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Non-local video memory heap passed but DDCAPS2_NONLOCALVIDMEM not specified" );
return FALSE;
}
}
else
{
if( (pvm->fpStart == (FLATPTR) NULL) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid video memory fpStart pointer passed" );
return FALSE;
}
/*
* This is not a local video memory heap and WC is specified. Currently
* this is not legal.
*/
#pragma message( REMIND( "Look into enabling WC on local vid mem" ) )
if( pvm->dwFlags & VIDMEM_ISWC )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Driver can't specify write combining with a local video memory heap" );
return FALSE;
}
}
}
/*
* validate pixel format
*
* NOTE: The dwSize check below may seem redundant since the DDPIXELFORMAT
* struct is embedded in a DDHAL struct whose size has already been validated.
* But removing this test caused stress failures with drivers that do not
* support DDraw. The drivers were running "accelerated" but with virtually
* no caps. So we'll keep this test until the problem is better understood.
*/
if( lpDDHALInfo->vmiData.ddpfDisplay.dwSize != sizeof( DDPIXELFORMAT ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid DDPIXELFORMAT in DDHALINFO.vmiData: bad size" );
return FALSE;
}
/*
* DX4; Validate it some more.
*/
if ( (lpDDHALInfo->vmiData.ddpfDisplay.dwFlags & DDPF_PALETTEINDEXED8) &&
(lpDDHALInfo->vmiData.ddpfDisplay.dwRGBBitCount != 8) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid DDPIXELFORMAT in DDHALINFO.vmiData: palettized mode must be 8bpp" );
return FALSE;
}
/*
* validate driver callback
*/
drvcb = lpDDHALInfo->lpDDCallbacks;
if( drvcb != NULL )
{
if( !VALID_PTR_PTR( drvcb ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid driver callback ptr" );
return FALSE;
}
if( !VALIDEX_DDCALLBACKSSIZE( drvcb ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid size field in lpDriverCallbacks" );
return FALSE;
}
numcb = NUM_CALLBACKS( drvcb );
bit = 1;
for( i=0;i<numcb;i++ )
{
if( drvcb->dwFlags & bit )
{
// 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
cbrtn = (LPVOID) (&drvcb->DestroyDriver)[i];
if( cbrtn != NULL )
{
#if defined(NT_FIX) || defined(WIN95) // check this some other way
if( !VALIDEX_CODE_PTR( cbrtn ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid 32-bit callback in lpDriverCallbacks" );
return FALSE;
}
#endif
}
}
bit <<= 1;
}
}
/*
* Turn off optimized surfaces just for now
*/
if (lpDDHALInfo->ddCaps.ddsCaps.dwCaps & DDSCAPS_OPTIMIZED)
{
DPF_ERR("****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Driver tried to set DDSCAPS_OPTIMIZED. Not allowed for this release");
return FALSE;
}
/*
* We used to ensure that no driver ever set dwCaps2. However,
* we have now run out of bits in ddCaps.dwCaps so we need to
* allow drivers to set bits in dwCaps2. Hence all we do now
* is ensure that drivers don't try and impersonate certified
* drivers by returning DDCAPS2_CERTIFIED. This is something
* we turn on - they can't set it.
*/
if( lpDDHALInfo->ddCaps.dwCaps2 & DDCAPS2_CERTIFIED )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Driver tried to set the DDCAPS2_CERTIFIED" );
return FALSE;
}
/*
* validate surface callbacks
*/
surfcb = lpDDHALInfo->lpDDSurfaceCallbacks;
if( surfcb != NULL )
{
if( !VALID_PTR_PTR( surfcb ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid surface callback ptr" );
return FALSE;
}
if( !VALIDEX_DDSURFACECALLBACKSSIZE( surfcb ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid size field in lpSurfaceCallbacks" );
return FALSE;
}
numcb = NUM_CALLBACKS( surfcb );
bit = 1;
for( i=0;i<numcb;i++ )
{
if( surfcb->dwFlags & bit )
{
// 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
cbrtn = (LPVOID) (&surfcb->DestroySurface)[i];
if( cbrtn != NULL )
{
#if defined(NT_FIX) || defined(WIN95) //check some other way
if( !VALIDEX_CODE_PTR( cbrtn ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid 32/64-bit callback in lpSurfaceCallbacks" );
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 0, "Callback = 0x%p, i = %d, bit = 0x%08lx", cbrtn, i, bit );
return FALSE;
}
#endif
}
}
bit <<= 1;
}
}
/*
* validate palette callbacks
*/
palcb = lpDDHALInfo->lpDDPaletteCallbacks;
if( palcb != NULL )
{
if( !VALID_PTR_PTR( palcb ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid palette callback ptr" );
return FALSE;
}
if( !VALIDEX_DDPALETTECALLBACKSSIZE( palcb ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid size field in lpPaletteCallbacks" );
return FALSE;
}
numcb = NUM_CALLBACKS( palcb );
bit = 1;
for( i=0;i<numcb;i++ )
{
if( palcb->dwFlags & bit )
{
// 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
cbrtn = (LPVOID) (&palcb->DestroyPalette)[i];
if( cbrtn != NULL )
{
#if defined(NT_FIX) || defined(WIN95)
if( !VALIDEX_CODE_PTR( cbrtn ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid 32-bit callback in lpPaletteCallbacks" );
return FALSE;
}
#endif
}
}
bit <<= 1;
}
}
/*
* validate execute buffer callbacks - but only (and I mean ONLY) if
* its a V2 driver and it knows about execute buffers.
*/
if( lpDDHALInfo->dwSize >= DDHALINFOSIZE_V2 )
{
exebufcb = lpDDHALInfo->lpDDExeBufCallbacks;
if( exebufcb != NULL )
{
if( !VALID_PTR_PTR( exebufcb ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid execute buffer callback ptr" );
return FALSE;
}
if( !VALIDEX_DDEXEBUFCALLBACKSSIZE( exebufcb ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid size field in lpExeBufCallbacks" );
return FALSE;
}
numcb = NUM_CALLBACKS( exebufcb );
bit = 1;
for( i=0;i<numcb;i++ )
{
if( exebufcb->dwFlags & bit )
{
// 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
cbrtn = (LPVOID) (&exebufcb->CanCreateExecuteBuffer)[i];
if( cbrtn != NULL )
{
#if defined(NT_FIX) || defined(WIN95)
if( !VALIDEX_CODE_PTR( cbrtn ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Invalid 32-bit callback in lpExeBufCallbacks" );
return FALSE;
}
#endif
}
}
bit <<= 1;
}
}
}
/*
* Make sure a mode table was specified
*/
if( ( lpDDHALInfo->dwNumModes > 0 ) &&
( lpDDHALInfo->lpModeInfo == NULL ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Driver says modes are supported, but DDHALINFO.lpModeInfo = NULL" );
return FALSE;
}
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Exception encountered validating driver HAL information" );
DEBUG_BREAK();
return FALSE;
}
return TRUE;
}
/*
* Fetch the new HAL information from a driver (if any) and validate it.
*/
static BOOL
GetAndValidateNewHALInfo( LPDDRAWI_DIRECTDRAW_GBL pddd,
LPDDHALINFO lpDDHALInfo )
{
pddd->lpD3DHALCallbacks2 = 0;
pddd->lpD3DHALCallbacks3 = 0;
pddd->lpZPixelFormats = NULL;
pddd->pGetDriverInfo = NULL;
#ifdef POSTPONED
pddd->lpDDUmodeDrvInfo = NULL;
pddd->lpDDOptSurfaceInfo = NULL;
#endif
TRY
{
memset(&pddd->lpDDCBtmp->HALDDMiscellaneous, 0, sizeof(pddd->lpDDCBtmp->HALDDMiscellaneous) );
memset(&pddd->lpDDCBtmp->HALDDMiscellaneous2, 0, sizeof(pddd->lpDDCBtmp->HALDDMiscellaneous2) );
#ifndef WIN95
memset(&pddd->lpDDCBtmp->HALDDNT, 0, sizeof(pddd->lpDDCBtmp->HALDDNT) );
#endif
memset(&pddd->lpDDCBtmp->HALDDVideoPort, 0, sizeof(pddd->lpDDCBtmp->HALDDVideoPort) );
memset(&pddd->lpDDCBtmp->HALDDColorControl, 0, sizeof(pddd->lpDDCBtmp->HALDDColorControl) );
memset(&pddd->lpDDCBtmp->HALDDKernel, 0, sizeof(pddd->lpDDCBtmp->HALDDKernel) );
/*
* Allocate memory for D3D DDI interfaces queried from GetDriverInfo
* (the freeing of this memory for failed driver init needs work)
*/
pddd->lpD3DHALCallbacks2 = MemAlloc( D3DHAL_CALLBACKS2SIZE );
if (! pddd->lpD3DHALCallbacks2)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Out of memory querying D3DCallbacks2" );
goto failed;
}
pddd->lpD3DHALCallbacks3 = MemAlloc( D3DHAL_CALLBACKS3SIZE );
if (! pddd->lpD3DHALCallbacks3)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Out of memory querying D3DCallbacks3" );
goto failed;
}
#ifdef POSTPONED
pddd->lpDDUmodeDrvInfo =
(LPDDUMODEDRVINFO) MemAlloc (sizeof (DDUMODEDRVINFO));
if (! pddd->lpDDUmodeDrvInfo)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Out of memory querying UserModeDriverInfo" );
goto failed;
}
#endif
if ( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET )
{
HRESULT ret;
DDHAL_GETDRIVERINFODATA gdidata;
D3DHAL_CALLBACKS2 D3DCallbacks2;
D3DHAL_CALLBACKS3 D3DCallbacks3;
if (! VALIDEX_CODE_PTR (lpDDHALInfo->GetDriverInfo) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: GetDriverInfo callback bit set, but not valid" );
goto failed;
}
// use fact that code pointer was validated before...
pddd->pGetDriverInfo=lpDDHALInfo->GetDriverInfo;
/*
* Probe the driver with a GUID of bogusness. If it claims to
* understand this one, then fail driver create.
*/
{
DWORD dwFakeGUID[4];
DWORD dwTemp[10];
memcpy(dwFakeGUID, &CLSID_DirectDraw, sizeof(dwFakeGUID));
dwFakeGUID[3] += GetCurrentProcessId();
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
dwTemp,
sizeof(dwTemp),
(const GUID *) dwFakeGUID, pddd,
FALSE /* bInOut */);
if ( ret == DD_OK )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Driver claimed support via GetDriverInfo for bogus GUID!" );
goto failed;
}
}
/*
* Notify driver about DXVERSION on NT
*/
#ifndef WIN95
if (lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFO2)
{
// This buffer is used to pass information down to the driver and get
// information back from the driver. The GetDriverInfo2 header and
// any additional information to pass to the driver is copied into this
// buffer prior to calling GetDriverInfo2. After the call the information
// returned by the driver is contained in this buffer. All information
// passed to and from the driver must fit within a buffer of this size.
// The buffer used by GetDriverInfo2 is constrained to the maximum size
// specified below by restrictions in the Win2K kernel. It is vital that
// all data passed to the driver and received from the driver via
// GetDriverInfo2 fit within a buffer of this number of DWORDS.
// This size has to be less than 1K to let the kernel do its own buffer
// overwrite testing.
#define MAX_GDI2_BUFFER_DWORD_SIZE (249)
DWORD buffer[MAX_GDI2_BUFFER_DWORD_SIZE];
DD_DXVERSION* pDXVersion;
// Set up the DXVersion call
memset(&buffer, 0, sizeof(buffer));
pDXVersion = (DD_DXVERSION *)buffer;
// Before we do anything else, we notify the
// driver about the DX version information. We ignore
// errors here.
pDXVersion->gdi2.dwReserved = sizeof(DD_STEREOMODE);
pDXVersion->gdi2.dwMagic = D3DGDI2_MAGIC;
pDXVersion->gdi2.dwType = D3DGDI2_TYPE_DXVERSION;
pDXVersion->gdi2.dwExpectedSize = sizeof(DD_DXVERSION);
pDXVersion->dwDXVersion = DD_RUNTIME_VERSION;
// We assert the sizes are the same because we need to
// persuade the kernel into accepting this call.
DDASSERT(sizeof(DD_STEREOMODE) == sizeof(DD_DXVERSION));
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
buffer,
sizeof(DD_STEREOMODE),
&GUID_GetDriverInfo2, pddd,
TRUE /* bInOut */);
// Errors are ignored here
ret = 0;
// Also notify the driver that we have the AGP aliasing
// work-around in place.
{
DD_DEFERRED_AGP_AWARE_DATA aad;
DWORD dwDrvRet;
GetDriverInfo2(pddd,
&dwDrvRet,
D3DGDI2_TYPE_DEFERRED_AGP_AWARE,
sizeof(aad), &aad);
}
}
#endif // !WIN95
memset(&pddd->lpDDCBtmp->HALDDMiscellaneous, 0, sizeof(DDHAL_DDMISCELLANEOUSCALLBACKS) );
/* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
&pddd->lpDDCBtmp->HALDDMiscellaneous,
sizeof(DDHAL_DDMISCELLANEOUSCALLBACKS),
&GUID_MiscellaneousCallbacks, pddd,
FALSE /* bInOut */ );
// GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
// overwrote its buffer.
if ( ret == DDERR_NODIRECTDRAWSUPPORT )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous): Driver overwrote callbacks buffer" );
goto failed;
}
if ( ret == DD_OK )
{
// Fail create if driver already failed validation or
// claims support but it's not valid.
if (! VALIDEX_DDMISCELLANEOUSCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDMiscellaneous ) ||
( gdidata.dwActualSize < sizeof(DDHAL_DDMISCELLANEOUSCALLBACKS ) ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous): size not valid" );
goto failed;
}
if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDMiscellaneous) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous): flags set incorrectly" );
goto failed;
}
}
// Get HALDDMiscellaneous2 interface.
memset(&pddd->lpDDCBtmp->HALDDMiscellaneous2, 0, sizeof(DDHAL_DDMISCELLANEOUS2CALLBACKS) );
/* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
&pddd->lpDDCBtmp->HALDDMiscellaneous2,
sizeof(DDHAL_DDMISCELLANEOUS2CALLBACKS),
&GUID_Miscellaneous2Callbacks, pddd,
FALSE /* bInOut */);
// GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
// overwrote its buffer.
if ( ret == DDERR_NODIRECTDRAWSUPPORT )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous2): Driver overwrote callbacks buffer" );
goto failed;
}
if ( ret == DD_OK )
{
// Fail create if driver already failed validation or
// claims support but it's not valid.
if (! VALIDEX_DDMISCELLANEOUS2CALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDMiscellaneous2 ) ||
( gdidata.dwActualSize < sizeof(DDHAL_DDMISCELLANEOUS2CALLBACKS ) ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous2): size not valid" );
goto failed;
}
if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDMiscellaneous2) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Miscellaneous2): flags set incorrectly" );
goto failed;
}
if (lpDDHALInfo->lpD3DGlobalDriverData &&
(lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps &
(D3DDEVCAPS_DRAWPRIMITIVES2EX | D3DDEVCAPS_HWTRANSFORMANDLIGHT) )
)
{
// If a driver responds to the Misc2 GUID, then it better return
// a non-null GetDriverState callback.
if (0 == pddd->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (HALDDMiscellaneous2): no GetDriverState support" );
goto failed;
}
#ifdef WIN95
// On Win95 the CreateSurfaceEx should be non-NULL
if (0 == pddd->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (HALDDMiscellaneous2): CreateSurfaceEx must be reported with D3DDEVCAPS_DRAWPRIMITIVES2EX" );
goto failed;
}
#else //WIN95
// DX7 drivers should export GetDriverState always, if they
// didnt, then most likely they are the transition drivers that
// are still DX6 and will need to be updated. For now dont
// validate the presence of this callback. Simply use its
// presence or absence to spoof the legacy texture callbacks.
DDASSERT( lpDDHALInfo->lpD3DHALCallbacks->TextureCreate == NULL);
DDASSERT( lpDDHALInfo->lpD3DHALCallbacks->TextureDestroy == NULL);
DDASSERT( lpDDHALInfo->lpD3DHALCallbacks->TextureSwap == NULL);
DDASSERT( lpDDHALInfo->lpD3DHALCallbacks->TextureGetSurf == NULL);
#endif //WIN95
}
}
#ifdef WIN95
if (0 != pddd->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx)
{
if (lpDDHALInfo->lpD3DGlobalDriverData)
{
if (!(lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps &
D3DDEVCAPS_DRAWPRIMITIVES2EX))
{
if(lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dpcTriCaps.dwRasterCaps &
D3DPRASTERCAPS_ZBUFFERLESSHSR)
//legacy powerVR stackable driver would actually forward new callbacks
//if the primary driver supports the new callbacks
{
pddd->lpDDCBtmp->HALDDMiscellaneous2.CreateSurfaceEx=0;
pddd->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState=0;
pddd->lpDDCBtmp->HALDDMiscellaneous2.DestroyDDLocal=0;
}
else
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (HALDDMiscellaneous2): CreateSurfaceEx must be reported with D3DDEVCAPS_DRAWPRIMITIVES2EX" );
goto failed;
}
}
}
}
#else //WIN95
memset(&pddd->lpDDCBtmp->HALDDNT, 0, sizeof(DDHAL_DDNTCALLBACKS) );
/* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
&pddd->lpDDCBtmp->HALDDNT,
sizeof(DDHAL_DDNTCALLBACKS),
&GUID_NTCallbacks, pddd,
FALSE /* bInOut */);
// GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
// overwrote its buffer.
if ( ret == DDERR_NODIRECTDRAWSUPPORT )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (NT): Driver overwrote callbacks buffer" );
goto failed;
}
if ( ret == DD_OK )
{
// Fail create if driver already failed validation or
// claims support but it's not valid.
if (! VALIDEX_DDNTCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDNT ) ||
( gdidata.dwActualSize < sizeof(DDHAL_DDNTCALLBACKS ) ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (NT): size not valid" );
goto failed;
}
if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDNT) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (NT): flags set incorrectly" );
goto failed;
}
}
memset(&pddd->lpDDCBtmp->HALDDVPE2, 0, sizeof(DDHAL_DDVPE2CALLBACKS) );
/* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
&pddd->lpDDCBtmp->HALDDVPE2,
sizeof(DDHAL_DDVPE2CALLBACKS),
&GUID_VPE2Callbacks, pddd,
FALSE /* bInOut */);
// GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
// overwrote its buffer.
if ( ret == DDERR_NODIRECTDRAWSUPPORT )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VPE2): Driver overwrote callbacks buffer" );
goto failed;
}
if ( ret == DD_OK )
{
// Fail create if driver already failed validation or
// claims support but it's not valid.
if (! VALIDEX_DDVPE2CALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDVPE2 ) ||
( gdidata.dwActualSize < sizeof(DDHAL_DDVPE2CALLBACKS ) ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VPE2): size not valid" );
goto failed;
}
if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDVPE2) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VPE2): flags set incorrectly" );
goto failed;
}
}
#endif
memset(&pddd->lpDDCBtmp->HALDDVideoPort, 0, sizeof(DDHAL_DDVIDEOPORTCALLBACKS) );
/* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
&pddd->lpDDCBtmp->HALDDVideoPort,
sizeof(DDHAL_DDVIDEOPORTCALLBACKS),
&GUID_VideoPortCallbacks, pddd,
FALSE /* bInOut */);
// GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
// overwrote its buffer.
if ( ret == DDERR_NODIRECTDRAWSUPPORT )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VideoPort): Driver overwrote callbacks buffer" );
goto failed;
}
if ( ret == DD_OK )
{
// Fail create if driver already failed validation or
// claims support but it's not valid.
if (! VALIDEX_DDVIDEOPORTCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDVideoPort ) ||
( gdidata.dwActualSize < sizeof(DDHAL_DDVIDEOPORTCALLBACKS ) ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VideoPort): size not valid" );
goto failed;
}
if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDVideoPort) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (VideoPort): flags set incorrectly" );
goto failed;
}
}
memset(&pddd->lpDDCBtmp->HALDDMotionComp, 0, sizeof(DDHAL_DDMOTIONCOMPCALLBACKS) );
/* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
&pddd->lpDDCBtmp->HALDDMotionComp,
sizeof(DDHAL_DDMOTIONCOMPCALLBACKS),
&GUID_MotionCompCallbacks, pddd,
FALSE /* bInOut */);
// GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
// overwrote its buffer.
if ( ret == DDERR_NODIRECTDRAWSUPPORT )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (MotionComp): Driver overwrote callbacks buffer" );
goto failed;
}
if ( ret == DD_OK )
{
// Fail create if driver already failed validation or
// claims support but it's not valid.
if (! VALIDEX_DDMOTIONCOMPCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDMotionComp ) ||
( gdidata.dwActualSize < sizeof(DDHAL_DDMOTIONCOMPCALLBACKS ) ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (MotionComp): size not valid" );
goto failed;
}
if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDMotionComp) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (MotionComp): flags set incorrectly" );
goto failed;
}
}
memset(&pddd->lpDDCBtmp->HALDDColorControl, 0, sizeof(DDHAL_DDCOLORCONTROLCALLBACKS) );
/* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
&pddd->lpDDCBtmp->HALDDColorControl,
sizeof(DDHAL_DDCOLORCONTROLCALLBACKS),
&GUID_ColorControlCallbacks, pddd,
FALSE /* bInOut */);
// GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
// overwrote its buffer.
if ( ret == DDERR_NODIRECTDRAWSUPPORT )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (ColorControl): Driver overwrote callbacks buffer" );
goto failed;
}
if ( ret == DD_OK )
{
// Fail create if driver already failed validation or
// claims support but it's not valid.
if (! VALIDEX_DDCOLORCONTROLCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDColorControl ) ||
( gdidata.dwActualSize < sizeof(DDHAL_DDCOLORCONTROLCALLBACKS ) ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (ColorControl): size not valid" );
goto failed;
}
if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDColorControl) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (ColorControl): flags set incorrectly" );
goto failed;
}
}
/*
* Probe and validate D3DCallbacks2 support
*/
// memset assures Clear2 will be NULL for DX5 drivers
memset(&D3DCallbacks2, 0, D3DHAL_CALLBACKS2SIZE );
/* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
&D3DCallbacks2, D3DHAL_CALLBACKS2SIZE,
&GUID_D3DCallbacks2, pddd,
FALSE /* bInOut */);
// GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
// overwrote its buffer.
if ( ret == DDERR_NODIRECTDRAWSUPPORT )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): Driver overwrote callbacks buffer" );
goto failed;
}
if ( ret == DD_OK )
{
// Fail create if driver already failed validation or
// claims support but it's not valid.
if (! VALIDEX_D3DCALLBACKS2SIZE (&D3DCallbacks2 ))
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): size not valid" );
goto failed;
}
if (! ValidateCallbacks(&D3DCallbacks2) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): flags set incorrectly" );
goto failed;
}
if ( (D3DCallbacks2.DrawOnePrimitive ||
D3DCallbacks2.DrawOneIndexedPrimitive ||
D3DCallbacks2.DrawPrimitives) &&
(! (D3DCallbacks2.DrawOnePrimitive &&
D3DCallbacks2.DrawOneIndexedPrimitive &&
D3DCallbacks2.DrawPrimitives) ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): must export all or none of DrawPrimitive callbacks" );
goto failed;
}
#if 0
if ( D3DCallbacks2.DrawOnePrimitive )
{
// If they export DrawPrimitive driver entry points but did
// not set D3DDEVCAPS_DRAWPRIMTLVERTEX, fail driver create.
if (! (lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_DRAWPRIMTLVERTEX) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): DrawPrimitive entry points exported" );
DPF_ERR( "from driver but D3DDEVCAPS_DRAWPRIMTLVERTEX not set" );
goto failed;
}
}
else
{
// If they set the caps but don't export the entry points,
// fail driver create.
if (lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_DRAWPRIMTLVERTEX )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks2): D3DDEVCAPS_DRAWPRIMTLVERTEX set" );
DPF_ERR( "but no DrawPrimitive entry points exported" );
goto failed;
}
}
#endif
memcpy((LPVOID) pddd->lpD3DHALCallbacks2, &D3DCallbacks2, D3DHAL_CALLBACKS2SIZE);
}
else{
memset((LPVOID) pddd->lpD3DHALCallbacks2, 0, D3DHAL_CALLBACKS2SIZE );
}
/*
* Probe and validate D3DCallbacks3 support
*/
memset(&D3DCallbacks3, 0, D3DHAL_CALLBACKS3SIZE );
/* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
&D3DCallbacks3, D3DHAL_CALLBACKS3SIZE,
&GUID_D3DCallbacks3, pddd,
FALSE /* bInOut */);
// GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
// overwrote its buffer.
if ( ret == DDERR_NODIRECTDRAWSUPPORT )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3): Driver overwrote callbacks buffer" );
goto failed;
}
if ( ret == DD_OK
#ifdef WIN95 // currently enforced in win95 to only make PowerVR DX5 driver work
&& (lpDDHALInfo->lpD3DGlobalDriverData &&
(lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2) )
#endif //WIN95
)
{
// Fail create if driver already failed validation or
// claims support but it's not valid.
if (! VALIDEX_D3DCALLBACKS3SIZE (&D3DCallbacks3 ) ||
( gdidata.dwActualSize < D3DHAL_CALLBACKS3SIZE ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3): size not valid" );
goto failed;
}
if (! ValidateCallbacks(&D3DCallbacks3) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3): flags set incorrectly" );
goto failed;
}
// DrawPrimitives2, ValidateTextureStageState and are the compulsory
// DDI in Callbacks3 DX6+ drivers support TextureStages, hence it is
// reasonable to require them to support ValidateTextureStageState
if (0 == D3DCallbacks3.DrawPrimitives2)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3): no DrawPrimitives2 support" );
goto failed;
}
if (0 == D3DCallbacks3.ValidateTextureStageState)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3): no ValidateTextureStageState support" );
goto failed;
}
#ifdef WIN95
// Now pass the driver the callback pointer to parse unknown
// execute-buffer commands.
// If this call fails then fail creating the driver. We need
// to be this harsh so that the IHVs are forced to
// implement this callback!
memset(&gdidata, 0, sizeof(gdidata) );
gdidata.dwSize = sizeof(gdidata);
gdidata.dwFlags = 0;
gdidata.dwContext = pddd->dwReserved3;
memcpy(&gdidata.guidInfo, &GUID_D3DParseUnknownCommandCallback, sizeof(GUID_D3DParseUnknownCommandCallback) );
gdidata.dwExpectedSize = 0;
gdidata.lpvData = &D3DParseUnknownCommand; // We pass the pointer to function
gdidata.ddRVal = DDERR_GENERIC;
ret = lpDDHALInfo->GetDriverInfo(&gdidata);
if (ret != DDHAL_DRIVER_HANDLED || gdidata.ddRVal != DD_OK)
{
// Fail driver creation!
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (D3DCallbacks3) GUID_D3DParseUnknownCommandCallback not recognized, fail driver creation" );
goto failed;
}
#endif
memcpy((LPVOID) pddd->lpD3DHALCallbacks3, &D3DCallbacks3, D3DHAL_CALLBACKS3SIZE);
}
else{
if (lpDDHALInfo->lpD3DGlobalDriverData)
lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps &= ~D3DDEVCAPS_DRAWPRIMITIVES2;
memset((LPVOID) pddd->lpD3DHALCallbacks3, 0, D3DHAL_CALLBACKS3SIZE );
}
#if WIN95
memset(&pddd->lpDDCBtmp->HALDDKernel, 0, sizeof(DDHAL_DDKERNELCALLBACKS) );
/* Get callbacks, validate them and put them in pddd->lpDDCBtmp */
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo, &gdidata,
&pddd->lpDDCBtmp->HALDDKernel,
sizeof(DDHAL_DDKERNELCALLBACKS),
&GUID_KernelCallbacks, pddd,
FALSE /* bInOut */);
// GetDriverInfo returns DDERR_NODIRECTDRAWSUPPORT if driver
// overwrote its buffer.
if ( ret == DDERR_NODIRECTDRAWSUPPORT )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Kernel): Driver overwrote callbacks buffer" );
goto failed;
}
if ( ret == DD_OK )
{
// Fail create if driver already failed validation or
// claims support but it's not valid.
if (! VALIDEX_DDKERNELCALLBACKSSIZE (&pddd->lpDDCBtmp->HALDDKernel ) ||
( gdidata.dwActualSize < sizeof(DDHAL_DDKERNELCALLBACKS ) ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Kernel): size not valid" );
goto failed;
}
if (! ValidateCallbacks(&pddd->lpDDCBtmp->HALDDKernel) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: CALLBACKS VALIDATION FAILURE (Kernel): flags set incorrectly" );
goto failed;
}
}
#endif
/*
* Get Z Pixel Formats, if driver supports this call.
* Ideally I'd like to handle this the same as TextureFormats, but
* D3DHAL_GLOBALDRIVERDATA is unexpandable if old drivers are to work,
* so must create new guid and graft this query onto callback validation
*/
{
DWORD tempbuf[249]; // make this <1K bytes or GetDriverInfo() fails cuz it cant do its "expected size overwrite" test within its own 1K tempbuffer
// variable size field--delay mallocing space until we know how much is needed.
// have GetDriverInfo stick results in tempbuf
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo,
&gdidata,
tempbuf,
sizeof(tempbuf), // "expected" bytesize is 249*4, this allows for 31 DDPIXELFORMATs which should be enough
&GUID_ZPixelFormats, pddd,
FALSE /* bInOut */);
if(ret!=DD_OK)
{
// A DX6+ driver (until we radically revamp our DDI) is
// one that responds to Callbacks3 (with DP2 support)
// This is a non-issue on NT, since the only DX6+ is
// available on it.
// DX6+ drivers have to field this GUID, if they
// report Clear2 (the DDI for stencil clear). No excuses!!
if (pddd->lpD3DHALCallbacks3->Clear2)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: A DX6+ driver should report its ZPixelFormats");
goto failed;
}
else
{
DPF(2,"GetDriverInfo: ZPixelFormats not supported by driver"); // driver is pre-dx6
pddd->dwNumZPixelFormats=0; pddd->lpZPixelFormats=NULL;
}
}
else
{
// verify returned buffer is of an expected size
if((gdidata.dwActualSize-sizeof(DWORD)) % sizeof(DDPIXELFORMAT) != 0) {
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Error in driver's ZPixelFormats query: driver returned bad-sized buffer");
goto failed;
}
if((tempbuf[0]*sizeof(DDPIXELFORMAT)+sizeof(DWORD))>sizeof(tempbuf)) {
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Error: driver returned bogus number of Z Formats: %u",pddd->dwNumZPixelFormats );
goto failed;
}
pddd->dwNumZPixelFormats=tempbuf[0];
pddd->lpZPixelFormats = MemAlloc(pddd->dwNumZPixelFormats*sizeof(DDPIXELFORMAT));
if (!pddd->lpZPixelFormats) {
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****: Out of memory querying Z Pixel Formats" );
goto failed;
}
memcpy(pddd->lpZPixelFormats,&tempbuf[1],pddd->dwNumZPixelFormats*sizeof(DDPIXELFORMAT));
#ifdef DEBUG
// simple validation of pixel format fields
{
DWORD ii;
DPF(5,E,"Number of Z Pixel Formats: %u",pddd->dwNumZPixelFormats);
for(ii=0;ii<pddd->dwNumZPixelFormats;ii++) {
DPF(5,E,"DDPF_ZBUFFER: %u, DDPF_STENCILBUFFER: %u",0!=(pddd->lpZPixelFormats[ii].dwFlags&DDPF_ZBUFFER),0!=(pddd->lpZPixelFormats[ii].dwFlags&DDPF_STENCILBUFFER));
DPF(5,E,"zbits %d, stencilbits %d, zbitmask %X, stencilbitmask %X",pddd->lpZPixelFormats[ii].dwZBufferBitDepth,
pddd->lpZPixelFormats[ii].dwStencilBitDepth,pddd->lpZPixelFormats[ii].dwZBitMask,pddd->lpZPixelFormats[ii].dwStencilBitMask);
if(!(pddd->lpZPixelFormats[ii].dwFlags&DDPF_ZBUFFER)) {
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Error in driver's returned ZPixelFormats: ZBUFFER flag not set");
goto failed;
}
}
}
#endif //DEBUG
}
}
DPF(4,E, "Done querying driver for callbacks");
} // if ( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERCALLBACKSSET )
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Exception encountered validating driver HAL information" );
DEBUG_BREAK();
goto failed;
}
return TRUE;
failed:
MemFree((LPVOID) pddd->lpZPixelFormats);
pddd->lpZPixelFormats = 0;
MemFree((LPVOID) pddd->lpD3DHALCallbacks2);
pddd->lpD3DHALCallbacks2 = 0;
MemFree((LPVOID) pddd->lpD3DHALCallbacks3);
pddd->lpD3DHALCallbacks3 = 0;
#ifdef POSTPONED
MemFree ((LPVOID) pddd->lpDDUmodeDrvInfo);
pddd->lpDDUmodeDrvInfo = 0;
MemFree ((LPVOID) pddd->lpDDOptSurfaceInfo);
pddd->lpDDOptSurfaceInfo = 0;
#endif
return FALSE;
}
/*
* GetExtendedHeapAlignment
* Call the driver to see if it requires alignment for the given heap.
* Return a pointer to the filled-in alignment data within the block passed in
* or NULL if failure or no alignment required.
*/
LPHEAPALIGNMENT GetExtendedHeapAlignment( LPDDRAWI_DIRECTDRAW_GBL pddd, LPDDHAL_GETHEAPALIGNMENTDATA pghad, int iHeap)
{
HRESULT rc;
LPDDHAL_GETHEAPALIGNMENT ghafn =
pddd->lpDDCBtmp->HALDDMiscellaneous.GetHeapAlignment;
DDASSERT(pghad);
ZeroMemory((LPVOID)pghad,sizeof(*pghad));
if( ghafn != NULL )
{
#ifdef WIN95
pghad->dwInstance = pddd->dwReserved3;
#else
pghad->dwInstance = pddd->hDD;
#endif
pghad->dwHeap = (DWORD)iHeap;
pghad->ddRVal = DDERR_GENERIC;
pghad->Alignment.dwSize = sizeof(HEAPALIGNMENT);
DOHALCALL_NOWIN16( GetHeapAlignment , ghafn, (*pghad), rc, FALSE );
if ( (rc == DDHAL_DRIVER_HANDLED) && (pghad->ddRVal == DD_OK) )
{
/*
* Validate alignment
*/
if ( pghad->Alignment.ddsCaps.dwCaps & ~DDHAL_ALIGNVALIDCAPS )
{
DPF(0,"****DirectDraw driver error****:Invalid alignment caps (at most %08x expected, %08x received) in heap %d",DDHAL_ALIGNVALIDCAPS, pghad->Alignment.ddsCaps.dwCaps,iHeap);
return NULL;
}
/*
* Turning on this flag means that ComputePitch will ignore the
* legacy alignment fields in VIDMEMINFO for all heaps, not just
* iHeap.
*/
DPF(5,V,"Driver reports extended alignment for heap %d",iHeap);
pddd->dwFlags |= DDRAWI_EXTENDEDALIGNMENT;
return & pghad->Alignment;
}
}
return NULL;
}
/*
* Get the non-local video memory blitting capabilities.
*/
BOOL GetNonLocalVidMemCaps( LPDDHALINFO lpDDHALInfo, LPDDRAWI_DIRECTDRAW_GBL pddd )
{
DDASSERT( NULL != lpDDHALInfo );
DDASSERT( NULL != pddd );
DDASSERT( NULL == pddd->lpddNLVCaps );
/*
* We are forced to treat NLVHELCaps and NLVBothCaps differently. Originally, we were destroying
* them here and letting a subsequent HELInit intiialize the HELCaps, and initcaps/mergeHELCaps
* rebuild them. Trouble is, there's no HELInit along the reset code path (resetting a driver
* object after a mode change). This means we were freeing the hel caps and never refilling them
* after a mode switch. Since the HEL caps are mode-independent, we can get away with not releasing
* the NLVHELCaps every mode switch. Now we will simply trust that once allocated, they are always valid.
* After this routine is called, a subsequent initcaps/mergeHELCaps will regenerate the NLVBothCaps
* from the driver caps (which may have changed- but we rebuilt them anyway) and the unchanging
* HEL caps.
*
* I am leaving this code here commented out as documentation.
*
* if( NULL != pddd->lpddNLVHELCaps )
* {
* MemFree( pddd->lpddNLVHELCaps );
* pddd->lpddNLVHELCaps = NULL;
* }
* if( NULL != pddd->lpddNLVBothCaps )
* {
* MemFree( pddd->lpddNLVBothCaps );
* pddd->lpddNLVBothCaps = NULL;
* }
*/
if( lpDDHALInfo->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM )
{
DDNONLOCALVIDMEMCAPS ddNLVCaps;
ZeroMemory( &ddNLVCaps, sizeof( ddNLVCaps ) );
if( lpDDHALInfo->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEMCAPS )
{
HRESULT hres;
/*
* The driver has different capabilities for non-local video memory
* to local video memory blitting. If the driver has a GetDriverInfo
* entry point defined then query it. If the driver doesn't want to
* handle the query then just assume it has no non-local video memory
* capabilities.
*/
hres = DDERR_GENERIC;
if( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET )
{
DDHAL_GETDRIVERINFODATA gdiData;
hres = GetDriverInfo( lpDDHALInfo->GetDriverInfo,
&gdiData,
&ddNLVCaps,
sizeof( DDNONLOCALVIDMEMCAPS ),
&GUID_NonLocalVidMemCaps,
pddd,
FALSE /* bInOut */ );
if( DD_OK == hres )
{
/*
* We should never get back more data than we asked for.
*/
DDASSERT( gdiData.dwActualSize <= sizeof( DDNONLOCALVIDMEMCAPS ) );
/*
* The driver thinks it worked. Check it has done something sensible.
*/
if( ( ddNLVCaps.dwSize < ( 2UL * sizeof( DWORD ) ) ) ||
( gdiData.dwActualSize < ( 2UL * sizeof( DWORD ) ) ) )
{
/*
* Invalid size returned by the driver. Fail initialization.
*/
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not initialization. Invalid non-local vidmem caps returned by driver" );
return FALSE;
}
/*
* We zeroed the structure before passing it to the driver so
* everything is cool if we got less data than we asked for.
* Just bump the size up to the expected size.
*/
ddNLVCaps.dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
}
else if ( DDERR_GENERIC != hres )
{
/*
* If we failed for any other reason than generic (which means
* driver not handled in this scenario) then fail initialization.
* Things have gone badly wrong.
*/
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Fatal error when querying for non-local video memory caps" );
return FALSE;
}
}
if( DDERR_GENERIC == hres )
{
/*
* Driver doesn't have a GetDriverInfo entry point or it does but doesn't
* want to handle GUID_GetNonLocalVidMemCaps. Assume this means no caps
* at all. The structure is already zeroed so just set the size.
*/
ddNLVCaps.dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
}
}
else
{
int i;
/*
* The driver does not have non-local video memory capabilities which
* are different from the video ones so just make the non-local case
* identical to the video memory ones.
*/
ddNLVCaps.dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
ddNLVCaps.dwNLVBCaps = lpDDHALInfo->ddCaps.dwCaps;
ddNLVCaps.dwNLVBCaps2 = lpDDHALInfo->ddCaps.dwCaps2;
ddNLVCaps.dwNLVBCKeyCaps = lpDDHALInfo->ddCaps.dwCKeyCaps;
ddNLVCaps.dwNLVBFXCaps = lpDDHALInfo->ddCaps.dwFXCaps;
for( i = 0; i < DD_ROP_SPACE; i++ )
ddNLVCaps.dwNLVBRops[i] = lpDDHALInfo->ddCaps.dwRops[i];
}
#ifndef WINNT
/*
* Memphis: Max AGP is sysmem-12megs, same as VGARTD,
*/
if ( (dwRegFlags & DDRAW_REGFLAGS_AGPPOLICYMAXBYTES) == 0)
{
/*
* If there's nothing in the registry, figure our own out
*/
MEMORYSTATUS s = {sizeof(s)};
GlobalMemoryStatus(&s);
if (s.dwTotalPhys > 0xc00000)
dwAGPPolicyMaxBytes = (DWORD)(s.dwTotalPhys - 0xc00000);
else
dwAGPPolicyMaxBytes = 0;
DPF(1,"Max AGP size set to %08x (total phys is %08x)",dwAGPPolicyMaxBytes,s.dwTotalPhys);
}
else
{
DPF(1,"Max AGP size set to registry value of %08x",dwAGPPolicyMaxBytes);
}
#endif
/*
* If we got this far we have some valid non-local video memory capabilities so
* allocate the storage in the driver object to hold them.
*/
pddd->lpddNLVCaps = (LPDDNONLOCALVIDMEMCAPS)MemAlloc( sizeof( DDNONLOCALVIDMEMCAPS ) );
if( NULL == pddd->lpddNLVCaps)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate non-local video memory capabilities" );
return FALSE;
}
/*
* If the NLVHELcaps pointer is null, we'll allocate it here.
*/
if( NULL == pddd->lpddNLVHELCaps)
pddd->lpddNLVHELCaps = (LPDDNONLOCALVIDMEMCAPS)MemAlloc( sizeof( DDNONLOCALVIDMEMCAPS ) );
if( NULL == pddd->lpddNLVHELCaps)
{
MemFree( pddd->lpddNLVCaps );
pddd->lpddNLVCaps = NULL;
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate non-local video memory capabilities" );
return FALSE;
}
/*
* If the NLVBothCaps pointer is null, we'll allocate it here.
*/
if( NULL == pddd->lpddNLVBothCaps)
pddd->lpddNLVBothCaps = (LPDDNONLOCALVIDMEMCAPS)MemAlloc( sizeof( DDNONLOCALVIDMEMCAPS ) );
if( NULL == pddd->lpddNLVBothCaps)
{
MemFree( pddd->lpddNLVCaps );
pddd->lpddNLVCaps = NULL;
MemFree( pddd->lpddNLVHELCaps );
pddd->lpddNLVHELCaps = NULL;
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate non-local video memory capabilities" );
return FALSE;
}
/*
* This code is structure so by this point the size of the temporary buffer should
* be sizeof( DDNONLOCALVIDMEMCAPS )
*/
DDASSERT( sizeof( DDNONLOCALVIDMEMCAPS ) == ddNLVCaps.dwSize );
CopyMemory(pddd->lpddNLVCaps, &ddNLVCaps, sizeof( DDNONLOCALVIDMEMCAPS ) );
/*
* The HEL caps and the merged caps are zero to start with (they are initialized later).
* (actually they may not be zero in the reset case: we don't destroy the hel caps
* on mode changes anymore.)
*/
pddd->lpddNLVHELCaps->dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
pddd->lpddNLVBothCaps->dwSize = sizeof( DDNONLOCALVIDMEMCAPS );
}
return TRUE;
} /* GetNonLocalVidMemCaps */
/*
* This function is currently only used in NT
*/
#ifdef WINNT
BOOL GetDDStereoMode( LPDDRAWI_DIRECTDRAW_GBL pdrv,
DWORD dwWidth,
DWORD dwHeight,
DWORD dwBpp,
DWORD dwRefreshRate)
{
DDHAL_GETDRIVERINFODATA gdidata;
HRESULT hres;
DDSTEREOMODE ddStereoMode;
DDASSERT( pdrv != NULL );
/*
* If driver does not support GetDriverInfo callback, it also
* has no extended capabilities to report, so we're done.
*/
if( !VALIDEX_CODE_PTR (pdrv->pGetDriverInfo) )
{
return FALSE;
}
/*
* The mode can't be stereo if the driver doesn't support it...
*/
if (0 == (pdrv->ddCaps.dwCaps2 & DDCAPS2_STEREO))
{
return FALSE;
}
ZeroMemory( &ddStereoMode, sizeof(DDSTEREOMODE));
ddStereoMode.dwSize=sizeof(DDSTEREOMODE);
ddStereoMode.dwWidth=dwWidth;
ddStereoMode.dwHeight=dwHeight;
ddStereoMode.dwBpp=dwBpp;
ddStereoMode.dwRefreshRate=dwRefreshRate;
ddStereoMode.bSupported = TRUE;
/*
* Get the actual driver data
*/
memset(&gdidata, 0, sizeof(gdidata) );
gdidata.dwSize = sizeof(gdidata);
gdidata.dwFlags = 0;
gdidata.guidInfo = GUID_DDStereoMode;
gdidata.dwExpectedSize = sizeof(DDSTEREOMODE);
gdidata.lpvData = &ddStereoMode;
gdidata.ddRVal = DDERR_GENERIC;
// Pass a context variable so that the driver
// knows which instance of itself to use
// w.r.t. this function. These are different
// values on Win95 and NT.
#ifdef WIN95
gdidata.dwContext = pdrv->dwReserved3;
#else
gdidata.dwContext = pdrv->hDD;
#endif
if ( pdrv->pGetDriverInfo(&gdidata) == DDHAL_DRIVER_HANDLED)
{
// GUID_DDStereoMode is a way to turn OFF stereo per-mode, since
// it is expected that a driver that can do stereo can do stereo in
// any mode.
if( gdidata.ddRVal == DD_OK )
{
return ddStereoMode.bSupported;
}
}
return TRUE;
} /* GetDDStereoMode */
#endif //WINNT
BOOL GetDDMoreSurfaceCaps( LPDDHALINFO lpDDHALInfo, LPDDRAWI_DIRECTDRAW_GBL pdrv )
{
DDHAL_GETDRIVERINFODATA gdiData;
HRESULT hres;
DWORD dwSize;
LPDDMORESURFACECAPS lpddMoreSurfaceCaps=NULL;
BOOL retval=TRUE;
DWORD heap;
DDASSERT( lpDDHALInfo != NULL );
DDASSERT( pdrv != NULL );
/*
* If driver does not support GetDriverInfo callback, it also
* has no extended capabilities to report, so we're done.
*/
if( !(lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET) )
{
goto Succeeded;
}
/*
* The size of DDMORESURFACECAPS is variable.
* We have to do this calculation signed, since dwNumHeaps might be zero, in which case we need
* to subtract some from sizeof DDMORESURFACECAPS.
*/
dwSize = (DWORD) (sizeof(DDMORESURFACECAPS) + (((signed int)pdrv->vmiData.dwNumHeaps)-1) * sizeof(DDSCAPSEX)*2 );
/*
* Allocate some temporary space.
* The caps bits will go into the pdrv, and the extended heap restrictions will go into
* the VMEMHEAP structs off of pdrv->vmiData->pvmList->lpHeap
*/
lpddMoreSurfaceCaps = (LPDDMORESURFACECAPS)MemAlloc( dwSize );
if (lpddMoreSurfaceCaps == NULL)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate extended surface capabilities" );
goto Failed;
}
ZeroMemory( lpddMoreSurfaceCaps , dwSize);
/*
* Get the actual driver data
*/
hres = GetDriverInfo( lpDDHALInfo->GetDriverInfo,
&gdiData,
lpddMoreSurfaceCaps,
dwSize,
&GUID_DDMoreSurfaceCaps,
pdrv,
FALSE /* bInOut */ );
if( hres != DD_OK )
{
goto Succeeded;
}
/*
* We should never get back more data than we asked for. If we
* do, that probably means the driver version is newer than the
* DirectDraw runtime version. In that case, we just fail.
*/
if( gdiData.dwActualSize > dwSize )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Driver gives too big a size for DDMORESURFACECAPS. Check the dwSize calculation." );
goto Failed;
}
/*
* The surface caps go into the pdrv:
*/
pdrv->ddsCapsMore = lpddMoreSurfaceCaps->ddsCapsMore;
if (pdrv->vmiData.dwNumHeaps == 0)
{
/*
* No heaps means we are done
*/
goto Succeeded;
}
DDASSERT(NULL != pdrv->vmiData.pvmList);
for (heap = 0; heap < pdrv->vmiData.dwNumHeaps; heap ++ )
{
LPVMEMHEAP lpHeap = pdrv->vmiData.pvmList[heap].lpHeap;
/*
* A quick sanity check. If we have nonzero dwNumHeaps, then we better have
* a heap descriptor pointer. This also saves us if someone rearranges the caller of this
* routine so that the vidmeminit calls have not yet been made.
*/
if (!lpHeap)
{
DPF_ERR("****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Rearrange this call to GetDDMoreSurfaceCaps so it comes after vidmeminit");
goto Failed;
}
lpHeap->ddsCapsEx = lpddMoreSurfaceCaps->ddsExtendedHeapRestrictions[heap].ddsCapsEx;
lpHeap->ddsCapsExAlt = lpddMoreSurfaceCaps->ddsExtendedHeapRestrictions[heap].ddsCapsExAlt;
}
Succeeded:
retval = TRUE;
goto Exit;
Failed:
retval = FALSE;
Exit:
MemFree(lpddMoreSurfaceCaps);
return retval;
} /* GetDDMoreSurfaceCaps */
/*
* Interrogate the driver to get more driver capabilities, as specified in
* the DDMORECAPS structure. These caps augment those specified by the
* driver in the DDHALINFO structure. Return TRUE if the call succeeds,
* or FALSE if an error condition is detected. If the call succeeds, the
* function ensures that storage is allocated for all of the DirectDraw
* object's additional caps.
*/
BOOL GetDDMoreCaps( LPDDHALINFO lpDDHALInfo, LPDDRAWI_DIRECTDRAW_GBL pdrv )
{
DDMORECAPS ddMoreCaps;
DDHAL_GETDRIVERINFODATA gdiData;
HRESULT hres;
DDASSERT( lpDDHALInfo != NULL );
DDASSERT( pdrv != NULL );
/*
* Make sure memory is allocated and initialized for the driver's
* lpddMoreCaps, lpddHELMoreCaps, and lpddBothMoreCaps pointers.
*/
if (pdrv->lpddMoreCaps == NULL) // hardware caps
{
pdrv->lpddMoreCaps = (LPDDMORECAPS)MemAlloc( sizeof( DDMORECAPS ) );
if (pdrv->lpddMoreCaps == NULL)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate extended capabilities" );
return FALSE;
}
}
ZeroMemory( pdrv->lpddMoreCaps, sizeof(DDMORECAPS) );
pdrv->lpddMoreCaps->dwSize = sizeof( DDMORECAPS );
if (pdrv->lpddHELMoreCaps == NULL) // HEL caps
{
pdrv->lpddHELMoreCaps = (LPDDMORECAPS)MemAlloc( sizeof( DDMORECAPS ) );
if (pdrv->lpddHELMoreCaps == NULL)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate extended capabilities" );
return FALSE;
}
ZeroMemory( pdrv->lpddHELMoreCaps, sizeof(DDMORECAPS) );
pdrv->lpddHELMoreCaps->dwSize = sizeof( DDMORECAPS );
}
if (pdrv->lpddBothMoreCaps == NULL) // bitwise AND of hardware and HEL caps
{
pdrv->lpddBothMoreCaps = (LPDDMORECAPS)MemAlloc( sizeof( DDMORECAPS ) );
if (pdrv->lpddBothMoreCaps == NULL)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate extended capabilities" );
return FALSE;
}
}
ZeroMemory( pdrv->lpddBothMoreCaps, sizeof(DDMORECAPS) );
pdrv->lpddBothMoreCaps->dwSize = sizeof( DDMORECAPS );
/*
* If driver does not support GetDriverInfo callback, it also
* has no extended capabilities to report, so we're done.
*/
if( !(lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET) )
{
return TRUE; // no extended capabilities to report
}
#if 0
/*
* Get the extended capabilities from the driver.
*/
ZeroMemory( &ddMoreCaps, sizeof( DDMORECAPS ) );
hres = GetDriverInfo( lpDDHALInfo->GetDriverInfo,
&gdiData,
&ddMoreCaps,
sizeof( DDMORECAPS ),
&GUID_DDMoreCaps,
pdrv );
if( hres != DD_OK )
{
return TRUE; // no extended capabilities to report
}
/*
* We should never get back more data than we asked for. If we
* do, that probably means the driver version is newer than the
* DirectDraw runtime version. In that case, we just fail.
*/
if( gdiData.dwActualSize > sizeof( DDMORECAPS ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Driver gives too big a size for DDMORECAPS" );
return FALSE; // error
}
/*
* We zeroed the structure before passing it to the driver so
* everything is cool if we got less data than we asked for.
* Just bump the size up to the expected size.
*/
ddMoreCaps.dwSize = sizeof( DDMORECAPS );
/*
* Store the hardware driver's extended caps in the global DirectDraw object.
*/
CopyMemory(pdrv->lpddMoreCaps, &ddMoreCaps, sizeof( DDMORECAPS ) );
#endif
return TRUE;
} /* GetDDMoreCaps */
/*
* DirectDrawObjectCreate
*
* Create a DIRECTDRAW object.
*/
LPDDRAWI_DIRECTDRAW_GBL DirectDrawObjectCreate(
LPDDHALINFO lpDDHALInfo,
BOOL reset,
LPDDRAWI_DIRECTDRAW_GBL oldpdd,
HANDLE hDDVxd,
char *szDrvName,
DWORD dwDriverContext,
DWORD dwLocalFlags )
{
LPDDRAWI_DIRECTDRAW_GBL pddd=NULL;
int drv_size;
int drv_callbacks_size;
int size;
LPVIDMEM pvm;
int i;
int j;
int devheapno;
int numcb;
LPDDHAL_DDCALLBACKS drvcb;
LPDDHAL_DDSURFACECALLBACKS surfcb;
LPDDHAL_DDPALETTECALLBACKS palcb;
LPDDHAL_DDEXEBUFCALLBACKS exebufcb;
DWORD bit;
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
DWORD freevm;
BOOL isagpaware;
#ifdef WIN95
DWORD ptr16;
#endif
#ifdef WINNT
/*
* Need somewhere to put the callback fn ptrs given to us by the NT driver...
*/
DDHAL_DDCALLBACKS ddNTHALDD;
DDHAL_DDSURFACECALLBACKS ddNTHALDDSurface;
DDHAL_DDPALETTECALLBACKS ddNTHALDDPalette;
D3DHAL_CALLBACKS d3dNTHALCallbacks;
D3DHAL_CALLBACKS *pd3dNTHALCallbacks=0;
D3DHAL_GLOBALDRIVERDATA d3dNTHALDriverData;
D3DHAL_GLOBALDRIVERDATA *pd3dNTHALDriverData;
LPDDSURFACEDESC pddsdD3dTextureFormats;
DDHAL_DDEXEBUFCALLBACKS ddNTHALBufferCallbacks;
LPDDHAL_DDEXEBUFCALLBACKS pddNTHALBufferCallbacks;
BOOL ismemalloced=FALSE;
#endif
ENTER_DDRAW();
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 4, "DirectDrawObjectCreate: oldpdd == 0x%p, reset = %d", oldpdd, reset );
DDASSERT( (oldpdd == NULL) == (reset==FALSE) );
/*
* make sure the driver isn't trying to lie to us about the old object
* This check should always be made at the top of this routine, since it's
* possible in stress scenarios for ddhelp's modeset thread to wake up
* just before it's killed at the end of DD_Release (since the code to kill
* the mode set thread is executed AFTER the last LEAVE_DDRAW in DD_Release).
*/
DPF( 5, "DIRECTDRAW object passed in = 0x%p", oldpdd );
if( oldpdd != NULL )
{
pdrv_lcl = lpDriverLocalList;
while( pdrv_lcl != NULL )
{
if( pdrv_lcl->lpGbl == oldpdd )
{
break;
}
pdrv_lcl = pdrv_lcl->lpLink;
}
if( pdrv_lcl == NULL )
{
DPF_ERR( "REUSED DRIVER OBJECT SPECIFIED, BUT NOT IN LIST" );
DDASSERT(FALSE);
goto ErrorExit;
}
}
// If a null driver name is passed in then use the one
// in the oldpdd passed in. We need one or the other!
if( szDrvName == NULL )
{
if( oldpdd == NULL )
{
DPF_ERR( "DDrawObjectCreate: oldpdd == NULL && szDrvName == NULL" );
DDASSERT( 0 );
goto ErrorExit;
}
szDrvName = oldpdd->cDriverName;
}
#ifdef USE_ALIAS
if( NULL != oldpdd )
{
/*
* The absolutely first thing we want to do is to check to see if there are
* any outstanding video memory locks and if there are we need to remap
* the aliased to dummy memory to ensure we don't write over memory we don't
* own or to memory that does not exist.
*/
if( ( NULL != oldpdd->phaiHeapAliases ) && ( oldpdd->phaiHeapAliases->dwRefCnt > 1UL ) )
{
DDASSERT( INVALID_HANDLE_VALUE != hDDVxd );
if( FAILED( MapHeapAliasesToDummyMem( hDDVxd, oldpdd->phaiHeapAliases ) ) )
{
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not map existing video memory aliases to dummy memory" );
goto ErrorExit;
}
}
}
#endif /* USE_ALIAS */
/*
* Is this OS AGP aware?
*
* NOTE: VXD handle is only necessary on Win95. On NT, hDDVxd will simply
* be NULL and be unused by this function.
*/
#ifdef WINNT
isagpaware = TRUE;
#else
isagpaware = OSIsAGPAware( hDDVxd );
if( !isagpaware )
{
if( dwRegFlags & DDRAW_REGFLAGS_FORCEAGPSUPPORT )
{
/*
* Pretend the OS is AGP aware for debugging purposes.
*/
DPF( 1, "Force enabling AGP support for debugging purposes" );
isagpaware = TRUE;
}
}
#endif //not WINNT
if( dwRegFlags & DDRAW_REGFLAGS_DISABLEAGPSUPPORT )
{
/*
* Pretend the OS is not AGP aware.
*/
DPF( 1, "Disabling APG support for debugging purposes" );
isagpaware = FALSE;
}
/*
* Under NT, we're forced to create a direct draw global object before we can
* query the driver for its ddhalinfo.
* Consequently, we validate the incoming ddhalinfo pointer first in its very
* own try-except block, then allocate the global structure, then (on NT only)
* call the driver to register the global object and get its halinfo.
* (Under win95, the halinfo will have been filled in by the caller) jeffno 960116
*/
/*
* initialize a new driver object if we don't have one already
*/
if( (oldpdd == NULL) || reset )
{
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 4, "oldpdd == 0x%p, reset = %d", oldpdd, reset );
/*
* Allocate memory for the global object.
* We also allocate a DDHAL_CALLBACKS structure with the global
* object. This structure is used to hold the single copy of
* the HAL function table under Win95 and it is used as
* temporary storage of the function table under NT
*/
drv_size = sizeof( DDRAWI_DIRECTDRAW_GBL );
drv_callbacks_size = drv_size + sizeof( DDHAL_CALLBACKS );
#ifdef WIN95
pddd = (LPDDRAWI_DIRECTDRAW_GBL) MemAlloc16( drv_callbacks_size, &ptr16 );
#else
pddd = (LPDDRAWI_DIRECTDRAW_GBL) MemAlloc( drv_callbacks_size );
#endif
DPF( 5,"Driver Object: %ld base bytes", drv_callbacks_size );
if( pddd == NULL )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not allocate space for driver object" );
goto ErrorExit;
}
#ifdef WIN95
// Store the value returned by the 32-bit driver
// into the pdrv; this allows the 32-bit driver to remember
// any state it needs to for all future calls to it. This
// was added for multi-monitor support. <kd>
if( oldpdd )
pddd->dwReserved3= oldpdd->dwReserved3;
else
pddd->dwReserved3 = dwDriverContext;
DPF( 5, "dwReserved3 of DDrawGbl is set to 0x%x", pddd->dwReserved3 );
// Initialize value of global DDRAW.VXD handle to INVALID_HANDLE_VALUE.
// This should always normally be INVALID_HANDLE_VALUE, unless if we
// are in the middle of a createSurface() call.
pddd->hDDVxd = (DWORD) INVALID_HANDLE_VALUE;
DPF( 6, "hDDVxd of DDrawGbl is set to INVALID_HANDLE_VALUE - 0x%p", pddd->hDDVxd );
#else
/*
* In the reset code path, this per-process hDD will have been stuffed into
* the oldpdd by FetchDirectDrawData.
*/
if (reset)
{
DDASSERT(oldpdd);
pddd->hDD = oldpdd->hDD;
}
#endif WIN95
pddd->lpDDCBtmp = (LPDDHAL_CALLBACKS)(((LPSTR) pddd) + drv_size );
#ifdef WINNT
pddd->SurfaceHandleList.dwList=NULL;
pddd->SurfaceHandleList.dwFreeList=0;
if (lpDDHALInfo && !(lpDDHALInfo->ddCaps.dwCaps & DDCAPS_NOHARDWARE))
{
HDC hDC;
BOOL bNewMode;
BOOL bRetVal;
/*
* Now that we have a ddraw GBL structure available, we can tell
* the driver about it...
*/
DPF(5,K,"WinNT driver conversation started");
if (!reset)
{
hDC = DD_CreateDC( szDrvName ); // create temporary DC
if (!hDC)
{
DPF(0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Unable to create temporary DC for driver");
goto ErrorExit;
}
bRetVal = DdCreateDirectDrawObject(pddd, hDC);
DD_DoneDC(hDC); // delete temporary DC
if (!bRetVal)
{
/*
* this means we're in emulation
*/
DPF(0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:NT Kernel mode would not create driver object... Failing over to emulation");
goto ErrorExit;
}
}
/*
* Now we can get the driver info...
* The first call to this routine lets us know how much space to
* reserve for the fourcc and vidmem lists
*/
if (!DdReenableDirectDrawObject(pddd,&bNewMode) ||
!DdQueryDirectDrawObject(pddd,
lpDDHALInfo,
&ddNTHALDD,
&ddNTHALDDSurface,
&ddNTHALDDPalette,
&d3dNTHALCallbacks,
&d3dNTHALDriverData,
&ddNTHALBufferCallbacks,
NULL,
NULL,
NULL))
{
DPF(1, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:First call to DdQueryDirectDrawObject failed!");
goto ErrorExit;
}
/*
* The second call allows the driver to fill in the fourcc and
* vidmem lists. First we make space for them.
*/
lpDDHALInfo->vmiData.pvmList = MemAlloc(lpDDHALInfo->vmiData.dwNumHeaps * sizeof(VIDMEM));
if (NULL == lpDDHALInfo->vmiData.pvmList)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:No RAM for pvmList");
goto ErrorExit;
}
lpDDHALInfo->lpdwFourCC = MemAlloc(lpDDHALInfo->ddCaps.dwNumFourCCCodes * sizeof(DWORD));
if (NULL == lpDDHALInfo->lpdwFourCC)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:No RAM for FourCC List");
goto ErrorExit;
}
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF(5, K, "numheaps = %d, numfourcc = %d", lpDDHALInfo->vmiData.dwNumHeaps, lpDDHALInfo->ddCaps.dwNumFourCCCodes);
DPF(5, K, "ptrs: 0x%p, 0x%p", lpDDHALInfo->lpdwFourCC, lpDDHALInfo->vmiData.pvmList);
// If Direct3D information was returned, allocate space for
// the real information to be stored in and for the
// appropriate number of texture formats
if (d3dNTHALCallbacks.dwSize > 0 &&
d3dNTHALDriverData.dwSize > 0)
{
// We need to allocate space for the d3dhalcallbacks etc. only once,
// since d3d caches them across mode changes.
// We are allowed to reallocate the texture format list, since d3d only
// caches a pointer to D3DHAL_GLOBALDRIVERDATA, which is where the pointer
// to the texture formats is kept.
if ( NULL == oldpdd || NULL == oldpdd->lpD3DHALCallbacks )
{
pddd->lpD3DHALCallbacks = pd3dNTHALCallbacks =
(LPD3DHAL_CALLBACKS) MemAlloc(sizeof(D3DHAL_CALLBACKS)+
sizeof(D3DHAL_GLOBALDRIVERDATA)+
sizeof(DDHAL_DDEXEBUFCALLBACKS));
// Mark memory allocated in this path (not get from old one)
// so that we can free this memory if error occur later.
ismemalloced = TRUE;
}
else
pddd->lpD3DHALCallbacks = pd3dNTHALCallbacks = oldpdd->lpD3DHALCallbacks;
if (pd3dNTHALCallbacks == NULL)
{
DPF_ERR("****DirectDraw/Direct3D DRIVER DISABLING ERROR****:D3D memory allocation failed!");
goto ErrorExit;
}
pd3dNTHALDriverData = (LPD3DHAL_GLOBALDRIVERDATA)
(pd3dNTHALCallbacks+1);
pddNTHALBufferCallbacks = (LPDDHAL_DDEXEBUFCALLBACKS)
(pd3dNTHALDriverData+1);
// free old texture list and allocate a new one.
MemFree(pd3dNTHALDriverData->lpTextureFormats);
pddsdD3dTextureFormats = pd3dNTHALDriverData->lpTextureFormats =
MemAlloc(sizeof(DDSURFACEDESC) * d3dNTHALDriverData.dwNumTextureFormats);
// WOW64: include the number of textures in the driver data so that WOW64 can
// thunk the texture formats
pd3dNTHALDriverData->dwNumTextureFormats = d3dNTHALDriverData.dwNumTextureFormats;
}
else
{
pd3dNTHALCallbacks = NULL;
pd3dNTHALDriverData = NULL;
pddNTHALBufferCallbacks = NULL;
pddsdD3dTextureFormats = NULL;
}
if (!DdQueryDirectDrawObject(pddd,
lpDDHALInfo,
&ddNTHALDD,
&ddNTHALDDSurface,
&ddNTHALDDPalette,
pd3dNTHALCallbacks,
pd3dNTHALDriverData,
pddNTHALBufferCallbacks,
pddsdD3dTextureFormats,
lpDDHALInfo->lpdwFourCC,
lpDDHALInfo->vmiData.pvmList))
{
DPF(1, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Third call to DdQueryDirectDrawObject failed!");
goto ErrorExit;
}
#ifdef DEBUG
{
int i;
DPF(5,K,"NT driver video ram data as reported by driver:");
DPF(5,K," VIDMEMINFO.fpPrimary =%08x",lpDDHALInfo->vmiData.fpPrimary);
DPF(5,K," VIDMEMINFO.dwFlags =%08x",lpDDHALInfo->vmiData.dwFlags);
DPF(5,K," VIDMEMINFO.dwDisplayWidth =%08x",lpDDHALInfo->vmiData.dwDisplayWidth);
DPF(5,K," VIDMEMINFO.dwDisplayHeight =%08x",lpDDHALInfo->vmiData.dwDisplayHeight);
DPF(5,K," VIDMEMINFO.lDisplayPitch =%08x",lpDDHALInfo->vmiData.lDisplayPitch);
DPF(5,K," VIDMEMINFO.dwOffscreenAlign =%08x",lpDDHALInfo->vmiData.dwOffscreenAlign);
DPF(5,K," VIDMEMINFO.dwOverlayAlign =%08x",lpDDHALInfo->vmiData.dwOverlayAlign);
DPF(5,K," VIDMEMINFO.dwTextureAlign =%08x",lpDDHALInfo->vmiData.dwTextureAlign);
DPF(5,K," VIDMEMINFO.dwZBufferAlign =%08x",lpDDHALInfo->vmiData.dwZBufferAlign);
DPF(5,K," VIDMEMINFO.dwAlphaAlign =%08x",lpDDHALInfo->vmiData.dwAlphaAlign);
DPF(5,K," VIDMEMINFO.dwNumHeaps =%08x",lpDDHALInfo->vmiData.dwNumHeaps);
DPF(5,K," VIDMEMINFO.ddpfDisplay.dwSize =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwSize);
DPF(5,K," VIDMEMINFO.ddpfDisplay.dwFlags =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwFlags);
DPF(5,K," VIDMEMINFO.ddpfDisplay.dwFourCC =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwFourCC);
DPF(5,K," VIDMEMINFO.ddpfDisplay.dwRGBBitCount =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwRGBBitCount);
DPF(5,K," VIDMEMINFO.ddpfDisplay.dwRBitMask =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwRBitMask);
DPF(5,K," VIDMEMINFO.ddpfDisplay.dwGBitMask =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwGBitMask);
DPF(5,K," VIDMEMINFO.ddpfDisplay.dwBBitMask =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwBBitMask);
DPF(5,K," VIDMEMINFO.ddpfDisplay.dwRGBAlphaBitMask =%08x",lpDDHALInfo->vmiData.ddpfDisplay.dwRGBAlphaBitMask);
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF(5, K, " Vidmem list ptr is 0x%p", lpDDHALInfo->vmiData.pvmList);
for (i=0;i<(int) lpDDHALInfo->vmiData.dwNumHeaps;i++)
{
DPF(5, K, " heap flags: %03x", lpDDHALInfo->vmiData.pvmList[i].dwFlags);
DPF(5, K, " Start of chunk: 0x%p", lpDDHALInfo->vmiData.pvmList[i].fpStart);
DPF(5, K, " End of chunk: 0x%p", lpDDHALInfo->vmiData.pvmList[i].fpEnd);
}
}
#endif
lpDDHALInfo->lpDDCallbacks = &ddNTHALDD;
lpDDHALInfo->lpDDSurfaceCallbacks = &ddNTHALDDSurface;
lpDDHALInfo->lpDDPaletteCallbacks = &ddNTHALDDPalette;
ddNTHALBufferCallbacks.dwSize =sizeof ddNTHALBufferCallbacks; //since kernel is busted
ddNTHALBufferCallbacks.dwFlags =
DDHAL_EXEBUFCB32_CANCREATEEXEBUF|
DDHAL_EXEBUFCB32_CREATEEXEBUF |
DDHAL_EXEBUFCB32_DESTROYEXEBUF |
DDHAL_EXEBUFCB32_LOCKEXEBUF |
DDHAL_EXEBUFCB32_UNLOCKEXEBUF ;
lpDDHALInfo->lpDDExeBufCallbacks = &ddNTHALBufferCallbacks;
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF(5, K, "Surface callback as reported by Kernel is 0x%p", lpDDHALInfo->lpDDCallbacks->CreateSurface);
}
else
{
/*
* Normally, we specify a null DC handle to register our fake
* DDraw driver, but with secondary monitors we need to specify
* a device DC or else things fall apart.
*/
HDC hdcTemp = NULL;
if( ( _stricmp( szDrvName, DISPLAY_STR ) != 0 ) &&
( _stricmp( szDrvName, g_szPrimaryDisplay ) != 0 ) &&
IsMultiMonitor() &&
( ( szDrvName[0] == '\\' ) &&
( szDrvName[1] == '\\' ) &&
( szDrvName[2] == '.') ) )
{
hdcTemp = DD_CreateDC( szDrvName ); // create temporary DC
}
if (!DdCreateDirectDrawObject(pddd, hdcTemp))
{
DPF(1, "NT Kernel mode would not create fake DD driver object");
goto ErrorExit;
}
if( hdcTemp != NULL )
{
DD_DoneDC(hdcTemp); // delete temporary DC
}
}
if (!GetCurrentMode(oldpdd, lpDDHALInfo, szDrvName))
{
DPF(0, "Could not get current mode information");
goto ErrorExit;
}
if (oldpdd && oldpdd->lpModeInfo)
{
DDASSERT(oldpdd->lpModeInfo == &oldpdd->ModeInfo);
memcpy(&oldpdd->ModeInfo, lpDDHALInfo->lpModeInfo, sizeof (DDHALMODEINFO));
}
#endif //WINNT
} //end if oldpdd==NULL || reset
if( !ValidateCoreHALInfo( lpDDHALInfo ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Exception encountered validating driver parameters" );
goto ErrorExit;
}
// We only want to get new HALInfo if we haven't already
// done this. The oldpdd == NULL check implies that we are
// building a driver from scratch.
if( (oldpdd == NULL) && pddd && !GetAndValidateNewHALInfo( pddd, lpDDHALInfo ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Exception encountered querying for optional driver parameters" );
goto ErrorExit;
}
/*
* reset specified without a driver object existing is just a create
*/
if( reset && (oldpdd == NULL) )
{
reset = FALSE;
}
/*
* initialize a new driver object if we don't have one already
*/
if( (oldpdd == NULL) || reset )
{
DPF(4,"oldpdd == NULL || reset");
/*
* validate blt stuff
*/
if( lpDDHALInfo->ddCaps.dwCaps & DDCAPS_BLT )
{
if( lpDDHALInfo->lpDDSurfaceCallbacks->Blt == NULL )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:No Blt Fn, but BLT specified" );
goto ErrorExit;
}
if( !(lpDDHALInfo->ddCaps.dwRops[ (SRCCOPY>>16)/32 ] &
(1<<((SRCCOPY>>16) % 32)) ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:BLT specified, but SRCCOPY not supported!" );
goto ErrorExit;
}
}
else
{
DPF( 2, "Driver can't blt" );
}
/*
* validate align fields
*/
if( lpDDHALInfo->ddCaps.ddsCaps.dwCaps & DDSCAPS_OFFSCREENPLAIN )
{
if( !VALID_ALIGNMENT( lpDDHALInfo->vmiData.dwOffscreenAlign ) )
{
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Invalid dwOffscreenAlign (%d) with DDSCAPS_OFFSCREENPLAIN specified",
lpDDHALInfo->vmiData.dwOffscreenAlign );
goto ErrorExit;
}
}
if( lpDDHALInfo->ddCaps.ddsCaps.dwCaps & DDSCAPS_OVERLAY )
{
if( !VALID_ALIGNMENT( lpDDHALInfo->vmiData.dwOverlayAlign ) )
{
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Invalid dwOverlayAlign (%d) with DDSCAPS_OVERLAY specified",
lpDDHALInfo->vmiData.dwOverlayAlign );
goto ErrorExit;
}
}
if( lpDDHALInfo->ddCaps.ddsCaps.dwCaps & DDSCAPS_ZBUFFER )
{
if( !VALID_ALIGNMENT( lpDDHALInfo->vmiData.dwZBufferAlign ) )
{
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Invalid dwZBufferAlign (%d) with DDSCAPS_ZBUFFER specified",
lpDDHALInfo->vmiData.dwZBufferAlign );
goto ErrorExit;
}
}
if( lpDDHALInfo->ddCaps.ddsCaps.dwCaps & DDSCAPS_TEXTURE )
{
if( !VALID_ALIGNMENT( lpDDHALInfo->vmiData.dwTextureAlign ) )
{
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Invalid dwTextureAlign (%d) with DDSCAPS_TEXTURE specified",
lpDDHALInfo->vmiData.dwTextureAlign );
goto ErrorExit;
}
}
#ifndef WINNT
/*
* NT only reports one display mode if we are in the Ctrl-Alt-Del screen
* so don't fail if NT changes the number of display modes.
*/
/*
* make sure display driver doesn't try to change the number of
* modes supported after a mode change
*/
if( reset )
{
if( lpDDHALInfo->dwNumModes != 0 )
{
if( lpDDHALInfo->dwNumModes != oldpdd->dwSaveNumModes )
{
DPF(0, "*******************************************************");
DPF(0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Reset attempted to change number of modes from %d to %d",oldpdd->dwSaveNumModes,lpDDHALInfo->dwNumModes );
DPF(0, "*******************************************************");
goto ErrorExit;
}
}
}
#endif
/* memory for pddd was allocated at the top of this routine */
/*
* If this is the first time through, initialize a bunch of stuff.
* There are a number of fields that we only need to fill in when
* the driver object is created.
*/
if( !reset )
{
#ifdef WIN95
/*
* set up a 16-bit pointer for use by the driver
*/
pddd->lp16DD = (LPVOID) ptr16;
DPF( 5, "pddd->lp16DD = %08lx", pddd->lp16DD );
#endif
/*
* fill in misc. values
*/
pddd->lpDriverHandle = pddd;
pddd->hInstance = lpDDHALInfo->hInstance;
// init doubly-linked overlay zorder list
pddd->dbnOverlayRoot.next = &(pddd->dbnOverlayRoot);
pddd->dbnOverlayRoot.prev = pddd->dbnOverlayRoot.next;
pddd->dbnOverlayRoot.object = NULL;
pddd->dbnOverlayRoot.object_int = NULL;
/*
* modes...
*/
pddd->dwNumModes = lpDDHALInfo->dwNumModes;
pddd->dwSaveNumModes = lpDDHALInfo->dwNumModes;
if( pddd->dwNumModes > 0 )
{
size = pddd->dwNumModes * sizeof( DDHALMODEINFO );
#ifdef WIN95
pddd->lpModeInfo = MemAlloc( size );
if( pddd->lpModeInfo == NULL )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate mode info!" );
goto ErrorExit;
}
#else
pddd->lpModeInfo = &pddd->ModeInfo;
DDASSERT( 1 == pddd->dwNumModes );
#endif
memcpy( pddd->lpModeInfo, lpDDHALInfo->lpModeInfo, size );
#ifdef WIN95
/*
* Check if we can add Mode X
*/
do
{
if (lpDDHALInfo->dwFlags & DDHALINFO_MODEXILLEGAL)
{
break;
}
/*
* ModeX not allowed for PC98
* Check OS's locale.
*/
if ( GetSystemDefaultLCID() == 0x0411 )
{
/*
* System is Windows 95 J
* Now retrieve keyboard ID to check PC98
*/
DWORD dwSubType = GetKeyboardType(1);
if (HIBYTE(dwSubType) == 0x0D)
{
/* NEC PC98 series */
break;
}
}
/* NOT NEC PC98 series */
if (IsVGADevice( szDrvName ))
{
AddModeXModes( pddd );
/*
* OR in modex and/or standard VGA caps, so the app knows if
* it can pass the standard vga flag to enum modes.
*/
lpDDHALInfo->ddCaps.ddsCaps.dwCaps |= (DDSCAPS_STANDARDVGAMODE|DDSCAPS_MODEX);
/*
* Do the HEL caps just for rationality
*/
pddd->ddHELCaps.ddsCaps.dwCaps |= (DDSCAPS_STANDARDVGAMODE|DDSCAPS_MODEX);
}
break;
} while(0);
ExpandModeTable( pddd );
MassageModeTable( pddd );
#endif
}
else
{
pddd->lpModeInfo = NULL;
}
/*
* driver naming.. This is a special case for when we are
* invoked by the display driver directly, and not through
* the DirectDrawCreate path. Basically, everything except
* special 'secondary devices' like the 3DFx are DISPLAYDRV.
*
* If the driver says it's primary; ok. Else if it is "DISPLAY"
* or if the name is like "\\.\display4" then it is a Memphis/NT5
* multi-mon display device.
*/
if( (lpDDHALInfo->dwFlags & DDHALINFO_ISPRIMARYDISPLAY) ||
_stricmp( szDrvName, DISPLAY_STR ) == 0 ||
(szDrvName[0] == '\\' && szDrvName[1] == '\\' && szDrvName[2] == '.') )
{
pddd->dwFlags |= DDRAWI_DISPLAYDRV;
pddd->dwFlags |= DDRAWI_GDIDRV;
lstrcpy( pddd->cDriverName, szDrvName );
}
/*
* modex modes are illegal on some hardware. specifically
* NEC machines in japan. this allows the driver to specify
* that its hardware does not support modex. modex modes are
* then turned off everywhere as a result.
*/
if( lpDDHALInfo->dwFlags & DDHALINFO_MODEXILLEGAL )
{
pddd->dwFlags |= DDRAWI_MODEXILLEGAL;
}
}
/*
* resetting
*/
else
{
/*
* copy old struct onto new one (before we start updating)
* preserve the lpDDCB pointer
*/
{
LPDDHAL_CALLBACKS save_ptr=pddd->lpDDCBtmp;
memcpy( pddd, oldpdd, drv_callbacks_size );
pddd->lpDDCBtmp = save_ptr;
}
/*
* mark all existing surfaces as gone. Note, we don't rebuild
* the aliases at this point as they are going to be rebuilt
* below anyway.
*/
InvalidateAllSurfaces( oldpdd, hDDVxd, FALSE );
#ifdef USE_ALIAS
/*
* The video memory heaps are about to go so release the
* aliases to those heaps that the local objects maintain.
*
* NOTE: If any surfaces are currently locked and using
* those aliases then the aliases will not actually be
* discarded until the last lock is released. In which
* case these aliases will be mapped to the dummy page
* by this point.
*/
if( NULL != oldpdd->phaiHeapAliases )
{
DDASSERT( INVALID_HANDLE_VALUE != hDDVxd );
ReleaseHeapAliases( hDDVxd, oldpdd->phaiHeapAliases );
/*
* NOTE: Need to NULL out the heap alias pointer in the
* new driver object also as we just copied them above.
*/
oldpdd->phaiHeapAliases = NULL;
pddd->phaiHeapAliases = NULL;
}
#endif /* USE_ALIAS */
#ifndef WINNT
/*
* discard old vidmem heaps
*/
for( i=0;i<(int)oldpdd->vmiData.dwNumHeaps;i++ )
{
pvm = &(oldpdd->vmiData.pvmList[i]);
if( pvm->lpHeap != NULL )
{
HeapVidMemFini( pvm, hDDVxd );
}
}
#endif //not WINNT
}
/*
* fill in misc data
*/
pddd->ddCaps = lpDDHALInfo->ddCaps;
pddd->vmiData.fpPrimary = lpDDHALInfo->vmiData.fpPrimary;
pddd->vmiData.dwFlags = lpDDHALInfo->vmiData.dwFlags;
pddd->vmiData.dwDisplayWidth = lpDDHALInfo->vmiData.dwDisplayWidth;
pddd->vmiData.dwDisplayHeight = lpDDHALInfo->vmiData.dwDisplayHeight;
pddd->vmiData.lDisplayPitch = lpDDHALInfo->vmiData.lDisplayPitch;
pddd->vmiData.ddpfDisplay = lpDDHALInfo->vmiData.ddpfDisplay;
pddd->vmiData.dwOffscreenAlign = lpDDHALInfo->vmiData.dwOffscreenAlign;
pddd->vmiData.dwOverlayAlign = lpDDHALInfo->vmiData.dwOverlayAlign;
pddd->vmiData.dwTextureAlign = lpDDHALInfo->vmiData.dwTextureAlign;
pddd->vmiData.dwZBufferAlign = lpDDHALInfo->vmiData.dwZBufferAlign;
pddd->vmiData.dwAlphaAlign = lpDDHALInfo->vmiData.dwAlphaAlign;
#ifdef WIN95
/*
* We need to compute the number of heaps that are actually usable.
* The number of usable heaps may be different from the number of
* heap descriptors passed to us by the driver due to AGP. If the
* driver attempts to pass AGP heaps to use and the OS we are running
* under doesn't have AGP support we can't use those heaps so we
* ignore them.
*/
pddd->vmiData.dwNumHeaps = lpDDHALInfo->vmiData.dwNumHeaps;
for( i=0;i<(int)lpDDHALInfo->vmiData.dwNumHeaps;i++ )
{
if( ( lpDDHALInfo->vmiData.pvmList[i].dwFlags & VIDMEM_ISNONLOCAL ) && !isagpaware )
{
DPF(3, "Discarding AGP heap %d", i);
pddd->vmiData.dwNumHeaps--;
}
}
/*
* NOTE: Its not illegal to end up with no video memory heaps at this point.
* Under the current AGP implementation the primary is always in local
* video memory so we always end up with a valid primary if nothing else.
* Therefore, we stay in non-emulated mode.
*/
#ifdef WIN95
#ifdef DEBUG
if( 0UL == pddd->vmiData.dwNumHeaps )
{
DPF( 2, "All video memory heaps have been disabled." );
}
#endif /* DEBUG */
#endif //WIN95
#endif
/*
* fpPrimaryOrig has no user-mode meaning under NT... primary's surface may have different address
* across processes.
* There is a new flag (DDRAWISURFGBL_ISGDISURFACE) which identifies a surface gbl object
* as representing the surface which GDI believes is the front buffer. jeffno 960122
*/
pddd->fpPrimaryOrig = lpDDHALInfo->vmiData.fpPrimary;
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF(5,"Primary video ram pointer is 0x%p", lpDDHALInfo->vmiData.fpPrimary);
#ifdef WIN95
pddd->dwMonitorFrequency = lpDDHALInfo->dwMonitorFrequency;
if( ( pddd->dwMonitorFrequency == 0 ) &&
( lpDDHALInfo->dwModeIndex != (DWORD) -1 ) &&
( lpDDHALInfo->lpModeInfo != NULL ) &&
( lpDDHALInfo->lpModeInfo[lpDDHALInfo->dwModeIndex].wRefreshRate != 0 ) &&
!( lpDDHALInfo->lpModeInfo[lpDDHALInfo->dwModeIndex].wFlags & DDMODEINFO_MAXREFRESH ))
{
pddd->dwMonitorFrequency = lpDDHALInfo->lpModeInfo[lpDDHALInfo->dwModeIndex].wRefreshRate;
}
pddd->dwModeIndexOrig = lpDDHALInfo->dwModeIndex;
pddd->dwModeIndex = lpDDHALInfo->dwModeIndex;
DPF( 5, "Current and Original Mode = %d", pddd->dwModeIndex );
DPF( 5, "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ MODE INDEX = %ld", pddd->dwModeIndex );
#else
pddd->dmiCurrent.wWidth = (WORD) lpDDHALInfo->lpModeInfo->dwWidth;
pddd->dmiCurrent.wHeight = (WORD) lpDDHALInfo->lpModeInfo->dwHeight;
if (lpDDHALInfo->lpModeInfo->dwBPP == 16)
{
pddd->dmiCurrent.wBPP = (lpDDHALInfo->lpModeInfo->wFlags & DDMODEINFO_555MODE) ? 15 : 16;
}
else
{
pddd->dmiCurrent.wBPP = (BYTE) lpDDHALInfo->lpModeInfo->dwBPP;
}
pddd->dmiCurrent.wRefreshRate = lpDDHALInfo->lpModeInfo->wRefreshRate;
pddd->dwMonitorFrequency = lpDDHALInfo->lpModeInfo->wRefreshRate;
pddd->dmiCurrent.wMonitorsAttachedToDesktop = (BYTE) GetNumberOfMonitorAttachedToDesktop();
#endif
/*
* pdevice info
*/
#ifdef WIN95
if( lpDDHALInfo->lpPDevice != NULL )
{
LPDIBENGINE pde;
pde = MapSLFix( (DWORD) lpDDHALInfo->lpPDevice );
if( (pde->deType != 0x5250) || !(pde->deFlags & MINIDRIVER))
{
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Not a DIBEngine mini driver" );
goto ErrorExit;
}
pddd->dwPDevice = (DWORD)lpDDHALInfo->lpPDevice;
pddd->lpwPDeviceFlags = &pde->deFlags;
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 5, "lpPDevice = 0x%p", pde );
if(pde->deBitsPixel == 16)
{
if(pde->deFlags & FIVE6FIVE)
{
pddd->vmiData.ddpfDisplay.dwRBitMask = 0xf800;
pddd->vmiData.ddpfDisplay.dwGBitMask = 0x07e0;
pddd->vmiData.ddpfDisplay.dwBBitMask = 0x001f;
}
else
{
pddd->vmiData.ddpfDisplay.dwRBitMask = 0x7c00;
pddd->vmiData.ddpfDisplay.dwGBitMask = 0x03e0;
pddd->vmiData.ddpfDisplay.dwBBitMask = 0x001f;
}
// Update the current mode to reflect the correct bitmasks
// NOTE: The driver can return a dwModeIndex of -1 if in
// a currently unsupported mode. Therefore, we must not
// initialize these masks if such an index has been
// returned.
if( 0xFFFFFFFFUL != pddd->dwModeIndex )
{
pddd->lpModeInfo[ pddd->dwModeIndex ].dwRBitMask = pddd->vmiData.ddpfDisplay.dwRBitMask;
pddd->lpModeInfo[ pddd->dwModeIndex ].dwGBitMask = pddd->vmiData.ddpfDisplay.dwGBitMask;
pddd->lpModeInfo[ pddd->dwModeIndex ].dwBBitMask = pddd->vmiData.ddpfDisplay.dwBBitMask;
}
DPF(5, "Setting the bitmasks for the driver (R:%04lx G:%04lx B:%04lx)",
pddd->vmiData.ddpfDisplay.dwRBitMask,
pddd->vmiData.ddpfDisplay.dwGBitMask,
pddd->vmiData.ddpfDisplay.dwBBitMask);
}
}
else
#else
/*
* Grab masks from NT driver
*/
pddd->vmiData.ddpfDisplay.dwRBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwRBitMask;
pddd->vmiData.ddpfDisplay.dwGBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwGBitMask;
pddd->vmiData.ddpfDisplay.dwBBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwBBitMask;
if( 0xFFFFFFFFUL != pddd->dwModeIndex )
{
pddd->lpModeInfo[ pddd->dwModeIndex ].dwRBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwRBitMask;
pddd->lpModeInfo[ pddd->dwModeIndex ].dwGBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwGBitMask;
pddd->lpModeInfo[ pddd->dwModeIndex ].dwBBitMask = lpDDHALInfo->vmiData.ddpfDisplay.dwBBitMask;
}
DPF(5, "Setting the bitmasks for the driver (R:%04lx G:%04lx B:%04lx)",
pddd->vmiData.ddpfDisplay.dwRBitMask,
pddd->vmiData.ddpfDisplay.dwGBitMask,
pddd->vmiData.ddpfDisplay.dwBBitMask);
#endif
{
if( !reset )
{
pddd->dwPDevice = 0;
pddd->lpwPDeviceFlags = (WORD *)&dwFakeFlags;
}
}
/*
* fourcc codes...
*/
MemFree( pddd->lpdwFourCC );
pddd->lpdwFourCC = NULL;
if (oldpdd != NULL)
{
oldpdd->lpdwFourCC = NULL;
}
pddd->ddCaps.dwNumFourCCCodes = lpDDHALInfo->ddCaps.dwNumFourCCCodes;
pddd->dwNumFourCC = pddd->ddCaps.dwNumFourCCCodes;
if( pddd->ddCaps.dwNumFourCCCodes > 0 )
{
size = pddd->ddCaps.dwNumFourCCCodes * sizeof( DWORD );
pddd->lpdwFourCC = MemAlloc( size );
if( pddd->lpdwFourCC == NULL )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate FOURCC data!" );
goto ErrorExit;
}
memcpy( pddd->lpdwFourCC, lpDDHALInfo->lpdwFourCC, size );
}
/*
* Extended 3D caps structure
*
*/
if ( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET )
{
HRESULT ret;
DDHAL_GETDRIVERINFODATA gdidata;
if (oldpdd != NULL)
{
oldpdd->lpD3DExtendedCaps = 0;
}
if (! pddd->lpD3DExtendedCaps)
{
pddd->lpD3DExtendedCaps = MemAlloc( D3DHAL_D3DEXTENDEDCAPSSIZE );
}
if (! pddd->lpD3DExtendedCaps)
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not allocate D3D extended caps structure" );
}
else
{
memset( (LPVOID) pddd->lpD3DExtendedCaps, 0, D3DHAL_D3DEXTENDEDCAPSSIZE );
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo,
&gdidata,
(LPVOID) pddd->lpD3DExtendedCaps,
D3DHAL_D3DEXTENDEDCAPSSIZE,
&GUID_D3DExtendedCaps,
pddd,
FALSE /* bInOut */);
if (ret != DD_OK)
{
DPF ( 2,"D3D Extended Caps query failed" );
MemFree( (LPVOID) pddd->lpD3DExtendedCaps );
pddd->lpD3DExtendedCaps = 0;
}
}
// Extended caps was not compulsory for pre-DX6 drivers.
// Extended caps is compulsory for DX6+ drivers since it contains
// information about the driver's multitexture capabilities, FVF
// support and stencil support.
if (pddd->lpD3DHALCallbacks3->DrawPrimitives2)
{
if (pddd->lpD3DExtendedCaps == NULL)
{
DPF_ERR ( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:DX6+ drivers should report D3D Extended Caps, failing driver creation" );
goto ErrorExit;
}
else if (gdidata.dwActualSize != pddd->lpD3DExtendedCaps->dwSize)
{
DPF_ERR ( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Actual size reported is not equal to dwSize field in the Extended caps structure" );
goto ErrorExit;
}
else if (pddd->lpD3DExtendedCaps->dwSize < D3DHAL_D3DDX6EXTENDEDCAPSSIZE)
{
DPF_ERR ( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Driver reported insufficient D3D Extended Caps, failing driver creation" );
goto ErrorExit;
}
// If stencil capabilities are reported the driver should have
// exported Clear2
if (pddd->lpD3DExtendedCaps->dwStencilCaps != 0)
{
if ((pddd->lpD3DHALCallbacks3->Clear2 == NULL) &&
(0 == pddd->lpDDCBtmp->HALDDMiscellaneous2.GetDriverState)
)
{
DPF_ERR ( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Pre DX7 Driver should report clear2 if any stencilcaps are set, failing driver creation" );
goto ErrorExit;
}
}
}
}
else // Driver doesn't have DDHALINFO_GETDRIVERINFOSET
{
if (pddd->lpD3DExtendedCaps)
{
memset( (LPVOID) pddd->lpD3DExtendedCaps, 0, D3DHAL_D3DEXTENDEDCAPSSIZE );
if (oldpdd)
{
oldpdd->lpD3DExtendedCaps = NULL;
}
}
}
if (lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFO2)
{
pddd->dwFlags |= DDRAWI_DRIVERINFO2;
}
/*
* video port descriptions
*/
if ( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET )
{
MemFree( pddd->lpDDVideoPortCaps );
pddd->lpDDVideoPortCaps = NULL;
if (oldpdd != NULL)
{
oldpdd->lpDDVideoPortCaps = NULL;
}
pddd->ddCaps.dwMaxVideoPorts = lpDDHALInfo->ddCaps.dwMaxVideoPorts;
if( pddd->ddCaps.dwMaxVideoPorts > 0 )
{
HRESULT ret;
DDHAL_GETDRIVERINFODATA gdidata;
size = pddd->ddCaps.dwMaxVideoPorts * sizeof( DDVIDEOPORTCAPS );
pddd->lpDDVideoPortCaps = MemAlloc( size );
if( pddd->lpDDVideoPortCaps == NULL )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate video port caps!" );
goto ErrorExit;
}
memset( pddd->lpDDVideoPortCaps, 0, size );
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo,
&gdidata,
pddd->lpDDVideoPortCaps,
size,
&GUID_VideoPortCaps, pddd,
FALSE /* bInOut */);
if (ret != DD_OK)
{
DPF ( 2,"VideoPortCaps query failed" );
MemFree(pddd->lpDDVideoPortCaps);
pddd->lpDDVideoPortCaps = NULL;
}
}
}
/*
* Kernel mode capabilities
*
* We only get these once we munge them when creating the driver
* object and we don't want to munge them everytime. We do need
* to munge the video port caps, however, to reflect the autoflip
* capabilities.
*/
if ( lpDDHALInfo->dwFlags & DDHALINFO_GETDRIVERINFOSET )
{
if (pddd->lpDDKernelCaps == NULL)
{
HRESULT ret;
DDHAL_GETDRIVERINFODATA gdidata;
size = sizeof( DDKERNELCAPS );
pddd->lpDDKernelCaps = MemAlloc( size );
if( pddd->lpDDKernelCaps == NULL )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate kernel caps!" );
goto ErrorExit;
}
memset( pddd->lpDDKernelCaps, 0, size );
ret = GetDriverInfo(lpDDHALInfo->GetDriverInfo,
&gdidata,
pddd->lpDDKernelCaps,
size,
&GUID_KernelCaps, pddd,
FALSE /* bInOut */);
#ifdef WIN95
if( !IsWindows98() )
{
ret = DDERR_GENERIC;
}
#endif
if (ret != DD_OK)
{
DPF ( 2, "KernelCaps query failed" );
MemFree(pddd->lpDDKernelCaps);
pddd->lpDDKernelCaps = NULL;
}
}
#ifdef WIN95
else
{
MungeAutoflipCaps(pddd);
}
#endif
}
/*
* fill in rops
*/
if( lpDDHALInfo->ddCaps.dwCaps & DDCAPS_BLT )
{
for( i=0;i<DD_ROP_SPACE;i++ )
{
pddd->ddCaps.dwRops[i] = lpDDHALInfo->ddCaps.dwRops[i];
}
}
/*
* get (or generate) the non-local video memory caps.
*/
MemFree( pddd->lpddNLVCaps );
pddd->lpddNLVCaps = NULL;
if (oldpdd != NULL)
{
oldpdd->lpddNLVCaps = NULL;
}
if( !GetNonLocalVidMemCaps( lpDDHALInfo, pddd ) )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not initialize non-local video memory caps" );
goto ErrorExit;
}
/*
* Get the driver's extended capabilities.
*/
if( !GetDDMoreCaps( lpDDHALInfo, pddd ) )
{
// An error occurred during GetDDMoreCaps() call above.
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not initialize extended caps" );
goto ErrorExit;
}
/*
* Direct3D data structures
*/
//#ifdef WINNT
// MemFree((void *)pddd->lpD3DHALCallbacks);
//#endif
if( lpDDHALInfo->dwSize >= DDHALINFOSIZE_V2 )
{
// Direct3D data is present
pddd->lpD3DGlobalDriverData = lpDDHALInfo->lpD3DGlobalDriverData;
pddd->lpD3DHALCallbacks = lpDDHALInfo->lpD3DHALCallbacks;
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 5, "DDHALInfo contains D3D pointers: 0x%p 0x%p", pddd->lpD3DGlobalDriverData, pddd->lpD3DHALCallbacks);
}
else
{
// No Direct3D data present in DDHALInfo
pddd->lpD3DGlobalDriverData = 0;
pddd->lpD3DHALCallbacks = 0;
DPF( 1, "No Direct3D Support in driver");
}
freevm = 0;
#ifndef WINNT
/*
* NT kernel does the memory management now
*/
MemFree( pddd->vmiData.pvmList );
pddd->vmiData.pvmList = NULL;
if (oldpdd != NULL)
{
oldpdd->vmiData.pvmList = NULL;
}
if( pddd->vmiData.dwNumHeaps > 0 )
{
size = sizeof( VIDMEM ) * pddd->vmiData.dwNumHeaps;
pddd->vmiData.pvmList = MemAlloc( size );
if( pddd->vmiData.pvmList == NULL )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Insufficient memory to allocate heap info!" );
goto ErrorExit;
}
}
devheapno = 0;
for( i=0;i<(int)lpDDHALInfo->vmiData.dwNumHeaps;i++ )
{
/*
* Ask driver for any additional heap alignment requirements
*/
DDHAL_GETHEAPALIGNMENTDATA ghad;
LPHEAPALIGNMENT pghad=0;
/*
* pghad will be null if no alignment
*/
pghad = GetExtendedHeapAlignment(pddd, &ghad, i );
if( !( lpDDHALInfo->vmiData.pvmList[i].dwFlags & VIDMEM_ISNONLOCAL ) || isagpaware )
{
DWORD dwHeapFlags;
pvm = &(pddd->vmiData.pvmList[devheapno]);
*pvm = lpDDHALInfo->vmiData.pvmList[i];
dwHeapFlags = 0UL;
/*
* if a heap is specified, then we don't need to allocate
* one ourselves (for shared media devices)
*/
if( !(pvm->dwFlags & VIDMEM_ISHEAP) )
{
#ifdef DEBUG
if( pvm->dwFlags & VIDMEM_ISLINEAR )
{
int vram = GetProfileInt("DirectDraw", "vram", -1);
if (vram > 0 && (pvm->fpStart + vram*1024L-1) < pvm->fpEnd)
{
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 1, "pretending display card has only %dk VRAM", vram);
DPF( 1, "pvm->fpStart = 0x%p, pvm->fpEnd = 0x%p", pvm->fpStart, pvm->fpEnd );
pvm->fpEnd = pvm->fpStart + vram*1024L-1;
}
}
#endif
DPF(5,V,"Heap #%d is 0x%08x x 0x%08x",devheapno,pvm->dwWidth,pvm->dwHeight);
if ( ! HeapVidMemInit( pvm, pddd->vmiData.lDisplayPitch, hDDVxd , pghad ) )
{
pvm->lpHeap = NULL;
/*
* If this is an AGP heap, we probably failed because we couldn't reserve
* any AGP memory. This this case, we simply want to remove the heap
* rather than fail to emulation. We do not want to remove the AGP
* caps, however, since some drivers (e.g. nVidia) can allocate it
* without using our heap.
*/
if( pvm->dwFlags & VIDMEM_ISNONLOCAL )
{
/*
* At this time, dwNumHeaps should always be greater than 0,
* but I added the check anyway in case something changes later.
*/
if( pddd->vmiData.dwNumHeaps > 0 )
{
if( --pddd->vmiData.dwNumHeaps == 0 )
{
MemFree( pddd->vmiData.pvmList );
pddd->vmiData.pvmList = NULL;
}
}
continue;
}
}
}
if( pvm->lpHeap == NULL )
{
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not create video memory heap!" );
for( j=0;j<devheapno;j++ )
{
pvm = &(pddd->vmiData.pvmList[j]);
HeapVidMemFini( pvm, hDDVxd );
}
goto ErrorExit;
}
freevm += VidMemAmountFree( pvm->lpHeap );
devheapno++;
}
else
{
/*
* This is an AGP memory heap but the operating system
* does not have the necessary AGP extensions. Discard
* this heap descriptor.
*/
DPF( 1, "Discarding AGP heap %d. OS does not have AGP support", i );
}
}
#endif //not WINNT
pddd->ddCaps.dwVidMemTotal = freevm;
/*
* Grab any extended surface caps and heap restrictions from the driver
*/
if( !GetDDMoreSurfaceCaps( lpDDHALInfo, pddd ) )
{
// An error occurred during GetDDMoreCaps() call above.
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not initialize extended surface caps" );
goto ErrorExit;
}
/*
* Differences between win95 and NT HAL setup.
* On Win95, the 32bit entry points (DDHALCALLBACKS.DDHAL...) are reset to point to the
* helper functions inside w95hal.c, and only overwritten (with what comes in in the
* DDHALINFO structure from the driver) if the corresponding bit is set in the DDHALINFO's
* lpDD*...dwFlags coming in from the driver.
* On NT, there's no thunking, so the only use for the pointers stored in the
* DDHALCALLBACKS.cb... entries is deciding if there's a HAL function pointer before
* doing a HALCALL. Since the 32 bit callbacks are not initialized to point
* to the w95hal.c stubs, we zero them out before copying the individual driver callbacks
* one by one.
*/
/*
* set up driver HAL
*/
#ifdef WIN95
//Initialise HAL to 32-bit stubs in w95hal.c:
pddd->lpDDCBtmp->HALDD = ddHALDD;
#else
memset(&pddd->lpDDCBtmp->HALDD,0,sizeof(pddd->lpDDCBtmp->HALDD));
#endif
drvcb = lpDDHALInfo->lpDDCallbacks;
if( drvcb != NULL )
{
numcb = NUM_CALLBACKS( drvcb );
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF(5,"DDHal callback flags:%08x",drvcb->dwFlags);
for (i=0;i<numcb;i++) DPF(5," 0x%p",(&drvcb->DestroyDriver)[i]);
bit = 1;
for( i=0;i<numcb;i++ )
{
if( drvcb->dwFlags & bit )
{
// 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
(&pddd->lpDDCBtmp->HALDD.DestroyDriver)[i] = (&drvcb->DestroyDriver)[i];
}
bit <<= 1;
}
}
/*
* set up surface HAL
*/
#ifdef WIN95
pddd->lpDDCBtmp->HALDDSurface = ddHALDDSurface;
#else
memset(&pddd->lpDDCBtmp->HALDDSurface,0,sizeof(pddd->lpDDCBtmp->HALDDSurface));
#endif
surfcb = lpDDHALInfo->lpDDSurfaceCallbacks;
if( surfcb != NULL )
{
numcb = NUM_CALLBACKS( surfcb );
bit = 1;
for( i=0;i<numcb;i++ )
{
if( surfcb->dwFlags & bit )
{
// 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
(&pddd->lpDDCBtmp->HALDDSurface.DestroySurface)[i] = (&surfcb->DestroySurface)[i];
}
bit <<= 1;
}
}
/*
* set up palette callbacks
*/
#ifdef WIN95
pddd->lpDDCBtmp->HALDDPalette = ddHALDDPalette;
#else
memset (&pddd->lpDDCBtmp->HALDDPalette,0,sizeof(pddd->lpDDCBtmp->HALDDPalette));
#endif
palcb = lpDDHALInfo->lpDDPaletteCallbacks;
if( palcb != NULL )
{
numcb = NUM_CALLBACKS( palcb );
bit = 1;
for( i=0;i<numcb;i++ )
{
if( palcb->dwFlags & bit )
{
// 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
(&pddd->lpDDCBtmp->HALDDPalette.DestroyPalette)[i] = (&palcb->DestroyPalette)[i];
}
bit <<= 1;
}
}
/*
* set up execute buffer callbacks
* NOTE: Need explicit check for V2 driver as V1 driver knows nothing
* about these. For an old driver the default HAL callback table will
* be used unmodified.
*/
#ifdef WIN95
pddd->lpDDCBtmp->HALDDExeBuf = ddHALDDExeBuf;
#endif
if( lpDDHALInfo->dwSize >= DDHALINFOSIZE_V2 )
{
exebufcb = lpDDHALInfo->lpDDExeBufCallbacks;
if( exebufcb != NULL )
{
numcb = NUM_CALLBACKS( exebufcb );
bit = 1;
for( i=0;i<numcb;i++ )
{
if( exebufcb->dwFlags & bit )
{
// 5/24/2000(RichGr): IA64: Remove (DWORD FAR*) casts from pointer assignment.
(&pddd->lpDDCBtmp->HALDDExeBuf.CanCreateExecuteBuffer)[i] = (&exebufcb->CanCreateExecuteBuffer)[i];
}
bit <<= 1;
}
}
}
/*
* make sure we wipe out old callbacks!
*/
memset( &pddd->lpDDCBtmp->cbDDCallbacks, 0, sizeof( pddd->lpDDCBtmp->cbDDCallbacks ) );
memset( &pddd->lpDDCBtmp->cbDDSurfaceCallbacks, 0, sizeof( pddd->lpDDCBtmp->cbDDSurfaceCallbacks ) );
memset( &pddd->lpDDCBtmp->cbDDPaletteCallbacks, 0, sizeof( pddd->lpDDCBtmp->cbDDPaletteCallbacks ) );
memset( &pddd->lpDDCBtmp->cbDDExeBufCallbacks, 0, sizeof( pddd->lpDDCBtmp->cbDDExeBufCallbacks ) );
/*
* copy callback routines
*/
if( lpDDHALInfo->lpDDCallbacks != NULL )
{
memcpy( &pddd->lpDDCBtmp->cbDDCallbacks, lpDDHALInfo->lpDDCallbacks,
(UINT) lpDDHALInfo->lpDDCallbacks->dwSize );
}
if( lpDDHALInfo->lpDDSurfaceCallbacks != NULL )
{
memcpy( &pddd->lpDDCBtmp->cbDDSurfaceCallbacks, lpDDHALInfo->lpDDSurfaceCallbacks,
(UINT) lpDDHALInfo->lpDDSurfaceCallbacks->dwSize );
}
if( lpDDHALInfo->lpDDPaletteCallbacks != NULL )
{
memcpy( &pddd->lpDDCBtmp->cbDDPaletteCallbacks, lpDDHALInfo->lpDDPaletteCallbacks,
(UINT) lpDDHALInfo->lpDDPaletteCallbacks->dwSize );
}
if( ( lpDDHALInfo->dwSize >= DDHALINFOSIZE_V2 ) &&
( lpDDHALInfo->lpDDExeBufCallbacks != NULL ) )
{
memcpy( &pddd->lpDDCBtmp->cbDDExeBufCallbacks, lpDDHALInfo->lpDDExeBufCallbacks,
(UINT) lpDDHALInfo->lpDDExeBufCallbacks->dwSize );
}
#ifndef WIN95
if (pddd->lpDDCBtmp->HALDDNT.SetExclusiveMode)
{
pddd->lpDDCBtmp->HALDD.SetExclusiveMode =
pddd->lpDDCBtmp->cbDDCallbacks.SetExclusiveMode =
pddd->lpDDCBtmp->HALDDNT.SetExclusiveMode;
}
if (pddd->lpDDCBtmp->HALDDNT.FlipToGDISurface)
{
pddd->lpDDCBtmp->HALDD.FlipToGDISurface =
pddd->lpDDCBtmp->cbDDCallbacks.FlipToGDISurface =
pddd->lpDDCBtmp->HALDDNT.FlipToGDISurface;
}
#endif
/*
* init shared caps
*/
capsInit( pddd );
mergeHELCaps( pddd );
/*
* if we were asked to reset, keep the new data
*/
if( reset )
{
/*
* copy new structure onto original one
* being careful to preserve lpDDCB
*/
{
LPDDHAL_CALLBACKS save_ptr = oldpdd->lpDDCBtmp;
memcpy( oldpdd, pddd, drv_callbacks_size );
oldpdd->lpDDCBtmp = save_ptr;
}
MemFree( pddd );
pddd = oldpdd;
}
}
else
{
DPF( 4, "Driver object already exists" );
#ifdef DEBUG
/*
* pddd is now allocated at the top of the routine, before the if that goes
* with the preceding else... jeffno 960115
*/
if (pddd)
{
DPF(4,"Allocated space for a driver object when it wasn't necessary!");
}
#endif
MemFree(pddd); //should be NULL, just in case...
pddd = oldpdd;
}
/*
* set bank switched
*/
if( pddd->dwFlags & DDRAWI_DISPLAYDRV )
{
HDC hdc;
hdc = DD_CreateDC( szDrvName );
if( DCIIsBanked( hdc ) ) //NT_FIX??
{
pddd->ddCaps.dwCaps |= DDCAPS_BANKSWITCHED;
DPF( 2, "Setting DDCAPS_BANKSWITCHED" );
}
else
{
pddd->ddCaps.dwCaps &= ~DDCAPS_BANKSWITCHED;
DPF( 2, "NOT Setting DDCAPS_BANKSWITCHED" );
}
DD_DoneDC( hdc );
/*
* Display drivers can all render windowed
*/
//BEGIN VOODOO2 HACK
if ( (0 == (dwRegFlags & DDRAW_REGFLAGS_ENUMERATEATTACHEDSECONDARIES)) ||
(IsVGADevice( szDrvName )) )
//END VOODOO2 HACK
{
pddd->ddCaps.dwCaps2 |= DDCAPS2_CANRENDERWINDOWED;
}
}
InitGamma( pddd, szDrvName );
/*
* Disable non-local video memory if the operating system
* is not AGP aware.
*/
if( ( pddd->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM ) && !isagpaware )
{
DPF( 2, "OS is not AGP aware. Disabling DDCAPS2_NONLOCALVIDMEM" );
pddd->ddCaps.dwCaps2 &= ~DDCAPS2_NONLOCALVIDMEM;
}
if( !( pddd->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM ))
{
if (lpDDHALInfo->lpD3DGlobalDriverData && (lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps & D3DDEVCAPS_TEXTURENONLOCALVIDMEM))
{ //some drivers(Riva128 on PCI) incorrectly sets D3DDEVCAPS_TEXTURENONLOCALVIDMEM
DPF( 1, "driver set D3DDEVCAPS_TEXTURENONLOCALVIDMEM w/o DDCAPS2_NONLOCALVIDMEM:turning off D3DDEVCAPS_TEXTURENONLOCALVIDMEM" );
lpDDHALInfo->lpD3DGlobalDriverData->hwCaps.dwDevCaps &= ~D3DDEVCAPS_TEXTURENONLOCALVIDMEM;
}
}
#ifdef USE_ALIAS
/*
* Can we use VRAM aliasing and PDEVICE modification to avoid taking
* the Win16 lock when locking a VRAM surface? Can't if the device is
* bankswitched or if the DIB Engine is not a version we recognize.
*/
if (!(lpDDHALInfo->ddCaps.dwCaps & DDCAPS_NOHARDWARE))
{
if( ( pddd->dwFlags & DDRAWI_DISPLAYDRV ) &&
( ( pddd->ddCaps.dwCaps & DDCAPS_BANKSWITCHED ) || ( !DD16_FixupDIBEngine() ) ) )
{
pddd->dwFlags |= DDRAWI_NEEDSWIN16FORVRAMLOCK;
DPF( 2, "Win16 lock must be taken for VRAM locks" );
}
else
{
pddd->dwFlags &= ~DDRAWI_NEEDSWIN16FORVRAMLOCK;
DPF( 2, "Taking the Win16 lock may not be necessary for VRAM locks" );
}
/*
* Create the virtual memory heap aliases for this global object
*/
if( ( pddd->dwFlags & DDRAWI_DISPLAYDRV ) &&
!( pddd->dwFlags & DDRAWI_NEEDSWIN16FORVRAMLOCK ) )
{
DDASSERT( INVALID_HANDLE_VALUE != hDDVxd );
if( FAILED( CreateHeapAliases( hDDVxd, pddd ) ) )
{
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Could not create the heap aliases for driver object 0x%p", pddd );
goto ErrorExit;
}
}
}
#endif /* USE_ALIAS */
#ifdef WIN95
/*
* If we have a driver which has AGP support and which has provided us with a
* notification callback so that we can tell it the GART linear and physical
* addresses of the heaps it provided to us then invoke that callback now
* for the non-local heaps we initialized.
*/
if( (NULL != pddd) && (pddd->ddCaps.dwCaps2 & DDCAPS2_NONLOCALVIDMEM) )
{
LPDDHAL_UPDATENONLOCALHEAP unlhfn;
DDHAL_UPDATENONLOCALHEAPDATA unlhd;
LPVIDMEM lpHeap;
DWORD rc;
unlhfn = pddd->lpDDCBtmp->HALDDMiscellaneous.UpdateNonLocalHeap;
if( NULL != unlhfn )
{
unlhd.lpDD = pddd;
unlhd.ulPolicyMaxBytes = dwAGPPolicyMaxBytes;
unlhd.ddRVal = DDERR_GENERIC; /* Force the driver to return something sensible */
unlhd.UpdateNonLocalHeap = NULL;
for( i = 0; i < (int)pddd->vmiData.dwNumHeaps; i++ )
{
lpHeap = &pddd->vmiData.pvmList[i];
if( lpHeap->dwFlags & VIDMEM_ISNONLOCAL )
{
DPF( 4, "Notifying driver of update to non-local heap %d", i );
unlhd.dwHeap = i;
unlhd.fpGARTLin = lpHeap->lpHeap->fpGARTLin;
unlhd.fpGARTDev = lpHeap->lpHeap->fpGARTDev;
DOHALCALL( UpdateNonLocalHeap, unlhfn, unlhd, rc, FALSE );
/*
* Currently this callback is pure notification. The driver
* cannot fail it.
*/
DDASSERT( DDHAL_DRIVER_HANDLED == rc );
DDASSERT( DD_OK == unlhd.ddRVal );
}
}
}
}
#endif
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 5, "DirectDrawObjectCreate: Returning global object 0x%p", pddd );
#ifdef WINNT
MemFree(lpDDHALInfo->lpdwFourCC);
MemFree(lpDDHALInfo->vmiData.pvmList);
#endif
LEAVE_DDRAW();
return pddd;
ErrorExit:
// We must not free memory in the reset path, since the oldpdd will survive this
// call to DirectDrawObjectCreate, and be freed by IDD::Release sometime later.
// We will not NULL out all these ptrs either, since that would invite a bazillion
// stress failures elsewhere in the code. We will leave the ptrs valid, but set
// DDUNSUPPORTEDMODE in the mode index, both to throttle further usage of this ddraw
// global (which now is full of caps etc. from the wrong mode) and as an indicator
// that this is what happened in future stress investigations.
// We are also going to wimp out and change only the NT path.
if (pddd
#ifdef WINNT
&& !reset
#endif
)
{
MemFree( pddd->lpDDVideoPortCaps );
MemFree( pddd->lpddNLVCaps );
MemFree( pddd->lpddNLVHELCaps );
MemFree( pddd->lpddNLVBothCaps );
MemFree( pddd->lpD3DHALCallbacks2 );
MemFree( pddd->lpD3DHALCallbacks3 );
MemFree( pddd->lpZPixelFormats );
MemFree( pddd->lpddMoreCaps );
MemFree( pddd->lpddHELMoreCaps );
MemFree( pddd->lpddBothMoreCaps );
#ifdef POSTPONED
MemFree( pddd->lpDDOptSurfaceInfo );
MemFree( pddd->lpDDUmodeDrvInfo );
#endif //POSTPONED
#ifdef WINNT
if (pddd->hDD != 0)
{
// Delete the object if not resetting. If we were just resetting
// we should not delete it as it may work later; the call to
// enable or query the DirectDraw object may have failed because
// the system is displaying the logon desktop, or is in 4 bpp or
// another unsupported mode.
if (!reset)
{
DdDeleteDirectDrawObject(pddd);
}
}
#endif //WINNT
MemFree( pddd );
}
#ifdef WINNT
if (reset && pddd)
{
pddd->dwModeIndex = DDUNSUPPORTEDMODE;
}
MemFree(lpDDHALInfo->lpdwFourCC);
MemFree(lpDDHALInfo->vmiData.pvmList);
if (ismemalloced && !reset)
{
MemFree(pd3dNTHALCallbacks);
}
#endif
LEAVE_DDRAW();
return NULL;
} /* DirectDrawObjectCreate */
#pragma message( REMIND( "I'm drowning in a sea of ancient unfixed pragma reminders" ) )
/*
* CleanUpD3DHAL
*
* Notify the Direct3D driver using the ContextDestroyAll callbacks
* that the given process has died so that it may cleanup any context
* associated with that process.
*
* NOTE: This function is only invoked if we have Direct3D
* support in the DirectDraw driver and if the process
* terminates without cleaning up normally.
*
* I would call the ContextDestroyAll callback directly from here
* instead of through this convoluted exported fn, but d3dhal.h
* can't be included here because of the dependencies.
*/
void CleanUpD3DHAL(LPD3DHAL_CALLBACKS lpD3DHALCallbacks, DWORD pid, LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl)
{
D3DHALCleanUpProc lpD3DHALCleanUpProc;
HINSTANCE hD3DInstance;
if (DDRAWILCL_DIRECTDRAW7 & pdrv_lcl->dwLocalFlags)
{
hD3DInstance = LoadLibrary( D3DDX7_DLLNAME );
DPF(4,"Calling %s in %s",D3DHALCLEANUP_PROCNAME,D3DDX7_DLLNAME);
}
else
{
hD3DInstance = LoadLibrary( D3D_DLLNAME );
DPF(4,"Calling %s in %s",D3DHALCLEANUP_PROCNAME,D3D_DLLNAME);
}
// Attempt to locate the cleanup entry point.
if (0 != hD3DInstance)
{
lpD3DHALCleanUpProc = (D3DHALCleanUpProc)GetProcAddress( hD3DInstance,
D3DHALCLEANUP_PROCNAME );
if( NULL == lpD3DHALCleanUpProc )
{
// this is really either an internal error, or d3dim.dll is suddenly missing
DPF(0,"Error: can't find cleanup entry point %s in %s, driver's 3D resources won't be freed",D3DHALCLEANUP_PROCNAME,D3D_DLLNAME);
}
else
{
(*lpD3DHALCleanUpProc)( lpD3DHALCallbacks, pid );
}
FreeLibrary(hD3DInstance);
}
}
#ifdef WIN95
/*
* CurrentProcessCleanup
*
* make sure terminating process cleans up after itself...
*/
BOOL CurrentProcessCleanup( BOOL was_term )
{
DWORD pid;
LPDDRAWI_DIRECTDRAW_INT pdrv_int;
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
LPDDRAWI_DIRECTDRAW_INT pdrv_link_int;
BOOL rc;
BOOL fD3DCleanedUp;
ENTER_DDRAW();
pid = GETCURRPID();
pdrv_int = lpDriverObjectList;
rc = FALSE;
fD3DCleanedUp = FALSE;
/*
* run through each driver, looking for the current process handle
* Delete all local objects created by this process.
*/
while( pdrv_int != NULL )
{
pdrv_link_int = pdrv_int->lpLink;
/*
* if we find the process, release it and remove it from list
*/
pdrv_lcl = pdrv_int->lpLcl;
if( pdrv_lcl->dwProcessId == pid )
{
DWORD refcnt;
pdrv = pdrv_lcl->lpGbl;
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 4, "Process %08lx still attached to driver 0x%p", pid, pdrv_int );
DPF( 5, " Refcnt = %ld", pdrv_int->dwIntRefCnt );
if( pdrv != NULL )
{
DPF( 5, " DRV Refcnt = %ld", pdrv->dwRefCnt );
}
// Clean up DX8
#ifdef WIN95
CleanupD3D8( pdrv, TRUE, pid);
#endif
rc = TRUE;
/*
* D3D uses a bogus DDraw interface to create surfaces, which
* means that we AddRef the LCL and GBL, but since the INT is
* not in the lpDriverObjectList, we never release them. The
* result is that LCL/GBLs are never released and this causes
* lots of problems (for example, we don't call DonExclusiveMode
* to turn off the 3DFX pass through). If the process cleans up
* correctly, so does D3D, but if we cleanup on DDHELPs thread,
* D3D has already been unloaded. The work-around is to
* determine if this is the last INT referncing the LCL and if
* the ref counts don't match, make the INT re count match the LCL.
*/
if( dwHelperPid == GetCurrentProcessId() )
{
LPDDRAWI_DIRECTDRAW_INT pTemp_int;
pTemp_int = lpDriverObjectList;
while( pTemp_int != NULL )
{
if( ( pTemp_int != pdrv_int ) &&
( pTemp_int->lpLcl == pdrv_lcl ) )
{
break;
}
pTemp_int = pTemp_int->lpLink;
}
if( pTemp_int == NULL )
{
pdrv_int->dwIntRefCnt = pdrv_lcl->dwLocalRefCnt;
}
}
/*
* punt process from any surfaces and palettes
*/
if( pdrv != NULL )
{
#ifdef POSTPONED2
ProcessSpriteCleanup( pdrv, pid ); // master sprite list
#endif //POSTPONED2
ProcessSurfaceCleanup( pdrv, pid, NULL );
ProcessPaletteCleanup( pdrv, pid, NULL );
ProcessClipperCleanup( pdrv, pid, NULL );
ProcessVideoPortCleanup( pdrv, pid, NULL );
}
/*
* Has the process terminated and a Direct3D driver
* object been queried off this driver object?
*/
if( was_term && ( pdrv_lcl->pD3DIUnknown != NULL ) )
{
/*
* Yes... so we need to do two things:
*
* 1) Simply discard the IUnknown interface pointer
* for the Direct3D object as that object is now
* gone (it was allocated by a local DLL in a
* local heap of a process that is now gone).
*
* 2) If we have hardware 3D support and we have not
* yet notified the driver of the death of this
* process tell it now.
*/
DPF( 4, "Discarding Direct3D interface - process terminated" );
pdrv_lcl->pD3DIUnknown = NULL;
if( ( pdrv->lpD3DHALCallbacks != NULL ) && !fD3DCleanedUp )
{
DPF( 4, "Notifying Direct3D driver of process termination" );
CleanUpD3DHAL( pdrv->lpD3DHALCallbacks, pid, pdrv_lcl);
fD3DCleanedUp = TRUE;
}
}
/*
* now release the driver object
* If exclusive mode was held by this process, it will
* be relinquished when the local object is deleted.
*/
refcnt = pdrv_int->dwIntRefCnt;
while( refcnt > 0 )
{
DD_Release( (LPDIRECTDRAW) pdrv_int );
refcnt--;
}
}
/*
* go to the next driver
*/
pdrv_int = pdrv_link_int;
}
/*
* Release driver independent clippers owned by this process.
*/
ProcessClipperCleanup( NULL, pid, NULL );
/*
* Remove any process entries from the window list. They could be left
* around if the window was subclassed.
*/
CleanupWindowList( pid );
LEAVE_DDRAW();
DPF( 4, "Done with CurrentProcessCleanup, rc = %d", rc);
return rc;
} /* CurrentProcessCleanup */
#endif //WIN95
/*
* RemoveDriverFromList
*
* remove driver object from linked list of driver objects.
* assumes DirectDraw lock is taken.
*/
void RemoveDriverFromList( LPDDRAWI_DIRECTDRAW_INT lpDD_int, BOOL final )
{
LPDDRAWI_DIRECTDRAW_INT pdrv_int;
LPDDRAWI_DIRECTDRAW_INT pdlast_int;
ENTER_DRIVERLISTCSECT();
pdrv_int = lpDriverObjectList;
pdlast_int = NULL;
while( pdrv_int != NULL )
{
if( pdrv_int == lpDD_int )
{
if( pdlast_int == NULL )
{
lpDriverObjectList = pdrv_int->lpLink;
}
else
{
pdlast_int->lpLink = pdrv_int->lpLink;
}
break;
}
pdlast_int = pdrv_int;
pdrv_int = pdrv_int->lpLink;
}
#ifdef DEBUG
if( pdrv_int == NULL )
{
DPF( 3, "ERROR!! Could not find driver in global object list" );
}
#endif
LEAVE_DRIVERLISTCSECT();
} /* RemoveDriverFromList */
/*
* RemoveLocalFromList
*
* remove local object from linked list of local objects.
* assumes DirectDraw lock is taken.
*/
void RemoveLocalFromList( LPDDRAWI_DIRECTDRAW_LCL this_lcl )
{
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDRAWI_DIRECTDRAW_LCL pdlast_lcl;
ENTER_DRIVERLISTCSECT();
pdrv_lcl = lpDriverLocalList;
pdlast_lcl = NULL;
while( pdrv_lcl != NULL )
{
if( pdrv_lcl == this_lcl )
{
if( pdlast_lcl == NULL )
{
lpDriverLocalList = pdrv_lcl->lpLink;
}
else
{
pdlast_lcl->lpLink = pdrv_lcl->lpLink;
}
break;
}
pdlast_lcl = pdrv_lcl;
pdrv_lcl = pdrv_lcl->lpLink;
}
#ifdef DEBUG
if( pdrv_lcl == NULL )
{
DPF( 3, "ERROR!! Could not find driver local in global list" );
}
#endif
LEAVE_DRIVERLISTCSECT();
} /* RemoveLocalFromList */
/*
* doneDC
*/
void DD_DoneDC( HDC hdc_dd )
{
if( hdc_dd != NULL )
{
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 5, "DeleteDC 0x%p", hdc_dd );
DeleteDC( hdc_dd );
hdc_dd = NULL;
}
} /* doneDC */
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawCreate"
// prototype for helinit
BOOL HELInit( LPDDRAWI_DIRECTDRAW_GBL pdrv, BOOL helonly );
/*
* helInit
*/
BOOL helInit( LPDDRAWI_DIRECTDRAW_GBL pdrv, DWORD dwFlags, BOOL hel_only )
{
if( (dwFlags & DDCREATE_HARDWAREONLY) )
{
return TRUE;
}
/*
* get the HEL to fill in details:
*
* - dwHELDriverCaps
* - dwHELStretchDriverCaps
* - dwHELRopsSupported
* - ddsHELCaps
* - HELDD
* - HELDDSurface
* - HELDDPalette
* - HELDDExeBuf
*/
if( HELInit( pdrv, hel_only ) )
{
/*
* find the intersection of the driver and the HEL caps...
*/
pdrv->dwFlags |= DDRAWI_EMULATIONINITIALIZED;
mergeHELCaps( pdrv );
}
else
{
DPF( 3, "HELInit failed" );
pdrv->dwFlags |= DDRAWI_NOEMULATION;
}
return TRUE;
} /* helInit */
/*
* createDC
*
* create a new DC given a device name.
* doneDC() should be called to free DC
*
* the following are valid for device names:
*
* DISPLAY - the main display device via CreateDC("DISPLAY", ...)
* this is the normal case.
*
* foobar - the foobar.drv via CreateDC("foobar", ...)
* used for secondary displays listed in the registry
*
* \\.\DisplayX - display device X via CreateDC(NULL,"\\.\DisplayX",...)
* used on Memphis and NT5 for secondary displays
*
*/
HDC DD_CreateDC( LPSTR pdrvname )
{
HDC hdc;
UINT u;
DDASSERT( pdrvname != NULL );
#ifdef DEBUG
if (pdrvname[0] == 0)
{
DPF( 3, "createDC() empty string!!!" );
DebugBreak();
return NULL;
}
#endif
#if defined(NT_FIX) || defined(WIN95)
u = SetErrorMode( SEM_NOOPENFILEERRORBOX );
#endif
#ifdef WINNT
/*
* Note that DirectDraw refers to the driver for the primary monitor
* in a multimon system as "display", but NT uses "display" to refer
* to the desktop as a whole. To handle this mismatch, we store
* NT's name for the primary monitor's driver in g_szPrimaryDisplay
* and substitute this name in place of "display" in our calls to NT.
*/
if ( GetSystemMetrics( SM_CMONITORS ) > 1 )
{
if ( (_stricmp(pdrvname, DISPLAY_STR) == 0) )
{
if (g_szPrimaryDisplay[0] == '\0')
{
getPrimaryDisplayName();
}
pdrvname = g_szPrimaryDisplay;
}
}
#endif //WINNT
DPF( 5, "createDC(%s)", pdrvname );
if (pdrvname[0] == '\\' && pdrvname[1] == '\\' && pdrvname[2] == '.')
hdc = CreateDC( NULL, pdrvname, NULL, NULL);
else
hdc = CreateDC( pdrvname, NULL, NULL, NULL);
#if defined(NT_FIX) || defined(WIN95) //fix this error mode stuff
SetErrorMode( u );
#endif
if (hdc == NULL)
{
DPF( 3, "createDC(%s) FAILED!", pdrvname );
}
return hdc;
} /* createDC */
/*
* CreateFirstDC
*
* same as DD_CreateDC, except DDHELP is notified of the new driver.
* used only durring
*/
static HDC DD_CreateFirstDC( LPSTR pdrvname )
{
#ifdef WIN95
if (pdrvname != NULL)
{
#ifndef WIN16_SEPARATE
LEAVE_DDRAW();
#endif
SignalNewDriver( pdrvname, TRUE );
#ifndef WIN16_SEPARATE
ENTER_DDRAW();
#endif
}
#endif
return DD_CreateDC(pdrvname);
} /* createDC */
/*
* strToGUID
*
* converts a string in the form xxxxxxxx-xxxx-xxxx-xx-xx-xx-xx-xx-xx-xx-xx
* into a guid
*/
static BOOL strToGUID( LPSTR str, GUID * pguid )
{
int idx;
LPSTR ptr;
LPSTR next;
DWORD data;
DWORD mul;
BYTE ch;
BOOL done;
idx = 0;
done = FALSE;
while( !done )
{
/*
* find the end of the current run of digits
*/
ptr = str;
while( (*str) != '-' && (*str) != 0 )
{
str++;
}
if( *str == 0 )
{
done = TRUE;
}
else
{
next = str+1;
}
/*
* scan backwards from the end of the string to the beginning,
* converting characters from hex chars to numbers as we go
*/
str--;
mul = 1;
data = 0;
while( str >= ptr )
{
ch = *str;
if( ch >= 'A' && ch <= 'F' )
{
data += mul * (DWORD) (ch-'A'+10);
}
else if( ch >= 'a' && ch <= 'f' )
{
data += mul * (DWORD) (ch-'a'+10);
}
else if( ch >= '0' && ch <= '9' )
{
data += mul * (DWORD) (ch-'0');
}
else
{
return FALSE;
}
mul *= 16;
str--;
}
/*
* stuff the current number into the guid
*/
switch( idx )
{
case 0:
pguid->Data1 = data;
break;
case 1:
pguid->Data2 = (WORD) data;
break;
case 2:
pguid->Data3 = (WORD) data;
break;
default:
pguid->Data4[ idx-3 ] = (BYTE) data;
break;
}
/*
* did we find all 11 numbers?
*/
idx++;
if( idx == 11 )
{
if( done )
{
return TRUE;
}
else
{
return FALSE;
}
}
str = next;
}
return FALSE;
} /* strToGUID */
/*
* getDriverNameFromGUID
*
* look up the name of a driver based on the interface id
*/
BOOL getDriverNameFromGUID( GUID *pguid, LPSTR pdrvname, BOOL *pisdisp, BOOL *pisprimary )
{
DWORD keyidx;
HKEY hkey;
HKEY hsubkey;
char keyname[256];
DWORD cb;
DWORD type;
GUID guid;
*pisdisp = FALSE;
*pdrvname = 0;
/*
* first check for a driver guid returned via EnumDisplayDevices.
*/
if (pguid->Data1 >= DisplayGUID.Data1 &&
pguid->Data1 <= DisplayGUID.Data1 + 32 &&
memcmp(&pguid->Data2,&DisplayGUID.Data2,sizeof(GUID)-sizeof(DWORD))==0)
{
DISPLAY_DEVICEA dd;
ZeroMemory(&dd, sizeof(dd));
dd.cb = sizeof(dd);
if (xxxEnumDisplayDevicesA(NULL, pguid->Data1 - DisplayGUID.Data1, &dd, 0)
#ifdef WINNT
&& (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
#endif
)
{
lstrcpy(pdrvname, dd.DeviceName);
if( dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE )
{
*pisprimary = TRUE;
}
*pisdisp = TRUE;
return TRUE;
}
return FALSE;
}
if( RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDHW, &hkey ) )
{
DPF( 3, "No registry information for any drivers" );
return FALSE;
}
keyidx = 0;
/*
* enumerate all subkeys under HKEY_LOCALMACHINE\Hardware\DirectDrawDrivers
*/
while( !RegEnumKey( hkey, keyidx, keyname, sizeof( keyname ) ) )
{
if( strToGUID( keyname, &guid ) )
{
if( !RegOpenKey( hkey, keyname, &hsubkey ) )
{
if( IsEqualGUID( pguid, &guid ) )
{
cb = MAX_PATH-1;
if( !RegQueryValueEx( hsubkey, REGSTR_KEY_DDHW_DRIVERNAME, NULL, &type,
(CONST LPBYTE)pdrvname, &cb ) )
{
if( type == REG_SZ )
{
DPF( 5, "Found driver \"%s\"\n", pdrvname );
RegCloseKey( hsubkey );
RegCloseKey( hkey );
return TRUE;
}
}
DPF_ERR( "Could not get driver name!" );
RegCloseKey( hsubkey );
RegCloseKey( hkey );
return FALSE;
}
RegCloseKey( hsubkey );
}
}
keyidx++;
}
RegCloseKey( hkey );
return FALSE;
} /* getDriverNameFromGUID */
/*
* NewDriverInterface
*
* contruct a new interface to an existing driver object
*/
LPVOID NewDriverInterface( LPDDRAWI_DIRECTDRAW_GBL pdrv, LPVOID lpvtbl )
{
LPDDRAWI_DIRECTDRAW_INT pnew_int;
LPDDRAWI_DIRECTDRAW_LCL pnew_lcl;
DWORD size;
if( (lpvtbl == &ddCallbacks) ||
(lpvtbl == &ddUninitCallbacks) ||
(lpvtbl == &dd2UninitCallbacks) ||
(lpvtbl == &dd2Callbacks) ||
(lpvtbl == &dd4UninitCallbacks) ||
// (lpvtbl == &ddUninitNonDelegatingUnknownCallbacks) ||
(lpvtbl == &dd4Callbacks) ||
(lpvtbl == &dd7UninitCallbacks) ||
(lpvtbl == &dd7Callbacks) )
{
size = sizeof( DDRAWI_DIRECTDRAW_LCL );
}
else
{
return NULL;
}
pnew_lcl = MemAlloc( size );
if( NULL == pnew_lcl )
{
return NULL;
}
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 5, "***New local allocated 0x%p for global pdrv 0x%p", pnew_lcl, pdrv );
pnew_int = MemAlloc( sizeof( DDRAWI_DIRECTDRAW_INT ) );
if( NULL == pnew_int )
{
MemFree( pnew_lcl );
return NULL;
}
/*
* set up data
*/
ENTER_DRIVERLISTCSECT();
pnew_int->lpVtbl = lpvtbl;
pnew_int->lpLcl = pnew_lcl;
pnew_int->dwIntRefCnt = 1;
pnew_int->lpLink = lpDriverObjectList;
lpDriverObjectList = pnew_int;
pnew_lcl->lpGbl = pdrv;
pnew_lcl->dwLocalRefCnt = 1;
pnew_lcl->dwProcessId = GetCurrentProcessId();
pnew_lcl->hGammaCalibrator = (ULONG_PTR) INVALID_HANDLE_VALUE;
pnew_lcl->lpGammaCalibrator = NULL;
#ifdef WIN95
pnew_lcl->SurfaceHandleList.dwList=NULL;
pnew_lcl->SurfaceHandleList.dwFreeList=0;
#endif //WIN95
pnew_lcl->lpLink = lpDriverLocalList;
lpDriverLocalList = pnew_lcl;
if( pdrv != NULL )
{
pnew_lcl->lpDDCB = pdrv->lpDDCBtmp;
pnew_lcl->lpGbl->dwRefCnt++;
#ifdef WIN95
pnew_lcl->dwPreferredMode = pdrv->dwModeIndex;
#else
pnew_lcl->dmiPreferred = pdrv->dmiCurrent;
#endif
}
#ifdef WIN95
/*
* NOTE: We no longer get the DirectSound VXD handle at this point.
* We not get initialize it in InternalDirectDrawCreate(). This works
* well as the only two places this code currently gets invoked are
* the class factory stuff and DirectDrawCreate(). In the case of the
* class factory stuff this means there will be no VXD handle until
* initialize is called. This is not a problem, however, as there
* is nothing you can do with the VXD handle until Initialize() is
* called.
*/
pnew_lcl->hDDVxd = (DWORD) INVALID_HANDLE_VALUE;
#endif /* WIN95 */
/*
* We lazily evaluate the Direct3D interface. Also note that
* the Direct3D IUnknown goes into the local DirectDraw object
* rather than the global one as the Direct3D DLL is not shared.
* Everyone gets their own copy.
*/
pnew_lcl->hD3DInstance = NULL;
pnew_lcl->pD3DIUnknown = NULL;
LEAVE_DRIVERLISTCSECT();
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 5, "New driver object created, interface ptr = 0x%p", pnew_int );
return pnew_int;
} /* NewDriverInterface */
/*
* FetchDirectDrawData
*
* Go get new HAL info...
*/
LPDDRAWI_DIRECTDRAW_GBL FetchDirectDrawData(
LPDDRAWI_DIRECTDRAW_GBL pdrv,
BOOL reset,
DWORD hInstance,
HANDLE hDDVxd,
char * szDrvName,
DWORD dwDriverContext,
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl )
{
DWORD dw16BitVidmemInfo;
DWORD dw32BitVidmemInfo;
DDHALINFO ddhi;
LPDDRAWI_DIRECTDRAW_GBL newpdrv;
BOOL bLoadedSecondary=FALSE;
if( szDrvName == NULL )
{
if ( pdrv == NULL )
{
// This shouldn't happen
DPF_ERR( "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:FetchDirectDrawData: Driver and Driver Name is NULL");
DDASSERT( 0 );
return 0;
}
szDrvName = pdrv->cDriverName;
}
if( pdrv != NULL && (pdrv->dwFlags & DDRAWI_NOHARDWARE) )
{
HDC hdc;
// ATTENTION: why do this? Can't we just say pdrv->hdc instead of creating a dc??
hdc = DD_CreateDC( pdrv->cDriverName );
newpdrv = FakeDDCreateDriverObject( hdc, pdrv->cDriverName, pdrv, TRUE, hDDVxd );
if (newpdrv)
{
newpdrv->ddCaps.dwCaps2 |= DDCAPS2_CERTIFIED;
UpdateRectFromDevice( newpdrv );
}
DD_DoneDC( hdc );
return newpdrv;
}
else
{
ZeroMemory(&ddhi, sizeof(ddhi));
if( pdrv != NULL )
{
ddhi.hInstance = pdrv->hInstance;
}
else
{
ddhi.hInstance = hInstance;
}
#if defined(WIN95)
ENTER_WIN16LOCK();
DD16_GetHALInfo( &ddhi );
if( ddhi.lpDDCallbacks != NULL )
{
ddhi.lpDDCallbacks = MapSLFix( (DWORD) ddhi.lpDDCallbacks );
}
if( ddhi.lpDDSurfaceCallbacks != NULL )
{
ddhi.lpDDSurfaceCallbacks = MapSLFix( (DWORD) ddhi.lpDDSurfaceCallbacks );
}
if( ddhi.lpDDPaletteCallbacks != NULL )
{
ddhi.lpDDPaletteCallbacks = MapSLFix( (DWORD) ddhi.lpDDPaletteCallbacks );
}
if( ( ddhi.dwSize >= DDHALINFOSIZE_V2 ) && ( ddhi.lpDDExeBufCallbacks != NULL ) )
{
ddhi.lpDDExeBufCallbacks = MapSLFix( (DWORD) ddhi.lpDDExeBufCallbacks );
}
if( ddhi.lpdwFourCC != NULL )
{
ddhi.lpdwFourCC = MapSLFix( (DWORD) ddhi.lpdwFourCC );
}
if( ddhi.lpModeInfo != NULL )
{
ddhi.lpModeInfo = MapSLFix( (DWORD) ddhi.lpModeInfo );
}
if( ddhi.vmiData.pvmList != NULL )
{
dw16BitVidmemInfo = (DWORD) ddhi.vmiData.pvmList;
ddhi.vmiData.pvmList = MapSLFix( (DWORD)dw16BitVidmemInfo );
dw32BitVidmemInfo = (DWORD) ddhi.vmiData.pvmList;
}
if ( ddhi.lpD3DGlobalDriverData &&
(ddhi.dwFlags & DDHALINFO_GETDRIVERINFOSET) && !reset)
{
// this is a hack to Enforce D3DDEVCAPS_DRAWPRIMITIVES2 only on satackable drivers
// but not on Primary drivers as we are reluctant to force DDI revised
ddhi.lpD3DGlobalDriverData->hwCaps.dwDevCaps |= D3DDEVCAPS_DRAWPRIMITIVES2;
}
/*
* Give a secondary driver (if any) a chance.
*/
if (IsVGADevice(szDrvName))
{
/*
* Only allow secondaries to hijack primary device
*/
bLoadedSecondary = loadSecondaryDriver( &ddhi );
}
#endif
#ifdef WINNT
/*
* This is necessary to make GetDriverInfo function on NT. The handle in pdrv-hDD is per-process,
* so we need to fetch it from the local object. If this is a create call, then pdrv and pdrv_lcl
* will be null, and DirectDrawObjectCreate will create the hDD for this driver/process pair.
* If this is not a create call then it's a reset call, and we can stuff the already created hDD
* into the global so that it can be passed into GetDriverInfo. (Yes, a hack).
*/
if (pdrv_lcl && pdrv)
{
DDASSERT(reset == TRUE);
pdrv->hDD = pdrv_lcl->hDD;
}
#endif
newpdrv = DirectDrawObjectCreate( &ddhi, reset, pdrv, hDDVxd, szDrvName, dwDriverContext,
pdrv_lcl ? pdrv_lcl->dwLocalFlags : 0);
if( newpdrv )
{
// Is this a
// Figure out the RECT for the device
UpdateRectFromDevice( newpdrv );
//Record if a secondary (PowerVR) was loaded
if ( bLoadedSecondary )
{
newpdrv->dwFlags |= DDRAWI_SECONDARYDRIVERLOADED;
}
}
#ifdef WINNT
/*
* On NT, they can switch to and from 4bpp modes where DDraw
* can't be used. If DirectDrawObjectCreate fails,
* set the mode index and clear out the caps and set
* dwModeIndex to unsupported so that it can't create or
* restore surfaces.
*/
if( pdrv != NULL)
{
if( newpdrv )
{
pdrv->dwModeIndex = 0;
}
else
{
pdrv->dwModeIndex = DDUNSUPPORTEDMODE;
memset( &( pdrv->ddCaps ), 0, sizeof( DDCORECAPS ) );
pdrv->ddCaps.dwSize = sizeof( DDCORECAPS );
pdrv->ddCaps.dwCaps = DDCAPS_NOHARDWARE;
}
}
#endif
/*
* Tell the HEL a mode has changed (possibly externally)
*/
ResetBITMAPINFO(newpdrv);
#ifdef WINNT
//GetCurrentMode will have allocated mem for this. If it's null, it hasn't.
MemFree( ddhi.lpModeInfo );
#endif
#if defined(WIN95)
LEAVE_WIN16LOCK();
#endif
}
return newpdrv;
} /* FetchDirectDrawData */
/*
* DirectDrawSupported
*/
BOOL DirectDrawSupported( BOOL bDisplayMessage )
{
HDC hdc;
unsigned u;
hdc = GetDC( NULL );
u = GetDeviceCaps( hdc, BITSPIXEL ) * GetDeviceCaps( hdc, PLANES );
ReleaseDC( NULL, hdc );
if(( u < 8 ) && bDisplayMessage)
{
DPF( 0, "DirectDraw does not work in less than 8bpp modes" );
#ifdef WIN95
DirectDrawMsg(MAKEINTRESOURCE(IDS_DONTWORK_BPP));
#endif
return FALSE;
}
return TRUE;
} /* DirectDrawSupported */
/*
* DirectDrawCreate
*
* One of the two end-user API exported from DDRAW.DLL.
* Creates the DIRECTDRAW object.
*/
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawCreate"
HRESULT WINAPI DirectDrawCreate(
GUID FAR * lpGUID,
LPDIRECTDRAW FAR *lplpDD,
IUnknown FAR *pUnkOuter )
{
HRESULT hr;
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF(2,A,"ENTERAPI: DirectDrawCreate");
DPF(3,A," GUID *: 0x%p, LPLPDD: 0x%p, pUnkOuter: 0x%p", lpGUID, lplpDD, pUnkOuter);
if (pUnkOuter )
{
return CLASS_E_NOAGGREGATION;
}
bReloadReg = FALSE;
if( GetProfileInt("DirectDraw","reloadreg",0) )
{
bReloadReg = TRUE;
DPF( 3, "Reload registry each time" );
}
hr = InternalDirectDrawCreate( lpGUID, lplpDD, NULL, 0UL, NULL );
#ifdef POSTPONED
/*
* Fix up the owning unknown for this object
*/
if (hr == DD_OK && *lplpDD)
{
LPDDRAWI_DIRECTDRAW_INT this_int = (LPDDRAWI_DIRECTDRAW_INT)*lplpDD;
if (pUnkOuter)
{
this_int->lpLcl->pUnkOuter = pUnkOuter;
}
else
{
this_int->lpLcl->pUnkOuter = (IUnknown*) &NonDelegatingIUnknownInterface;
}
}
#endif
#ifdef DEBUG
if (hr == DD_OK)
/*
* DD_OK implies lplpDD must be a valid pointer, so can't AV.
*/
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF(3,A," DirectDrawCreate succeeds, and returns ddraw pointer 0x%p", *lplpDD);
else
DPF_APIRETURNS(hr);
#endif //debug
return hr;
} /* DirectDrawCreate */
/*
* DirectDrawCreateEx
*
* One of the two end-user API exported from DDRAW.DLL.
* Creates the DIRECTDRAW object.
*/
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawCreateEx"
HRESULT WINAPI DirectDrawCreateEx(
LPGUID rGuid,
LPVOID *lplpDD,
REFIID iid,
IUnknown FAR *pUnkOuter )
{
HRESULT hr;
LPDIRECTDRAW lpDD1;
DPF(2,A,"ENTERAPI: DirectDrawCreateEx");
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF(3,A,"rGuid: 0x%p, LPLPDD: 0x%p, pUnkOuter: 0x%p", rGuid, lplpDD, pUnkOuter);
if (pUnkOuter )
{
return CLASS_E_NOAGGREGATION;
}
if ( rGuid != NULL )
{
if ( !VALID_IID_PTR( rGuid ) )
{
DPF_ERR( "GUID reference is invalid" );
return DDERR_INVALIDPARAMS;
}
}
if (!IsEqualIID(iid, &IID_IDirectDraw7 ) )
{
DPF_ERR( "only IID_IDirectDraw7 is supported" );
return DDERR_INVALIDPARAMS;
}
bReloadReg = FALSE;
if( GetProfileInt("DirectDraw","reloadreg",0) )
{
bReloadReg = TRUE;
DPF( 3, "Reload registry each time" );
}
hr = InternalDirectDrawCreate((GUID FAR *)rGuid,&lpDD1, NULL, DDRAWILCL_DIRECTDRAW7, NULL );
#ifdef POSTPONED
/*
* Fix up the owning unknown for this object
*/
if (hr == DD_OK && lpDD1)
{
LPDDRAWI_DIRECTDRAW_INT this_int = (LPDDRAWI_DIRECTDRAW_INT)lpDD1;
if (pUnkOuter)
{
this_int->lpLcl->pUnkOuter = pUnkOuter;
}
else
{
this_int->lpLcl->pUnkOuter = (IUnknown*) &NonDelegatingIUnknownInterface;
}
}
#endif
if (DD_OK != hr)
{
*lplpDD=NULL;
}
if (hr == DD_OK)
{
/*
* DD_OK implies lpDD1 must be a valid pointer, so can't AV.
*/
// Now QI for the IDirectDraw7 interface
hr=lpDD1->lpVtbl->QueryInterface(lpDD1,&IID_IDirectDraw7,lplpDD);
lpDD1->lpVtbl->Release(lpDD1);
#ifdef DEBUG
if (lpDD1)
{
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF(3,A," DirectDrawCreateEx succeeds, and returns ddraw pointer 0x%p", *lplpDD);
}
#endif //debug
}
else
{
DPF_APIRETURNS(hr);
}
return hr;
} /* DirectDrawCreateEx */
/*
* getDriverInterface
*/
static LPDDRAWI_DIRECTDRAW_INT getDriverInterface(
LPDDRAWI_DIRECTDRAW_INT pnew_int,
LPDDRAWI_DIRECTDRAW_GBL pdrv )
{
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
if( pnew_int != NULL )
{
/*
* an interface was already created, so just assign the
* global data pointer and initialize a few things
*/
DPF( 4, "Interface pointer already exists!" );
pdrv_lcl = pnew_int->lpLcl;
pdrv_lcl->lpGbl = pdrv;
pdrv_lcl->lpDDCB = pdrv->lpDDCBtmp;
#ifdef WIN95
pdrv_lcl->dwPreferredMode = pdrv->dwModeIndex;
#else
pdrv_lcl->dmiPreferred = pdrv->dmiCurrent;
#endif
pdrv->dwRefCnt += pdrv_lcl->dwLocalRefCnt;
}
else
{
pnew_int = NewDriverInterface( pdrv, &ddCallbacks );
}
return pnew_int;
} /* getDriverInterface */
// Utility function that tells us if there is more than
// one display device in the system. (We count all devices,
// regardless of whether they are attached to the desktop.)
BOOL IsMultiMonitor(void)
{
int i, n;
// Each loop below enumerates one display device.
for (i = 0, n = 0; ; i++)
{
DISPLAY_DEVICEA dd;
// Zero the memory of the DISPLAY_DEVICE struct between calls to
// EnumDisplayDevices
ZeroMemory(&dd, sizeof(dd));
dd.cb = sizeof(dd);
if (!xxxEnumDisplayDevicesA(NULL, i, &dd, 0))
{
break; // no more devices to enumerate
}
if (dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER)
{
continue; // not a real hardware display driver
}
// We're just trying to count the number of display devices in the
// system and see if there is more than one.
if (++n > 1)
{
return TRUE; // multiple display devices
}
}
return FALSE; // single display device
}
extern DWORD HackMeBaby( void );
BOOL fDoesGDI(HDC hdc)
{
//
// the 3Dfx driver always return 1 to every thing
// verify GetNearest() color works.
//
BOOL b = GetNearestColor(hdc, 0x000000) == 0x000000 &&
GetNearestColor(hdc, 0xFFFFFF) == 0xFFFFFF;
if(b)
{
DPF(3,"Driver is a GDI driver");
}
return b;
}
/*
* IsAttachedToDesktop
*
* DCI is hardwired to the primary display which means it can't
* be used on a multi-mon system. Usually GDI disables it for
* us, but it does not when there are two monitors and only one
* of them uses the desktop. We'd still like to use DCI for
* the desktop in this case, but we can't use it if the monitor
* is not attached to the desktop. That is why this function exists.
*/
BOOL IsAttachedToDesktop( LPGUID lpGuid )
{
DWORD n;
GUID guid;
DISPLAY_DEVICEA dd;
if( !IsMultiMonitor() )
{
return TRUE;
}
/*
* Assume that the primary is always attached
*/
if( (lpGuid == (GUID *) DDCREATE_EMULATIONONLY) ||
(lpGuid == (GUID *) DDCREATE_HARDWAREONLY) ||
(lpGuid == NULL) ||
(IsEqualGUID( lpGuid, &GUID_NULL) ) )
{
return TRUE;
}
ZeroMemory(&dd, sizeof(dd));
dd.cb = sizeof(dd);
for( n=0; xxxEnumDisplayDevicesA( NULL, n, &dd, 0 ); n++ )
{
guid = DisplayGUID;
guid.Data1 += n;
if( IsEqualIID( lpGuid, &guid) )
{
if( dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP )
{
return TRUE;
}
else
{
return FALSE;
}
}
ZeroMemory( &dd, sizeof(dd) );
dd.cb = sizeof(dd);
}
return TRUE;
} /* IsAttachedToDesktop */
/*
* Functions to dynamically link against exports we need in user32 on
* older OSes
*/
//These statics will be per-process, cuz it's outside the shared section
typedef BOOL (WINAPI * LPENUMMONITORS) (HDC, LPRECT, MONITORENUMPROC, LPARAM);
typedef BOOL (WINAPI * LPGETMONINFO) (HMONITOR, MONITORINFO *);
typedef BOOL (WINAPI * LPISDEBUG) (void);
static LPISDEBUG pIsDebuggerPresent = 0;
static LPENUMMONITORS pEnumMonitors = 0;
static LPGETMONINFO pGetMonitorInfo = 0;
static BOOL bTriedToGetProcAlready = FALSE;
BOOL DynamicLinkToOS(void)
{
if (1) //!pEnumMonitors)
{
HMODULE hUser32;
HMODULE hKernel32;
if (0) //bTriedToGetProcAlready)
return FALSE;
bTriedToGetProcAlready = TRUE;
hUser32 = GetModuleHandle(TEXT("USER32"));
pEnumMonitors = (LPENUMMONITORS) GetProcAddress(hUser32,"EnumDisplayMonitors");
pGetMonitorInfo = (LPGETMONINFO) GetProcAddress(hUser32,"GetMonitorInfoA");
hKernel32 = GetModuleHandle(TEXT("KERNEL32"));
pIsDebuggerPresent = (LPISDEBUG) GetProcAddress(hKernel32,"IsDebuggerPresent");
if (!pEnumMonitors || !pGetMonitorInfo || !pIsDebuggerPresent)
{
DPF(3,"Failed to get proc addresses");
return FALSE;
}
}
DDASSERT(pEnumMonitors);
DDASSERT(pGetMonitorInfo);
DDASSERT(pEnumMonitors);
return TRUE;
}
BOOL InternalGetMonitorInfo(HMONITOR hMon, MONITORINFO *lpInfo)
{
DynamicLinkToOS();
if (!pGetMonitorInfo)
return FALSE;
return pGetMonitorInfo(hMon, lpInfo);
}
typedef struct
{
LPSTR pName;
HMONITOR hMon;
} CALLBACKSTRUCT, * LPCALLBACKSTRUCT;
BOOL InternalEnumMonitors(MONITORENUMPROC proc, LPCALLBACKSTRUCT lp)
{
DynamicLinkToOS();
if (!pEnumMonitors)
return FALSE;
pEnumMonitors(NULL,NULL,proc,(LPARAM)lp);
return TRUE;
}
/*
* InternalIsDebuggerPresent
* A little helper so that this runtime runs against older OSes
*/
BOOL InternalIsDebuggerPresent(void)
{
DynamicLinkToOS();
if (!pIsDebuggerPresent)
return FALSE;
return pIsDebuggerPresent();
}
//
// getPrimaryDisplayName
//
void getPrimaryDisplayName(void)
{
DISPLAY_DEVICE dd;
int i;
ZeroMemory(&dd, sizeof dd);
dd.cb = sizeof dd;
for (i = 0; xxxEnumDisplayDevicesA(NULL, i, &dd, 0); ++i)
{
if (dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)
{
lstrcpyn(g_szPrimaryDisplay, dd.DeviceName, sizeof g_szPrimaryDisplay);
return;
}
}
lstrcpy(g_szPrimaryDisplay, DISPLAY_STR);
}
/*
* InternalDirectDrawCreate
*/
HRESULT InternalDirectDrawCreate(
GUID * lpGUID,
LPDIRECTDRAW *lplpDD,
LPDDRAWI_DIRECTDRAW_INT pnew_int,
DWORD dwCallFlags,
char * pDeviceName)
{
DCICMD cmd;
UINT u;
int rc;
LPDDRAWI_DIRECTDRAW_GBL pdrv;
LPDDRAWI_DIRECTDRAW_LCL pdrv_lcl;
LPDDRAWI_DIRECTDRAW_INT pdrv_int;
LPSTR pdrvname;
HDC hdc_dd;
BOOL isdispdrv;
BOOL hel_only;
DWORD dwFlags;
char drvname[MAX_PATH];
DWORD pid;
HKEY hkey;
DWORD hackflags;
#ifdef WIN95
int halver;
#endif
HANDLE hDDVxd;
BOOL bIsPrimary;
BOOL bExplicitMonitor = FALSE;
ULONG_PTR hDD;
#ifndef DX_FINAL_RELEASE
#pragma message( REMIND( "Remove time bomb for final!" ))
{
SYSTEMTIME st;
TCHAR tstrText[MAX_PATH];
TCHAR tstrTitle[MAX_PATH];
GetSystemTime( &st );
if( ( st.wYear > DX_EXPIRE_YEAR ) ||
( ( st.wYear == DX_EXPIRE_YEAR ) &&
( ( st.wMonth > DX_EXPIRE_MONTH ) || ( ( st.wMonth == DX_EXPIRE_MONTH ) && ( st.wDay >= DX_EXPIRE_DAY ) ) ) ) )
{
LoadString( hModule, IDS_TIME_BOMB, tstrText, MAX_PATH);
LoadString( hModule, IDS_TIME_BOMB_TITLE, tstrTitle, MAX_PATH);
if( 0 == MessageBox( NULL, tstrText, tstrTitle, MB_OK) )
{
DPF( 0, "DirectDraw Beta Expired. Please Update" );
*lplpDD = (LPDIRECTDRAW) NULL;
return DDERR_GENERIC;
}
}
}
#endif //DX_FINAL_RELEASE
/*
* validate parameters
*/
if( !VALIDEX_PTR_PTR( lplpDD ) )
{
DPF_ERR( "Invalid lplpDD" );
return DDERR_INVALIDPARAMS;
}
*lplpDD = (LPDIRECTDRAW) NULL;
/*
* check for < 8 bpp and disallow.
*/
if( !DirectDrawSupported(!(dwCallFlags & DDRAWILCL_DIRECTDRAW8)) )
{
return DDERR_NODIRECTDRAWSUPPORT;
}
ENTER_CSDDC();
ENTER_DDRAW();
hackflags = HackMeBaby();
DPF( 5, "DirectDrawCreate: pid = %08lx", GETCURRPID() );
/*
* pull in registry values
*/
DPF( 4, "Reading Registry" );
if( !RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDRAW, &hkey ) )
{
DWORD type;
DWORD value;
DWORD cb;
cb = sizeof( value );
dwRegFlags &= ~(DDRAW_REGFLAGS_MODEXONLY |
DDRAW_REGFLAGS_EMULATIONONLY |
DDRAW_REGFLAGS_SHOWFRAMERATE |
DDRAW_REGFLAGS_ENABLEPRINTSCRN |
DDRAW_REGFLAGS_DISABLEWIDESURF |
DDRAW_REGFLAGS_NODDSCAPSINDDSD |
DDRAW_REGFLAGS_DISABLEMMX |
DDRAW_REGFLAGS_FORCEREFRESHRATE |
DDRAW_REGFLAGS_DISABLEAGPSUPPORT);
dwRegFlags &= ~DDRAW_REGFLAGS_AGPPOLICYMAXBYTES;
#ifndef WINNT
#ifdef DEBUG
dwAGPPolicyCommitDelta = DEFAULT_AGP_COMMIT_DELTA;
#endif /* DEBUG */
#endif
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_MODEXONLY, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " ModeXOnly: %d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_MODEXONLY;
}
}
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_EMULATIONONLY, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " EmulationOnly: %d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_EMULATIONONLY;
}
}
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_SHOWFRAMERATE, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " ShowFrameRate: %d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_SHOWFRAMERATE;
}
}
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_ENABLEPRINTSCRN, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " EnablePrintScreen: %d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_ENABLEPRINTSCRN;
}
}
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_FORCEAGPSUPPORT, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " ForceAGPSupport: %d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_FORCEAGPSUPPORT;
}
}
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLEAGPSUPPORT, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " DisableAGPSupport: %d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_DISABLEAGPSUPPORT;
}
}
cb = sizeof( value );
#ifdef WIN95
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_AGPPOLICYMAXPAGES, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " AGPPolicyMaxPages: %d", value );
dwRegFlags |= DDRAW_REGFLAGS_AGPPOLICYMAXBYTES;
dwAGPPolicyMaxBytes = value * 4096;
}
#ifdef DEBUG
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_AGPPOLICYCOMMITDELTA, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " AGPPolicyCommitDelta: %d", value );
dwAGPPolicyCommitDelta = value;
}
#endif /* DEBUG */
#endif
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLEMMX, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " DisableMMX: %d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_DISABLEMMX;
}
}
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_NODDSCAPSINDDSD, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " Disable ddscaps in DDSURFACEDESC: %d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_NODDSCAPSINDDSD;
}
}
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLEWIDERSURFACES, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " DisableWiderSurfaces:%d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_DISABLEWIDESURF;
}
}
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_D3D_USENONLOCALVIDMEM, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " UseNonLocalVidmem:%d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_USENONLOCALVIDMEM;
}
}
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_FORCEREFRESHRATE, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " ForceRefreshRate:%d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_FORCEREFRESHRATE;
dwForceRefreshRate = value;
}
}
#ifdef DEBUG
/*
* NOSYSLOCK (No Win16 locking) control flags. DEBUG only.
*/
dwRegFlags &= ~(DDRAW_REGFLAGS_DISABLENOSYSLOCK | DDRAW_REGFLAGS_FORCENOSYSLOCK | DDRAW_REGFLAGS_DISABLEINACTIVATE);
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLENOSYSLOCK, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " DisableNoSysLock:%d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_DISABLENOSYSLOCK;
}
}
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_FORCENOSYSLOCK, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " ForceNoSysLock:%d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_FORCENOSYSLOCK;
}
}
if( ( dwRegFlags & DDRAW_REGFLAGS_DISABLENOSYSLOCK ) &&
( dwRegFlags & DDRAW_REGFLAGS_FORCENOSYSLOCK ) )
{
DPF( 0, "Attempt to both disable and force NOSYSLOCK on locks. Ignoring both" );
dwRegFlags &= ~(DDRAW_REGFLAGS_DISABLENOSYSLOCK | DDRAW_REGFLAGS_FORCENOSYSLOCK);
}
/*
* Hack to allow multi-mon debugging w/o minimizing the exclusive
* mode app when it gets a WM_ACTIVATEAPP msg. We only do this
* in the debug version.
*/
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLEINACTIVATE, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " DisableInactivate:%d", value );
if( value && InternalIsDebuggerPresent() )
{
dwRegFlags |= DDRAW_REGFLAGS_DISABLEINACTIVATE;
}
}
#endif /* DEBUG */
RegCloseKey(hkey);
}
if( !RegOpenKey( HKEY_LOCAL_MACHINE, RESPATH_D3D, &hkey ) )
{
DWORD type;
DWORD value;
DWORD cb;
cb = sizeof( value );
dwRegFlags &= ~DDRAW_REGFLAGS_FLIPNONVSYNC;
if( !RegQueryValueEx( hkey, REGSTR_VAL_D3D_FLIPNOVSYNC, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, REGSTR_VAL_D3D_FLIPNOVSYNC" :%d", value );
if( value )
{
dwRegFlags |= DDRAW_REGFLAGS_FLIPNONVSYNC;
}
}
RegCloseKey(hkey);
}
hdc_dd = NULL;
hDD = 0;
dwFlags = 0;
//
// Get the primary display name, which will usually be something like
// \\.\Display1 and in some cases may be \\.\Display1\Unit0. We only
// do this one time, and store it globally. On Win98, the global name
// will be shared between all processes, and on NT5, each process will
// have its own copy. Also, note that the primary device name may change
// on NT5; we need to look into this.
//
if (g_szPrimaryDisplay[0] == '\0')
{
getPrimaryDisplayName();
}
/*
* any special cases?
*/
bIsPrimary = FALSE;
isdispdrv = FALSE;
if( dwRegFlags & DDRAW_REGFLAGS_EMULATIONONLY )
{
DWORD cMonitors = GetSystemMetrics( SM_CMONITORS );
dwFlags |= DDCREATE_EMULATIONONLY;
if( cMonitors <= 1 )
{
// For compatibility with pre-multimon versions of DDraw
bIsPrimary = TRUE;
}
}
if( pDeviceName == NULL)
{
if( lpGUID == (GUID *) DDCREATE_EMULATIONONLY )
{
dwFlags |= DDCREATE_EMULATIONONLY;
bIsPrimary = TRUE;
}
else if( lpGUID == NULL )
{
bIsPrimary = TRUE;
}
else if( lpGUID == (GUID *) DDCREATE_HARDWAREONLY )
{
dwFlags |= DDCREATE_HARDWAREONLY;
bIsPrimary = TRUE;
}
if (bIsPrimary)
{
lpGUID = (GUID *) &GUID_NULL; // primary monitor
}
else if( !VALIDEX_GUID_PTR( lpGUID ) )
{
DPF_ERR( "Invalid GUID passed in" );
LEAVE_DDRAW();
LEAVE_CSDDC();
return DDERR_INVALIDPARAMS;
}
if( IsEqualGUID( lpGUID, &GUID_NULL ) )
{
pdrvname = DISPLAY_STR; // "display"
isdispdrv = TRUE;
bIsPrimary = TRUE;
}
else
{
if( !getDriverNameFromGUID( lpGUID, drvname, &isdispdrv, &bIsPrimary ) )
{
DPF_ERR( "Invalid GUID for driver" );
LEAVE_DDRAW();
LEAVE_CSDDC();
return DDERR_INVALIDDIRECTDRAWGUID;
}
pdrvname = drvname;
}
}
else
{
pdrvname = pDeviceName;
}
if ((ULONG_PTR)pdrvname != (ULONG_PTR)DISPLAY_STR)
{
bExplicitMonitor = TRUE;
if (_stricmp(pdrvname, g_szPrimaryDisplay) == 0)
{
pdrvname = DISPLAY_STR;
}
}
pid = GETCURRPID();
#ifdef WIN95
/*
* We need to ensure that DDHELP has a handle to the DirectX VXD
* that it can use when creating, freeing or mapping virtual memory
* aliases or AGP heaps on mode switches or cleanups.
*/
if( INVALID_HANDLE_VALUE == hHelperDDVxd )
{
hHelperDDVxd = HelperGetDDVxd();
if( INVALID_HANDLE_VALUE == hHelperDDVxd )
{
DPF_ERR( "DDHELP could not load the DirectX VXD" );
LEAVE_DDRAW();
LEAVE_CSDDC();
return DDERR_GENERIC;
}
}
/*
* Create a handle for VXD communication. We will use this for
* alias construction in this function and we will later store
* this in the local object for later alias manipulation and
* page locking purposes.
*/
hDDVxd = GetDXVxdHandle();
if( INVALID_HANDLE_VALUE == hDDVxd )
{
DPF_ERR( "Unable to open the DirectX VXD" );
LEAVE_DDRAW();
LEAVE_CSDDC();
return DDERR_GENERIC;
}
#else /* WIN95 */
hDDVxd = INVALID_HANDLE_VALUE;
#endif /* WIN95 */
/*
* run the driver list, looking for one that already exists. We used to run
* the interface list, but thanks to D3D it is possible for all locals to exist
* w/o anything in the interface list.
*/
pdrv_lcl = lpDriverLocalList;
while( pdrv_lcl != NULL )
{
pdrv = pdrv_lcl->lpGbl;
if( pdrv != NULL )
{
if( !_stricmp( pdrv->cDriverName, pdrvname ) )
{
// If they asked for hardware; then don't accept the
// emulated driver
if( !(dwFlags & DDCREATE_EMULATIONONLY) &&
!(pdrv->dwFlags & DDRAWI_NOHARDWARE) )
{
DPF( 2, "Driver \"%s\" found for hardware", pdrvname );
break;
}
// If they asked for emulation; then don't accept the
// hardware driver
if( (dwFlags & DDCREATE_EMULATIONONLY) &&
(pdrv->dwFlags & DDRAWI_NOHARDWARE) )
{
DPF( 2, "Driver \"%s\" found for emulation", pdrvname );
break;
}
// Compatibility: on single monitor systems take whatever
// we got. (This is what we did in DX3)
if( pdrv->cMonitors <= 1 )
{
DPF( 2, "Driver \"%s\" found", pdrvname );
break;
}
}
}
pdrv_lcl = pdrv_lcl->lpLink;
}
/*
* if driver object already exists, get emulation layer if needed,
* create a new interface to it and return
*/
if( pdrv_lcl != NULL )
{
LPDDRAWI_DIRECTDRAW_LCL tmp_lcl;
// This is the hdc we need to release if something
// goes wrong; since we are sometimes
// sharing an HDC with an existing LCL, we must
// be careful not to release it while it is still
// in use.
HDC hdcCleanup = NULL;
/*
* see if the current process has attached to this driver before...
*/
tmp_lcl = lpDriverLocalList;
while( tmp_lcl != NULL )
{
if( tmp_lcl->dwProcessId == pid &&
tmp_lcl->lpGbl == pdrv)
{
break;
}
tmp_lcl = tmp_lcl->lpLink;
}
if( tmp_lcl == NULL )
{
hdc_dd = NULL;
}
else
{
// We found the process/driver pair we were looking for.
hdc_dd = (HDC) tmp_lcl->hDC;
DDASSERT(hdc_dd != 0);
hDD = tmp_lcl->hDD;
}
/*
* we need a new DC if this is a new process/driver pair...
*/
if( hdc_dd == NULL )
{
DWORD flags;
flags = pdrv->dwFlags;
hdc_dd = DD_CreateFirstDC( pdrvname );
if( hdc_dd == NULL )
{
DPF_ERR( "Could not get a DC for the driver" );
CLOSEVXD( hDDVxd );
LEAVE_DDRAW();
LEAVE_CSDDC();
/* GEE: decided this error was rare enough to be left generic */
return DDERR_GENERIC;
}
if (!(pdrv->dwFlags & DDRAWI_DISPLAYDRV))
{
if (fDoesGDI(hdc_dd))
{
pdrv->dwFlags |= DDRAWI_GDIDRV;
}
else
{
pdrv->dwFlags &= ~DDRAWI_GDIDRV;
}
}
// We need to free it if something goes wrong
hdcCleanup = hdc_dd;
}
/*
* Set up emulation for display and non-display drivers
*/
if( dwFlags & DDCREATE_EMULATIONONLY )
{
if( !(pdrv->dwFlags & DDRAWI_NOHARDWARE) )
{
DD_DoneDC(hdcCleanup);
DPF_ERR( "EMULATIONONLY requested, but driver exists and has hardware" );
CLOSEVXD( hDDVxd );
LEAVE_DDRAW();
LEAVE_CSDDC();
/* GEE: Why do we fail emulation only calls just because we have a driver? */
return DDERR_GENERIC;
}
}
/*
* we will need to load the emulation layer...
*/
if( !(pdrv->dwFlags & DDRAWI_NOEMULATION) &&
!(pdrv->dwFlags & DDRAWI_EMULATIONINITIALIZED ) )
{
capsInit( pdrv );
hel_only = ((dwFlags & DDCREATE_EMULATIONONLY) != 0);
if( !helInit( pdrv, dwFlags, hel_only ) )
{
DD_DoneDC(hdcCleanup);
DPF_ERR( "HEL initialization failed" );
CLOSEVXD( hDDVxd );
LEAVE_DDRAW();
LEAVE_CSDDC();
/* GEE: HEL can only fail in v1 for lack of memory */
return DDERR_GENERIC;
}
}
pdrv_int = getDriverInterface( pnew_int, pdrv );
if( pdrv_int == NULL )
{
DD_DoneDC(hdcCleanup);
DPF_ERR( "No memory for driver callbacks." );
CLOSEVXD( hDDVxd );
LEAVE_DDRAW();
LEAVE_CSDDC();
return DDERR_OUTOFMEMORY;
}
pdrv_lcl = pdrv_int->lpLcl;
pdrv_lcl->dwAppHackFlags = hackflags;
#ifdef DEBUG
if( dwRegFlags & DDRAW_REGFLAGS_DISABLEINACTIVATE )
{
pdrv_lcl->dwLocalFlags |= DDRAWILCL_DISABLEINACTIVATE;
}
#endif
if( IsAttachedToDesktop( lpGUID ) )
{
pdrv->dwFlags |= DDRAWI_ATTACHEDTODESKTOP;
}
if (bExplicitMonitor)
{
pdrv_lcl->dwLocalFlags |= DDRAWILCL_EXPLICITMONITOR;
}
pdrv_lcl->dwLocalFlags |= dwCallFlags;
pdrv_lcl->hDDVxd = (ULONG_PTR) hDDVxd;
#ifdef WIN95
if( hdcCleanup )
{
// If we had to create a DC from
// scratch then we need to mark it
// private so that it will be never
// be deleted out from under us
DDASSERT( hdcCleanup == hdc_dd );
DD16_MakeObjectPrivate( hdc_dd, TRUE );
}
#endif
#ifdef WINNT
if( hdcCleanup )
{
BOOL bRetVal;
// We had to create a DC from scratch for this process/driver pair.
DDASSERT(hdcCleanup == hdc_dd);
// GDI creates a DirectDraw handle for each unique process/driver pair.
if( pdrv->dwFlags & DDRAWI_NOHARDWARE )
{
// A fake DDraw driver that lets the HEL do everything.
bRetVal = DdCreateDirectDrawObject(pdrv, (HDC)0);
}
else
{
// A real DDraw driver with hardware acceleration.
bRetVal = DdCreateDirectDrawObject(pdrv, hdc_dd);
}
if (!bRetVal)
{
DPF_ERR( "Call to DdCreateDirectDrawObject failed!");
DD_DoneDC(hdc_dd);
LEAVE_DDRAW();
LEAVE_CSDDC();
return DDERR_NODIRECTDRAWHW;
}
// The DdCreateDirectDrawObject() call above loaded a DD handle into a
// into a temp location in the driver GBL object, but we must now save
// the handle in the driver LCL object so it won't be overwritten if
// another process calls DdCreateDirectDrawObject() on the same driver.
hDD = pdrv->hDD;
}
pdrv_lcl->hDD = hDD;
#endif //WINNT
(HDC) pdrv_lcl->hDC = hdc_dd;
*lplpDD = (LPDIRECTDRAW) pdrv_int;
LEAVE_DDRAW();
LEAVE_CSDDC();
return DD_OK;
}
/*
* if no match among the existing drivers, then we have to go off
* and create one
*/
hdc_dd = DD_CreateFirstDC( pdrvname );
if( hdc_dd == NULL )
{
DPF_ERR( "Could not create driver, CreateDC failed!" );
CLOSEVXD( hDDVxd );
LEAVE_DDRAW();
LEAVE_CSDDC();
return DDERR_CANTCREATEDC;
}
#ifdef WIN95
/*
* HACK-O-RAMA TIME! We need to do something smart if the VGA is
* powered down or if we're in a DOS box. We don't have the pDevice
* yet, so we'll hack around w/ the DC we just created.
*/
if( DD16_IsDeviceBusy( hdc_dd ) )
{
/*
* Something is happenning, but we don't know what. If it's
* a DOS box, creating a simple POPUP should make it go away.
*/
WNDCLASS cls;
HWND hWnd;
cls.lpszClassName = "DDrawHackWindow";
cls.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
cls.hInstance = hModule;
cls.hIcon = NULL;
cls.hCursor = NULL;
cls.lpszMenuName = NULL;
cls.style = CS_BYTEALIGNCLIENT | CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS;
cls.lpfnWndProc = DefWindowProc;
cls.cbWndExtra = 0;
cls.cbClsExtra = 0;
RegisterClass(&cls);
hWnd = CreateWindowEx(WS_EX_TOPMOST|WS_EX_TOOLWINDOW,
"DDrawHackWindow", "DDrawHackWindow",
WS_OVERLAPPED|WS_POPUP|WS_VISIBLE, 0, 0, 2, 2,
NULL, NULL, hModule, NULL);
if( hWnd != NULL )
{
DestroyWindow( hWnd );
UnregisterClass( "DDrawHackWindow", hModule );
}
/*
* Check again, and if we're still busy, that probably means
* that the device is powered down. In that case, forcing
* emulaiton is probably the right thing to do.
*/
if( DD16_IsDeviceBusy( hdc_dd ) )
{
dwFlags |= DDCREATE_EMULATIONONLY;
}
}
#endif
if( dwFlags & DDCREATE_EMULATIONONLY )
{
hel_only = TRUE;
}
else
{
hel_only = FALSE;
/*
* "That's the chicago way..."
* Win95 drivers are talked to through the ExtEscape DCI extensions.
* Under NT we get at our drivers through the gdi32p dll.
* Consequently all this dci stuff goes away for NT. You'll find the
* equivalent stuff done at the top of DirectDrawObjectCreate
*/
#ifdef WIN95
/*
* see if the DCICOMMAND escape is supported
*/
u = DCICOMMAND;
halver = ExtEscape( hdc_dd, QUERYESCSUPPORT, sizeof(u),
(LPCSTR)&u, 0, NULL );
if( (halver != DD_HAL_VERSION) && (halver != DD_HAL_VERSION_EXTERNAL) )
{
if( halver <= 0 )
{
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:No DIRECTDRAW escape support" );
}
else
{
if (halver == 0x5250)
{
DPF(0,"****DirectDraw/Direct3D DRIVER DISABLING ERROR****:Acceleration slider is set to NONE");
}
else
{
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:DIRECTDRAW driver is wrong version, got 0x%04lx, expected 0x%04lx",
halver, DD_HAL_VERSION_EXTERNAL );
}
}
// We don't release the DC anymore becuase it always becomes part
// of the DDRAW_GBL object in all DisplayDrv cases.
hel_only = TRUE;
}
#endif //win95
}
if( hel_only && (dwFlags & DDCREATE_HARDWAREONLY))
{
DPF_ERR( "Only emulation available, but HARDWAREONLY requested" );
CLOSEVXD( hDDVxd );
LEAVE_DDRAW();
LEAVE_CSDDC();
DD_DoneDC(hdc_dd);
return DDERR_NODIRECTDRAWHW;
}
#ifdef WIN95
// On non-multi-mon systems, we do this because
// we did it in DX3. We set TRUE for multi-mon systems
// because that will prevent us from using Death/Resurrection
// which is Dangerous if some future DDraw object ever is
// created for the secondary device. We can't wait until
// the second device is created; because it's possible that
// primary device is already in the middle of a death/resurrection
// sequence and it is bad bad karma to change the flag between
// the beginning of modex and the end of modex. (Specifically,
// we'll see either a resurrection not being called when it should
// have been or a resurrection called when it shouldn't have been.)
if( IsMultiMonitor() )
DD16_SetCertified( TRUE );
else
DD16_SetCertified( FALSE );
#endif
/*
* go try to create the driver object
*/
if( !hel_only )
{
DWORD hInstance = 0;
DWORD dwDriverData32 = 0;
DWORD p16;
DDHALDDRAWFNS ddhddfns;
BOOL bFailedWhackoVersion = FALSE;
BOOL bPassDriverInit = TRUE;
/*
* "That's the chicago way..."
* Win95 drivers are talked to through the ExtEscape DCI extensions.
* Under NT we get at our drivers through the gdi32p dll.
* Consequently all this dci stuff goes away for NT. You'll find the
* equivalent stuff done at the top of DirectDrawObjectCreate
*/
#ifdef WIN95
DD32BITDRIVERDATA data;
DDVERSIONDATA verdata;
/*
* Notify the driver of the DirectDraw version.
*
* Why this is neccesary: After DX3 it became a requirement for
* newer DDraws to work w/ older HALs and visa versa. DD_VERSION
* was set at 0x200 in DX3 and all of the drivers hardcoded it.
* Therefore, setting dwVersion to anything other than 0x200 would
* cause DX3 HALs to fail. The other option was to put the real
* version in dwParam1 of the DDGET32BITDRIVERNAME call, but this
* option seems a little cleaner. Since the information could be
* useful in the future, we also ask the HAL to tell us what
* version of DirectDraw they were designed for.
*/
DPF( 4, "DDVERSIONINFO" );
/*
* On debug builds, probe the driver with a totally whacko ddraw version
* This ensures we can increment this version in the future i.e. that
* any existing drivers which catch this escape don't hard code for
* whatever version of the DDK they use
* We fail the driver if they give out on some large random ddraw version but
* pass on 0x500
*/
cmd.dwCommand = (DWORD) DDVERSIONINFO;
cmd.dwParam1 = (GetCurrentProcessId() & 0xfff) + 0x501; //always > 0x500
cmd.dwParam2 = 0;
cmd.dwReserved = 0;
cmd.dwVersion = DD_VERSION; // So older HALs won't fail
verdata.dwHALVersion = 0;
verdata.dwReserved1 = 0;
verdata.dwReserved2 = 0;
rc = ExtEscape( hdc_dd, DCICOMMAND, sizeof( cmd ),
(LPCSTR)&cmd, sizeof( verdata ), (LPSTR) &verdata );
if (rc <= 0)
{
//Removed this DPF: It's misleading
//DPF(1,"Driver failed random future DDraw version");
bFailedWhackoVersion = TRUE;
}
cmd.dwCommand = (DWORD) DDVERSIONINFO;
cmd.dwParam1 = DD_RUNTIME_VERSION;
cmd.dwParam2 = 0;
cmd.dwReserved = 0;
cmd.dwVersion = DD_VERSION; // So older HALs won't fail
verdata.dwHALVersion = 0;
verdata.dwReserved1 = 0;
verdata.dwReserved2 = 0;
rc = ExtEscape( hdc_dd, DCICOMMAND, sizeof( cmd ),
(LPCSTR)&cmd, sizeof( verdata ), (LPSTR) &verdata );
DPF( 5, "HAL version: %X", verdata.dwHALVersion );
/*
* If the driver failed the whacko version, but passed for 0x500 (DX5),
* then fail the driver.
*/
if( rc > 0 && verdata.dwHALVersion >= 0x500 && bFailedWhackoVersion )
{
DPF_ERR("****DirectDraw/Direct3D DRIVER DISABLING ERROR****Driver Failed a DDVERSIONINFO for a random future ddraw version but passed for DX5.");
bPassDriverInit = FALSE;
isdispdrv = FALSE;
pdrv = NULL;
hel_only = TRUE;
}
/*
* load up the 32-bit display driver DLL
*/
DPF( 4, "DDGET32BITDRIVERNAME" );
cmd.dwCommand = (DWORD) DDGET32BITDRIVERNAME;
cmd.dwParam1 = 0;
cmd.dwVersion = DD_VERSION;
rc = ExtEscape( hdc_dd, DCICOMMAND, sizeof( cmd ),
(LPCSTR)&cmd, sizeof( data ), (LPSTR) &data );
if( rc > 0 )
{
#ifndef WIN16_SEPARATE
LEAVE_DDRAW();
#endif
dwDriverData32 = HelperLoadDLL( data.szName, data.szEntryPoint, data.dwContext );
DPF( 5, "DriverInit returned 0x%x", dwDriverData32 );
#ifndef WIN16_SEPARATE
ENTER_DDRAW();
#endif
}
/*
* get the 16-bit callbacks
*/
DD16_GetDriverFns( &ddhddfns );
DPF( 4, "DDNEWCALLBACKFNS" );
cmd.dwCommand = (DWORD) DDNEWCALLBACKFNS;
#ifdef WIN95
p16 = MapLS( &ddhddfns );
cmd.dwParam1 = p16;
cmd.dwParam2 = 0;
#else
cmd.dwParam1 = (UINT) &ddhddfns;
cmd.dwParam2 = 0;
#endif
cmd.dwVersion = DD_VERSION;
cmd.dwReserved = 0;
ExtEscape( hdc_dd, DCICOMMAND, sizeof( cmd ),
(LPCSTR)&cmd, 0, NULL );
UnMapLS( p16 );
/*
* try to create the driver object now
*/
DPF( 4, "DDCREATEDRIVEROBJECT" );
cmd.dwCommand = (DWORD) DDCREATEDRIVEROBJECT;
cmd.dwParam1 = dwDriverData32;
cmd.dwParam2 = 0;
cmd.dwVersion = DD_VERSION;
cmd.dwReserved = 0;
rc = ExtEscape( hdc_dd, DCICOMMAND, sizeof( cmd ),
(LPCSTR)&cmd, sizeof( DWORD ), (LPVOID) &hInstance );
DPF( 5, "hInstance = %08lx", hInstance );
if( rc <= 0 )
{
DPF( 0, "ExtEscape rc=%ld, GetLastError=%ld", rc, GetLastError() );
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:No DDCREATEDRIVEROBJECT support in driver" );
isdispdrv = FALSE;
pdrv = NULL;
hel_only = TRUE;
}
DPF(5,"bPassDriverInit:%d, rc:%d",bPassDriverInit,rc);
if ( (bPassDriverInit) && (rc > 0) )
#endif //WIN95
{
/*
* create our driver object
*/
#ifdef WINNT
uDisplaySettingsUnique=DdQueryDisplaySettingsUniqueness();
#endif
pdrv = FetchDirectDrawData( NULL, FALSE, hInstance, hDDVxd, pdrvname, dwDriverData32 , NULL);
if( pdrv )
{
#ifdef WIN95
pdrv->dwInternal1 = verdata.dwHALVersion;
//Record 32-bit driver data so we can get its version info later
pdrv->dd32BitDriverData = data;
#else
/*
* NT gets the same driver version as ddraw. Kernel
* has to filter ddraw.dll's ravings for the driver
*/
pdrv->dwInternal1 = DD_RUNTIME_VERSION;
#endif
strcpy( pdrv->cDriverName, pdrvname );
#ifdef WIN95
//
// If we have to run in emulation only, then we better make sure we are
// on a minidriver. If not, then emulation is unreliable so we'll bail
// This is done to work around some messed up "remote control" programs
// that turn off C1_DIBENGINE and make us fail (IsWin95MiniDriver used
// to be called from IsDirectDrawSupported). The thinking is that if there's ddraw
// support, then it is pretty much guaranteed to be a minidriver. If there's
// no support, then we can trust the absence of C1_DIBENGINE and thus fail ddraw init
//
if( (pdrv->ddCaps.dwCaps & DDCAPS_NOHARDWARE) && !DD16_IsWin95MiniDriver() )
{
DPF( 0, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:DirectDraw requires a Windows95 display driver" );
DirectDrawMsg(MAKEINTRESOURCE(IDS_DONTWORK_DRV));
CLOSEVXD( hDDVxd );
LEAVE_DDRAW();
LEAVE_CSDDC();
DD_DoneDC(hdc_dd);
return DDERR_GENERIC;
}
#endif
}
// 5/24/2000(RichGr): IA64: Use %p format specifier for 32/64-bit pointers.
DPF( 5, "pdrv = 0x%p", pdrv );
if( pdrv == NULL )
{
DPF( 3, "Got returned NULL pdrv!" );
isdispdrv = FALSE;
hel_only = TRUE;
}
#ifdef WIN95
else
{
/*
* The only certified drivers are ones that we produced.
* DD_HAL_VERSION is different for internal vs external.
* We use this difference pick out ours.
*/
if( halver == DD_HAL_VERSION )
{
pdrv->ddCaps.dwCaps2 |= DDCAPS2_CERTIFIED;
DD16_SetCertified( TRUE );
}
}
#endif
}
}
/*
* no driver object found, so fake one up for the HEL (only do this
* for generic display drivers)
*/
if( pdrv == NULL || hel_only )
{
hel_only = TRUE;
pdrv = FakeDDCreateDriverObject( hdc_dd, pdrvname, NULL, FALSE, hDDVxd );
if( pdrv == NULL )
{
DPF_ERR( "Could not create HEL object" );
CLOSEVXD( hDDVxd );
LEAVE_DDRAW();
LEAVE_CSDDC();
DD_DoneDC(hdc_dd);
return DDERR_GENERIC;
}
/*
* the HEL is certified
*/
pdrv->ddCaps.dwCaps2 |= DDCAPS2_CERTIFIED;
strcpy( pdrv->cDriverName, pdrvname );
// Initialize Rect information for this pdrv
UpdateRectFromDevice( pdrv );
}
/*
* Even if it's not a display driver, it may still be a GDI driver
*/
if( hdc_dd != NULL )
{
if( !(pdrv->dwFlags & DDRAWI_DISPLAYDRV))
{
if (fDoesGDI(hdc_dd))
{
pdrv->dwFlags |= DDRAWI_GDIDRV;
}
else
{
pdrv->dwFlags &= ~DDRAWI_GDIDRV;
}
}
}
/*
* initialize for HEL usage
*/
capsInit( pdrv );
if( !helInit( pdrv, dwFlags, hel_only ) )
{
DPF_ERR( "helInit FAILED" );
CLOSEVXD( hDDVxd );
LEAVE_DDRAW();
LEAVE_CSDDC();
/* GEE: HEL can only fail in v1 for lack of memory */
DD_DoneDC(hdc_dd);
return DDERR_GENERIC;
}
/*
* create a new interface, and update the driver object with
* random bits o' data.
*/
pdrv_int = getDriverInterface( pnew_int, pdrv );
if( pdrv_int == NULL )
{
DPF_ERR( "No memory for driver callbacks." );
CLOSEVXD( hDDVxd );
LEAVE_DDRAW();
LEAVE_CSDDC();
DD_DoneDC(hdc_dd);
return DDERR_OUTOFMEMORY;
}
pdrv_lcl = pdrv_int->lpLcl;
pdrv_lcl->dwAppHackFlags = hackflags;
#ifdef DEBUG
if( dwRegFlags & DDRAW_REGFLAGS_DISABLEINACTIVATE )
{
pdrv_lcl->dwLocalFlags |= DDRAWILCL_DISABLEINACTIVATE;
}
#endif
if( IsAttachedToDesktop( lpGUID ) )
{
pdrv->dwFlags |= DDRAWI_ATTACHEDTODESKTOP;
}
if (bExplicitMonitor)
{
pdrv_lcl->dwLocalFlags |= DDRAWILCL_EXPLICITMONITOR;
}
pdrv_lcl->dwLocalFlags |= dwCallFlags;
/*
* Will be initialized to NULL on NT.
*/
pdrv_lcl->hDDVxd = (ULONG_PTR) hDDVxd;
if( hdc_dd != NULL )
{
#ifdef WIN95
// Make sure it doesn't get released by mistake
DD16_MakeObjectPrivate(hdc_dd, TRUE);
#endif
(HDC) pdrv_lcl->hDC = hdc_dd;
}
strcpy( pdrv->cDriverName, pdrvname );
#ifdef WINNT
/*
* The FetchDirectDrawData() call above loaded a DD handle into a
* into a temp location in the driver GBL object; we must now save
* the handle in the driver LCL object so it won't be overwritten.
*/
pdrv_lcl->hDD = pdrv->hDD;
#endif //WINNT
// Initialize cObsolete just in case some driver references the
// field. It will always be initialized to "DISPLAY".
lstrcpy(pdrv->cObsolete, DISPLAY_STR);
/*
* Initialize the kernel interface
*/
if( isdispdrv && !hel_only )
{
InitKernelInterface( pdrv_lcl );
}
LEAVE_DDRAW();
#ifdef WIN95
if( !hel_only )
{
extern DWORD WINAPI OpenVxDHandle( HANDLE hWin32Obj );
DWORD event16;
HANDLE h;
HelperCreateModeSetThread( DDNotifyModeSet, &h, pdrv_lcl->lpGbl,
pdrv->hInstance );
if( h != NULL )
{
event16 = OpenVxDHandle( h );
DPF( 4, "16-bit event handle=%08lx", event16 );
DD16_SetEventHandle( pdrv->hInstance, event16 );
pdrv->dwEvent16 = event16;
CloseHandle( h );
}
}
/*
* Create thread that will notify us when we are returning from
* a DOS box so we can invalidate the surfaces.
*/
if( !hel_only && bIsPrimary && IsWindows98() )
{
DWORD event16;
HANDLE h;
HelperCreateDOSBoxThread( DDNotifyDOSBox, &h, pdrv_lcl->lpGbl,
pdrv->hInstance );
if( h != NULL )
{
event16 = OpenVxDHandle( h );
DPF( 4, "DOS Box event handle=%08lx", event16 );
pdrv->dwDOSBoxEvent = event16;
SetKernelDOSBoxEvent( pdrv_lcl );
CloseHandle( h );
}
}
#endif
LEAVE_CSDDC();
*lplpDD = (LPDIRECTDRAW) pdrv_int;
return DD_OK;
} /* InternalDirectDrawCreate */
BOOL CALLBACK MonitorEnumProc(HMONITOR hMon, HDC hdc, LPRECT lpr, LPARAM lParam)
{
MONITORINFOEX mix;
MONITORINFO mi;
LPCALLBACKSTRUCT lpcb = (LPCALLBACKSTRUCT) lParam;
mi.cbSize = sizeof(mi);
if (!InternalGetMonitorInfo(hMon,&mi))
return FALSE;
mix.cbSize = sizeof(mix);
if (!InternalGetMonitorInfo(hMon,(MONITORINFO*) &mix))
return FALSE;
if (!strcmp(lpcb->pName,(LPSTR)mix.szDevice))
{
//Found it!!
lpcb->hMon = hMon;
return FALSE;
}
return TRUE;
}
/*
* GetMonitorFromDeviceName
*/
HMONITOR GetMonitorFromDeviceName(LPSTR szName)
{
CALLBACKSTRUCT cbs;
cbs.pName = szName;
cbs.hMon = NULL;
if (!InternalEnumMonitors(MonitorEnumProc, &cbs))
return NULL;
return cbs.hMon;
}
/*
* These callbacks are used to munge DirectDrawEnumerateEx's callback into the old
* style callback.
*/
typedef struct
{
LPDDENUMCALLBACKA lpCallback;
LPVOID lpContext;
} ENUMCALLBACKTRANSLATORA, * LPENUMCALLBACKTRANSLATORA;
BOOL FAR PASCAL TranslateCallbackA(GUID FAR *lpGUID, LPSTR pName , LPSTR pDesc , LPVOID pContext, HMONITOR hm)
{
LPENUMCALLBACKTRANSLATORA pTrans = (LPENUMCALLBACKTRANSLATORA) pContext;
return (pTrans->lpCallback) (lpGUID,pName,pDesc,pTrans->lpContext);
}
typedef struct
{
LPDDENUMCALLBACKW lpCallback;
LPVOID lpContext;
} ENUMCALLBACKTRANSLATORW, * LPENUMCALLBACKTRANSLATORW;
BOOL FAR PASCAL TranslateCallbackW(GUID FAR *lpGUID, LPWSTR pName , LPWSTR pDesc , LPVOID pContext, HMONITOR hm)
{
LPENUMCALLBACKTRANSLATORW pTrans = (LPENUMCALLBACKTRANSLATORW) pContext;
return (pTrans->lpCallback) (lpGUID,pName,pDesc,pTrans->lpContext);
}
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawEnumerateA"
/*
* DirectDrawEnumerateA
*/
HRESULT WINAPI DirectDrawEnumerateA(
LPDDENUMCALLBACKA lpCallback,
LPVOID lpContext )
{
ENUMCALLBACKTRANSLATORA Translate;
Translate.lpCallback = lpCallback;
Translate.lpContext = lpContext;
DPF(2,A,"ENTERAPI: DirectDrawEnumerateA");
if( !VALIDEX_CODE_PTR( lpCallback ) )
{
DPF( 0, "Invalid callback routine" );
return DDERR_INVALIDPARAMS;
}
#ifdef DEBUG
if (IsMultiMonitor())
{
DPF(0,"***********************************************");
DPF(0,"* Use DirectDrawEnumerateEx to enumerate *");
DPF(0,"* multiple monitors *");
DPF(0,"***********************************************");
}
#endif
return DirectDrawEnumerateExA(TranslateCallbackA, (LPVOID) & Translate, DDENUM_NONDISPLAYDEVICES);
} /* DirectDrawEnumerateA */
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawEnumerateW"
/*
* DirectDrawEnumerateW
*/
HRESULT WINAPI DirectDrawEnumerateW(
LPDDENUMCALLBACKW lpCallback,
LPVOID lpContext )
{
ENUMCALLBACKTRANSLATORW Translate;
Translate.lpCallback = lpCallback;
Translate.lpContext = lpContext;
DPF(2,A,"ENTERAPI: DirectDrawEnumerateW");
if( !VALIDEX_CODE_PTR( lpCallback ) )
{
DPF( 0, "Invalid callback routine" );
return DDERR_INVALIDPARAMS;
}
#ifdef DEBUG
if (IsMultiMonitor())
{
DPF(0,"***********************************************");
DPF(0,"* Use DirectDrawEnumerateEx to enumerate *");
DPF(0,"* multiple monitors *");
DPF(0,"***********************************************");
}
#endif
return DirectDrawEnumerateExW(TranslateCallbackW, (LPVOID) & Translate, DDENUM_NONDISPLAYDEVICES);
} /* DirectDrawEnumerateW */
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawEnumerateA"
/*
* DirectDrawEnumerateA
*/
HRESULT WINAPI DirectDrawEnumerateExA(
LPDDENUMCALLBACKEXA lpCallback,
LPVOID lpContext,
DWORD dwFlags )
{
DWORD rc;
DWORD keyidx;
HKEY hkey;
HKEY hsubkey;
char keyname[256];
char desc[256];
char drvname[MAX_PATH];
DWORD cb;
DWORD n;
DWORD type;
GUID guid;
HDC hdc;
DISPLAY_DEVICEA dd;
BOOL bEnumerateSecondariesLike3dfx=FALSE;
DPF(2,A,"ENTERAPI: DirectDrawEnumerateExA");
//BEGIN VOODOO2 HACK
{
HKEY hkey;
dwRegFlags &= ~DDRAW_REGFLAGS_ENUMERATEATTACHEDSECONDARIES;
if( !RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDRAW, &hkey ) )
{
DWORD cb;
DWORD value;
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_ENUMSECONDARY, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
DPF( 2, " EnumerateAttachedSecondaries: %d", value );
if( value )
{
bEnumerateSecondariesLike3dfx = TRUE;
dwRegFlags |= DDRAW_REGFLAGS_ENUMERATEATTACHEDSECONDARIES;
}
}
RegCloseKey(hkey);
}
}
//END VOODOO2 HACK
#ifdef WIN95
/*
* Did DDHELP fail to initialize properly?
*/
if( dwHelperPid == 0 )
{
return DDERR_NODIRECTDRAWSUPPORT;
}
#endif
if( !VALIDEX_CODE_PTR( lpCallback ) )
{
DPF( 0, "Invalid callback routine" );
return DDERR_INVALIDPARAMS;
}
if( dwFlags & ~DDENUM_VALID)
{
DPF_ERR("Invalid flags for DirectDrawEnumerateEx");
return DDERR_INVALIDPARAMS;
}
#ifdef WINNT
// We do not support detached devices on NT so silently ignore the flag:
dwFlags &= ~DDENUM_DETACHEDSECONDARYDEVICES;
#endif
LoadString( hModule, IDS_PRIMARYDISPLAY, desc, sizeof(desc) );
TRY
{
rc = lpCallback( NULL, desc, DISPLAY_STR, lpContext, NULL );
}
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
{
DPF_ERR( "Exception occurred during DirectDrawEnumerateEx callback" );
return DDERR_INVALIDPARAMS;
}
if( !rc )
{
return DD_OK;
}
if (dwFlags & DDENUM_NONDISPLAYDEVICES)
{
if( RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDHW, &hkey ) == 0 )
{
/*
* enumerate all subkeys under HKEY_LOCALMACHINE\Hardware\DirectDrawDrivers
*/
keyidx = 0;
while( !RegEnumKey( hkey, keyidx, keyname, sizeof( keyname ) ) )
{
if( strToGUID( keyname, &guid ) )
{
if( !RegOpenKey( hkey, keyname, &hsubkey ) )
{
cb = sizeof( desc ) - 1;
if( !RegQueryValueEx( hsubkey, REGSTR_KEY_DDHW_DESCRIPTION, NULL, &type,
(CONST LPBYTE)desc, &cb ) )
{
if( type == REG_SZ )
{
desc[cb] = 0;
cb = sizeof( drvname ) - 1;
if( !RegQueryValueEx( hsubkey, REGSTR_KEY_DDHW_DRIVERNAME, NULL, &type,
(CONST LPBYTE)drvname, &cb ) )
{
/*
* It is possible that the registry is out
* of date, so we will try to create a DC.
* The problem is that the Voodoo 1 driver
* will suceed on a Voodoo 2, Banshee, or
* Voodoo 3 (and hang later), so we need to
* hack around it.
*/
drvname[cb] = 0;
if( Voodoo1GoodToGo( &guid ) )
{
hdc = DD_CreateDC( drvname );
}
else
{
hdc = NULL;
}
if( ( type == REG_SZ ) &&
( hdc != NULL ) )
{
drvname[cb] = 0;
DPF( 5, "Enumerating GUID "
"%08lx-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
guid.Data1,
guid.Data2,
guid.Data3,
guid.Data4[ 0 ],
guid.Data4[ 1 ],
guid.Data4[ 2 ],
guid.Data4[ 3 ],
guid.Data4[ 4 ],
guid.Data4[ 5 ],
guid.Data4[ 6 ],
guid.Data4[ 7 ] );
DPF( 5, " Driver Name = %s", drvname );
DPF( 5, " Description = %s", desc );
rc = lpCallback( &guid, desc, drvname, lpContext , NULL);
if( !rc )
{
DD_DoneDC( hdc );
RegCloseKey( hsubkey );
RegCloseKey( hkey );
return DD_OK;
}
}
if( hdc != NULL )
{
DD_DoneDC( hdc );
}
}
}
}
RegCloseKey( hsubkey );
}
}
keyidx++;
}
RegCloseKey( hkey );
}
}
else
{
DPF( 3, "No registry information for any drivers" );
}
/*
* now enumerate all devices returned by EnumDisplayDevices
* We do this after the secondary drivers to hopefully not confuse people
* who are looking for 3DFx and have written bad code. Putting these
* after the 3DFx seems the safest thing to do..
*/
/* If there is only one device in the system then we don't
* enumerate it because it already is implicitly the primary
* This will improve behavior for badly written (i.e. our samples)
* D3D apps that are searching for a 3DFx device.
*/
if( !IsMultiMonitor() )
{
// If there is only one device; then just stop here.
DPF( 3, "Only one Display device in the current system." );
return DD_OK;
}
DPF( 3, "More than one display device in the current system." );
// Zero the memory of the DisplayDevice struct between calls to
// EnumDisplayDevices
ZeroMemory(&dd, sizeof(dd));
dd.cb = sizeof(dd);
for( n=0; xxxEnumDisplayDevicesA( NULL, n, &dd, 0 ); n++ )
{
GUID guid;
//
// skip drivers that are not hardware devices
//
if( dd.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER )
continue;
guid = DisplayGUID;
guid.Data1 += n;
if ( (dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) ?
((dwFlags & DDENUM_ATTACHEDSECONDARYDEVICES) ||
//BEGIN VOODOO2 HACK
(bEnumerateSecondariesLike3dfx && !(dd.StateFlags & DISPLAY_DEVICE_PRIMARY_DEVICE)) ):
//END VOODOO2 HACK
(dwFlags & DDENUM_DETACHEDSECONDARYDEVICES) )
{
HMONITOR hMonitor;
DPF( 5, "Enumerating GUID "
"%08lx-%04x-%04x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
guid.Data1,
guid.Data2,
guid.Data3,
guid.Data4[ 0 ],
guid.Data4[ 1 ],
guid.Data4[ 2 ],
guid.Data4[ 3 ],
guid.Data4[ 4 ],
guid.Data4[ 5 ],
guid.Data4[ 6 ],
guid.Data4[ 7 ] );
DPF( 5, " Driver Name = %s", dd.DeviceName );
DPF( 5, " Description = %s", dd.DeviceString );
hMonitor = GetMonitorFromDeviceName(dd.DeviceName);
rc = lpCallback( &guid, dd.DeviceString, dd.DeviceName, lpContext, hMonitor);
if( !rc )
{
return DD_OK;
}
}
// Zero the memory of the DisplayDevice struct between calls to
// EnumDisplayDevices
ZeroMemory( &dd, sizeof(dd) );
dd.cb = sizeof(dd);
}
return DD_OK;
} /* DirectDrawEnumerateExA */
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawEnumerateExW"
/*
* DirectDrawEnumerateExW
*/
HRESULT WINAPI DirectDrawEnumerateExW(
LPDDENUMCALLBACKEXW lpCallback,
LPVOID lpContext,
DWORD dwFlags)
{
DPF(2,A,"ENTERAPI: DirectDrawEnumerateExW");
DPF_ERR( "DirectDrawEnumerateEx for unicode is not created" );
return DDERR_UNSUPPORTED;
} /* DirectDrawEnumerateExW */
/*
* these are exported... temp. hack for non-Win95
*/
#ifndef WIN95
void DDAPI thk3216_ThunkData32( void )
{
}
void DDAPI thk1632_ThunkData32( void )
{
}
DWORD DDAPI DDGetPID( void )
{
return 0;
}
int DDAPI DDGetRequest( void )
{
return 0;
}
BOOL DDAPI DDGetDCInfo( LPSTR fname )
{
return 0;
}
void DDAPI DDHAL32_VidMemFree(
LPVOID this,
int heap,
FLATPTR ptr )
{
}
FLATPTR DDAPI DDHAL32_VidMemAlloc(
LPVOID this,
int heap,
DWORD dwWidth,
DWORD dwHeight )
{
return 0;
}
#ifdef POSTPONED
BOOL DDAPI DD32_HandleExternalModeChange(LPDEVMODE pModeInfo)
{
return FALSE;
}
#endif
#endif
/*
* _DirectDrawMsg
*/
DWORD WINAPI _DirectDrawMsg(LPVOID msg)
{
char title[80];
char ach[512];
MSGBOXPARAMS mb;
LoadString( hModule, IDS_TITLE, title, sizeof(title) );
if( HIWORD((ULONG_PTR)msg) )
{
lstrcpy( ach, (LPSTR)msg );
}
else
{
LoadString( hModule, (int)((ULONG_PTR)msg), ach, sizeof(ach) );
}
mb.cbSize = sizeof(mb);
mb.hwndOwner = NULL;
mb.hInstance = hModule;
mb.lpszText = ach;
mb.lpszCaption = title;
mb.dwStyle = MB_OK|MB_SETFOREGROUND|MB_TOPMOST|MB_ICONSTOP;
mb.lpszIcon = 0;
mb.dwContextHelpId = 0;
mb.lpfnMsgBoxCallback = NULL;
mb.dwLanguageId = 0;
return MessageBoxIndirect(&mb);
} /* _DirectDrawMsg */
/*
* DirectDrawMsg
*
* display an error message to the user, bring the message box up
* in another thread so the caller does not get reentered.
*/
DWORD DirectDrawMsg( LPSTR msg )
{
HANDLE h;
DWORD dw;
HKEY hkey;
//
// get the current error mode, dont show a message box if the app
// does not want us too.
//
dw = SetErrorMode(0);
SetErrorMode(dw);
if( dw & SEM_FAILCRITICALERRORS )
{
return 0;
}
/*
* If the registry says no dialogs, then no dialogs.
*/
if( !RegOpenKey( HKEY_LOCAL_MACHINE, REGSTR_PATH_DDRAW, &hkey ) )
{
DWORD type;
DWORD value;
DWORD cb;
cb = sizeof( value );
if( !RegQueryValueEx( hkey, REGSTR_VAL_DDRAW_DISABLEDIALOGS, NULL, &type, (CONST LPBYTE)&value, &cb ) )
{
if (value)
{
RegCloseKey( hkey );
return 0;
}
}
RegCloseKey( hkey );
}
if( h = CreateThread(NULL, 0, _DirectDrawMsg, (LPVOID)msg, 0, &dw) )
{
WaitForSingleObject( h, INFINITE );
GetExitCodeThread( h, &dw );
CloseHandle( h );
}
else
{
dw = 0;
}
return dw;
} /* DirectDrawMsg */
/*
* convertV1DDHALINFO
*
* Convert an obsolete DDHALINFO structure to the latest and greatest structure.
* This function takes a pointer to an LPDDHALINFO structure which has the same size as
* the new structure but has been filled in as if it is the V1 structure. Information is moved
* around in the structure and the new fields are cleared.
*/
void convertV1DDHALINFO( LPDDHALINFO lpDDHALInfo )
{
DDHALINFO ddNew;
LPDDHALINFO_V1 lpddOld = (LPVOID)lpDDHALInfo;
int i;
ddNew.dwSize = sizeof( DDHALINFO );
ddNew.lpDDCallbacks = lpddOld->lpDDCallbacks;
ddNew.lpDDSurfaceCallbacks = lpddOld->lpDDSurfaceCallbacks;
ddNew.lpDDPaletteCallbacks = lpddOld->lpDDPaletteCallbacks;
ddNew.vmiData = lpddOld->vmiData;
// ddCaps
ddNew.ddCaps.dwSize = lpddOld->ddCaps.dwSize;
ddNew.ddCaps.dwCaps = lpddOld->ddCaps.dwCaps;
ddNew.ddCaps.dwCaps2 = lpddOld->ddCaps.dwCaps2;
ddNew.ddCaps.dwCKeyCaps = lpddOld->ddCaps.dwCKeyCaps;
ddNew.ddCaps.dwFXCaps = lpddOld->ddCaps.dwFXCaps;
ddNew.ddCaps.dwFXAlphaCaps = lpddOld->ddCaps.dwFXAlphaCaps;
ddNew.ddCaps.dwPalCaps = lpddOld->ddCaps.dwPalCaps;
ddNew.ddCaps.dwSVCaps = lpddOld->ddCaps.dwSVCaps;
ddNew.ddCaps.dwAlphaBltConstBitDepths = lpddOld->ddCaps.dwAlphaBltConstBitDepths;
ddNew.ddCaps.dwAlphaBltPixelBitDepths = lpddOld->ddCaps.dwAlphaBltPixelBitDepths;
ddNew.ddCaps.dwAlphaBltSurfaceBitDepths = lpddOld->ddCaps.dwAlphaBltSurfaceBitDepths;
ddNew.ddCaps.dwAlphaOverlayConstBitDepths = lpddOld->ddCaps.dwAlphaOverlayConstBitDepths;
ddNew.ddCaps.dwAlphaOverlayPixelBitDepths = lpddOld->ddCaps.dwAlphaOverlayPixelBitDepths;
ddNew.ddCaps.dwAlphaOverlaySurfaceBitDepths = lpddOld->ddCaps.dwAlphaOverlaySurfaceBitDepths;
ddNew.ddCaps.dwZBufferBitDepths = lpddOld->ddCaps.dwZBufferBitDepths;
ddNew.ddCaps.dwVidMemTotal = lpddOld->ddCaps.dwVidMemTotal;
ddNew.ddCaps.dwVidMemFree = lpddOld->ddCaps.dwVidMemFree;
ddNew.ddCaps.dwMaxVisibleOverlays = lpddOld->ddCaps.dwMaxVisibleOverlays;
ddNew.ddCaps.dwCurrVisibleOverlays = lpddOld->ddCaps.dwCurrVisibleOverlays;
ddNew.ddCaps.dwNumFourCCCodes = lpddOld->ddCaps.dwNumFourCCCodes;
ddNew.ddCaps.dwAlignBoundarySrc = lpddOld->ddCaps.dwAlignBoundarySrc;
ddNew.ddCaps.dwAlignSizeSrc = lpddOld->ddCaps.dwAlignSizeSrc;
ddNew.ddCaps.dwAlignBoundaryDest = lpddOld->ddCaps.dwAlignBoundaryDest;
ddNew.ddCaps.dwAlignSizeDest = lpddOld->ddCaps.dwAlignSizeDest;
ddNew.ddCaps.dwAlignStrideAlign = lpddOld->ddCaps.dwAlignStrideAlign;
ddNew.ddCaps.ddsCaps = lpddOld->ddCaps.ddsCaps;
ddNew.ddCaps.dwMinOverlayStretch = lpddOld->ddCaps.dwMinOverlayStretch;
ddNew.ddCaps.dwMaxOverlayStretch = lpddOld->ddCaps.dwMaxOverlayStretch;
ddNew.ddCaps.dwMinLiveVideoStretch = lpddOld->ddCaps.dwMinLiveVideoStretch;
ddNew.ddCaps.dwMaxLiveVideoStretch = lpddOld->ddCaps.dwMaxLiveVideoStretch;
ddNew.ddCaps.dwMinHwCodecStretch = lpddOld->ddCaps.dwMinHwCodecStretch;
ddNew.ddCaps.dwMaxHwCodecStretch = lpddOld->ddCaps.dwMaxHwCodecStretch;
ddNew.ddCaps.dwSVBCaps = 0;
ddNew.ddCaps.dwSVBCKeyCaps = 0;
ddNew.ddCaps.dwSVBFXCaps = 0;
ddNew.ddCaps.dwVSBCaps = 0;
ddNew.ddCaps.dwVSBCKeyCaps = 0;
ddNew.ddCaps.dwVSBFXCaps = 0;
ddNew.ddCaps.dwSSBCaps = 0;
ddNew.ddCaps.dwSSBCKeyCaps = 0;
ddNew.ddCaps.dwSSBFXCaps = 0;
ddNew.ddCaps.dwMaxVideoPorts = 0;
ddNew.ddCaps.dwCurrVideoPorts = 0;
ddNew.ddCaps.dwReserved1 = lpddOld->ddCaps.dwReserved1;
ddNew.ddCaps.dwReserved2 = lpddOld->ddCaps.dwReserved2;
ddNew.ddCaps.dwReserved3 = lpddOld->ddCaps.dwReserved3;
ddNew.ddCaps.dwSVBCaps2 = 0;
for(i=0; i<DD_ROP_SPACE; i++)
{
ddNew.ddCaps.dwRops[i] = lpddOld->ddCaps.dwRops[i];
ddNew.ddCaps.dwSVBRops[i] = 0;
ddNew.ddCaps.dwVSBRops[i] = 0;
ddNew.ddCaps.dwSSBRops[i] = 0;
}
ddNew.dwMonitorFrequency = lpddOld->dwMonitorFrequency;
ddNew.GetDriverInfo = NULL; // was unused hWndListBox in v1
ddNew.dwModeIndex = lpddOld->dwModeIndex;
ddNew.lpdwFourCC = lpddOld->lpdwFourCC;
ddNew.dwNumModes = lpddOld->dwNumModes;
ddNew.lpModeInfo = lpddOld->lpModeInfo;
ddNew.dwFlags = lpddOld->dwFlags;
ddNew.lpPDevice = lpddOld->lpPDevice;
ddNew.hInstance = lpddOld->hInstance;
ddNew.lpD3DGlobalDriverData = 0;
ddNew.lpD3DHALCallbacks = 0;
ddNew.lpDDExeBufCallbacks = NULL;
*lpDDHALInfo = ddNew;
}
// The callback used by Win9x drivers and the software rasterizers to help them
// parse execute buffers.
HRESULT CALLBACK D3DParseUnknownCommand (LPVOID lpvCommands,
LPVOID *lplpvReturnedCommand)
{
LPD3DINSTRUCTION lpInstr = (LPD3DINSTRUCTION) lpvCommands;
// Initialize the return address to the command's address
*lplpvReturnedCommand = lpvCommands;
switch (lpInstr->bOpcode)
{
case D3DOP_PROCESSVERTICES:
// cannot do D3DOP_PROCESSVERTICES here even for in-place copy because we
// generally don't pass the execute buffer's vertex buffer as the DP2 vertex buffer
return D3DERR_COMMAND_UNPARSED;
case D3DOP_SPAN:
*lplpvReturnedCommand = (LPVOID) ((LPBYTE)lpInstr +
sizeof (D3DINSTRUCTION) +
lpInstr->wCount *
lpInstr->bSize);
return DD_OK;
case D3DDP2OP_VIEWPORTINFO:
*lplpvReturnedCommand = (LPVOID) ((LPBYTE)lpInstr +
sizeof(D3DHAL_DP2COMMAND) +
lpInstr->wCount *
sizeof(D3DHAL_DP2VIEWPORTINFO));
return DD_OK;
case D3DDP2OP_WINFO:
*lplpvReturnedCommand = (LPVOID) ((LPBYTE)lpInstr +
sizeof(D3DHAL_DP2COMMAND) +
lpInstr->wCount *
sizeof(D3DHAL_DP2WINFO));
return DD_OK;
case D3DOP_MATRIXLOAD:
case D3DOP_MATRIXMULTIPLY:
case D3DOP_STATETRANSFORM:
case D3DOP_STATELIGHT:
case D3DOP_TEXTURELOAD:
case D3DOP_BRANCHFORWARD:
case D3DOP_SETSTATUS:
case D3DOP_EXIT:
return D3DERR_COMMAND_UNPARSED;
default:
return DDERR_GENERIC;
}
}
/*
* fetchModeXData
*/
LPDDRAWI_DIRECTDRAW_GBL fetchModeXData(
LPDDRAWI_DIRECTDRAW_GBL pdrv,
LPDDHALMODEINFO pmi,
HANDLE hDDVxd )
{
DDHALINFO ddhi;
LPDDRAWI_DIRECTDRAW_GBL new_pdrv;
DDPIXELFORMAT dpf;
#ifdef WINNT
DDHALMODEINFO dmi;
#endif
/*
* initialize the DDHALINFO struct
*/
memset( &ddhi, 0, sizeof( ddhi ) );
ddhi.dwSize = sizeof( ddhi );
/*
* capabilities supported (none)
*/
ddhi.ddCaps.dwCaps = 0;
ddhi.ddCaps.dwFXCaps = 0;
ddhi.ddCaps.dwCKeyCaps = 0;
ddhi.ddCaps.ddsCaps.dwCaps = 0;
/*
* pointer to primary surface.
*/
if ( pmi->wFlags & DDMODEINFO_STANDARDVGA )
{
ddhi.vmiData.fpPrimary = 0xa0000;
}
else
{
//This needs to be SCREEN_PTR or the HEL won't realize it's a bad address
//(since when restoring display modes, restoreSurface for the primary will
//call into AllocSurfaceMem which will triviallt allocate the primary surface
//by setting fpVidMem == fpPrimaryOrig which will have been set to whatever
//we set here.
ddhi.vmiData.fpPrimary = 0xffbadbad;
}
/*
* build mode and pixel format info
*/
ddhi.vmiData.dwDisplayHeight = pmi->dwHeight;
ddhi.vmiData.dwDisplayWidth = pmi->dwWidth;
ddhi.vmiData.lDisplayPitch = pmi->lPitch;
BuildPixelFormat( NULL, pmi, &dpf );
ddhi.vmiData.ddpfDisplay = dpf;
/*
* fourcc code information
*/
ddhi.ddCaps.dwNumFourCCCodes = 0;
ddhi.lpdwFourCC = NULL;
/*
* Fill in heap info
*/
ddhi.vmiData.dwNumHeaps = 0;
ddhi.vmiData.pvmList = NULL;
/*
* required alignments of the scanlines of each kind of memory
* (DWORD is the MINIMUM)
*/
ddhi.vmiData.dwOffscreenAlign = sizeof( DWORD );
ddhi.vmiData.dwTextureAlign = sizeof( DWORD );
ddhi.vmiData.dwZBufferAlign = sizeof( DWORD );
/*
* callback functions
*/
ddhi.lpDDCallbacks = NULL;
ddhi.lpDDSurfaceCallbacks = NULL;
ddhi.lpDDPaletteCallbacks = NULL;
/*
* create the driver object
*/
#ifdef WINNT
//We can only get into modex if the ddraw object has already been created:
DDASSERT(pdrv);
//Don't fetch the driver's caps
ddhi.ddCaps.dwCaps = DDCAPS_NOHARDWARE;
//Force the modex data into the pdd. This causes GetCurrentMode to be a noop.
//pdrv->dwFlags |= DDRAWI_NOHARDWARE;
pdrv->dmiCurrent.wWidth =(WORD)pmi->dwWidth;
pdrv->dmiCurrent.wHeight =(WORD)pmi->dwHeight;
pdrv->dmiCurrent.wBPP =(BYTE)pmi->dwBPP;
pdrv->dmiCurrent.wRefreshRate =pmi->wRefreshRate;
pdrv->dmiCurrent.wMonitorsAttachedToDesktop=(BYTE)GetNumberOfMonitorAttachedToDesktop();
#endif
new_pdrv = DirectDrawObjectCreate( &ddhi, TRUE, pdrv, hDDVxd, NULL, 0 , 0 /* ATTENTION: No local flags for modex driver */ );
DPF(5,"MODEX driver object's display is %dx%d, pitch is %d", ddhi.vmiData.dwDisplayHeight,ddhi.vmiData.dwDisplayWidth,ddhi.vmiData.lDisplayPitch);
if( new_pdrv != NULL )
{
new_pdrv->dwFlags |= DDRAWI_MODEX;
if ( pmi->wFlags & DDMODEINFO_STANDARDVGA )
{
new_pdrv->dwFlags |= DDRAWI_STANDARDVGA;
}
#ifdef WIN95
if( new_pdrv->dwPDevice != 0 )
{
new_pdrv->dwPDevice = 0;
new_pdrv->lpwPDeviceFlags = (WORD *)&dwFakeFlags;
}
#endif //WIN95
}
DPF( 5, "ModeX DirectDraw object created (Standard VGA flag:%d)", (new_pdrv->dwFlags & DDRAWI_STANDARDVGA) ? 1 : 0 );
DPF( 5, " width=%ld, height=%ld, %ld bpp",
new_pdrv->vmiData.dwDisplayWidth,
new_pdrv->vmiData.dwDisplayHeight,
new_pdrv->vmiData.ddpfDisplay.dwRGBBitCount );
DPF( 5, " lDisplayPitch = %ld", new_pdrv->vmiData.lDisplayPitch );
return new_pdrv;
} /* fetchModeXData */
#ifdef WINNT
/*
* GetDriverInfo2
*/
DWORD APIENTRY GetDriverInfo2(LPDDRAWI_DIRECTDRAW_GBL lpGbl,
DWORD* pdwDrvRet,
DWORD dwType,
DWORD dwSize,
void* pBuffer)
{
DD_GETDRIVERINFO2DATA* pGDI2Data;
DWORD ret;
DDHAL_GETDRIVERINFODATA gdidata;
// We cannot do anything if the driver doesn't support GetDriverInfo2
if ((lpGbl == NULL) || (!(lpGbl->dwFlags & DDRAWI_DRIVERINFO2)))
{
return 0;
}
// Setup GetDriverInfo2 call
pGDI2Data = (DD_GETDRIVERINFO2DATA*) pBuffer;
memset(pGDI2Data, 0, sizeof(*pGDI2Data));
pGDI2Data->dwReserved = sizeof(DD_STEREOMODE);
pGDI2Data->dwMagic = D3DGDI2_MAGIC;
pGDI2Data->dwType = dwType;
pGDI2Data->dwExpectedSize = dwSize;
ret = GetDriverInfo(lpGbl->pGetDriverInfo,
&gdidata,
pBuffer,
sizeof(DD_STEREOMODE),
&GUID_GetDriverInfo2,
lpGbl,
TRUE /* bInOut */);
*pdwDrvRet = gdidata.ddRVal;
return ret;
}
/*
* NotifyDriverOfFreeAliasedLocks
*
* This notifies the driver that we have unlocked all outstanding aliased
* locks on the device. It is possible to have multiple GBLs using the same
* physical device, so we need to handle that.
*/
void NotifyDriverOfFreeAliasedLocks()
{
DD_FREE_DEFERRED_AGP_DATA fad;
DWORD dwDrvRet;
LPDDRAWI_DIRECTDRAW_LCL pdd_lcl;
LPDDRAWI_DIRECTDRAW_LCL pdd_temp;
BOOL bSkipThisOne;
if (dwNumLockedWhenModeSwitched == 0)
{
// Notify each device that all outstanding syslocks are gone
fad.dwProcessId = GetCurrentProcessId();
pdd_lcl = lpDriverLocalList;
while (pdd_lcl != NULL)
{
bSkipThisOne = FALSE;
pdd_temp = lpDriverLocalList;
while ((pdd_temp != NULL) &&
(pdd_temp != pdd_lcl))
{
if (pdd_temp->lpGbl == pdd_lcl->lpGbl)
{
bSkipThisOne = TRUE;
break;
}
pdd_temp = pdd_temp->lpLink;
}
if (!bSkipThisOne)
{
GetDriverInfo2(pdd_lcl->lpGbl, &dwDrvRet,
D3DGDI2_TYPE_FREE_DEFERRED_AGP,
sizeof(fad), &fad);
}
pdd_lcl = pdd_lcl->lpLink;
}
}
}
/*
* NotifyDriverToDeferFrees
*
* This notifies the driver that we are doing a mode change and they
* should start defering AGP free if they need to.
*/
void NotifyDriverToDeferFrees()
{
DD_FREE_DEFERRED_AGP_DATA fad;
DWORD dwDrvRet;
LPDDRAWI_DIRECTDRAW_LCL pdd_lcl;
LPDDRAWI_DIRECTDRAW_LCL pdd_temp;
BOOL bSkipThisOne;
// Notify each device that all outstanding syslocks are gone
fad.dwProcessId = GetCurrentProcessId();
pdd_lcl = lpDriverLocalList;
while (pdd_lcl != NULL)
{
bSkipThisOne = FALSE;
pdd_temp = lpDriverLocalList;
while ((pdd_temp != NULL) &&
(pdd_temp != pdd_lcl))
{
if (pdd_temp->lpGbl == pdd_lcl->lpGbl)
{
bSkipThisOne = TRUE;
break;
}
pdd_temp = pdd_temp->lpLink;
}
if (!bSkipThisOne)
{
GetDriverInfo2(pdd_lcl->lpGbl, &dwDrvRet,
D3DGDI2_TYPE_DEFER_AGP_FREES,
sizeof(fad), &fad);
}
pdd_lcl = pdd_lcl->lpLink;
}
}
/*
* CheckAliasedLocksOnModeChange
*
* On NT we have to tell the driver when we are done using all surfaces that were
* locked with NOSYSLOCK so they can properly handle the case when they manage
* their own AGP heaps.
*/
void CheckAliasedLocksOnModeChange()
{
DWORD dwGDI2Ret;
LPDDRAWI_DIRECTDRAW_LCL pdd_lcl;
LPDDRAWI_DIRECTDRAW_LCL pdd_temp;
LPDDRAWI_DDRAWSURFACE_INT psurf_int;
BOOL bSkipThisOne;
// For each device, figure out how many surfs are holding aliased locks and
// mark the surfaces.
dwNumLockedWhenModeSwitched = 0;
pdd_lcl = lpDriverLocalList;
while (pdd_lcl != NULL)
{
// if we have already processed this GBL, don't do it again!
bSkipThisOne = FALSE;
pdd_temp = lpDriverLocalList;
while ((pdd_temp != NULL) &&
(pdd_temp != pdd_lcl))
{
if (pdd_temp->lpGbl == pdd_lcl->lpGbl)
{
bSkipThisOne = TRUE;
break;
}
pdd_temp = pdd_temp->lpLink;
}
if (!bSkipThisOne &&
(pdd_lcl->lpGbl != NULL))
{
// We need to start fresh with each device, so clear all flags we
// have outstanding as to whether the surface has an outstanding
// NOSYSLOCK lock.
psurf_int = pdd_lcl->lpGbl->dsList;
while (psurf_int != NULL)
{
if (psurf_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_NOTIFYWHENUNLOCKED)
{
psurf_int->lpLcl->lpGbl->dwGlobalFlags &= ~DDRAWISURFGBL_NOTIFYWHENUNLOCKED;
}
psurf_int = psurf_int->lpLink;
}
// Now we go back through them and re-mark them.
psurf_int = pdd_lcl->lpGbl->dsList;
while (psurf_int != NULL)
{
if ((psurf_int->lpLcl->lpGbl->dwUsageCount > 0) &&
!(psurf_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_NOTIFYWHENUNLOCKED))
{
// The code below relies on the fact that the NT kernel
// cannot handle multiple locks to the same surface if any
// one of them is a NOSYSLOCK. If this ever changes, this
// code needs to be changed.
if (psurf_int->lpLcl->lpGbl->dwGlobalFlags & DDRAWISURFGBL_LOCKNOTHOLDINGWIN16LOCK)
{
psurf_int->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_NOTIFYWHENUNLOCKED;
dwNumLockedWhenModeSwitched++;
}
else if ((psurf_int->lpLcl->lpGbl->lpRectList != NULL) &&
(psurf_int->lpLcl->lpGbl->lpRectList->dwFlags & ACCESSRECT_NOTHOLDINGWIN16LOCK))
{
psurf_int->lpLcl->lpGbl->dwGlobalFlags |= DDRAWISURFGBL_NOTIFYWHENUNLOCKED;
dwNumLockedWhenModeSwitched++;
}
}
psurf_int = psurf_int->lpLink;
}
}
pdd_lcl = pdd_lcl->lpLink;
}
// Now see if we can notify the drivers to free the surfaces or not.
if ((dwNumLockedWhenModeSwitched == 0) &&
(lpDriverLocalList != NULL))
{
// For DX9, add logic here to handle bad PDEVs
NotifyDriverOfFreeAliasedLocks();
}
}
#endif