|
|
/*==========================================================================
* * 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 somebody 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 * ***************************************************************************/ extern "C" { #include "ddrawpr.h"
#ifdef WINNT
#include "ddrawgdi.h"
#define BUILD_DDDDK
#include "d3dhal.h"
#endif
#ifdef WIN95
#include "d3dhal.h"
#endif
} // extern C
#include "pixel.hpp"
#ifdef DEBUG
#define static
#endif
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawObjectCreate"
#define DISPLAY_STR "display"
#define D3DFORMAT_OP_BACKBUFFER 0x00000020L
char g_szPrimaryDisplay[MAX_DRIVER_NAME] = "";
void getPrimaryDisplayName(void);
#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
/*
* 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
#undef DPF_MODNAME
#define DPF_MODNAME "MakeDX8Caps"
void MakeDX8Caps( D3DCAPS8 *pCaps8, const D3D8_GLOBALDRIVERDATA* pGblDrvData, const D3DHAL_D3DEXTENDEDCAPS* pExtCaps ) { // we shouldn't memset pCaps8 as members like Caps, Caps2, Caps3 (dwSVCaps) and
// CursorCaps are already set by Thunk layer
pCaps8->DevCaps = pGblDrvData->hwCaps.dwDevCaps;
pCaps8->PrimitiveMiscCaps = pGblDrvData->hwCaps.dpcTriCaps.dwMiscCaps; pCaps8->RasterCaps = pGblDrvData->hwCaps.dpcTriCaps.dwRasterCaps; pCaps8->ZCmpCaps = pGblDrvData->hwCaps.dpcTriCaps.dwZCmpCaps; pCaps8->SrcBlendCaps = pGblDrvData->hwCaps.dpcTriCaps.dwSrcBlendCaps; pCaps8->DestBlendCaps = pGblDrvData->hwCaps.dpcTriCaps.dwDestBlendCaps; pCaps8->AlphaCmpCaps = pGblDrvData->hwCaps.dpcTriCaps.dwAlphaCmpCaps; pCaps8->ShadeCaps = pGblDrvData->hwCaps.dpcTriCaps.dwShadeCaps; pCaps8->TextureCaps = pGblDrvData->hwCaps.dpcTriCaps.dwTextureCaps; pCaps8->TextureFilterCaps = pGblDrvData->hwCaps.dpcTriCaps.dwTextureFilterCaps;
// Adjust the texture filter caps for the legacy drivers that
// set only the legacy texture filter caps and not the newer ones.
if ((pCaps8->TextureFilterCaps & (D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MIPFLINEAR)) == 0) { if (pCaps8->TextureFilterCaps & D3DPTFILTERCAPS_NEAREST) { pCaps8->TextureFilterCaps |= (D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MAGFPOINT); }
if (pCaps8->TextureFilterCaps & D3DPTFILTERCAPS_LINEAR) { pCaps8->TextureFilterCaps |= (D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MAGFLINEAR); }
if (pCaps8->TextureFilterCaps & D3DPTFILTERCAPS_MIPNEAREST) { pCaps8->TextureFilterCaps |= (D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MIPFPOINT); }
if (pCaps8->TextureFilterCaps & D3DPTFILTERCAPS_MIPLINEAR) { pCaps8->TextureFilterCaps |= (D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MIPFPOINT); }
if (pCaps8->TextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPNEAREST) { pCaps8->TextureFilterCaps |= (D3DPTFILTERCAPS_MINFPOINT | D3DPTFILTERCAPS_MAGFPOINT | D3DPTFILTERCAPS_MIPFLINEAR); }
if (pCaps8->TextureFilterCaps & D3DPTFILTERCAPS_LINEARMIPLINEAR) { pCaps8->TextureFilterCaps |= (D3DPTFILTERCAPS_MINFLINEAR | D3DPTFILTERCAPS_MAGFLINEAR | D3DPTFILTERCAPS_MIPFLINEAR); } } pCaps8->TextureAddressCaps = pGblDrvData->hwCaps.dpcTriCaps.dwTextureAddressCaps;
// Set the cube-texture filter caps only if the device supports
// cubemaps.
if (pCaps8->TextureCaps & D3DPTEXTURECAPS_CUBEMAP) { pCaps8->CubeTextureFilterCaps = pGblDrvData->hwCaps.dpcTriCaps.dwTextureFilterCaps; } const D3DPRIMCAPS* pTC = &pGblDrvData->hwCaps.dpcTriCaps; const D3DPRIMCAPS* pLC = &pGblDrvData->hwCaps.dpcLineCaps; if (pLC->dwTextureCaps) pCaps8->LineCaps |= D3DLINECAPS_TEXTURE ; if (pLC->dwZCmpCaps == pTC->dwZCmpCaps) pCaps8->LineCaps |= D3DLINECAPS_ZTEST; if ( (pLC->dwSrcBlendCaps == pTC->dwSrcBlendCaps) && (pLC->dwDestBlendCaps == pTC->dwDestBlendCaps) ) pCaps8->LineCaps |= D3DLINECAPS_BLEND; if (pLC->dwAlphaCmpCaps == pTC->dwAlphaCmpCaps) pCaps8->LineCaps |= D3DLINECAPS_ALPHACMP; if (pLC->dwRasterCaps & (D3DPRASTERCAPS_FOGVERTEX|D3DPRASTERCAPS_FOGTABLE)) pCaps8->LineCaps |= D3DLINECAPS_FOG;
if( pExtCaps->dwMaxTextureWidth == 0 ) pCaps8->MaxTextureWidth = 256; else pCaps8->MaxTextureWidth = pExtCaps->dwMaxTextureWidth; if( pExtCaps->dwMaxTextureHeight == 0 ) pCaps8->MaxTextureHeight = 256; else pCaps8->MaxTextureHeight = pExtCaps->dwMaxTextureHeight;
pCaps8->MaxTextureRepeat = pExtCaps->dwMaxTextureRepeat; pCaps8->MaxTextureAspectRatio = pExtCaps->dwMaxTextureAspectRatio; pCaps8->MaxAnisotropy = pExtCaps->dwMaxAnisotropy; pCaps8->MaxVertexW = pExtCaps->dvMaxVertexW;
pCaps8->GuardBandLeft = pExtCaps->dvGuardBandLeft; pCaps8->GuardBandTop = pExtCaps->dvGuardBandTop; pCaps8->GuardBandRight = pExtCaps->dvGuardBandRight; pCaps8->GuardBandBottom = pExtCaps->dvGuardBandBottom;
pCaps8->ExtentsAdjust = pExtCaps->dvExtentsAdjust; pCaps8->StencilCaps = pExtCaps->dwStencilCaps;
pCaps8->FVFCaps = pExtCaps->dwFVFCaps; pCaps8->TextureOpCaps = pExtCaps->dwTextureOpCaps; pCaps8->MaxTextureBlendStages = pExtCaps->wMaxTextureBlendStages; pCaps8->MaxSimultaneousTextures = pExtCaps->wMaxSimultaneousTextures;
pCaps8->VertexProcessingCaps = pExtCaps->dwVertexProcessingCaps; pCaps8->MaxActiveLights = pExtCaps->dwMaxActiveLights; pCaps8->MaxUserClipPlanes = pExtCaps->wMaxUserClipPlanes; pCaps8->MaxVertexBlendMatrices = pExtCaps->wMaxVertexBlendMatrices; if (pCaps8->MaxVertexBlendMatrices == 1) pCaps8->MaxVertexBlendMatrices = 0;
//
// Stuff in the DX8 caps that cannot be reported by the pre DX8 drivers
//
pCaps8->MaxPointSize = 0; pCaps8->MaxPrimitiveCount = 0xffff; pCaps8->MaxVertexIndex = 0xffff; pCaps8->MaxStreams = 0; pCaps8->MaxStreamStride = 255; pCaps8->MaxVertexBlendMatrixIndex = 0; pCaps8->MaxVolumeExtent = 0;
// Format is 8.8 in bottom of DWORD
pCaps8->VertexShaderVersion = D3DVS_VERSION(0,0); pCaps8->MaxVertexShaderConst = 0; pCaps8->PixelShaderVersion = D3DPS_VERSION(0,0); pCaps8->MaxPixelShaderValue = 1.0f;
} // MakeDX8Caps
/*
* 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) { HMODULE h = GetModuleHandle("USER32"); BOOL (WINAPI *pfnEnumDisplayDevices)(LPVOID, DWORD, DISPLAY_DEVICEA *, DWORD);
*((void **)&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); }
//else we emulate the function for 95, NT4:
if (iDevice > 0) return FALSE;
pdd->StateFlags = DISPLAY_DEVICE_PRIMARY_DEVICE; lstrcpy(pdd->DeviceName, DISPLAY_STR); LoadString(g_hModule, IDS_PRIMARYDISPLAY, pdd->DeviceString, sizeof(pdd->DeviceString));
return TRUE; }
// 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
#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 S_OK; } } return E_FAIL; } #endif
/*
* 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) || ((szDevice[0] == '\\') && (szDevice[1] == '\\') && (szDevice[2] == '.'))) { return TRUE; }
return FALSE; }
/*
* 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 = E_FAIL;
// 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
return TRUE;
} /* GetDDStereoMode */
#endif //WINNT
/*
* doneDC */ void DD_DoneDC(HDC hdc_dd) { if (hdc_dd != NULL) { DPF(5, "DeleteDC 0x%x", hdc_dd); DeleteDC(hdc_dd); hdc_dd = NULL; }
} /* doneDC */
#undef DPF_MODNAME
#define DPF_MODNAME "DirectDrawCreate"
/*
* 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 */
/*****************************Private*Routine******************************\
* DdConvertFromOldFormat * * History: * 13-Nov-1999 -by- Scott MacDonald [smac] * Wrote it. \**************************************************************************/
#undef DPF_MODNAME
#define DPF_MODNAME "ConvertFromOldFormat"
void ConvertFromOldFormat(LPDDPIXELFORMAT pOldFormat, D3DFORMAT *pNewFormat) { *pNewFormat = D3DFMT_UNKNOWN; if (pOldFormat->dwFlags & DDPF_FOURCC) { *pNewFormat = (D3DFORMAT) pOldFormat->dwFourCC; } else if (pOldFormat->dwFlags == DDPF_RGB) { switch (pOldFormat->dwRGBBitCount) { case 8: if ((pOldFormat->dwRBitMask == 0x000000e0) && (pOldFormat->dwGBitMask == 0x0000001c) && (pOldFormat->dwBBitMask == 0x00000003)) { *pNewFormat = D3DFMT_R3G3B2; } else { *pNewFormat = D3DFMT_P8; } break;
case 16: if ((pOldFormat->dwRBitMask == 0x0000f800) && (pOldFormat->dwGBitMask == 0x000007e0) && (pOldFormat->dwBBitMask == 0x0000001f)) { *pNewFormat = D3DFMT_R5G6B5; } else if ((pOldFormat->dwRBitMask == 0x00007c00) && (pOldFormat->dwGBitMask == 0x000003e0) && (pOldFormat->dwBBitMask == 0x0000001f)) { *pNewFormat = D3DFMT_X1R5G5B5; } else if ((pOldFormat->dwRBitMask == 0x00000f00) && (pOldFormat->dwGBitMask == 0x000000f0) && (pOldFormat->dwBBitMask == 0x0000000f)) { *pNewFormat = D3DFMT_X4R4G4B4; } break;
case 24: if ((pOldFormat->dwRBitMask == 0x00ff0000) && (pOldFormat->dwGBitMask == 0x0000ff00) && (pOldFormat->dwBBitMask == 0x000000ff)) { *pNewFormat = D3DFMT_R8G8B8; } break;
case 32: if ((pOldFormat->dwRBitMask == 0x00ff0000) && (pOldFormat->dwGBitMask == 0x0000ff00) && (pOldFormat->dwBBitMask == 0x000000ff)) { *pNewFormat = D3DFMT_X8R8G8B8; } break; } } else if (pOldFormat->dwFlags == (DDPF_RGB | DDPF_ALPHAPIXELS)) { switch (pOldFormat->dwRGBBitCount) { case 16: if ((pOldFormat->dwRGBAlphaBitMask == 0x0000FF00) && (pOldFormat->dwRBitMask == 0x000000e0) && (pOldFormat->dwGBitMask == 0x0000001c) && (pOldFormat->dwBBitMask == 0x00000003)) { *pNewFormat = D3DFMT_A8R3G3B2; } else if ((pOldFormat->dwRGBAlphaBitMask == 0x0000f000) && (pOldFormat->dwRBitMask == 0x00000f00) && (pOldFormat->dwGBitMask == 0x000000f0) && (pOldFormat->dwBBitMask == 0x0000000f)) { *pNewFormat = D3DFMT_A4R4G4B4; } else if ((pOldFormat->dwRGBAlphaBitMask == 0x0000FF00) && (pOldFormat->dwRBitMask == 0x00000f00) && (pOldFormat->dwGBitMask == 0x000000f0) && (pOldFormat->dwBBitMask == 0x0000000f)) { *pNewFormat = D3DFMT_A4R4G4B4; } else if ((pOldFormat->dwRGBAlphaBitMask == 0x00008000) && (pOldFormat->dwRBitMask == 0x00007c00) && (pOldFormat->dwGBitMask == 0x000003e0) && (pOldFormat->dwBBitMask == 0x0000001f)) { *pNewFormat = D3DFMT_A1R5G5B5; } break;
case 32: if ((pOldFormat->dwRGBAlphaBitMask == 0xff000000) && (pOldFormat->dwRBitMask == 0x00ff0000) && (pOldFormat->dwGBitMask == 0x0000ff00) && (pOldFormat->dwBBitMask == 0x000000ff)) { *pNewFormat = D3DFMT_A8R8G8B8; } break; } } #if 0
// We don't convert the old representation of A8 to
// the new format because there are some existing DX7 drivers
// that expose the old format but don't implement it correctly
// or completely. We've seen Blt failures, and Rendering failures.
// So this becomes a DX8+ only feature; in which case
// we will get a new-style format from the driver.
// MB43799
else if (pOldFormat->dwFlags == DDPF_ALPHA) { if (pOldFormat->dwAlphaBitDepth == 8) { *pNewFormat = D3DFMT_A8; } } #endif
else if (pOldFormat->dwFlags & (DDPF_PALETTEINDEXED8 | DDPF_RGB)) { switch (pOldFormat->dwRGBBitCount) { case 8: if (pOldFormat->dwFlags == (DDPF_PALETTEINDEXED8 | DDPF_RGB)) { *pNewFormat = D3DFMT_P8; } break;
case 16: if (pOldFormat->dwFlags == (DDPF_PALETTEINDEXED8 | DDPF_RGB | DDPF_ALPHAPIXELS) && pOldFormat->dwRGBAlphaBitMask == 0xFF00) {
*pNewFormat = D3DFMT_A8P8; } break; } } else if (pOldFormat->dwFlags == DDPF_ZBUFFER) { switch (pOldFormat->dwZBufferBitDepth) { case 32: if (pOldFormat->dwZBitMask == 0xffffffff) { *pNewFormat = D3DFMT_D32; } else if (pOldFormat->dwZBitMask == 0x00FFFFFF) { *pNewFormat = D3DFMT_X8D24; } else if (pOldFormat->dwZBitMask == 0xFFFFFF00) { *pNewFormat = D3DFMT_D24X8; } break;
case 16: if (pOldFormat->dwZBitMask == 0xffff) { *pNewFormat = D3DFMT_D16_LOCKABLE; } break; } } else if (pOldFormat->dwFlags == (DDPF_ZBUFFER | DDPF_STENCILBUFFER)) { switch (pOldFormat->dwZBufferBitDepth) { case 32: if ((pOldFormat->dwZBitMask == 0xffffff00) && (pOldFormat->dwStencilBitMask == 0x000000ff) && (pOldFormat->dwStencilBitDepth == 8)) { *pNewFormat = D3DFMT_D24S8; } else if ((pOldFormat->dwZBitMask == 0x00ffffff) && (pOldFormat->dwStencilBitMask == 0xff000000) && (pOldFormat->dwStencilBitDepth == 8)) { *pNewFormat = D3DFMT_S8D24; } else if ((pOldFormat->dwZBitMask == 0xffffff00) && (pOldFormat->dwStencilBitMask == 0x0000000f) && (pOldFormat->dwStencilBitDepth == 4)) { *pNewFormat = D3DFMT_D24X4S4; } else if ((pOldFormat->dwZBitMask == 0x00ffffff) && (pOldFormat->dwStencilBitMask == 0x0f000000) && (pOldFormat->dwStencilBitDepth == 4)) { *pNewFormat = D3DFMT_X4S4D24; } break; case 16: if ((pOldFormat->dwZBitMask == 0xfffe) && (pOldFormat->dwStencilBitMask == 0x0001) && (pOldFormat->dwStencilBitDepth == 1)) { *pNewFormat = D3DFMT_D15S1; } else if ((pOldFormat->dwZBitMask == 0x7fff) && (pOldFormat->dwStencilBitMask == 0x8000) && (pOldFormat->dwStencilBitDepth == 1)) { *pNewFormat = D3DFMT_S1D15; } break; } } else if (pOldFormat->dwFlags == DDPF_LUMINANCE) { switch (pOldFormat->dwLuminanceBitCount) { case 8: if (pOldFormat->dwLuminanceBitMask == 0xFF) { *pNewFormat = D3DFMT_L8; } break; } } else if (pOldFormat->dwFlags == (DDPF_LUMINANCE | DDPF_ALPHAPIXELS)) { switch (pOldFormat->dwLuminanceBitCount) { case 8: if (pOldFormat->dwLuminanceBitMask == 0x0F && pOldFormat->dwLuminanceAlphaBitMask == 0xF0) { *pNewFormat = D3DFMT_A4L4; } case 16: if (pOldFormat->dwLuminanceBitMask == 0x00FF && pOldFormat->dwLuminanceAlphaBitMask == 0xFF00) { *pNewFormat = D3DFMT_A8L8; }
break; } } else if (pOldFormat->dwFlags == DDPF_BUMPDUDV) { switch (pOldFormat->dwBumpBitCount) { case 16: if (pOldFormat->dwBumpDuBitMask == 0xFF && pOldFormat->dwBumpDvBitMask == 0xFF00) { *pNewFormat = D3DFMT_V8U8; } break; } } else if (pOldFormat->dwFlags == (DDPF_BUMPDUDV | DDPF_BUMPLUMINANCE)) { switch (pOldFormat->dwBumpBitCount) { case 16: if (pOldFormat->dwBumpDuBitMask == 0x001F && pOldFormat->dwBumpDvBitMask == 0x03E0 && pOldFormat->dwBumpLuminanceBitMask == 0xFC00) { *pNewFormat = D3DFMT_L6V5U5; } break;
case 32: if (pOldFormat->dwBumpDuBitMask == 0x0000FF && pOldFormat->dwBumpDvBitMask == 0x00FF00 && pOldFormat->dwBumpLuminanceBitMask == 0xFF0000) { *pNewFormat = D3DFMT_X8L8V8U8; } break; } } }
/*
* FetchDirectDrawData * * Go get new HAL info... */ void FetchDirectDrawData( PD3D8_DEVICEDATA pBaseData, void* pInitFunction, D3DFORMAT Unknown16, DDSURFACEDESC* pHalOpList, DWORD NumHalOps) { BOOL bNewMode; BOOL bRetVal; UINT i=0; BOOL bAlreadyAnOpList = FALSE; LPDDPIXELFORMAT pZStencilFormatList=0; DDSURFACEDESC *pTextureList=0; D3D8_GLOBALDRIVERDATA D3DGlobalDriverData; D3DHAL_D3DEXTENDEDCAPS D3DExtendedCaps; BOOL bBackbuffersExist = FALSE; BOOL bReset = FALSE; ZeroMemory( &D3DGlobalDriverData, sizeof(D3DGlobalDriverData) ); ZeroMemory( &D3DExtendedCaps, sizeof(D3DExtendedCaps) ); if (pBaseData->hDD == NULL) { #ifdef WINNT
D3D8CreateDirectDrawObject(pBaseData->hDC, pBaseData->DriverName, &pBaseData->hDD, pBaseData->DeviceType, &pBaseData->hLibrary, pInitFunction); #else
D3D8CreateDirectDrawObject(&pBaseData->Guid, pBaseData->DriverName, &pBaseData->hDD, pBaseData->DeviceType, &pBaseData->hLibrary, pInitFunction); #endif
if (pBaseData->hDD == NULL) { #ifdef WINNT
DPF(1, "****DirectDraw/Direct3D DRIVER DISABLING ERROR****:NT Kernel mode would not create driver object... Failing over to emulation"); #endif
goto ErrorExit; } } else { // If we already have 3D caps, then we are resetting
if ((pBaseData->DriverData.dwFlags & DDIFLAG_D3DCAPS8) && (pBaseData->DriverData.D3DCaps.DevCaps != 0)) { bReset = TRUE; } }
// Now we can get the driver info...
// The first call returns the amount of space we need to allocate for the
// texture and z/stencil lists
UINT cTextureFormats; UINT cZStencilFormats;
if (bReset) { // If we are ressting, we do not want to rebuild all of the caps, the
// format list, etc., but we still need to call the thunk layer because
// on NT this resets the kernel.
D3D8_DRIVERCAPS TempData; D3D8_CALLBACKS TempCallbacks;
if (!D3D8ReenableDirectDrawObject(pBaseData->hDD,&bNewMode) || !D3D8QueryDirectDrawObject(pBaseData->hDD, &TempData, &TempCallbacks, pBaseData->DriverName, pBaseData->hLibrary, &D3DGlobalDriverData, &D3DExtendedCaps, NULL, NULL, &cTextureFormats, &cZStencilFormats)) { goto ErrorExit; } pBaseData->DriverData.DisplayWidth = TempData.DisplayWidth; pBaseData->DriverData.DisplayHeight = TempData.DisplayHeight; pBaseData->DriverData.DisplayFormatWithAlpha = TempData.DisplayFormatWithAlpha; pBaseData->DriverData.DisplayFormatWithoutAlpha = TempData.DisplayFormatWithoutAlpha; pBaseData->DriverData.DisplayFrequency = TempData.DisplayFrequency; } else { MemFree (pBaseData->DriverData.pGDD8SupportedFormatOps); pBaseData->DriverData.pGDD8SupportedFormatOps = NULL;
if (!D3D8ReenableDirectDrawObject(pBaseData->hDD,&bNewMode) || !D3D8QueryDirectDrawObject(pBaseData->hDD, &pBaseData->DriverData, &pBaseData->Callbacks, pBaseData->DriverName, pBaseData->hLibrary, &D3DGlobalDriverData, &D3DExtendedCaps, NULL, NULL, &cTextureFormats, &cZStencilFormats)) { DPF(1, "****Direct3D DRIVER DISABLING ERROR****:First call to DdQueryDirectDrawObject failed!"); D3D8DeleteDirectDrawObject(pBaseData->hDD); pBaseData->hDD = NULL; goto ErrorExit; }
// First we make space for the formats
// let's do memalloc for pTextureList just once, 3 extra for possible backbuffers
// 3 extra for D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET
pTextureList = (DDSURFACEDESC *) MemAlloc ((cTextureFormats+ cZStencilFormats + 6) * sizeof (*pTextureList)); if (pTextureList == NULL) { DPF_ERR("****Direct3D DRIVER DISABLING ERROR****:Unable to allocate memory for texture formats!"); D3D8DeleteDirectDrawObject(pBaseData->hDD); pBaseData->hDD = NULL; goto ErrorExit; }
if (cZStencilFormats > 0) { pZStencilFormatList = (DDPIXELFORMAT *) MemAlloc (cZStencilFormats * sizeof (*pZStencilFormatList)); if (pZStencilFormatList == NULL) { DPF_ERR("****Direct3D DRIVER DISABLING ERROR****:Unable to allocate memory for Z/Stencil formats!"); D3D8DeleteDirectDrawObject(pBaseData->hDD); pBaseData->hDD = NULL; goto ErrorExit; } }
//Now that we've allocated space for the texture and z/stencil lists, we can go get em.
if (!D3D8QueryDirectDrawObject(pBaseData->hDD, &pBaseData->DriverData, &pBaseData->Callbacks, pBaseData->DriverName, pBaseData->hLibrary, &D3DGlobalDriverData, &D3DExtendedCaps, pTextureList, pZStencilFormatList, &cTextureFormats, &cZStencilFormats)) { DPF_ERR("****Direct3D DRIVER DISABLING ERROR****:Second call to DdQueryDirectDrawObject failed!"); D3D8DeleteDirectDrawObject(pBaseData->hDD); pBaseData->hDD = NULL; goto ErrorExit; }
// If no D3DCAPS8 was reported by the thunk layer, then the driver
// must be a pre-DX8 driver. We must sew together the
// D3DGlobalDriverData and the ExtendedCaps (which have to be reported).
// Note: The thunk layer already has plugged in the DDraw Caps such
// as the Caps, Caps2 and Caps3 (dwSVCaps).
if( (pBaseData->DriverData.dwFlags & DDIFLAG_D3DCAPS8) == 0 ) { MakeDX8Caps( &pBaseData->DriverData.D3DCaps, &D3DGlobalDriverData, &D3DExtendedCaps ); pBaseData->DriverData.dwFlags |= DDIFLAG_D3DCAPS8;
} else { // They reported the DX8 caps.
// Internally we check MaxPointSize if it is zero or not
// to determine if PointSprites are supported or not. So if a DX8 driver said 1.0
// set it to Zero
if (pBaseData->DriverData.D3DCaps.MaxPointSize == 1.0) { pBaseData->DriverData.D3DCaps.MaxPointSize = 0; } }
// There are some legacy caps that are reported by the drivers that
// we dont want the applications to see. Should weed them out here.
pBaseData->DriverData.D3DCaps.PrimitiveMiscCaps &= ~(D3DPMISCCAPS_MASKPLANES | D3DPMISCCAPS_CONFORMANT); pBaseData->DriverData.D3DCaps.DevCaps &= ~(D3DDEVCAPS_FLOATTLVERTEX | D3DDEVCAPS_SORTINCREASINGZ | D3DDEVCAPS_SORTDECREASINGZ | D3DDEVCAPS_SORTEXACT);
pBaseData->DriverData.D3DCaps.TextureCaps &= ~(D3DPTEXTURECAPS_TRANSPARENCY | D3DPTEXTURECAPS_BORDER | D3DPTEXTURECAPS_COLORKEYBLEND); pBaseData->DriverData.D3DCaps.VertexProcessingCaps &= ~(D3DVTXPCAPS_VERTEXFOG);
pBaseData->DriverData.D3DCaps.RasterCaps &= ~(D3DPRASTERCAPS_SUBPIXEL | D3DPRASTERCAPS_SUBPIXELX | D3DPRASTERCAPS_STIPPLE | D3DPRASTERCAPS_ANTIALIASSORTDEPENDENT | D3DPRASTERCAPS_ANTIALIASSORTINDEPENDENT | D3DPRASTERCAPS_TRANSLUCENTSORTINDEPENDENT);
pBaseData->DriverData.D3DCaps.ShadeCaps &= ~(D3DPSHADECAPS_COLORFLATMONO | D3DPSHADECAPS_COLORFLATRGB | D3DPSHADECAPS_COLORGOURAUDMONO | D3DPSHADECAPS_COLORPHONGMONO | D3DPSHADECAPS_COLORPHONGRGB | D3DPSHADECAPS_SPECULARFLATMONO | D3DPSHADECAPS_SPECULARFLATRGB | D3DPSHADECAPS_SPECULARGOURAUDMONO | D3DPSHADECAPS_SPECULARPHONGMONO | D3DPSHADECAPS_SPECULARPHONGRGB | D3DPSHADECAPS_ALPHAFLATBLEND | D3DPSHADECAPS_ALPHAFLATSTIPPLED | D3DPSHADECAPS_ALPHAGOURAUDSTIPPLED | D3DPSHADECAPS_ALPHAPHONGBLEND | D3DPSHADECAPS_ALPHAPHONGSTIPPLED | D3DPSHADECAPS_FOGFLAT | D3DPSHADECAPS_FOGPHONG);
// Now we generate the list of supported ops from the texture format
// list and z/stencil list.
//
// A DX7 or older driver will return to us a simple list of pixel formats.
// We will take this list and convert it into a list of supported
// texture formats in the DX8 style. To that we will append any
// z/stencil formats.
//
// First step in generating supported op lists: see if the list is
// already a DX8 style format list. If it is (i.e. if any
// entries are DDPF_D3DFORMAT, then all we need to do is
// yank out the old-style entries (drivers are allowed to
// keep both so they can run against old runtimes).
for (i = 0; i < cTextureFormats; i++) {
if (pTextureList[i].ddpfPixelFormat.dwFlags == DDPF_D3DFORMAT) { bAlreadyAnOpList = TRUE; break; } }
if (bAlreadyAnOpList) { // mmmmm.... dx8 driver. We'll ignore its Z/stencil list because
// such a driver is supposed to put additional op entries in the
// "texture" list (i.e. the op list) for its z/stencil formats
// Now all we have to do is ZAP all the old-style entries.
for (i = 0; i < (INT)cTextureFormats; i++) { if (pTextureList[i].ddpfPixelFormat.dwFlags != DDPF_D3DFORMAT && i < (INT)cTextureFormats) { // ha! zap that evil old-style entry!
// (scroll the remainder of the list down
// to squish this entry)
DDASSERT(cTextureFormats > 0); //after all, we're in a for loop.
if (i < (INT)(cTextureFormats - 1)) { memcpy(pTextureList + i, pTextureList + i + 1, sizeof(*pTextureList)*(cTextureFormats - i - 1)); } cTextureFormats--; i--; } }
// TODO: Remove this as soon as we think that drivers have caught up to
// our OP LIST changes.
for (i = 0; i < cTextureFormats; i++) { if (pTextureList[i].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_BACKBUFFER) { pTextureList[i].ddpfPixelFormat.dwOperations &= ~D3DFORMAT_OP_BACKBUFFER; pTextureList[i].ddpfPixelFormat.dwOperations |= D3DFORMAT_OP_3DACCELERATION; if (pBaseData->DeviceType == D3DDEVTYPE_HAL) { pTextureList[i].ddpfPixelFormat.dwOperations |= D3DFORMAT_OP_DISPLAYMODE; } } }
// If it's a SW driver, we've got a lot of extra work to do.
if ((pBaseData->DeviceType == D3DDEVTYPE_REF) || (pBaseData->DeviceType == D3DDEVTYPE_SW)) { // First, make sure that the SW driver didn't erroneuously report any
// D3DFORMAT_OP_DISPLAYMODE entries.
for (i = 0; i < cTextureFormats; i++) { if (pTextureList[i].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_DISPLAYMODE) { DPF_ERR("*****The SW driver is disabled because it claims to support D3DFORMAT_OP_DISPLAYMODE*****"); D3D8DeleteDirectDrawObject(pBaseData->hDD); pBaseData->hDD = NULL; goto ErrorExit; } } // Now for the hard part. The HAL reports which display modes
// it can support, and the SW driver reports which display
// modes it can accelerate. We need to prune the SW list so
// that it matches the HW list.
for (i = 0; i < cTextureFormats; i++) { if (pTextureList[i].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_3DACCELERATION) { // Does the HAL support this mode?
if (IsSupportedOp ((D3DFORMAT) pTextureList[i].ddpfPixelFormat.dwFourCC, pHalOpList, NumHalOps, D3DFORMAT_OP_DISPLAYMODE)) { pTextureList[i].ddpfPixelFormat.dwOperations |= D3DFORMAT_OP_DISPLAYMODE; } else { pTextureList[i].ddpfPixelFormat.dwOperations &= ~D3DFORMAT_OP_3DACCELERATION; } } } }
// since we found one op-style entry, we shouldn't have
// killed them all
DDASSERT(cTextureFormats); } else { // Hmmm.. yucky non DX8 driver! Better go through its texture list
// and turn it into an op list
INT i; for(i=0; i< (INT)cTextureFormats; i++) { // we proved this above:
DDASSERT(pTextureList[i].ddpfPixelFormat.dwFlags != DDPF_D3DFORMAT);
D3DFORMAT NewFormat; ConvertFromOldFormat(&pTextureList[i].ddpfPixelFormat, &NewFormat );
if (NewFormat != D3DFMT_UNKNOWN) // we succeeded the conversion
{ pTextureList[i].ddpfPixelFormat.dwFourCC = (DWORD) NewFormat; pTextureList[i].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT; pTextureList[i].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_TEXTURE;
if (pBaseData->DriverData.D3DCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP) { // It is assumed that any texture format works for cubes
pTextureList[i].ddpfPixelFormat.dwOperations |= D3DFORMAT_OP_CUBETEXTURE;
if (NewFormat == D3DFMT_X1R5G5B5 || NewFormat == D3DFMT_R5G6B5 || NewFormat == D3DFMT_A8R8G8B8 || NewFormat == D3DFMT_X8R8G8B8) { // For these three formats, we assume
// all cube-map hw supports rendering to them.
//
// Testing indicates that these formats don't work
// well if they are in bitdepth other than the primary;
// so we only specify that the RT aspect of these
// formats work if they are basically the same
// as the primary.
pTextureList[i].ddpfPixelFormat.dwOperations |= D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET; } }
// If they can support render target textures, add those flags in now
DWORD RTBit = D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET; if (pBaseData->DriverData.KnownDriverFlags & KNOWN_CANMISMATCHRT) { RTBit = D3DFORMAT_OP_OFFSCREEN_RENDERTARGET; } if ((NewFormat == D3DFMT_X1R5G5B5) && (pBaseData->DriverData.KnownDriverFlags & KNOWN_RTTEXTURE_X1R5G5B5)) { pTextureList[i].ddpfPixelFormat.dwOperations |= RTBit; } else if ((NewFormat == D3DFMT_R5G6B5) && (pBaseData->DriverData.KnownDriverFlags & KNOWN_RTTEXTURE_R5G6B5)) { pTextureList[i].ddpfPixelFormat.dwOperations |= RTBit; } else if ((NewFormat == D3DFMT_X8R8G8B8) && (pBaseData->DriverData.KnownDriverFlags & KNOWN_RTTEXTURE_X8R8G8B8)) { pTextureList[i].ddpfPixelFormat.dwOperations |= RTBit; } else if ((NewFormat == D3DFMT_A8R8G8B8) && (pBaseData->DriverData.KnownDriverFlags & KNOWN_RTTEXTURE_A8R8G8B8)) { pTextureList[i].ddpfPixelFormat.dwOperations |= RTBit; } else if ((NewFormat == D3DFMT_A1R5G5B5) && (pBaseData->DriverData.KnownDriverFlags & KNOWN_RTTEXTURE_A1R5G5B5)) { pTextureList[i].ddpfPixelFormat.dwOperations |= RTBit; } else if ((NewFormat == D3DFMT_A4R4G4B4) && (pBaseData->DriverData.KnownDriverFlags & KNOWN_RTTEXTURE_A4R4G4B4)) { pTextureList[i].ddpfPixelFormat.dwOperations |= RTBit; }
pTextureList[i].ddpfPixelFormat.dwPrivateFormatBitCount = 0; pTextureList[i].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0; pTextureList[i].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0; } else { DPF(3,"This driver exposes an unrecognized DX7- style texture format"); // and we eat it up:
// (scroll the remainder of the list down to
// squish this entry)
DDASSERT(cTextureFormats>0); //after all, we're in a for loop.
if (i < (INT)(cTextureFormats - 1)) { memcpy(pTextureList + i, pTextureList + i + 1, sizeof(*pTextureList)*(cTextureFormats - i - 1)); } cTextureFormats--; i--; } }
//And laboriously tack on the z/stencil formats. Phew.
for (i = 0; i < (INT)cZStencilFormats; i++) { DDASSERT(pZStencilFormatList);
//we proved this above:
DDASSERT(pZStencilFormatList[i].dwFlags != DDPF_D3DFORMAT);
D3DFORMAT NewFormat;
ConvertFromOldFormat(&pZStencilFormatList[i], &NewFormat); if (NewFormat != D3DFMT_UNKNOWN) //we succeeded the conversion
{ // Room for these elements was allocated above...
pTextureList[cTextureFormats].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT; pTextureList[cTextureFormats].ddpfPixelFormat.dwFourCC = (DWORD) NewFormat; pTextureList[cTextureFormats].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_ZSTENCIL; pTextureList[cTextureFormats].ddpfPixelFormat.dwPrivateFormatBitCount = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0;
// See if part is "known good" i.e. it can mix-and-match
// ZBuffer and RT formats
if (pBaseData->DriverData.KnownDriverFlags & KNOWN_ZSTENCILDEPTH) { pTextureList[cTextureFormats].ddpfPixelFormat.dwOperations |= D3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH; }
// If part successfully supports lockable 16-bit zbuffer tests
// then we allow D16_LOCKABLE through; else we only expose D3DFMT_D16
if (NewFormat == D3DFMT_D16_LOCKABLE) { if (!(pBaseData->DriverData.KnownDriverFlags & KNOWN_D16_LOCKABLE)) { pTextureList[cTextureFormats].ddpfPixelFormat.dwFourCC = (DWORD) D3DFMT_D16; } }
cTextureFormats++; } else { DPF(3,"This driver exposes an unrecognized DX6 style Z/Stencil format"); } }
// Now we need to add in off-screen render target formats for this Non-DX8 driver.
// DX8 doesn't allow back buffers to be used as textures, so we add
// a whole new entry to the op list for each supported back buffer
// format (i.e. don't go searching for any existing texturable format
// entry that matches and OR in the RT op).
//
//If the format is a back-buffer format, we assume it can be rendered when in the same
//display mode. Note the presence of this entry in the format op list doesn't imply
//necessarily that the device can render in that depth. CheckDeviceFormat could still
//fail for modes of that format... This gives us license to blindly add the formats
//here before we really know what set of back buffer formats the device can do.
//(Note only display devices are given this boost, since voodoos don't run windowed)
if (pBaseData->dwFlags & DD_DISPLAYDRV) { pTextureList[cTextureFormats].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT; pTextureList[cTextureFormats].ddpfPixelFormat.dwFourCC = (DWORD) Unknown16; pTextureList[cTextureFormats].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET; pTextureList[cTextureFormats].ddpfPixelFormat.dwPrivateFormatBitCount = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0; cTextureFormats ++;
pTextureList[cTextureFormats].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT; pTextureList[cTextureFormats].ddpfPixelFormat.dwFourCC = (DWORD) D3DFMT_X8R8G8B8; pTextureList[cTextureFormats].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET; pTextureList[cTextureFormats].ddpfPixelFormat.dwPrivateFormatBitCount = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0; cTextureFormats ++; } else { // Voodood 2 hack - The V2 doesn't really support offscreen
// render targets, but we need to add a 565 RT anyway or else
// our op list won't create the device.
// CONSIDER: Adding an internal OP flag indicating that this format
// should NOT succeed in a call to CreateRenderTarget.
pTextureList[cTextureFormats].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT; pTextureList[cTextureFormats].ddpfPixelFormat.dwFourCC = (DWORD) Unknown16; pTextureList[cTextureFormats].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET; pTextureList[cTextureFormats].ddpfPixelFormat.dwPrivateFormatBitCount = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0; cTextureFormats ++; }
// Now add in the supported display modes
if (D3DGlobalDriverData.hwCaps.dwDeviceRenderBitDepth & DDBD_16) { pTextureList[cTextureFormats].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT; pTextureList[cTextureFormats].ddpfPixelFormat.dwFourCC = (DWORD) Unknown16; pTextureList[cTextureFormats].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_DISPLAYMODE|D3DFORMAT_OP_3DACCELERATION; pTextureList[cTextureFormats].ddpfPixelFormat.dwPrivateFormatBitCount = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0; cTextureFormats++; } if (D3DGlobalDriverData.hwCaps.dwDeviceRenderBitDepth & DDBD_24) { pTextureList[cTextureFormats].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT; pTextureList[cTextureFormats].ddpfPixelFormat.dwFourCC = (DWORD) D3DFMT_R8G8B8; pTextureList[cTextureFormats].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_DISPLAYMODE|D3DFORMAT_OP_3DACCELERATION; pTextureList[cTextureFormats].ddpfPixelFormat.dwPrivateFormatBitCount = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0; cTextureFormats++; } if (D3DGlobalDriverData.hwCaps.dwDeviceRenderBitDepth & DDBD_32) { pTextureList[cTextureFormats].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT; pTextureList[cTextureFormats].ddpfPixelFormat.dwFourCC = (DWORD) D3DFMT_X8R8G8B8; pTextureList[cTextureFormats].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_DISPLAYMODE|D3DFORMAT_OP_3DACCELERATION; pTextureList[cTextureFormats].ddpfPixelFormat.dwPrivateFormatBitCount = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0; cTextureFormats++; }
// This is a hack for those really, really old drivers that don't
// support any D3D at all. We will fill in 16 and 32bpp modes, but remove
// the 32bpp mode later if we can't find it in the mode table.
if ((D3DGlobalDriverData.hwCaps.dwDeviceRenderBitDepth == 0) #ifdef WIN95
&& (pBaseData->DriverData.D3DCaps.Caps & DDCAPS_BLT) && !(pBaseData->DriverData.D3DCaps.Caps & DDCAPS_NOHARDWARE) #endif
) { pTextureList[cTextureFormats].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT; pTextureList[cTextureFormats].ddpfPixelFormat.dwFourCC = (DWORD) Unknown16; pTextureList[cTextureFormats].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_DISPLAYMODE; pTextureList[cTextureFormats].ddpfPixelFormat.dwPrivateFormatBitCount = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0; cTextureFormats++;
pTextureList[cTextureFormats].ddpfPixelFormat.dwFlags = DDPF_D3DFORMAT; pTextureList[cTextureFormats].ddpfPixelFormat.dwFourCC = (DWORD) D3DFMT_X8R8G8B8; pTextureList[cTextureFormats].ddpfPixelFormat.dwOperations = D3DFORMAT_OP_DISPLAYMODE; pTextureList[cTextureFormats].ddpfPixelFormat.dwPrivateFormatBitCount = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wFlipMSTypes = 0; pTextureList[cTextureFormats].ddpfPixelFormat.MultiSampleCaps.wBltMSTypes = 0; cTextureFormats++; } }
// As a final pass we infer operations as necessary. If we have an
// general operation that implies other specific operations; then we
// turn on the bits of those specific operations. This is better
// than relying on the driver to get everything right; because it lets us
// add more specific operations in future releases without breaking
// old releases.
for (i = 0; i < cTextureFormats; i++) { DWORD *pdwOperations = &(pTextureList[i].ddpfPixelFormat.dwOperations);
// Off-screen RT means truly mode-independent
if ((*pdwOperations) & D3DFORMAT_OP_OFFSCREEN_RENDERTARGET) { (*pdwOperations) |= D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET; (*pdwOperations) |= D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET; }
// Same except for alpha means exact same is good too
if ((*pdwOperations) & D3DFORMAT_OP_SAME_FORMAT_UP_TO_ALPHA_RENDERTARGET) { (*pdwOperations) |= D3DFORMAT_OP_SAME_FORMAT_RENDERTARGET; }
// Color Independent Z implies that forced Z matching is ok too.
if ((*pdwOperations) & D3DFORMAT_OP_ZSTENCIL_WITH_ARBITRARY_COLOR_DEPTH) { (*pdwOperations) |= D3DFORMAT_OP_ZSTENCIL; } }
// Now we make a final pass to verify that they driver did gave us an
// OP list that makes sense. The OP list rules are:
//
// 1. Only One Endian-ness for any DS format is allowed i.e. D15S1 OR
// S1D15, not both independent of other bits.
// 2. A list should only include D3DFORMAT_OP_DISPLAYMODE for exactly
// one 16bpp format (i.e. shouldn�t enumerate 5:5:5 and 5:6:5).
// 3. A list should not any alpha formats with D3DFORMAT_OP_DISPLAYMODE
// or D3DFORMAT_OP_3DACCEL set.
// 4. Make sure no mode has OP_3DACCEL set that doesn�t also have
// OP_DISPLAYMODE set.
//
// We also register IHV formats with CPixel.
//
BOOL BadOpList = FALSE; for (i = 0; i < cTextureFormats; i++) { if ((pTextureList[i].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_PIXELSIZE) && pTextureList[i].ddpfPixelFormat.dwPrivateFormatBitCount != 0) { CPixel::Register((D3DFORMAT)pTextureList[i].ddpfPixelFormat.dwFourCC, pTextureList[i].ddpfPixelFormat.dwPrivateFormatBitCount); }
if ((pTextureList[i].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_3DACCELERATION) && !(pTextureList[i].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_DISPLAYMODE)) { DPF_ERR("***Driver disabled because it reported a format with D3DFORMAT_OP_3DACCELERATION without D3DFORMAT_OP_DISPLAYMODE"); BadOpList = TRUE; } if ((pTextureList[i].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_3DACCELERATION) && ((pTextureList[i].ddpfPixelFormat.dwFourCC == (DWORD) D3DFMT_A8R8G8B8) || (pTextureList[i].ddpfPixelFormat.dwFourCC == (DWORD) D3DFMT_A1R5G5B5))) { DPF_ERR("***Driver disabled because it reported an alpha format with D3DFORMAT_OP_3DACCELERATION"); BadOpList = TRUE; }
if ((pTextureList[i].ddpfPixelFormat.dwOperations & D3DFORMAT_OP_DISPLAYMODE) && (pTextureList[i].ddpfPixelFormat.dwFourCC == (DWORD) D3DFMT_R5G6B5)) { if (IsSupportedOp (D3DFMT_X1R5G5B5, pTextureList, cTextureFormats, D3DFORMAT_OP_DISPLAYMODE)) { DPF_ERR("***Driver disabled because it reported both D3DFMT_R5G6B5 and D3DFMT_X1R5G5B5 as a display mode"); BadOpList = TRUE; } }
if (pTextureList[i].ddpfPixelFormat.dwFourCC == (DWORD) D3DFMT_D15S1) { if (IsSupportedOp (D3DFMT_S1D15, pTextureList, cTextureFormats, 0)) { DPF_ERR("***Driver disabled because it reported both D3DFMT_D15S1 and D3DFMT_S1D15"); BadOpList = TRUE; } } else if (pTextureList[i].ddpfPixelFormat.dwFourCC == (DWORD) D3DFMT_D24S8) { if (IsSupportedOp (D3DFMT_S8D24, pTextureList, cTextureFormats, 0)) { DPF_ERR("***Driver disabled because it reported both D3DFMT_D24S8 and D3DFMT_S8D24"); BadOpList = TRUE; } } else if (pTextureList[i].ddpfPixelFormat.dwFourCC == (DWORD) D3DFMT_D24X8) { if (IsSupportedOp (D3DFMT_X8D24, pTextureList, cTextureFormats, 0)) { DPF_ERR("***Driver disabled because it reported both D3DFMT_D24X8 and D3DFMT_X8D24"); BadOpList = TRUE; } } else if (pTextureList[i].ddpfPixelFormat.dwFourCC == (DWORD) D3DFMT_D24X4S4) { if (IsSupportedOp (D3DFMT_X4S4D24, pTextureList, cTextureFormats, 0)) { DPF_ERR("***Driver disabled because it reported both D3DFMT_D24X4S4 and D3DFMT_X4S4D24"); BadOpList = TRUE; } } } if (BadOpList) { D3D8DeleteDirectDrawObject(pBaseData->hDD); pBaseData->hDD = NULL; goto ErrorExit; }
// and now we assign the texture list to its place in the driver data
pBaseData->DriverData.pGDD8SupportedFormatOps = pTextureList; if (pTextureList != NULL) { pTextureList = NULL; //so it won't be freed later
pBaseData->DriverData.GDD8NumSupportedFormatOps = cTextureFormats; } else { pBaseData->DriverData.GDD8NumSupportedFormatOps = 0; }
if (!(pBaseData->DriverData.D3DCaps.Caps2 & DDCAPS2_NONLOCALVIDMEM)) { if (pBaseData->DriverData.D3DCaps.DevCaps & 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"); pBaseData->DriverData.D3DCaps.DevCaps &= ~D3DDEVCAPS_TEXTURENONLOCALVIDMEM; } }
// For pre-DX8, we have some munging of caps that is necessary
if (pBaseData->DriverData.D3DCaps.MaxStreams == 0) { DWORD *pdwTextureCaps = &pBaseData->DriverData.D3DCaps.TextureCaps; if (*pdwTextureCaps & D3DPTEXTURECAPS_CUBEMAP) { if (pBaseData->DriverData.KnownDriverFlags & KNOWN_MIPPEDCUBEMAPS) { *pdwTextureCaps |= D3DPTEXTURECAPS_MIPCUBEMAP; } else { // Turn off Mip filter flags since this is card doesnt support a mipped cubemap.
pBaseData->DriverData.D3DCaps.CubeTextureFilterCaps &= ~(D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MIPFLINEAR); } // Also we need to specify that cube-maps must
// be power-of-two
*pdwTextureCaps |= D3DPTEXTURECAPS_CUBEMAP_POW2; }
// We need to determine the part can support mipmaps...
if (pBaseData->DriverData.D3DCaps.TextureFilterCaps & (D3DPTFILTERCAPS_MIPNEAREST | D3DPTFILTERCAPS_MIPLINEAR | D3DPTFILTERCAPS_LINEARMIPNEAREST | D3DPTFILTERCAPS_LINEARMIPLINEAR | D3DPTFILTERCAPS_MIPFPOINT | D3DPTFILTERCAPS_MIPFLINEAR)) { *pdwTextureCaps |= D3DPTEXTURECAPS_MIPMAP; } else { DPF(3, "Device doesn't support mip-maps"); } }
// We disable driver-management for pre-dx8 parts because
// the semantics for driver-management are now different
// for dx8; and hence we can't use old driver's logic.
pBaseData->DriverData.D3DCaps.Caps2 &= ~DDCAPS2_CANMANAGETEXTURE;
// For HW that needs separate banks of texture memory; we
// disable multi-texturing. This is done because we don't want to
// have an API that puts the burden on the application to specifically
// code for this case.
if (pBaseData->DriverData.D3DCaps.DevCaps & D3DDEVCAPS_SEPARATETEXTUREMEMORIES) { pBaseData->DriverData.D3DCaps.MaxSimultaneousTextures = 1;
// Turn off this flag.
pBaseData->DriverData.D3DCaps.DevCaps &= ~D3DDEVCAPS_SEPARATETEXTUREMEMORIES; } }
ErrorExit:
if (NULL != pTextureList) MemFree(pTextureList);
// It was only temporary, having now been merged into the supported op list.
if (NULL != pZStencilFormatList) MemFree(pZStencilFormatList);
return;
} /* FetchDirectDrawData */
/*
* DirectDrawSupported */ BOOL DirectDrawSupported(void) { HDC hdc; unsigned u;
hdc = GetDC(NULL); u = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES); ReleaseDC(NULL, hdc);
if (u < 8) { return FALSE; } return TRUE;
} /* DirectDrawSupported */
// 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
}
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; }
/*
* 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( PD3D8_DEVICEDATA* ppBaseData, PADAPTERINFO pDeviceInfo, D3DDEVTYPE DeviceType, VOID* pInitFunction, D3DFORMAT Unknown16, DDSURFACEDESC* pHalOpList, DWORD NumHalOps) { int rc; HDC hdc_dd; HKEY hkey; ULONG_PTR hDD; PD3D8_DEVICEDATA pBaseData;
*ppBaseData = (PD3D8_DEVICEDATA) NULL;
/*
* check for < 8 bpp and disallow. */ if (!DirectDrawSupported()) { DPF_ERR("DDraw and Direct3D are not supported in less than 8bpp modes. Creating Device fails."); return D3DERR_NOTAVAILABLE; }
ENTER_CSDDC();
hdc_dd = NULL; hDD = 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(); }
// Create the object and get all of the data.
hdc_dd = DD_CreateDC(pDeviceInfo->DeviceName); if (hdc_dd == NULL) { DPF_ERR("Could not create driver, CreateDC failed! Creating Device fails."); LEAVE_CSDDC(); return E_OUTOFMEMORY; }
// Create the driver object
pBaseData = (PD3D8_DEVICEDATA) MemAlloc (sizeof (D3D8_DEVICEDATA)); if (pBaseData == NULL) { DPF_ERR("Insufficient system memory! Creating Device fails. "); DD_DoneDC(hdc_dd); LEAVE_CSDDC(); return E_OUTOFMEMORY; } ZeroMemory( pBaseData, sizeof(D3D8_DEVICEDATA) ); strcpy(pBaseData->DriverName, pDeviceInfo->DeviceName); pBaseData->hDC = hdc_dd; pBaseData->Guid = pDeviceInfo->Guid; pBaseData->DeviceType = DeviceType;
// Even if it's not a display driver, it may still be a GDI driver
if (hdc_dd != NULL) { if (pDeviceInfo->bIsDisplay) { pBaseData->dwFlags |= DD_DISPLAYDRV; } else if (fDoesGDI(hdc_dd)) { pBaseData->dwFlags |= DD_GDIDRV; } }
// Get all of the driver caps and callbacks
FetchDirectDrawData(pBaseData, pInitFunction, Unknown16, pHalOpList, NumHalOps);
if (pBaseData->hDD == NULL) { DDASSERT(NULL == pBaseData->DriverData.pGDD8SupportedFormatOps); DD_DoneDC(hdc_dd); MemFree(pBaseData); LEAVE_CSDDC(); return D3DERR_NOTAVAILABLE; } *ppBaseData = pBaseData; LEAVE_CSDDC(); return S_OK;
} /* InternalDirectDrawCreate */
/*
* InternalDirectDrawRelease */
HRESULT InternalDirectDrawRelease(PD3D8_DEVICEDATA pBaseData) { D3D8DeleteDirectDrawObject(pBaseData->hDD); DD_DoneDC(pBaseData->hDC); MemFree(pBaseData->DriverData.pGDD8SupportedFormatOps); MemFree(pBaseData);
return S_OK; } /* InternalDirectDrawRelease */
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 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; }
#ifdef POSTPONED
BOOL DDAPI DD32_HandleExternalModeChange(LPDEVMODE pModeInfo) { return FALSE; } #endif
#endif
|